@funnelsgrove/runtime 0.1.17 → 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
  }, [
@@ -51,6 +51,13 @@ export type ManageSubscriptionsResponse = {
51
51
  billingInterval?: string | null;
52
52
  billingIntervalCount?: number | null;
53
53
  discountCouponIds?: string[];
54
+ retentionDiscount?: {
55
+ couponId: string;
56
+ discountPercent: number;
57
+ amountCents: number;
58
+ discountedAmountCents: number;
59
+ originalAmountCents: number;
60
+ };
54
61
  environment: 'test' | 'live';
55
62
  }>;
56
63
  eventsCount: number;
@@ -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
  }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelsgrove/runtime",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "main": "./dist/index.js",