@funnelsgrove/runtime 0.1.16 → 0.1.18
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.
|
@@ -271,9 +271,6 @@ export function usePreviewBridge({ activeStepId, onGoToStep, resolveRenderableSt
|
|
|
271
271
|
emitPreviewReady(activeStepId);
|
|
272
272
|
}, [activeStepId]);
|
|
273
273
|
useEffect(() => {
|
|
274
|
-
if (shouldLockToInitialStep) {
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
274
|
const handlePreviewMessage = (event) => {
|
|
278
275
|
const action = parsePreviewBridgeMessage(event.data);
|
|
279
276
|
if (!action) {
|
|
@@ -298,6 +295,9 @@ export function usePreviewBridge({ activeStepId, onGoToStep, resolveRenderableSt
|
|
|
298
295
|
setRuntimeMode(action.mode);
|
|
299
296
|
return;
|
|
300
297
|
}
|
|
298
|
+
if (shouldLockToInitialStep) {
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
301
|
const targetStepId = resolveRenderableStepId(action.stepId);
|
|
302
302
|
if (!targetStepId) {
|
|
303
303
|
logger.warn({
|
|
@@ -340,7 +340,7 @@ export function useFunnelFlowController({ initialStepId, lockToInitialStep = fal
|
|
|
340
340
|
endedAt: record.completedAt,
|
|
341
341
|
selected: record.choices,
|
|
342
342
|
});
|
|
343
|
-
capturePostHogStepEvent('step_completed', Object.assign({ distinct_id: currentUserIdRef.current, funnel_id: FUNNEL_ID || undefined, funnel_version_id: FUNNEL_VERSION_ID || undefined, project_id: PROJECT_ID || undefined, step_id: record.stepId, step_name: record.stepName, started_at: startedAt, ended_at: record.completedAt, duration_ms: Number.isFinite(durationMs) ? durationMs : undefined, selected: record.choices }, buildFeatureFlagProperties(postHogFeatureFlagsRef.current)));
|
|
343
|
+
capturePostHogStepEvent('step_completed', Object.assign({ distinct_id: currentUserIdRef.current, funnel_id: FUNNEL_ID || undefined, funnel_version_id: FUNNEL_VERSION_ID || undefined, project_id: PROJECT_ID || undefined, environment: runtimeMode, step_id: record.stepId, step_name: record.stepName, started_at: startedAt, ended_at: record.completedAt, duration_ms: Number.isFinite(durationMs) ? durationMs : undefined, selected: record.choices }, buildFeatureFlagProperties(postHogFeatureFlagsRef.current)));
|
|
344
344
|
}
|
|
345
345
|
setUser((prev) => {
|
|
346
346
|
var _a, _b;
|
|
@@ -390,7 +390,7 @@ export function useFunnelFlowController({ initialStepId, lockToInitialStep = fal
|
|
|
390
390
|
stepName,
|
|
391
391
|
startedAt,
|
|
392
392
|
});
|
|
393
|
-
capturePostHogStepEvent('step_started', Object.assign({ distinct_id: currentUserIdRef.current, funnel_id: FUNNEL_ID || undefined, funnel_version_id: FUNNEL_VERSION_ID || undefined, project_id: PROJECT_ID || undefined, step_id: renderedStepId, step_name: stepName, started_at: startedAt }, buildFeatureFlagProperties(postHogFeatureFlagsRef.current)));
|
|
393
|
+
capturePostHogStepEvent('step_started', Object.assign({ distinct_id: currentUserIdRef.current, funnel_id: FUNNEL_ID || undefined, funnel_version_id: FUNNEL_VERSION_ID || undefined, project_id: PROJECT_ID || undefined, environment: runtimeMode, step_id: renderedStepId, step_name: stepName, started_at: startedAt }, buildFeatureFlagProperties(postHogFeatureFlagsRef.current)));
|
|
394
394
|
}
|
|
395
395
|
attributesAtStepStart.current = Object.assign({}, attributesRef.current);
|
|
396
396
|
prevStepIdRef.current = renderedStepId;
|
|
@@ -420,7 +420,7 @@ export function useFunnelFlowController({ initialStepId, lockToInitialStep = fal
|
|
|
420
420
|
engagementThresholdMs: FIRST_STEP_ENGAGEMENT_THRESHOLD_MS,
|
|
421
421
|
},
|
|
422
422
|
});
|
|
423
|
-
capturePostHogStepEvent('step_engaged', Object.assign({ distinct_id: currentUserIdRef.current, funnel_id: FUNNEL_ID || undefined, funnel_version_id: FUNNEL_VERSION_ID || undefined, project_id: PROJECT_ID || undefined, step_id: engagedStepId, step_name: engagedStepName, started_at: engagedStartedAt, ended_at: engagedAt, duration_ms: FIRST_STEP_ENGAGEMENT_THRESHOLD_MS, engagement_threshold_ms: FIRST_STEP_ENGAGEMENT_THRESHOLD_MS }, buildFeatureFlagProperties(postHogFeatureFlagsRef.current)));
|
|
423
|
+
capturePostHogStepEvent('step_engaged', Object.assign({ distinct_id: currentUserIdRef.current, funnel_id: FUNNEL_ID || undefined, funnel_version_id: FUNNEL_VERSION_ID || undefined, project_id: PROJECT_ID || undefined, environment: runtimeMode, step_id: engagedStepId, step_name: engagedStepName, started_at: engagedStartedAt, ended_at: engagedAt, duration_ms: FIRST_STEP_ENGAGEMENT_THRESHOLD_MS, engagement_threshold_ms: FIRST_STEP_ENGAGEMENT_THRESHOLD_MS }, buildFeatureFlagProperties(postHogFeatureFlagsRef.current)));
|
|
424
424
|
}, FIRST_STEP_ENGAGEMENT_THRESHOLD_MS);
|
|
425
425
|
return () => window.clearTimeout(timer);
|
|
426
426
|
}, [
|
|
@@ -50,6 +50,14 @@ export type ManageSubscriptionsResponse = {
|
|
|
50
50
|
currency?: string | null;
|
|
51
51
|
billingInterval?: string | null;
|
|
52
52
|
billingIntervalCount?: number | null;
|
|
53
|
+
discountCouponIds?: string[];
|
|
54
|
+
retentionDiscount?: {
|
|
55
|
+
couponId: string;
|
|
56
|
+
discountPercent: number;
|
|
57
|
+
amountCents: number;
|
|
58
|
+
discountedAmountCents: number;
|
|
59
|
+
originalAmountCents: number;
|
|
60
|
+
};
|
|
53
61
|
environment: 'test' | 'live';
|
|
54
62
|
}>;
|
|
55
63
|
eventsCount: number;
|
|
@@ -102,7 +110,8 @@ declare class ApiService {
|
|
|
102
110
|
getManageSubscriptions(): Promise<ManageSubscriptionsResponse>;
|
|
103
111
|
updateSubscription(input: {
|
|
104
112
|
subscriptionId: string;
|
|
105
|
-
action: 'cancel' | 'renew';
|
|
113
|
+
action: 'cancel' | 'renew' | 'apply-discount';
|
|
114
|
+
couponId?: string | null;
|
|
106
115
|
}): Promise<ManageSubscriptionsResponse>;
|
|
107
116
|
}
|
|
108
117
|
export declare const apiService: ApiService;
|
|
@@ -2,9 +2,58 @@ import { buildMainApiUrl, buildSdkHeaders, FUNNEL_ID, FUNNEL_VERSION_ID, getFunn
|
|
|
2
2
|
import { mergeFunnelUserAttribution, } from '../runtime/funnel-attribution.js';
|
|
3
3
|
import { applyUrlUserAttributesToUser, hasUrlUserProfileAttributes, resolveUrlUserAttributes, } from '../runtime/url-user-attributes.js';
|
|
4
4
|
const DEFAULT_USER_ID_STORAGE_KEY = 'funnel:user-id';
|
|
5
|
+
const DEFAULT_FUNNEL_DOMAIN_SIGNAL = 'funnelsgrove';
|
|
5
6
|
const canUseDom = () => {
|
|
6
7
|
return typeof window !== 'undefined';
|
|
7
8
|
};
|
|
9
|
+
const normalizeRuntimeEnvironment = (value) => {
|
|
10
|
+
if (typeof value !== 'string') {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
const normalized = value.trim().toLowerCase();
|
|
14
|
+
if (normalized === 'test') {
|
|
15
|
+
return 'test';
|
|
16
|
+
}
|
|
17
|
+
if (normalized === 'live' || normalized === 'prod' || normalized === 'production') {
|
|
18
|
+
return 'live';
|
|
19
|
+
}
|
|
20
|
+
return null;
|
|
21
|
+
};
|
|
22
|
+
const readCookieValue = (name) => {
|
|
23
|
+
var _a, _b;
|
|
24
|
+
if (!canUseDom() || typeof document === 'undefined') {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return (((_b = (_a = document.cookie) === null || _a === void 0 ? void 0 : _a.split(';').map((part) => part.trim()).find((part) => part.startsWith(`${name}=`))) === null || _b === void 0 ? void 0 : _b.slice(name.length + 1)) || null);
|
|
28
|
+
};
|
|
29
|
+
const resolveRuntimeAnalyticsEnvironment = () => {
|
|
30
|
+
var _a, _b, _c, _d;
|
|
31
|
+
if (!canUseDom()) {
|
|
32
|
+
return 'live';
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const queryMode = normalizeRuntimeEnvironment(new URLSearchParams(((_a = window.location) === null || _a === void 0 ? void 0 : _a.search) || '').get('mode'));
|
|
36
|
+
if (queryMode) {
|
|
37
|
+
return queryMode;
|
|
38
|
+
}
|
|
39
|
+
const cookieMode = normalizeRuntimeEnvironment(readCookieValue('funnel-mode'));
|
|
40
|
+
if (cookieMode) {
|
|
41
|
+
return cookieMode;
|
|
42
|
+
}
|
|
43
|
+
const hostname = ((_c = (_b = window.location) === null || _b === void 0 ? void 0 : _b.hostname) === null || _c === void 0 ? void 0 : _c.trim().toLowerCase()) || '';
|
|
44
|
+
if (hostname.includes(DEFAULT_FUNNEL_DOMAIN_SIGNAL)) {
|
|
45
|
+
return 'test';
|
|
46
|
+
}
|
|
47
|
+
const storageMode = normalizeRuntimeEnvironment((_d = window.localStorage) === null || _d === void 0 ? void 0 : _d.getItem('funnel-mode'));
|
|
48
|
+
if (storageMode) {
|
|
49
|
+
return storageMode;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
catch (_e) {
|
|
53
|
+
return 'live';
|
|
54
|
+
}
|
|
55
|
+
return 'live';
|
|
56
|
+
};
|
|
8
57
|
const isRecord = (value) => {
|
|
9
58
|
return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
10
59
|
};
|
|
@@ -80,7 +129,7 @@ const buildSdkEvent = (event) => {
|
|
|
80
129
|
startedAt: event.startedAt || null,
|
|
81
130
|
endedAt: event.endedAt || null,
|
|
82
131
|
selected: event.selected || {},
|
|
83
|
-
metadata: event.metadata || {},
|
|
132
|
+
metadata: Object.assign({ environment: resolveRuntimeAnalyticsEnvironment() }, (event.metadata || {})),
|
|
84
133
|
};
|
|
85
134
|
};
|
|
86
135
|
const withMergedAttributionDocument = (document, attribution) => {
|
|
@@ -236,6 +285,7 @@ class ApiService {
|
|
|
236
285
|
fullName: inputName,
|
|
237
286
|
metadata: {
|
|
238
287
|
source: 'funnel-session',
|
|
288
|
+
environment: resolveRuntimeAnalyticsEnvironment(),
|
|
239
289
|
},
|
|
240
290
|
attribution: input === null || input === void 0 ? void 0 : input.attribution,
|
|
241
291
|
}),
|
|
@@ -285,6 +335,7 @@ class ApiService {
|
|
|
285
335
|
},
|
|
286
336
|
metadata: {
|
|
287
337
|
source: 'funnel',
|
|
338
|
+
environment: resolveRuntimeAnalyticsEnvironment(),
|
|
288
339
|
},
|
|
289
340
|
attribution: options === null || options === void 0 ? void 0 : options.attribution,
|
|
290
341
|
}),
|
|
@@ -481,6 +532,7 @@ class ApiService {
|
|
|
481
532
|
return (await response.json());
|
|
482
533
|
}
|
|
483
534
|
async updateSubscription(input) {
|
|
535
|
+
var _a;
|
|
484
536
|
const userId = this.getSubscriptionManagementUserId();
|
|
485
537
|
const stripeCustomerId = this.getSubscriptionManagementStripeCustomerId();
|
|
486
538
|
const response = await fetch(buildMainApiUrl(`/sdk/public/subscriptions/${encodeURIComponent(input.subscriptionId)}/${input.action}`), {
|
|
@@ -492,6 +544,7 @@ class ApiService {
|
|
|
492
544
|
user_id: userId || undefined,
|
|
493
545
|
stripe_customer_id: stripeCustomerId || undefined,
|
|
494
546
|
funnelId: FUNNEL_ID || undefined,
|
|
547
|
+
coupon_id: ((_a = input.couponId) === null || _a === void 0 ? void 0 : _a.trim()) || undefined,
|
|
495
548
|
}),
|
|
496
549
|
});
|
|
497
550
|
if (!response.ok) {
|