@ak--47/dungeon-master 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/dungeons/technical/ad-spend-schema.json +2 -2
  2. package/dungeons/technical/ad-spend.js +16 -5
  3. package/dungeons/technical/anonymous-users-schema.json +4 -3
  4. package/dungeons/technical/anonymous-users.js +16 -6
  5. package/dungeons/technical/array-of-object-lookup-schema.json +1 -1
  6. package/dungeons/technical/array-of-object-lookup.js +22 -6
  7. package/dungeons/technical/experiments-schema.json +25 -19
  8. package/dungeons/technical/experiments.js +24 -6
  9. package/dungeons/technical/foobar.js +29 -13
  10. package/dungeons/technical/group-analytics-schema.json +92 -0
  11. package/dungeons/technical/group-analytics.js +16 -6
  12. package/dungeons/technical/mirror-strategies-schema.json +4 -4
  13. package/dungeons/technical/mirror-strategies.js +16 -6
  14. package/dungeons/technical/nested-objects.js +16 -5
  15. package/dungeons/technical/retention-cadence.js +14 -9
  16. package/dungeons/technical/sanity-schema.json +22 -22
  17. package/dungeons/technical/sanity.js +26 -6
  18. package/dungeons/technical/scale-test.js +16 -5
  19. package/dungeons/technical/scd-schema.json +230 -33
  20. package/dungeons/technical/scd.js +25 -5
  21. package/dungeons/technical/simple-schema.json +132 -48
  22. package/dungeons/technical/simple.js +21 -6
  23. package/dungeons/technical/simplest-schema.json +168 -79
  24. package/dungeons/technical/simplest.js +24 -7
  25. package/dungeons/technical/text-generation-schema.json +7 -4
  26. package/dungeons/technical/text-generation.js +23 -8
  27. package/dungeons/user/.gitkeep +0 -0
  28. package/dungeons/user/shalini.js +847 -0
  29. package/dungeons/vertical/community-schema.json +71 -49
  30. package/dungeons/vertical/community.js +57 -30
  31. package/dungeons/vertical/devtools-schema.json +69 -48
  32. package/dungeons/vertical/devtools.js +58 -31
  33. package/dungeons/vertical/ecommerce-schema.json +126 -108
  34. package/dungeons/vertical/ecommerce.js +32 -8
  35. package/dungeons/vertical/education-schema.json +5261 -272
  36. package/dungeons/vertical/education.js +45 -22
  37. package/dungeons/vertical/fintech-schema.json +165 -98
  38. package/dungeons/vertical/fintech.js +43 -11
  39. package/dungeons/vertical/fitness-schema.json +69 -47
  40. package/dungeons/vertical/fitness.js +56 -24
  41. package/dungeons/vertical/food-delivery-schema.json +36237 -187
  42. package/dungeons/vertical/food-delivery.js +67 -15
  43. package/dungeons/vertical/gaming-schema.json +104 -60
  44. package/dungeons/vertical/gaming.js +61 -16
  45. package/dungeons/vertical/healthcare-schema.json +70 -48
  46. package/dungeons/vertical/healthcare.js +77 -42
  47. package/dungeons/vertical/insurance-application-schema.json +66 -47
  48. package/dungeons/vertical/insurance-application.js +34 -10
  49. package/dungeons/vertical/logistics-schema.json +60 -38
  50. package/dungeons/vertical/logistics.js +77 -43
  51. package/dungeons/vertical/marketplace-schema.json +65 -43
  52. package/dungeons/vertical/marketplace.js +52 -21
  53. package/dungeons/vertical/media-schema.json +4085 -123
  54. package/dungeons/vertical/media.js +65 -18
  55. package/dungeons/vertical/rpg-schema.json +1984 -147
  56. package/dungeons/vertical/rpg.js +47 -11
  57. package/dungeons/vertical/sass-schema.json +2622 -147
  58. package/dungeons/vertical/sass.js +40 -10
  59. package/dungeons/vertical/social-schema.json +146 -78
  60. package/dungeons/vertical/social.js +39 -10
  61. package/dungeons/vertical/travel-schema.json +57 -35
  62. package/dungeons/vertical/travel.js +58 -21
  63. package/index.js +4 -1
  64. package/lib/core/config-validator.js +13 -2
  65. package/lib/core/context.js +9 -0
  66. package/lib/core/storage.js +2 -0
  67. package/lib/generators/events.js +3 -5
  68. package/lib/orchestrators/user-loop.js +24 -1
  69. package/lib/utils/utils.js +129 -9
  70. package/package.json +1 -1
  71. package/scripts/extract-dungeon-schema.mjs +64 -18
  72. package/types.d.ts +8 -3
