flowgrid-sdk 1.4.1 → 1.4.2
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.
- package/README.md +17 -29
- package/dist/flowgrid.min.js +1 -1
- package/dist/flowgrid.min.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/lib/flowgrid.d.ts +719 -6
- package/dist/lib/flowgrid.js +655 -12
- package/dist/lib/flowgrid.js.map +1 -1
- package/dist/umd/index.js +1 -1
- package/dist/umd/index.js.map +1 -1
- package/package.json +1 -1
package/dist/lib/flowgrid.js
CHANGED
|
@@ -36,6 +36,75 @@ import { PageViews, Sessions, Events, Identify, Funnels, Retention, Attribution,
|
|
|
36
36
|
import { Products, CartTracking, Checkout, Purchases, Refunds, Promotions, WishlistTracking, CustomerLTV, SearchAnalytics, Subscriptions, } from "./features/ecommerce";
|
|
37
37
|
import { Engagement, Cohorts, ChurnAnalytics, Monetization, MultiPathFunnels, SupportAnalytics, AcquisitionAnalytics, PathAnalytics, AlertsAnalytics, SecurityAnalytics, Forecasting, } from "./features/enterprise";
|
|
38
38
|
import { ActivationTracker, ExperimentTracker, FeatureTracker, PromptTracker, EventTracker, PageViewTracker, SessionTracker, IdentifyTracker, FunnelTracker, RetentionTracker, AttributionTracker, HeatmapTracker, PerformanceTracker, ReplayTracker, ProductTracker, CartTracker, CheckoutTracker, PurchaseTracker, RefundTracker, PromotionTracker, WishlistTracker, SubscriptionTracker, LTVTracker, SearchTracker, EngagementTracker, CohortTracker, ChurnTracker, MonetizationTracker, MultiPathFunnelTracker, SupportTracker, AcquisitionTracker, PathTracker, AlertTracker, SecurityTracker, ForecastingTracker, } from "./tracking";
|
|
39
|
+
const UNHANDLED_TRACK = { handled: false };
|
|
40
|
+
const PRODUCT_KEYS = [
|
|
41
|
+
"productId",
|
|
42
|
+
"name",
|
|
43
|
+
"brand",
|
|
44
|
+
"category",
|
|
45
|
+
"variant",
|
|
46
|
+
"price",
|
|
47
|
+
"currency",
|
|
48
|
+
"quantity",
|
|
49
|
+
"discount",
|
|
50
|
+
"coupon",
|
|
51
|
+
"position",
|
|
52
|
+
"url",
|
|
53
|
+
"imageUrl",
|
|
54
|
+
"rating",
|
|
55
|
+
"reviewCount",
|
|
56
|
+
"stockStatus",
|
|
57
|
+
"attributes",
|
|
58
|
+
];
|
|
59
|
+
function handled(value) {
|
|
60
|
+
return { handled: true, value };
|
|
61
|
+
}
|
|
62
|
+
function isRecord(value) {
|
|
63
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
64
|
+
}
|
|
65
|
+
function stringValue(props, key) {
|
|
66
|
+
const value = props[key];
|
|
67
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
68
|
+
}
|
|
69
|
+
function numberValue(props, key) {
|
|
70
|
+
const value = props[key];
|
|
71
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
72
|
+
}
|
|
73
|
+
function booleanValue(props, key) {
|
|
74
|
+
const value = props[key];
|
|
75
|
+
return typeof value === "boolean" ? value : undefined;
|
|
76
|
+
}
|
|
77
|
+
function recordValue(props, key) {
|
|
78
|
+
const value = props[key];
|
|
79
|
+
return isRecord(value) ? value : undefined;
|
|
80
|
+
}
|
|
81
|
+
function hasValue(props, key) {
|
|
82
|
+
const value = props[key];
|
|
83
|
+
return value !== undefined && value !== null && !(typeof value === "string" && value.length === 0);
|
|
84
|
+
}
|
|
85
|
+
function omitProperties(props, keys) {
|
|
86
|
+
const next = {};
|
|
87
|
+
const blocked = new Set([...keys, "domain"]);
|
|
88
|
+
for (const [key, value] of Object.entries(props)) {
|
|
89
|
+
if (!blocked.has(key))
|
|
90
|
+
next[key] = value;
|
|
91
|
+
}
|
|
92
|
+
return next;
|
|
93
|
+
}
|
|
94
|
+
function productFrom(props) {
|
|
95
|
+
const nested = recordValue(props, "product");
|
|
96
|
+
if (nested)
|
|
97
|
+
return { ...nested, currency: nested.currency ?? "USD" };
|
|
98
|
+
if (!hasValue(props, "productId") || !hasValue(props, "name") || !hasValue(props, "price")) {
|
|
99
|
+
return undefined;
|
|
100
|
+
}
|
|
101
|
+
const product = { currency: "USD" };
|
|
102
|
+
for (const key of PRODUCT_KEYS) {
|
|
103
|
+
if (props[key] !== undefined)
|
|
104
|
+
product[key] = props[key];
|
|
105
|
+
}
|
|
106
|
+
return product;
|
|
107
|
+
}
|
|
39
108
|
const DEFAULT_ENDPOINT = "https://core.flow-grid.xyz";
|
|
40
109
|
/**
|
|
41
110
|
* Unified FlowGrid SDK client. Instantiate once, use everywhere.
|
|
@@ -185,20 +254,594 @@ export class FlowGrid {
|
|
|
185
254
|
get alerts() { return this.wrap("alerts", AlertsAnalytics, AlertTracker); }
|
|
186
255
|
get security() { return this.wrap("security", SecurityAnalytics, SecurityTracker); }
|
|
187
256
|
get forecasting() { return this.wrap("forecasting", Forecasting, ForecastingTracker); }
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
*
|
|
194
|
-
* @example
|
|
195
|
-
* ```ts
|
|
196
|
-
* fg.track("signup_completed", { plan: "pro" });
|
|
197
|
-
* ```
|
|
198
|
-
*/
|
|
199
|
-
track(eventName, properties, options) {
|
|
257
|
+
track(eventName, properties = {}, options = {}) {
|
|
258
|
+
const contextualProperties = this.withTrackContext(properties, options);
|
|
259
|
+
const routed = this.dispatchTrack(eventName, contextualProperties, Boolean(options.domain), options.domain);
|
|
260
|
+
if (routed.handled)
|
|
261
|
+
return routed.value;
|
|
200
262
|
return this.events.track(eventName, properties, options);
|
|
201
263
|
}
|
|
264
|
+
withTrackContext(properties, options) {
|
|
265
|
+
return {
|
|
266
|
+
...properties,
|
|
267
|
+
...(options.userId !== undefined && properties.userId === undefined ? { userId: options.userId } : {}),
|
|
268
|
+
...(options.sessionId !== undefined && properties.sessionId === undefined ? { sessionId: options.sessionId } : {}),
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
requireTrackProperties(eventName, properties, keys, strict) {
|
|
272
|
+
const missing = keys.filter(key => !hasValue(properties, key));
|
|
273
|
+
if (missing.length === 0)
|
|
274
|
+
return true;
|
|
275
|
+
if (strict) {
|
|
276
|
+
throw new Error(`FlowGrid.track("${eventName}") missing required properties: ${missing.join(", ")}`);
|
|
277
|
+
}
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
dispatchTrack(eventName, properties, strict, domain) {
|
|
281
|
+
const dispatchers = [];
|
|
282
|
+
if (!domain || domain === "activation")
|
|
283
|
+
dispatchers.push(() => this.dispatchActivationTrack(eventName, properties, strict));
|
|
284
|
+
if (!domain || domain === "feature")
|
|
285
|
+
dispatchers.push(() => this.dispatchFeatureTrack(eventName, properties, strict));
|
|
286
|
+
if (!domain || domain === "prompt")
|
|
287
|
+
dispatchers.push(() => this.dispatchPromptTrack(eventName, properties, strict));
|
|
288
|
+
if (!domain || domain === "experiment")
|
|
289
|
+
dispatchers.push(() => this.dispatchExperimentTrack(eventName, properties, strict));
|
|
290
|
+
if (!domain || domain === "analytics" || domain === "funnel" || domain === "retention" || domain === "attribution") {
|
|
291
|
+
dispatchers.push(() => this.dispatchAnalyticsTrack(eventName, properties, strict, domain));
|
|
292
|
+
}
|
|
293
|
+
if (!domain || domain === "ecommerce")
|
|
294
|
+
dispatchers.push(() => this.dispatchEcommerceTrack(eventName, properties, strict));
|
|
295
|
+
if (!domain ||
|
|
296
|
+
domain === "engagement" ||
|
|
297
|
+
domain === "churn" ||
|
|
298
|
+
domain === "monetization" ||
|
|
299
|
+
domain === "support" ||
|
|
300
|
+
domain === "acquisition" ||
|
|
301
|
+
domain === "paths" ||
|
|
302
|
+
domain === "security" ||
|
|
303
|
+
domain === "multiPathFunnels") {
|
|
304
|
+
dispatchers.push(() => this.dispatchEnterpriseTrack(eventName, properties, strict, domain));
|
|
305
|
+
}
|
|
306
|
+
for (const dispatch of dispatchers) {
|
|
307
|
+
const result = dispatch();
|
|
308
|
+
if (result.handled)
|
|
309
|
+
return result;
|
|
310
|
+
}
|
|
311
|
+
return UNHANDLED_TRACK;
|
|
312
|
+
}
|
|
313
|
+
dispatchActivationTrack(eventName, properties, strict) {
|
|
314
|
+
switch (eventName) {
|
|
315
|
+
case "signup_completed": {
|
|
316
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "method"], strict))
|
|
317
|
+
return UNHANDLED_TRACK;
|
|
318
|
+
return handled(this.activation.signup(stringValue(properties, "userId"), stringValue(properties, "method"), stringValue(properties, "source"), omitProperties(properties, ["userId", "method", "source"])));
|
|
319
|
+
}
|
|
320
|
+
case "onboarding_step": {
|
|
321
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "stepId", "stepName", "stepOrder", "totalSteps"], strict))
|
|
322
|
+
return UNHANDLED_TRACK;
|
|
323
|
+
return handled(this.activation.onboardingStep(stringValue(properties, "userId"), stringValue(properties, "stepId"), stringValue(properties, "stepName"), numberValue(properties, "stepOrder"), numberValue(properties, "totalSteps"), {
|
|
324
|
+
skipped: booleanValue(properties, "skipped"),
|
|
325
|
+
timeSpent: numberValue(properties, "timeSpent"),
|
|
326
|
+
properties: omitProperties(properties, ["userId", "stepId", "stepName", "stepOrder", "totalSteps", "skipped", "timeSpent"]),
|
|
327
|
+
}));
|
|
328
|
+
}
|
|
329
|
+
case "onboarding_completed": {
|
|
330
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "totalTimeSpent", "stepsCompleted"], strict))
|
|
331
|
+
return UNHANDLED_TRACK;
|
|
332
|
+
return handled(this.activation.onboardingComplete(stringValue(properties, "userId"), numberValue(properties, "totalTimeSpent"), numberValue(properties, "stepsCompleted"), numberValue(properties, "stepsSkipped") ?? 0));
|
|
333
|
+
}
|
|
334
|
+
case "first_action": {
|
|
335
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "actionName", "timeSinceSignup"], strict))
|
|
336
|
+
return UNHANDLED_TRACK;
|
|
337
|
+
return handled(this.activation.firstAction(stringValue(properties, "userId"), stringValue(properties, "actionName"), numberValue(properties, "timeSinceSignup"), omitProperties(properties, ["userId", "actionName", "timeSinceSignup"])));
|
|
338
|
+
}
|
|
339
|
+
default:
|
|
340
|
+
if (strict)
|
|
341
|
+
return handled(this.activation.event(eventName, properties));
|
|
342
|
+
return UNHANDLED_TRACK;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
dispatchFeatureTrack(eventName, properties, strict) {
|
|
346
|
+
const actions = {
|
|
347
|
+
feature_viewed: "viewed",
|
|
348
|
+
feature_used: "used",
|
|
349
|
+
feature_completed: "completed",
|
|
350
|
+
feature_abandoned: "abandoned",
|
|
351
|
+
};
|
|
352
|
+
const action = actions[eventName] ?? (eventName === "feature_usage"
|
|
353
|
+
? properties.action : undefined);
|
|
354
|
+
if (eventName === "feature_usage" || action) {
|
|
355
|
+
if (!this.requireTrackProperties(eventName, properties, ["featureId", "featureName"], strict))
|
|
356
|
+
return UNHANDLED_TRACK;
|
|
357
|
+
return handled(this.features.client.trackUsage({
|
|
358
|
+
...properties,
|
|
359
|
+
action: typeof action === "string" ? action : "used",
|
|
360
|
+
}));
|
|
361
|
+
}
|
|
362
|
+
if (strict) {
|
|
363
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "featureName"], true))
|
|
364
|
+
return UNHANDLED_TRACK;
|
|
365
|
+
return handled(this.features.create(stringValue(properties, "userId"), eventName, stringValue(properties, "featureName"), omitProperties(properties, ["userId", "featureName"])));
|
|
366
|
+
}
|
|
367
|
+
return UNHANDLED_TRACK;
|
|
368
|
+
}
|
|
369
|
+
dispatchPromptTrack(eventName, properties, strict) {
|
|
370
|
+
switch (eventName) {
|
|
371
|
+
case "prompt_submitted":
|
|
372
|
+
if (!this.requireTrackProperties(eventName, properties, ["promptId", "promptType"], strict))
|
|
373
|
+
return UNHANDLED_TRACK;
|
|
374
|
+
return handled(this.prompts.client.trackSubmission(properties));
|
|
375
|
+
case "prompt_response":
|
|
376
|
+
if (!this.requireTrackProperties(eventName, properties, ["promptId", "responseTime", "completed"], strict))
|
|
377
|
+
return UNHANDLED_TRACK;
|
|
378
|
+
return handled(this.prompts.client.trackResponse(properties));
|
|
379
|
+
case "prompt_feedback":
|
|
380
|
+
if (!this.requireTrackProperties(eventName, properties, ["promptId", "feedbackType"], strict))
|
|
381
|
+
return UNHANDLED_TRACK;
|
|
382
|
+
return handled(this.prompts.client.trackFeedback(properties));
|
|
383
|
+
case "prompt_conversation":
|
|
384
|
+
if (!this.requireTrackProperties(eventName, properties, ["conversationId", "userId", "turnCount", "totalDuration"], strict))
|
|
385
|
+
return UNHANDLED_TRACK;
|
|
386
|
+
return handled(this.prompts.conversation(stringValue(properties, "conversationId"), stringValue(properties, "userId"), numberValue(properties, "turnCount"), numberValue(properties, "totalDuration")));
|
|
387
|
+
default:
|
|
388
|
+
if (strict || eventName.startsWith("prompt_"))
|
|
389
|
+
return handled(this.prompts.event(eventName, properties));
|
|
390
|
+
return UNHANDLED_TRACK;
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
dispatchExperimentTrack(eventName, properties, strict) {
|
|
394
|
+
switch (eventName) {
|
|
395
|
+
case "experiment_assignment":
|
|
396
|
+
if (!this.requireTrackProperties(eventName, properties, ["experimentId", "userId", "variantId"], strict))
|
|
397
|
+
return UNHANDLED_TRACK;
|
|
398
|
+
return handled(this.experiments.client.assign(properties));
|
|
399
|
+
case "experiment_exposure":
|
|
400
|
+
if (!this.requireTrackProperties(eventName, properties, ["experimentId", "userId", "variantId"], strict))
|
|
401
|
+
return UNHANDLED_TRACK;
|
|
402
|
+
return handled(this.experiments.exposure(stringValue(properties, "experimentId"), stringValue(properties, "userId"), stringValue(properties, "variantId")));
|
|
403
|
+
case "experiment_conversion":
|
|
404
|
+
if (!this.requireTrackProperties(eventName, properties, ["experimentId", "userId", "variantId", "metricName"], strict))
|
|
405
|
+
return UNHANDLED_TRACK;
|
|
406
|
+
return handled(this.experiments.client.trackConversion({
|
|
407
|
+
...properties,
|
|
408
|
+
value: numberValue(properties, "value") ?? 1,
|
|
409
|
+
}));
|
|
410
|
+
default:
|
|
411
|
+
if (strict || eventName.startsWith("experiment_")) {
|
|
412
|
+
if (!this.requireTrackProperties(eventName, properties, ["variant"], strict))
|
|
413
|
+
return UNHANDLED_TRACK;
|
|
414
|
+
return handled(this.experiments.client.track({
|
|
415
|
+
eventName,
|
|
416
|
+
variant: stringValue(properties, "variant"),
|
|
417
|
+
properties: omitProperties(properties, ["variant"]),
|
|
418
|
+
}));
|
|
419
|
+
}
|
|
420
|
+
return UNHANDLED_TRACK;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
dispatchAnalyticsTrack(eventName, properties, strict, domain) {
|
|
424
|
+
switch (eventName) {
|
|
425
|
+
case "click_event":
|
|
426
|
+
if (!this.requireTrackProperties(eventName, properties, ["elementId", "elementText"], strict))
|
|
427
|
+
return UNHANDLED_TRACK;
|
|
428
|
+
return handled(this.events.client.trackClick(properties));
|
|
429
|
+
case "form_event":
|
|
430
|
+
if (!this.requireTrackProperties(eventName, properties, ["formId", "formName"], strict))
|
|
431
|
+
return UNHANDLED_TRACK;
|
|
432
|
+
return handled(this.events.client.trackForm(properties));
|
|
433
|
+
case "search_event":
|
|
434
|
+
if (!this.requireTrackProperties(eventName, properties, ["query", "category"], strict))
|
|
435
|
+
return UNHANDLED_TRACK;
|
|
436
|
+
return handled(this.events.client.trackSearch(properties));
|
|
437
|
+
case "error_event":
|
|
438
|
+
if (!this.requireTrackProperties(eventName, properties, ["message", "type"], strict))
|
|
439
|
+
return UNHANDLED_TRACK;
|
|
440
|
+
return handled(this.events.client.trackError(properties));
|
|
441
|
+
case "funnel_step":
|
|
442
|
+
if (!this.requireTrackProperties(eventName, properties, ["funnelId", "step", "stepNumber"], strict))
|
|
443
|
+
return UNHANDLED_TRACK;
|
|
444
|
+
return handled(this.funnels.client.trackStep(properties));
|
|
445
|
+
case "funnel_complete":
|
|
446
|
+
if (!this.requireTrackProperties(eventName, properties, ["funnelId"], strict))
|
|
447
|
+
return UNHANDLED_TRACK;
|
|
448
|
+
return handled(this.funnels.complete(stringValue(properties, "funnelId"), stringValue(properties, "userId"), omitProperties(properties, ["funnelId", "userId"])));
|
|
449
|
+
case "funnel_abandon":
|
|
450
|
+
if (!this.requireTrackProperties(eventName, properties, ["funnelId", "lastStep"], strict))
|
|
451
|
+
return UNHANDLED_TRACK;
|
|
452
|
+
return handled(this.funnels.abandon(stringValue(properties, "funnelId"), stringValue(properties, "lastStep"), stringValue(properties, "userId"), stringValue(properties, "reason")));
|
|
453
|
+
case "user_activity":
|
|
454
|
+
if (domain && domain !== "retention")
|
|
455
|
+
return UNHANDLED_TRACK;
|
|
456
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId"], strict))
|
|
457
|
+
return UNHANDLED_TRACK;
|
|
458
|
+
return handled(this.retention.client.trackActivity(properties));
|
|
459
|
+
case "attribution_touchpoint":
|
|
460
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "channel"], strict))
|
|
461
|
+
return UNHANDLED_TRACK;
|
|
462
|
+
return handled(this.attribution.client.trackTouchpoint(properties));
|
|
463
|
+
case "attribution_conversion":
|
|
464
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "conversionType"], strict))
|
|
465
|
+
return UNHANDLED_TRACK;
|
|
466
|
+
return handled(this.attribution.client.recordConversion(properties));
|
|
467
|
+
default:
|
|
468
|
+
return UNHANDLED_TRACK;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
dispatchEcommerceTrack(eventName, properties, strict) {
|
|
472
|
+
switch (eventName) {
|
|
473
|
+
case "product_view": {
|
|
474
|
+
const product = productFrom(properties);
|
|
475
|
+
if (!product) {
|
|
476
|
+
if (strict)
|
|
477
|
+
throw new Error(`FlowGrid.track("${eventName}") missing required properties: product or productId, name, price`);
|
|
478
|
+
return UNHANDLED_TRACK;
|
|
479
|
+
}
|
|
480
|
+
return handled(this.products.client.view({
|
|
481
|
+
...product,
|
|
482
|
+
...omitProperties(properties, ["product", ...PRODUCT_KEYS]),
|
|
483
|
+
}));
|
|
484
|
+
}
|
|
485
|
+
case "product_impression":
|
|
486
|
+
if (!this.requireTrackProperties(eventName, properties, ["list"], strict))
|
|
487
|
+
return UNHANDLED_TRACK;
|
|
488
|
+
return handled(this.products.client.impression(properties));
|
|
489
|
+
case "product_click": {
|
|
490
|
+
const product = productFrom(properties);
|
|
491
|
+
if (!product || !this.requireTrackProperties(eventName, properties, ["listId", "position"], strict))
|
|
492
|
+
return UNHANDLED_TRACK;
|
|
493
|
+
return handled(this.products.client.click({
|
|
494
|
+
...properties,
|
|
495
|
+
product,
|
|
496
|
+
}));
|
|
497
|
+
}
|
|
498
|
+
case "add_to_cart":
|
|
499
|
+
case "remove_from_cart": {
|
|
500
|
+
const product = productFrom(properties);
|
|
501
|
+
if (!product) {
|
|
502
|
+
if (strict)
|
|
503
|
+
throw new Error(`FlowGrid.track("${eventName}") missing required properties: product or productId, name, price`);
|
|
504
|
+
return UNHANDLED_TRACK;
|
|
505
|
+
}
|
|
506
|
+
const config = {
|
|
507
|
+
...omitProperties(properties, ["product", ...PRODUCT_KEYS]),
|
|
508
|
+
product,
|
|
509
|
+
quantity: numberValue(properties, "quantity") ?? 1,
|
|
510
|
+
};
|
|
511
|
+
return handled(eventName === "add_to_cart"
|
|
512
|
+
? this.cart.client.addItem(config)
|
|
513
|
+
: this.cart.client.removeItem(config));
|
|
514
|
+
}
|
|
515
|
+
case "update_cart_item": {
|
|
516
|
+
const product = productFrom(properties);
|
|
517
|
+
if (!product || !this.requireTrackProperties(eventName, properties, ["previousQuantity", "newQuantity"], strict))
|
|
518
|
+
return UNHANDLED_TRACK;
|
|
519
|
+
return handled(this.cart.client.updateItem({
|
|
520
|
+
...omitProperties(properties, ["product", ...PRODUCT_KEYS]),
|
|
521
|
+
product,
|
|
522
|
+
}));
|
|
523
|
+
}
|
|
524
|
+
case "view_cart":
|
|
525
|
+
if (!this.requireTrackProperties(eventName, properties, ["cart"], strict))
|
|
526
|
+
return UNHANDLED_TRACK;
|
|
527
|
+
return handled(this.cart.client.view(properties));
|
|
528
|
+
case "begin_checkout":
|
|
529
|
+
if (!this.requireTrackProperties(eventName, properties, ["cart"], strict))
|
|
530
|
+
return UNHANDLED_TRACK;
|
|
531
|
+
return handled(this.checkout.client.begin(properties));
|
|
532
|
+
case "checkout_step":
|
|
533
|
+
if (!this.requireTrackProperties(eventName, properties, ["step", "stepNumber", "cart"], strict))
|
|
534
|
+
return UNHANDLED_TRACK;
|
|
535
|
+
return handled(this.checkout.client.step(properties));
|
|
536
|
+
case "add_shipping_info":
|
|
537
|
+
if (!this.requireTrackProperties(eventName, properties, ["cart", "shipping"], strict))
|
|
538
|
+
return UNHANDLED_TRACK;
|
|
539
|
+
return handled(this.checkout.client.addShipping(properties));
|
|
540
|
+
case "add_payment_info":
|
|
541
|
+
if (!this.requireTrackProperties(eventName, properties, ["cart", "payment"], strict))
|
|
542
|
+
return UNHANDLED_TRACK;
|
|
543
|
+
return handled(this.checkout.client.addPayment(properties));
|
|
544
|
+
case "purchase":
|
|
545
|
+
if (!this.requireTrackProperties(eventName, properties, ["order"], strict))
|
|
546
|
+
return UNHANDLED_TRACK;
|
|
547
|
+
return handled(this.purchases.client.track(properties));
|
|
548
|
+
case "refund":
|
|
549
|
+
if (!this.requireTrackProperties(eventName, properties, ["orderId", "refundId", "amount", "currency"], strict))
|
|
550
|
+
return UNHANDLED_TRACK;
|
|
551
|
+
return handled(this.refunds.client.track(properties));
|
|
552
|
+
case "refund_requested":
|
|
553
|
+
if (!this.requireTrackProperties(eventName, properties, ["orderId"], strict))
|
|
554
|
+
return UNHANDLED_TRACK;
|
|
555
|
+
return handled(this.refunds.client.request(stringValue(properties, "orderId"), properties.items, stringValue(properties, "reason")));
|
|
556
|
+
case "refund_approved":
|
|
557
|
+
if (!this.requireTrackProperties(eventName, properties, ["refundId", "approvedAmount"], strict))
|
|
558
|
+
return UNHANDLED_TRACK;
|
|
559
|
+
return handled(this.refunds.client.approve(stringValue(properties, "refundId"), numberValue(properties, "approvedAmount")));
|
|
560
|
+
case "refund_denied":
|
|
561
|
+
if (!this.requireTrackProperties(eventName, properties, ["refundId", "reason"], strict))
|
|
562
|
+
return UNHANDLED_TRACK;
|
|
563
|
+
return handled(this.refunds.client.deny(stringValue(properties, "refundId"), stringValue(properties, "reason")));
|
|
564
|
+
case "refund_completed":
|
|
565
|
+
if (!this.requireTrackProperties(eventName, properties, ["refundId", "processedAmount"], strict))
|
|
566
|
+
return UNHANDLED_TRACK;
|
|
567
|
+
return handled(this.refunds.client.complete(stringValue(properties, "refundId"), numberValue(properties, "processedAmount")));
|
|
568
|
+
case "promotion_view":
|
|
569
|
+
if (!this.requireTrackProperties(eventName, properties, ["promotionId", "name", "creative", "position"], strict))
|
|
570
|
+
return UNHANDLED_TRACK;
|
|
571
|
+
return handled(this.promotions.client.view(properties));
|
|
572
|
+
case "promotion_click":
|
|
573
|
+
if (!this.requireTrackProperties(eventName, properties, ["promotionId", "name", "creative", "position"], strict))
|
|
574
|
+
return UNHANDLED_TRACK;
|
|
575
|
+
return handled(this.promotions.client.click(properties));
|
|
576
|
+
case "coupon_used":
|
|
577
|
+
if (!this.requireTrackProperties(eventName, properties, ["code", "orderId", "discountValue", "discountType", "orderValueBefore", "orderValueAfter"], strict))
|
|
578
|
+
return UNHANDLED_TRACK;
|
|
579
|
+
return handled(this.promotions.client.couponUsed(properties));
|
|
580
|
+
case "add_to_wishlist":
|
|
581
|
+
case "remove_from_wishlist": {
|
|
582
|
+
const product = productFrom(properties);
|
|
583
|
+
if (!product) {
|
|
584
|
+
if (strict)
|
|
585
|
+
throw new Error(`FlowGrid.track("${eventName}") missing required properties: product or productId, name, price`);
|
|
586
|
+
return UNHANDLED_TRACK;
|
|
587
|
+
}
|
|
588
|
+
const config = { ...omitProperties(properties, ["product", ...PRODUCT_KEYS]), product };
|
|
589
|
+
return handled(eventName === "add_to_wishlist"
|
|
590
|
+
? this.wishlist.client.add(config)
|
|
591
|
+
: this.wishlist.client.remove(config));
|
|
592
|
+
}
|
|
593
|
+
case "view_wishlist":
|
|
594
|
+
if (!this.requireTrackProperties(eventName, properties, ["wishlist"], strict))
|
|
595
|
+
return UNHANDLED_TRACK;
|
|
596
|
+
return handled(this.wishlist.client.view(recordValue(properties, "wishlist")));
|
|
597
|
+
case "wishlist_to_cart": {
|
|
598
|
+
const product = productFrom(properties);
|
|
599
|
+
if (!product) {
|
|
600
|
+
if (strict)
|
|
601
|
+
throw new Error(`FlowGrid.track("${eventName}") missing required properties: product or productId, name, price`);
|
|
602
|
+
return UNHANDLED_TRACK;
|
|
603
|
+
}
|
|
604
|
+
return handled(this.wishlist.client.moveToCart(product, stringValue(properties, "wishlistId")));
|
|
605
|
+
}
|
|
606
|
+
case "share_wishlist":
|
|
607
|
+
if (!this.requireTrackProperties(eventName, properties, ["wishlistId", "method"], strict))
|
|
608
|
+
return UNHANDLED_TRACK;
|
|
609
|
+
return handled(this.wishlist.client.share(stringValue(properties, "wishlistId"), stringValue(properties, "method")));
|
|
610
|
+
case "subscription_start":
|
|
611
|
+
if (!this.requireTrackProperties(eventName, properties, ["subscriptionId", "userId", "plan", "mrr", "billingCycle"], strict))
|
|
612
|
+
return UNHANDLED_TRACK;
|
|
613
|
+
return handled(this.subscriptions.client.start(properties));
|
|
614
|
+
case "subscription_change":
|
|
615
|
+
if (!this.requireTrackProperties(eventName, properties, ["subscriptionId", "userId", "previousPlan", "newPlan", "previousMrr", "newMrr", "changeType"], strict))
|
|
616
|
+
return UNHANDLED_TRACK;
|
|
617
|
+
return handled(this.subscriptions.client.change(properties));
|
|
618
|
+
case "subscription_cancel":
|
|
619
|
+
if (!this.requireTrackProperties(eventName, properties, ["subscriptionId", "userId", "plan", "lostMrr"], strict))
|
|
620
|
+
return UNHANDLED_TRACK;
|
|
621
|
+
return handled(this.subscriptions.client.cancel(properties));
|
|
622
|
+
case "subscription_renew":
|
|
623
|
+
if (!this.requireTrackProperties(eventName, properties, ["subscriptionId", "userId", "mrr"], strict))
|
|
624
|
+
return UNHANDLED_TRACK;
|
|
625
|
+
return handled(this.subscriptions.client.renew(stringValue(properties, "subscriptionId"), stringValue(properties, "userId"), recordValue(properties, "mrr")));
|
|
626
|
+
case "trial_converted":
|
|
627
|
+
if (!this.requireTrackProperties(eventName, properties, ["subscriptionId", "userId", "plan", "mrr"], strict))
|
|
628
|
+
return UNHANDLED_TRACK;
|
|
629
|
+
return handled(this.subscriptions.client.trialConverted(stringValue(properties, "subscriptionId"), stringValue(properties, "userId"), stringValue(properties, "plan"), recordValue(properties, "mrr")));
|
|
630
|
+
case "trial_expired":
|
|
631
|
+
if (!this.requireTrackProperties(eventName, properties, ["subscriptionId", "userId"], strict))
|
|
632
|
+
return UNHANDLED_TRACK;
|
|
633
|
+
return handled(this.subscriptions.client.trialExpired(stringValue(properties, "subscriptionId"), stringValue(properties, "userId")));
|
|
634
|
+
case "record_acquisition_cost":
|
|
635
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "cost", "channel"], strict))
|
|
636
|
+
return UNHANDLED_TRACK;
|
|
637
|
+
return handled(this.ltv.client.recordAcquisitionCost(properties));
|
|
638
|
+
case "update_customer_segment":
|
|
639
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "newSegment"], strict))
|
|
640
|
+
return UNHANDLED_TRACK;
|
|
641
|
+
return handled(this.ltv.client.updateSegment(stringValue(properties, "userId"), stringValue(properties, "newSegment")));
|
|
642
|
+
case "site_search":
|
|
643
|
+
if (!this.requireTrackProperties(eventName, properties, ["query", "resultsCount"], strict))
|
|
644
|
+
return UNHANDLED_TRACK;
|
|
645
|
+
return handled(this.search.client.track(properties));
|
|
646
|
+
case "search_result_click": {
|
|
647
|
+
const product = productFrom(properties);
|
|
648
|
+
if (!product || !this.requireTrackProperties(eventName, properties, ["query", "position"], strict))
|
|
649
|
+
return UNHANDLED_TRACK;
|
|
650
|
+
return handled(this.search.client.trackClick({ ...properties, product }));
|
|
651
|
+
}
|
|
652
|
+
case "search_refinement":
|
|
653
|
+
if (!this.requireTrackProperties(eventName, properties, ["originalQuery", "refinedQuery", "refinementType"], strict))
|
|
654
|
+
return UNHANDLED_TRACK;
|
|
655
|
+
return handled(this.search.client.trackRefinement(stringValue(properties, "originalQuery"), stringValue(properties, "refinedQuery"), stringValue(properties, "refinementType")));
|
|
656
|
+
case "search_suggestion":
|
|
657
|
+
if (!this.requireTrackProperties(eventName, properties, ["partialQuery", "selectedSuggestion", "suggestionPosition"], strict))
|
|
658
|
+
return UNHANDLED_TRACK;
|
|
659
|
+
return handled(this.search.client.trackSuggestion(stringValue(properties, "partialQuery"), stringValue(properties, "selectedSuggestion"), numberValue(properties, "suggestionPosition")));
|
|
660
|
+
default:
|
|
661
|
+
return UNHANDLED_TRACK;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
dispatchEnterpriseTrack(eventName, properties, strict, domain) {
|
|
665
|
+
switch (eventName) {
|
|
666
|
+
case "engagement.dwell_time":
|
|
667
|
+
case "engagement_dwell_time":
|
|
668
|
+
if (domain && domain !== "engagement")
|
|
669
|
+
return UNHANDLED_TRACK;
|
|
670
|
+
if (!this.requireTrackProperties(eventName, properties, ["featureId", "dwellTimeMs"], strict))
|
|
671
|
+
return UNHANDLED_TRACK;
|
|
672
|
+
return handled(this.engagement.client.trackDwellTime(properties));
|
|
673
|
+
case "engagement.session_depth":
|
|
674
|
+
case "engagement_session_depth":
|
|
675
|
+
if (domain && domain !== "engagement")
|
|
676
|
+
return UNHANDLED_TRACK;
|
|
677
|
+
if (!this.requireTrackProperties(eventName, properties, ["sessionId", "pagesVisited", "featuresUsed", "actionsTaken", "durationMs"], strict))
|
|
678
|
+
return UNHANDLED_TRACK;
|
|
679
|
+
return handled(this.engagement.client.trackSessionDepth(properties));
|
|
680
|
+
case "engagement.content_consumption":
|
|
681
|
+
case "engagement_content_consumption":
|
|
682
|
+
if (domain && domain !== "engagement")
|
|
683
|
+
return UNHANDLED_TRACK;
|
|
684
|
+
if (!this.requireTrackProperties(eventName, properties, ["contentId", "contentType", "percentageConsumed", "timeSpentMs"], strict))
|
|
685
|
+
return UNHANDLED_TRACK;
|
|
686
|
+
return handled(this.engagement.client.trackContentConsumption(properties));
|
|
687
|
+
case "engagement.user_activity":
|
|
688
|
+
case "engagement_user_activity":
|
|
689
|
+
if (domain && domain !== "engagement")
|
|
690
|
+
return UNHANDLED_TRACK;
|
|
691
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "activityType", "durationMs"], strict))
|
|
692
|
+
return UNHANDLED_TRACK;
|
|
693
|
+
return handled(this.engagement.client.trackUserActivity(properties));
|
|
694
|
+
case "churn.usage_decay":
|
|
695
|
+
case "churn_usage_decay":
|
|
696
|
+
if (domain && domain !== "churn")
|
|
697
|
+
return UNHANDLED_TRACK;
|
|
698
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "metric", "periods"], strict))
|
|
699
|
+
return UNHANDLED_TRACK;
|
|
700
|
+
return handled(this.churn.client.trackUsageDecay(properties));
|
|
701
|
+
case "churn.nps":
|
|
702
|
+
case "churn_nps":
|
|
703
|
+
if (domain && domain !== "churn")
|
|
704
|
+
return UNHANDLED_TRACK;
|
|
705
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "score"], strict))
|
|
706
|
+
return UNHANDLED_TRACK;
|
|
707
|
+
return handled(this.churn.client.trackNPS(properties));
|
|
708
|
+
case "churn.churn_event":
|
|
709
|
+
case "churn_churn_event":
|
|
710
|
+
if (domain && domain !== "churn")
|
|
711
|
+
return UNHANDLED_TRACK;
|
|
712
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "churnType"], strict))
|
|
713
|
+
return UNHANDLED_TRACK;
|
|
714
|
+
return handled(this.churn.client.trackChurn(properties));
|
|
715
|
+
case "churn.prevention_action":
|
|
716
|
+
case "churn_prevention_action":
|
|
717
|
+
if (domain && domain !== "churn")
|
|
718
|
+
return UNHANDLED_TRACK;
|
|
719
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "actionType"], strict))
|
|
720
|
+
return UNHANDLED_TRACK;
|
|
721
|
+
return handled(this.churn.client.trackPreventionAction(properties));
|
|
722
|
+
case "monetization.revenue":
|
|
723
|
+
case "monetization_revenue":
|
|
724
|
+
if (domain && domain !== "monetization")
|
|
725
|
+
return UNHANDLED_TRACK;
|
|
726
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "amount", "currency", "type"], strict))
|
|
727
|
+
return UNHANDLED_TRACK;
|
|
728
|
+
return handled(this.monetization.client.trackRevenue(properties));
|
|
729
|
+
case "support.ticket_created":
|
|
730
|
+
case "support_ticket_created":
|
|
731
|
+
if (domain && domain !== "support")
|
|
732
|
+
return UNHANDLED_TRACK;
|
|
733
|
+
if (!this.requireTrackProperties(eventName, properties, ["ticketId", "userId", "subject", "category", "priority", "channel"], strict))
|
|
734
|
+
return UNHANDLED_TRACK;
|
|
735
|
+
return handled(this.support.client.trackTicket(properties));
|
|
736
|
+
case "support.ticket_updated":
|
|
737
|
+
case "support_ticket_updated":
|
|
738
|
+
if (domain && domain !== "support")
|
|
739
|
+
return UNHANDLED_TRACK;
|
|
740
|
+
if (!this.requireTrackProperties(eventName, properties, ["ticketId", "status"], strict))
|
|
741
|
+
return UNHANDLED_TRACK;
|
|
742
|
+
return handled(this.support.client.updateTicket(properties));
|
|
743
|
+
case "support.csat":
|
|
744
|
+
case "support_csat":
|
|
745
|
+
if (domain && domain !== "support")
|
|
746
|
+
return UNHANDLED_TRACK;
|
|
747
|
+
if (!this.requireTrackProperties(eventName, properties, ["ticketId", "userId", "score"], strict))
|
|
748
|
+
return UNHANDLED_TRACK;
|
|
749
|
+
return handled(this.support.client.trackCSAT(properties));
|
|
750
|
+
case "support.feature_complaint":
|
|
751
|
+
case "support_feature_complaint":
|
|
752
|
+
if (domain && domain !== "support")
|
|
753
|
+
return UNHANDLED_TRACK;
|
|
754
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "featureId", "complaintType", "severity"], strict))
|
|
755
|
+
return UNHANDLED_TRACK;
|
|
756
|
+
return handled(this.support.client.trackFeatureComplaint(properties));
|
|
757
|
+
case "acquisition.acquired":
|
|
758
|
+
case "acquisition_acquired":
|
|
759
|
+
if (domain && domain !== "acquisition")
|
|
760
|
+
return UNHANDLED_TRACK;
|
|
761
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "source"], strict))
|
|
762
|
+
return UNHANDLED_TRACK;
|
|
763
|
+
return handled(this.acquisition.client.trackAcquisition(properties));
|
|
764
|
+
case "acquisition.lifecycle_transition":
|
|
765
|
+
case "acquisition_lifecycle_transition":
|
|
766
|
+
if (domain && domain !== "acquisition")
|
|
767
|
+
return UNHANDLED_TRACK;
|
|
768
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "fromStage", "toStage"], strict))
|
|
769
|
+
return UNHANDLED_TRACK;
|
|
770
|
+
return handled(this.acquisition.client.trackLifecycleTransition(properties));
|
|
771
|
+
case "acquisition.campaign_spend":
|
|
772
|
+
case "acquisition_campaign_spend":
|
|
773
|
+
if (domain && domain !== "acquisition")
|
|
774
|
+
return UNHANDLED_TRACK;
|
|
775
|
+
if (!this.requireTrackProperties(eventName, properties, ["campaignId", "amount", "date"], strict))
|
|
776
|
+
return UNHANDLED_TRACK;
|
|
777
|
+
return handled(this.acquisition.client.trackCampaignSpend(properties));
|
|
778
|
+
case "paths.transition":
|
|
779
|
+
case "paths_transition":
|
|
780
|
+
if (domain && domain !== "paths")
|
|
781
|
+
return UNHANDLED_TRACK;
|
|
782
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "fromScreen", "toScreen"], strict))
|
|
783
|
+
return UNHANDLED_TRACK;
|
|
784
|
+
return handled(this.paths.client.trackTransition(properties));
|
|
785
|
+
case "paths.feature_sequence":
|
|
786
|
+
case "paths_feature_sequence":
|
|
787
|
+
if (domain && domain !== "paths")
|
|
788
|
+
return UNHANDLED_TRACK;
|
|
789
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "feature", "order"], strict))
|
|
790
|
+
return UNHANDLED_TRACK;
|
|
791
|
+
return handled(this.paths.client.trackFeatureSequence(properties));
|
|
792
|
+
case "security.login_attempt":
|
|
793
|
+
case "security_login_attempt":
|
|
794
|
+
if (domain && domain !== "security")
|
|
795
|
+
return UNHANDLED_TRACK;
|
|
796
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "success"], strict))
|
|
797
|
+
return UNHANDLED_TRACK;
|
|
798
|
+
return handled(this.security.client.trackLoginAttempt(properties));
|
|
799
|
+
case "security.role_change":
|
|
800
|
+
case "security_role_change":
|
|
801
|
+
if (domain && domain !== "security")
|
|
802
|
+
return UNHANDLED_TRACK;
|
|
803
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "changedBy", "previousRole", "newRole"], strict))
|
|
804
|
+
return UNHANDLED_TRACK;
|
|
805
|
+
return handled(this.security.client.trackRoleChange(properties));
|
|
806
|
+
case "security.permission_change":
|
|
807
|
+
case "security_permission_change":
|
|
808
|
+
if (domain && domain !== "security")
|
|
809
|
+
return UNHANDLED_TRACK;
|
|
810
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "changedBy", "permission", "action"], strict))
|
|
811
|
+
return UNHANDLED_TRACK;
|
|
812
|
+
return handled(this.security.client.trackPermissionChange(properties));
|
|
813
|
+
case "security.data_access":
|
|
814
|
+
case "security_data_access":
|
|
815
|
+
if (domain && domain !== "security")
|
|
816
|
+
return UNHANDLED_TRACK;
|
|
817
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "resourceType", "accessType"], strict))
|
|
818
|
+
return UNHANDLED_TRACK;
|
|
819
|
+
return handled(this.security.client.trackDataAccess(properties));
|
|
820
|
+
case "security.compliance_event":
|
|
821
|
+
case "security_compliance_event":
|
|
822
|
+
if (domain && domain !== "security")
|
|
823
|
+
return UNHANDLED_TRACK;
|
|
824
|
+
if (!this.requireTrackProperties(eventName, properties, ["userId", "eventType"], strict))
|
|
825
|
+
return UNHANDLED_TRACK;
|
|
826
|
+
return handled(this.security.client.trackComplianceEvent(properties));
|
|
827
|
+
case "multi_path_funnels.track_step":
|
|
828
|
+
case "multi_path_funnels_track_step":
|
|
829
|
+
if (domain && domain !== "multiPathFunnels")
|
|
830
|
+
return UNHANDLED_TRACK;
|
|
831
|
+
if (!this.requireTrackProperties(eventName, properties, ["funnelId", "step", "userId"], strict))
|
|
832
|
+
return UNHANDLED_TRACK;
|
|
833
|
+
return handled(this.multiPathFunnels.client.trackStep(properties));
|
|
834
|
+
case "multi_path_funnels.track_micro_conversion":
|
|
835
|
+
case "multi_path_funnels_track_micro_conversion":
|
|
836
|
+
if (domain && domain !== "multiPathFunnels")
|
|
837
|
+
return UNHANDLED_TRACK;
|
|
838
|
+
if (!this.requireTrackProperties(eventName, properties, ["conversionId", "userId"], strict))
|
|
839
|
+
return UNHANDLED_TRACK;
|
|
840
|
+
return handled(this.multiPathFunnels.client.trackMicroConversion(properties));
|
|
841
|
+
default:
|
|
842
|
+
return UNHANDLED_TRACK;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
202
845
|
/**
|
|
203
846
|
* Record an experiment exposure for a user.
|
|
204
847
|
*
|