@@ -1,16 +1,23 @@
1
+ // ── TWEAK THESE ──
2
+ const SEED = "dm4-healthcare";
3
+ const num_days = 100;
4
+ const num_users = 5_000;
5
+ const avg_events_per_user = 120;
6
+ let token = "your-mixpanel-token";
7
+
8
+ // ── env overrides ──
9
+ if (process.env.MP_TOKEN) token = process.env.MP_TOKEN;
10
+
1
11
  import dayjs from "dayjs";
2
12
  import utc from "dayjs/plugin/utc.js";
3
13
  import "dotenv/config";
4
14
  import * as u from "../../lib/utils/utils.js";
5
15
  import * as v from "ak-tools";
6
16
 
7
- const SEED = "dm4-healthcare";
8
17
  dayjs.extend(utc);
9
18
  const chance = u.initChance(SEED);
10
- const num_users = 5_000;
11
- const days = 100;
12
19
  const NOW = dayjs();
13
- const DATASET_START = NOW.subtract(days, "days");
20
+ const DATASET_START = NOW.subtract(num_days, "days");
14
21
 
15
22
  /** @typedef {import("../../types").Dungeon} Config */
16
23
 
@@ -199,22 +206,25 @@ const clinicIds = v.range(1, 25).map(() => `CLINIC_${v.uid(4)}`);
199
206
  * and experience levels that affect patient matching.
200
207
  *
201
208
  * ───────────────────────────────────────────────────────────────
202
- * 8. PREMIUM BOOKING FUNNEL LIFT (funnel-pre hook)
209
+ * 8. FREE-TIER CONVERSION DROP (everything hook)
203
210
  * ───────────────────────────────────────────────────────────────
204
211
  *
205
- * PATTERN: Users with subscription_tier "premium" get 1.4x conversion
206
- * rate on the booking funnel. Premium patients have priority scheduling.
212
+ * PATTERN: Free-tier users lose ~30% of "consultation completed"
213
+ * events (last step of the Booking to Consultation funnel).
214
+ * This is implemented via event filtering in the everything hook
215
+ * rather than conversionRate modification in funnel-pre, so the
216
+ * effect is not diluted by organic (non-funnel) events.
207
217
  *
208
218
  * HOW TO FIND IT IN MIXPANEL:
209
219
  *
210
220
  * Report 1: Booking Conversion by Tier
211
221
  * • Report type: Funnels
212
222
  * • Steps: "symptom search" → "appointment booked" → "consultation completed"
213
- * • Breakdown: "subscription_tier" (superProp)
214
- * • Expected: premium56% vs free ≈ 40% conversion
223
+ * • Breakdown: "subscription_tier"
224
+ * • Expected: free28% vs basic/premium ≈ 40% conversion
215
225
  *
216
- * REAL-WORLD ANALOGUE: Premium telehealth subscribers get priority
217
- * scheduling and shorter wait times, improving conversion.
226
+ * REAL-WORLD ANALOGUE: Free-tier patients face longer wait times
227
+ * and limited scheduling, reducing completed consultations.
218
228
  *
219
229
  * ═══════════════════════════════════════════════════════════════
220
230
  * EXPECTED METRICS SUMMARY
@@ -229,15 +239,15 @@ const clinicIds = v.range(1, 25).map(() => `CLINIC_${v.uid(4)}`);
229
239
  * Chronic Refill Chain | refills (chronic) | 1 | 3-4 | 3-4x
230
240
  * Occasional No-Shows | booking→consult | 95% | 75% | 0.79x
231
241
  * Doctor Specialization | years_experience | 5 | 22 | 4.4x
232
- * Premium Booking Lift | funnel conversion | 40% | 56% | 1.4x
242
+ * Free-Tier Conversion Drop | funnel conversion | 40% | 28% | 0.7x
233
243
  */
234
244
 
235
245
  /** @type {Config} */
236
246
  const config = {
237
- token: "",
247
+ token,
238
248
  seed: SEED,
239
- numDays: days,
240
- numEvents: num_users * 120,
249
+ numDays: num_days,
250
+ numEvents: num_users * avg_events_per_user,
241
251
  numUsers: num_users,
242
252
  hasAnonIds: false,
243
253
  hasSessionIds: true,
@@ -254,10 +264,16 @@ const config = {
254
264
  hasAdSpend: false,
255
265
  percentUsersBornInDataset: 35,
256
266
  hasAvatar: true,
257
- batchSize: 2_500_000,
258
267
  concurrency: 1,
259
268
  writeToDisk: false,
260
- scdProps: {},
269
+ scdProps: {
270
+ care_plan: {
271
+ values: ["preventive", "routine", "chronic", "acute"],
272
+ frequency: "month",
273
+ timing: "fuzzy",
274
+ max: 8
275
+ }
276
+ },
261
277
  mirrorProps: {},
262
278
  lookupTables: [],
263
279
 
@@ -479,7 +495,7 @@ const config = {
479
495
  // ── SuperProps ──────────────────────────────────────────
480
496
  superProps: {
481
497
  subscription_tier: ["free", "free", "free", "basic", "basic", "premium"],
482
- platform: ["ios", "android", "web"],
498
+ Platform: ["ios", "android", "web"],
483
499
  },
484
500
 
485
501
  // ── UserProps ──────────────────────────────────────────
@@ -490,6 +506,8 @@ const config = {
490
506
  preferred_language: ["en", "en", "en", "en", "es", "pt", "de", "fr"],
491
507
  has_chronic_condition: [false, false, false, true],
492
508
  age_range: ["18-25", "26-35", "26-35", "36-45", "36-45", "46-55", "56-65", "65+"],
509
+ subscription_tier: ["free", "free", "free", "basic", "basic", "premium"],
510
+ Platform: ["ios", "android", "web"],
493
511
  },
494
512
 
495
513
  // ── Personas ──────────────────────────────────
@@ -639,16 +657,9 @@ const config = {
639
657
  }
640
658
 
641
659
  // ── HOOK 8: PREMIUM BOOKING FUNNEL LIFT (funnel-pre) ─
642
- // Premium subscribers convert 1.4x better through booking funnel.
660
+ // (conversionRate boost removed filtering applied in everything hook instead)
643
661
  if (type === "funnel-pre") {
644
- if (meta && meta.profile) {
645
- const tier = meta.profile.subscription_tier;
646
- if (tier === "premium") {
647
- record.conversionRate = Math.min(record.conversionRate * 1.4, 95);
648
- } else if (tier === "basic") {
649
- record.conversionRate = Math.min(record.conversionRate * 1.15, 90);
650
- }
651
- }
662
+ // no-op: conversion differentiation handled via event filtering below
652
663
  }
653
664
 
654
665
  // ── HOOK 1: AFTER-HOURS SURGE PRICING (event) ────────
@@ -681,18 +692,42 @@ const config = {
681
692
 
682
693
  // ── EVERYTHING HOOKS ─────────────────────────────────
683
694
  if (type === "everything") {
684
- const events = record;
685
- if (!events.length) return record;
695
+ if (!record.length) return record;
696
+ const profile = meta.profile;
697
+
698
+ // ── SUPER-PROP STAMPING ──────────────────────────
699
+ // Stamp superProps from profile so they are consistent per-user.
700
+ if (profile) {
701
+ const tier = profile.subscription_tier;
702
+ const plat = profile.Platform;
703
+ record.forEach(e => {
704
+ if (tier) e.subscription_tier = tier;
705
+ if (plat) e.Platform = plat;
706
+ });
707
+ }
708
+
709
+ // ── HOOK 8: FREE-TIER CONVERSION DROP ────────────
710
+ // Free-tier users lose ~30% of "consultation completed" events
711
+ // (last step of Booking to Consultation funnel), simulating
712
+ // lower conversion for non-paying patients.
713
+ if (profile && profile.subscription_tier === "free") {
714
+ record = record.filter(e => {
715
+ if (e.event === "consultation completed" && chance.bool({ likelihood: 30 })) {
716
+ return false;
717
+ }
718
+ return true;
719
+ });
720
+ }
686
721
 
687
722
  // ── HOOK 3: EXPERIENCED DOCTOR SATISFACTION ──────
688
723
  // Users with >50 consultation events get boosted satisfaction scores.
689
724
  let consultCount = 0;
690
- events.forEach(e => {
725
+ record.forEach(e => {
691
726
  if (e.event === "consultation completed") consultCount++;
692
727
  });
693
728
 
694
729
  if (consultCount > 50) {
695
- events.forEach(e => {
730
+ record.forEach(e => {
696
731
  if (e.event === "consultation completed") {
697
732
  e.satisfaction_score = chance.floating({ min: 4.0, max: 5.0, fixed: 1 });
698
733
  }
@@ -701,18 +736,18 @@ const config = {
701
736
 
702
737
  // ── HOOK 4: VIDEO CONSULTATION FOLLOW-UP LIFT ────
703
738
  // Patients with video consultations get 2x follow-up events.
704
- const hasVideoConsult = events.some(e =>
739
+ const hasVideoConsult = record.some(e =>
705
740
  e.event === "consultation completed" && e.consultation_mode === "video"
706
741
  );
707
742
  if (hasVideoConsult) {
708
- const templateFollowUp = events.find(e => e.event === "follow up scheduled");
743
+ const templateFollowUp = record.find(e => e.event === "follow up scheduled");
709
744
  if (templateFollowUp) {
710
- const videoConsults = events.filter(e =>
745
+ const videoConsults = record.filter(e =>
711
746
  e.event === "consultation completed" && e.consultation_mode === "video"
712
747
  );
713
748
  videoConsults.forEach(vc => {
714
749
  if (chance.bool({ likelihood: 60 })) {
715
- events.push({
750
+ record.push({
716
751
  ...templateFollowUp,
717
752
  time: dayjs(vc.time).add(chance.integer({ min: 1, max: 7 }), "days").toISOString(),
718
753
  user_id: vc.user_id,
@@ -726,17 +761,17 @@ const config = {
726
761
 
727
762
  // ── HOOK 5: CHRONIC CONDITION REFILL CHAIN ───────
728
763
  // Patients with chronic prescriptions get refills every ~30 days.
729
- const chronicRxs = events.filter(e =>
764
+ const chronicRxs = record.filter(e =>
730
765
  e.event === "prescription issued" && e.condition_type === "chronic"
731
766
  );
732
767
  if (chronicRxs.length > 0) {
733
- const templateRefill = events.find(e => e.event === "prescription refill");
768
+ const templateRefill = record.find(e => e.event === "prescription refill");
734
769
  if (templateRefill) {
735
770
  chronicRxs.forEach(rx => {
736
771
  const rxTime = dayjs(rx.time);
737
772
  const refillsToAdd = chance.integer({ min: 2, max: 4 });
738
773
  for (let i = 1; i <= refillsToAdd; i++) {
739
- events.push({
774
+ record.push({
740
775
  ...templateRefill,
741
776
  time: rxTime.add(30 * i + chance.integer({ min: -3, max: 3 }), "days").toISOString(),
742
777
  user_id: rx.user_id,
@@ -751,10 +786,10 @@ const config = {
751
786
 
752
787
  // ── HOOK 6: OCCASIONAL PATIENT NO-SHOWS ──────────
753
788
  // Low-activity patients (< 15 events) lose 25% of appointments.
754
- if (events.length < 15) {
755
- for (let i = events.length - 1; i >= 0; i--) {
756
- if (events[i].event === "appointment booked" && chance.bool({ likelihood: 25 })) {
757
- events.splice(i, 1);
789
+ if (record.length < 15) {
790
+ for (let i = record.length - 1; i >= 0; i--) {
791
+ if (record[i].event === "appointment booked" && chance.bool({ likelihood: 25 })) {
792
+ record.splice(i, 1);
758
793
  }
759
794
  }
760
795
  }
@@ -364,52 +364,6 @@
364
364
  }
365
365
  }
366
366
  ],
367
- "superProps": {
368
- "platform": [
369
- "web",
370
- "ios",
371
- "android"
372
- ],
373
- "insurance_type": [
374
- "auto",
375
- "home",
376
- "life",
377
- "health",
378
- "renters"
379
- ],
380
- "app_version": [
381
- "2.10"
382
- ]
383
- },
384
- "userProps": {
385
- "age_range": [
386
- "18-25",
387
- "26-35",
388
- "36-45",
389
- "46-55",
390
- "56-65",
391
- "65+"
392
- ],
393
- "risk_profile": [
394
- "low",
395
- "medium",
396
- "high"
397
- ],
398
- "policy_count": [
399
- 3
400
- ],
401
- "lifetime_premium": {
402
- "$range": [
403
- 8131,
404
- 43291
405
- ]
406
- },
407
- "preferred_contact": [
408
- "email",
409
- "phone",
410
- "app_notification"
411
- ]
412
- },
413
367
  "funnels": [
414
368
  {
415
369
  "sequence": [
@@ -417,6 +371,7 @@
417
371
  "page viewed",
418
372
  "quote requested"
419
373
  ],
374
+ "name": "Onboarding",
420
375
  "isFirstFunnel": true,
421
376
  "conversionRate": 85,
422
377
  "timeToConvert": 0.5
@@ -428,6 +383,7 @@
428
383
  "document uploaded",
429
384
  "application submitted"
430
385
  ],
386
+ "name": "Application Completion",
431
387
  "conversionRate": 60,
432
388
  "timeToConvert": 48,
433
389
  "weight": 4
@@ -438,6 +394,7 @@
438
394
  "application approved",
439
395
  "policy activated"
440
396
  ],
397
+ "name": "Application Approval",
441
398
  "conversionRate": 70,
442
399
  "timeToConvert": 72,
443
400
  "weight": 3
@@ -448,6 +405,7 @@
448
405
  "claim status checked",
449
406
  "support ticket created"
450
407
  ],
408
+ "name": "Claims Process",
451
409
  "conversionRate": 50,
452
410
  "timeToConvert": 24,
453
411
  "weight": 2
@@ -458,9 +416,70 @@
458
416
  "payment made",
459
417
  "renewal completed"
460
418
  ],
419
+ "name": "Policy Renewal",
461
420
  "conversionRate": 65,
462
421
  "timeToConvert": 72,
463
422
  "weight": 3
464
423
  }
465
- ]
424
+ ],
425
+ "superProps": {
426
+ "Platform": [
427
+ "web",
428
+ "ios",
429
+ "android"
430
+ ],
431
+ "insurance_type": [
432
+ "auto",
433
+ "home",
434
+ "life",
435
+ "health",
436
+ "renters"
437
+ ],
438
+ "app_version": [
439
+ "2.10"
440
+ ]
441
+ },
442
+ "userProps": {
443
+ "age_range": [
444
+ "18-25",
445
+ "26-35",
446
+ "36-45",
447
+ "46-55",
448
+ "56-65",
449
+ "65+"
450
+ ],
451
+ "risk_profile": [
452
+ "low",
453
+ "medium",
454
+ "high"
455
+ ],
456
+ "policy_count": [
457
+ 3
458
+ ],
459
+ "lifetime_premium": {
460
+ "$range": [
461
+ 8131,
462
+ 43291
463
+ ]
464
+ },
465
+ "preferred_contact": [
466
+ "email",
467
+ "phone",
468
+ "app_notification"
469
+ ]
470
+ },
471
+ "scdProps": {
472
+ "policy_status": {
473
+ "type": "user",
474
+ "frequency": "month",
475
+ "timing": "fuzzy",
476
+ "max": 8,
477
+ "values": [
478
+ "pending",
479
+ "active",
480
+ "lapsed",
481
+ "renewed"
482
+ ]
483
+ }
484
+ }
466
485
  }
@@ -1,13 +1,20 @@
1
+ // ── TWEAK THESE ──
2
+ const SEED = "dm4-insurance";
3
+ const num_days = 100;
4
+ const num_users = 5_000;
5
+ const avg_events_per_user = 120;
6
+ let token = "your-mixpanel-token";
7
+
8
+ // ── env overrides ──
9
+ if (process.env.MP_TOKEN) token = process.env.MP_TOKEN;
10
+
1
11
  import dayjs from "dayjs";
2
12
  import utc from "dayjs/plugin/utc.js";
3
13
  import "dotenv/config";
4
14
  import * as u from "../../lib/utils/utils.js";
5
15
 
6
- const SEED = "dm4-insurance";
7
16
  dayjs.extend(utc);
8
17
  const chance = u.initChance(SEED);
9
- const num_users = 5_000;
10
- const days = 100;
11
18
 
12
19
  /** @typedef {import("../../types").Dungeon} Config */
13
20
 
@@ -126,17 +133,17 @@ const days = 100;
126
133
 
127
134
  // ── Time constants for hook calculations ──
128
135
  const NOW = dayjs();
129
- const DATASET_START = NOW.subtract(days, "days");
136
+ const DATASET_START = NOW.subtract(num_days, "days");
130
137
  const V211_DATE = DATASET_START.add(30, "days");
131
138
  const V212_DATE = DATASET_START.add(60, "days");
132
139
  const V213_DATE = NOW.subtract(10, "days");
133
140
 
134
141
  /** @type {Config} */
135
142
  const config = {
136
- token: "",
143
+ token,
137
144
  seed: SEED,
138
- numDays: days,
139
- numEvents: num_users * 120,
145
+ numDays: num_days,
146
+ numEvents: num_users * avg_events_per_user,
140
147
  numUsers: num_users,
141
148
  hasAnonIds: false,
142
149
  hasSessionIds: true,
@@ -153,11 +160,17 @@ const config = {
153
160
  hasAdSpend: false,
154
161
  percentUsersBornInDataset: 35,
155
162
  hasAvatar: true,
156
- batchSize: 2_500_000,
157
163
  concurrency: 1,
158
164
  writeToDisk: false,
159
165
 
160
- scdProps: {},
166
+ scdProps: {
167
+ policy_status: {
168
+ values: ["pending", "active", "lapsed", "renewed"],
169
+ frequency: "month",
170
+ timing: "fuzzy",
171
+ max: 8
172
+ }
173
+ },
161
174
  mirrorProps: {},
162
175
  lookupTables: [],
163
176
 
@@ -425,13 +438,16 @@ const config = {
425
438
 
426
439
  // ── Super Props (on every event) ──
427
440
  superProps: {
428
- platform: ["web", "ios", "android"],
441
+ Platform: ["web", "ios", "android"],
429
442
  insurance_type: ["auto", "home", "life", "health", "renters"],
430
443
  app_version: ["2.10"],
431
444
  },
432
445
 
433
446
  // ── User Props (set once per user) ──
434
447
  userProps: {
448
+ Platform: ["web", "ios", "android"],
449
+ insurance_type: ["auto", "home", "life", "health", "renters"],
450
+ app_version: ["2.10"],
435
451
  age_range: ["18-25", "26-35", "36-45", "46-55", "56-65", "65+"],
436
452
  risk_profile: ["low", "medium", "high"],
437
453
  policy_count: u.weighNumRange(0, 5, 0.5, 1),
@@ -471,6 +487,14 @@ const config = {
471
487
  const userEvents = record;
472
488
  if (userEvents.length === 0) return record;
473
489
 
490
+ // Stamp superProps from profile for consistency
491
+ const profile = meta.profile;
492
+ userEvents.forEach(e => {
493
+ e.Platform = profile.Platform;
494
+ e.insurance_type = profile.insurance_type;
495
+ e.app_version = profile.app_version;
496
+ });
497
+
474
498
  // ─── Hook #1: VERSION STAMPING ───
475
499
  // Deterministic app_version on every event based on its final timestamp.
476
500
  // v2.10 (days 0-30) → v2.11 (30-60) → v2.12 (60-90) → v2.13 (last 10 days)
@@ -446,6 +446,9 @@
446
446
  },
447
447
  {
448
448
  "event": "account deactivated",
449
+ "isChurnEvent": true,
450
+ "returnLikelihood": 0.1,
451
+ "isStrictEvent": true,
449
452
  "properties": {
450
453
  "reason": [
451
454
  "too_expensive",
@@ -457,43 +460,6 @@
457
460
  }
458
461
  }
459
462
  ],
460
- "superProps": {
461
- "platform": [
462
- "web",
463
- "desktop_app"
464
- ],
465
- "subscription_plan": [
466
- "free_trial",
467
- "starter",
468
- "professional",
469
- "enterprise"
470
- ]
471
- },
472
- "userProps": {
473
- "company_tier": [
474
- "small_business"
475
- ],
476
- "warehouse_count": [
477
- 8,
478
- 3
479
- ],
480
- "employee_count": {
481
- "$range": [
482
- 94,
483
- 385
484
- ]
485
- },
486
- "industry": [
487
- "retail",
488
- "manufacturing",
489
- "food_beverage",
490
- "pharma",
491
- "electronics"
492
- ],
493
- "integration_count": [
494
- 0
495
- ]
496
- },
497
463
  "funnels": [
498
464
  {
499
465
  "sequence": [
@@ -502,6 +468,7 @@
502
468
  "integration connected",
503
469
  "report generated"
504
470
  ],
471
+ "name": "Onboarding",
505
472
  "isFirstFunnel": true,
506
473
  "conversionRate": 40,
507
474
  "timeToConvert": 72,
@@ -514,6 +481,7 @@
514
481
  "order received",
515
482
  "shipment tracked"
516
483
  ],
484
+ "name": "Order Fulfillment",
517
485
  "conversionRate": 35,
518
486
  "timeToConvert": 168,
519
487
  "weight": 5
@@ -524,6 +492,7 @@
524
492
  "purchase order created",
525
493
  "invoice processed"
526
494
  ],
495
+ "name": "Supplier Management",
527
496
  "conversionRate": 45,
528
497
  "timeToConvert": 336,
529
498
  "weight": 3
@@ -534,6 +503,7 @@
534
503
  "report generated",
535
504
  "alert configured"
536
505
  ],
506
+ "name": "Integration Setup",
537
507
  "conversionRate": 30,
538
508
  "timeToConvert": 48,
539
509
  "weight": 2
@@ -544,9 +514,61 @@
544
514
  "purchase order created",
545
515
  "order received"
546
516
  ],
517
+ "name": "Alert Response",
547
518
  "conversionRate": 50,
548
519
  "timeToConvert": 120,
549
520
  "weight": 3
550
521
  }
551
- ]
522
+ ],
523
+ "superProps": {
524
+ "Platform": [
525
+ "web",
526
+ "desktop_app"
527
+ ],
528
+ "subscription_plan": [
529
+ "free_trial",
530
+ "starter",
531
+ "professional",
532
+ "enterprise"
533
+ ]
534
+ },
535
+ "userProps": {
536
+ "company_tier": [
537
+ "small_business"
538
+ ],
539
+ "warehouse_count": [
540
+ 8,
541
+ 3
542
+ ],
543
+ "employee_count": {
544
+ "$range": [
545
+ 94,
546
+ 385
547
+ ]
548
+ },
549
+ "industry": [
550
+ "retail",
551
+ "manufacturing",
552
+ "food_beverage",
553
+ "pharma",
554
+ "electronics"
555
+ ],
556
+ "integration_count": [
557
+ 0
558
+ ]
559
+ },
560
+ "scdProps": {
561
+ "company_tier": {
562
+ "type": "user",
563
+ "frequency": "month",
564
+ "timing": "fuzzy",
565
+ "max": 6,
566
+ "values": [
567
+ "trial",
568
+ "starter",
569
+ "professional",
570
+ "enterprise"
571
+ ]
572
+ }
573
+ }
552
574
  }