@funnelsgrove/runtime 0.1.54 → 0.1.56
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.
|
@@ -15,4 +15,5 @@ export declare const collectCurrentFunnelAttribution: (input?: {
|
|
|
15
15
|
posthogProperties?: Record<string, unknown> | null;
|
|
16
16
|
}) => FunnelUserAttribution;
|
|
17
17
|
export declare const mergeFunnelUserAttribution: (current: unknown, incoming: FunnelUserAttribution | null | undefined) => FunnelUserAttribution;
|
|
18
|
+
export declare const buildFunnelAttributionEventMetadata: (attribution: FunnelUserAttribution | null | undefined) => Record<string, string>;
|
|
18
19
|
export declare const getFunnelUserAttribution: (document: unknown) => FunnelUserAttribution | null;
|
|
@@ -6,6 +6,22 @@ const INTERNAL_ATTRIBUTION_QUERY_KEYS = new Set([
|
|
|
6
6
|
'step',
|
|
7
7
|
'user_id',
|
|
8
8
|
]);
|
|
9
|
+
const EVENT_ATTRIBUTION_CLICK_ID_KEYS = new Set([
|
|
10
|
+
'_fbc',
|
|
11
|
+
'_fbp',
|
|
12
|
+
'epik',
|
|
13
|
+
'fbc',
|
|
14
|
+
'fbclid',
|
|
15
|
+
'fbp',
|
|
16
|
+
'gbraid',
|
|
17
|
+
'gclid',
|
|
18
|
+
'li_fat_id',
|
|
19
|
+
'msclkid',
|
|
20
|
+
'scclid',
|
|
21
|
+
'ttclid',
|
|
22
|
+
'twclid',
|
|
23
|
+
'wbraid',
|
|
24
|
+
]);
|
|
9
25
|
const POSTHOG_CONTEXT_MAPPINGS = {
|
|
10
26
|
$geoip_city_name: 'cityName',
|
|
11
27
|
$geoip_country_code: 'countryCode',
|
|
@@ -41,6 +57,13 @@ const normalizeTouch = (value) => {
|
|
|
41
57
|
return [[normalizedKey, normalizedValue]];
|
|
42
58
|
}));
|
|
43
59
|
};
|
|
60
|
+
const isEventAttributionKey = (key) => {
|
|
61
|
+
const normalizedKey = key.trim().toLowerCase();
|
|
62
|
+
return normalizedKey.startsWith('utm_') || EVENT_ATTRIBUTION_CLICK_ID_KEYS.has(normalizedKey);
|
|
63
|
+
};
|
|
64
|
+
const normalizeEventAttributionTouch = (value) => {
|
|
65
|
+
return Object.fromEntries(Object.entries(normalizeTouch(value)).filter(([key]) => isEventAttributionKey(key)));
|
|
66
|
+
};
|
|
44
67
|
const normalizeContext = (value) => {
|
|
45
68
|
if (!isRecord(value)) {
|
|
46
69
|
return {};
|
|
@@ -219,6 +242,7 @@ export const mergeFunnelUserAttribution = (current, incoming) => {
|
|
|
219
242
|
context: deepMergeRecords(currentContext, nextContext),
|
|
220
243
|
};
|
|
221
244
|
};
|
|
245
|
+
export const buildFunnelAttributionEventMetadata = (attribution) => normalizeEventAttributionTouch(attribution === null || attribution === void 0 ? void 0 : attribution.firstTouch);
|
|
222
246
|
export const getFunnelUserAttribution = (document) => {
|
|
223
247
|
if (!isRecord(document) || !isRecord(document.attribution)) {
|
|
224
248
|
return null;
|
|
@@ -2,6 +2,7 @@ import { type Dispatch, type SetStateAction } from 'react';
|
|
|
2
2
|
import type { FunnelContextValue } from '../components/FunnelContext.js';
|
|
3
3
|
import type { FunnelManifestExperiment } from '../config/funnel.manifest.types.js';
|
|
4
4
|
import type { FunnelUserAnswers } from '../sdk/userAnswers.js';
|
|
5
|
+
import { type FunnelUserAttribution } from './funnel-attribution.js';
|
|
5
6
|
import type { FunnelStepMeta } from '../steps/types.js';
|
|
6
7
|
export type FunnelFlowControllerExperiment<StepId extends string> = FunnelManifestExperiment & {
|
|
7
8
|
stepId: StepId;
|
|
@@ -18,6 +19,7 @@ type FunnelFlowAnalyticsAdapter = {
|
|
|
18
19
|
stepName: string;
|
|
19
20
|
stepType?: string;
|
|
20
21
|
startedAt: string;
|
|
22
|
+
metadata?: Record<string, unknown>;
|
|
21
23
|
featureFlags?: Record<string, string>;
|
|
22
24
|
}) => string | null;
|
|
23
25
|
trackStepCompleted?: (input: {
|
|
@@ -29,6 +31,7 @@ type FunnelFlowAnalyticsAdapter = {
|
|
|
29
31
|
startedAt: string;
|
|
30
32
|
endedAt: string;
|
|
31
33
|
selected?: Record<string, unknown>;
|
|
34
|
+
metadata?: Record<string, unknown>;
|
|
32
35
|
featureFlags?: Record<string, string>;
|
|
33
36
|
}) => string | null;
|
|
34
37
|
trackFunnelStarted?: (input: {
|
|
@@ -38,6 +41,7 @@ type FunnelFlowAnalyticsAdapter = {
|
|
|
38
41
|
stepName: string;
|
|
39
42
|
stepType?: string;
|
|
40
43
|
occurredAt: string;
|
|
44
|
+
metadata?: Record<string, unknown>;
|
|
41
45
|
featureFlags?: Record<string, string>;
|
|
42
46
|
}) => string | null;
|
|
43
47
|
trackFirstStepViewed?: (input: {
|
|
@@ -47,6 +51,7 @@ type FunnelFlowAnalyticsAdapter = {
|
|
|
47
51
|
stepName: string;
|
|
48
52
|
stepType?: string;
|
|
49
53
|
occurredAt: string;
|
|
54
|
+
metadata?: Record<string, unknown>;
|
|
50
55
|
featureFlags?: Record<string, string>;
|
|
51
56
|
}) => string | null;
|
|
52
57
|
};
|
|
@@ -99,8 +104,16 @@ type UseFunnelFlowControllerResult<StepId extends string> = {
|
|
|
99
104
|
setRuntimeMode: (mode: 'test' | 'live') => void;
|
|
100
105
|
showShellContinue: boolean;
|
|
101
106
|
};
|
|
107
|
+
export declare function resolveFunnelEventAttribution(document: unknown, provisionalAttribution: FunnelUserAttribution | null): FunnelUserAttribution | null;
|
|
108
|
+
export declare function buildReadyFunnelAttributionEventMetadata(attributionReady: boolean, attribution: FunnelUserAttribution | null): Record<string, string> | null;
|
|
109
|
+
export declare function scheduleAttributionFailOpen(onReady: () => void, timeoutMs: number): () => void;
|
|
110
|
+
export declare function takeInitialFunnelAttributionMetadata(tracked: boolean, attributionReady: boolean, attribution: FunnelUserAttribution | null): {
|
|
111
|
+
tracked: boolean;
|
|
112
|
+
metadata: Record<string, string> | null;
|
|
113
|
+
};
|
|
102
114
|
export declare function computeRenderSuspended(input: {
|
|
103
115
|
activeStepId: string;
|
|
116
|
+
attributionReady?: boolean;
|
|
104
117
|
postHogReady: boolean;
|
|
105
118
|
experiments: ReadonlyArray<{
|
|
106
119
|
stepId: string;
|
|
@@ -8,14 +8,38 @@ import { buildHostedStepLocation, dispatchWindowCustomEvent, } from './browser-h
|
|
|
8
8
|
import { isPreviewStepLockRequested, resolveNextStepFromContext, shouldRunAutoAdvanceTimer, } from './funnel-flow.js';
|
|
9
9
|
import { usePreviewBridge } from './preview-bridge.js';
|
|
10
10
|
import { resolveExperimentAssignment, resolveForcedExperimentAssignment, } from './experiment-assignment.js';
|
|
11
|
-
import { collectCurrentFunnelAttribution } from './funnel-attribution.js';
|
|
11
|
+
import { buildFunnelAttributionEventMetadata, collectCurrentFunnelAttribution, getFunnelUserAttribution, } from './funnel-attribution.js';
|
|
12
12
|
import { resolveUrlUserAttributes } from './url-user-attributes.js';
|
|
13
13
|
import { bootstrapPostHog, identifyPostHog, isPostHogReady, resolveExperimentVariant, } from './posthog-flags.js';
|
|
14
14
|
import { getRuntimeMode, isEditorEnabled, useRuntimeMode } from '../services/runtime-mode.service.js';
|
|
15
15
|
import { isPreviewFrameRuntime } from '../services/preview-frame.service.js';
|
|
16
|
+
export function resolveFunnelEventAttribution(document, provisionalAttribution) {
|
|
17
|
+
var _a;
|
|
18
|
+
return (_a = getFunnelUserAttribution(document)) !== null && _a !== void 0 ? _a : provisionalAttribution;
|
|
19
|
+
}
|
|
20
|
+
export function buildReadyFunnelAttributionEventMetadata(attributionReady, attribution) {
|
|
21
|
+
return attributionReady ? buildFunnelAttributionEventMetadata(attribution) : null;
|
|
22
|
+
}
|
|
23
|
+
export function scheduleAttributionFailOpen(onReady, timeoutMs) {
|
|
24
|
+
const timeoutId = setTimeout(onReady, timeoutMs);
|
|
25
|
+
return () => clearTimeout(timeoutId);
|
|
26
|
+
}
|
|
27
|
+
export function takeInitialFunnelAttributionMetadata(tracked, attributionReady, attribution) {
|
|
28
|
+
if (tracked) {
|
|
29
|
+
return { tracked, metadata: null };
|
|
30
|
+
}
|
|
31
|
+
const metadata = buildReadyFunnelAttributionEventMetadata(attributionReady, attribution);
|
|
32
|
+
return { tracked: metadata !== null, metadata };
|
|
33
|
+
}
|
|
16
34
|
export function computeRenderSuspended(input) {
|
|
17
35
|
var _a;
|
|
18
|
-
if (input.isPreviewRuntime
|
|
36
|
+
if (input.isPreviewRuntime) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
if (input.attributionReady === false) {
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
if (input.postHogReady) {
|
|
19
43
|
return false;
|
|
20
44
|
}
|
|
21
45
|
const activeExperiment = input.experiments.find((experiment) => experiment.stepId === input.activeStepId);
|
|
@@ -114,6 +138,7 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
114
138
|
completedSteps: [],
|
|
115
139
|
}));
|
|
116
140
|
const [userBootstrapped, setUserBootstrapped] = useState(isPreviewRuntime);
|
|
141
|
+
const [attributionReady, setAttributionReady] = useState(isPreviewRuntime);
|
|
117
142
|
const attributesAtStepStart = useRef({});
|
|
118
143
|
const attributesRef = useRef(attributes);
|
|
119
144
|
const postHogFeatureFlagsRef = useRef({});
|
|
@@ -121,14 +146,16 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
121
146
|
const firstStepViewedTrackedRef = useRef(false);
|
|
122
147
|
const stepStartedAtByIdRef = useRef({});
|
|
123
148
|
const currentUserIdRef = useRef(user.id);
|
|
149
|
+
const initialAttributionRef = useRef(null);
|
|
124
150
|
const safeActiveStepId = useMemo(() => { var _a; return (_a = resolveRenderableStepId(activeStepId)) !== null && _a !== void 0 ? _a : safeInitialStepId; }, [activeStepId, resolveRenderableStepId, safeInitialStepId]);
|
|
125
151
|
const activeStepMeta = stepById[safeActiveStepId];
|
|
126
152
|
const renderSuspended = useMemo(() => computeRenderSuspended({
|
|
127
153
|
activeStepId: safeActiveStepId,
|
|
154
|
+
attributionReady,
|
|
128
155
|
postHogReady,
|
|
129
156
|
experiments: funnelExperiments,
|
|
130
157
|
isPreviewRuntime,
|
|
131
|
-
}), [funnelExperiments, isPreviewRuntime, postHogReady, safeActiveStepId]);
|
|
158
|
+
}), [attributionReady, funnelExperiments, isPreviewRuntime, postHogReady, safeActiveStepId]);
|
|
132
159
|
const resolveExperimentVariantKey = useCallback((experiment) => {
|
|
133
160
|
var _a;
|
|
134
161
|
const override = editorVariantOverrides[experiment.experimentId];
|
|
@@ -189,22 +216,6 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
189
216
|
}
|
|
190
217
|
setActiveStepId(safeStepId);
|
|
191
218
|
}, [getPathForStep, resolveRenderableStepId, safeInitialStepId, shouldLockToInitialStep]);
|
|
192
|
-
useEffect(() => {
|
|
193
|
-
if (!activeExperimentForStep ||
|
|
194
|
-
renderSuspended ||
|
|
195
|
-
shouldLockToInitialStep ||
|
|
196
|
-
renderedStepId === safeActiveStepId) {
|
|
197
|
-
return;
|
|
198
|
-
}
|
|
199
|
-
goToStep(renderedStepId);
|
|
200
|
-
}, [
|
|
201
|
-
activeExperimentForStep,
|
|
202
|
-
goToStep,
|
|
203
|
-
renderSuspended,
|
|
204
|
-
renderedStepId,
|
|
205
|
-
safeActiveStepId,
|
|
206
|
-
shouldLockToInitialStep,
|
|
207
|
-
]);
|
|
208
219
|
const setAnswer = useCallback((key, value) => {
|
|
209
220
|
setAttributes((prev) => (Object.assign(Object.assign({}, prev), { [key]: value })));
|
|
210
221
|
}, []);
|
|
@@ -267,11 +278,13 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
267
278
|
const urlUserAttributes = resolveUrlUserAttributes();
|
|
268
279
|
const bootstrapCandidateUserId = apiService.getBootstrapCandidateUserId(localUserId);
|
|
269
280
|
const initialAttribution = collectCurrentFunnelAttribution();
|
|
281
|
+
initialAttributionRef.current = initialAttribution;
|
|
270
282
|
setUserBootstrapped(isPreviewRuntime);
|
|
271
283
|
setUser((prev) => (Object.assign(Object.assign({}, prev), { id: localUserId })));
|
|
272
284
|
if (isPreviewRuntime) {
|
|
273
285
|
return;
|
|
274
286
|
}
|
|
287
|
+
const cancelAttributionFailOpen = scheduleAttributionFailOpen(() => setAttributionReady(true), 5000);
|
|
275
288
|
const postHogBootstrap = bootstrapPostHog({
|
|
276
289
|
apiKey: POSTHOG_PROJECT_API_KEY,
|
|
277
290
|
apiHost: POSTHOG_API_HOST,
|
|
@@ -292,14 +305,17 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
292
305
|
attribution: initialAttribution,
|
|
293
306
|
})
|
|
294
307
|
.then((sessionUser) => {
|
|
308
|
+
cancelAttributionFailOpen();
|
|
295
309
|
const sessionAttributes = Object.keys(sessionUser.attributes || {}).length > 0
|
|
296
310
|
? sessionUser.attributes
|
|
297
311
|
: null;
|
|
298
312
|
if (sessionAttributes) {
|
|
299
313
|
setAttributes((prev) => (Object.assign(Object.assign({}, sessionAttributes), prev)));
|
|
300
314
|
}
|
|
315
|
+
initialAttributionRef.current = resolveFunnelEventAttribution(sessionUser.document, initialAttribution);
|
|
301
316
|
setUser((prev) => (Object.assign(Object.assign({}, prev), { id: sessionUser.id || prev.id, name: sessionUser.name || prev.name, email: sessionUser.email || prev.email, document: sessionUser.document, attributes: sessionAttributes ? Object.assign(Object.assign({}, sessionAttributes), prev.attributes) : prev.attributes })));
|
|
302
317
|
setUserBootstrapped(true);
|
|
318
|
+
setAttributionReady(true);
|
|
303
319
|
void apiService.pingUserContext(sessionUser.id)
|
|
304
320
|
.then((pingedUser) => {
|
|
305
321
|
if (!pingedUser) {
|
|
@@ -317,8 +333,10 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
317
333
|
return sessionUser;
|
|
318
334
|
})
|
|
319
335
|
.catch((error) => {
|
|
336
|
+
cancelAttributionFailOpen();
|
|
320
337
|
logger.error('Failed to bootstrap user session:', error);
|
|
321
338
|
setUserBootstrapped(false);
|
|
339
|
+
setAttributionReady(true);
|
|
322
340
|
return null;
|
|
323
341
|
});
|
|
324
342
|
Promise.all([postHogBootstrap, sessionBootstrap])
|
|
@@ -330,6 +348,7 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
330
348
|
.catch((error) => {
|
|
331
349
|
logger.error('Failed to identify PostHog user:', error);
|
|
332
350
|
});
|
|
351
|
+
return cancelAttributionFailOpen;
|
|
333
352
|
}, [isPreviewRuntime]);
|
|
334
353
|
const recordStepCompletion = useCallback((stepId, explicitChoices) => {
|
|
335
354
|
var _a;
|
|
@@ -337,6 +356,10 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
337
356
|
if (!meta) {
|
|
338
357
|
return;
|
|
339
358
|
}
|
|
359
|
+
const attributionMetadata = buildReadyFunnelAttributionEventMetadata(attributionReady, initialAttributionRef.current);
|
|
360
|
+
if (attributionMetadata === null) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
340
363
|
let choices;
|
|
341
364
|
if (explicitChoices) {
|
|
342
365
|
choices = explicitChoices;
|
|
@@ -370,6 +393,7 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
370
393
|
startedAt,
|
|
371
394
|
endedAt: record.completedAt,
|
|
372
395
|
selected: record.choices,
|
|
396
|
+
metadata: attributionMetadata,
|
|
373
397
|
featureFlags: postHogFeatureFlagsRef.current,
|
|
374
398
|
});
|
|
375
399
|
}
|
|
@@ -394,7 +418,7 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
394
418
|
}
|
|
395
419
|
return updatedUser;
|
|
396
420
|
});
|
|
397
|
-
}, [analytics, isPreviewRuntime, stepById]);
|
|
421
|
+
}, [analytics, attributionReady, isPreviewRuntime, stepById]);
|
|
398
422
|
const completeStep = useCallback((stepId, choices) => {
|
|
399
423
|
recordStepCompletion(stepId, choices);
|
|
400
424
|
}, [recordStepCompletion]);
|
|
@@ -420,6 +444,12 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
420
444
|
const stepType = renderedStepMeta === null || renderedStepMeta === void 0 ? void 0 : renderedStepMeta.type;
|
|
421
445
|
stepStartedAtByIdRef.current[renderedStepId] = startedAt;
|
|
422
446
|
const analyticsRuntimeMode = getRuntimeMode();
|
|
447
|
+
attributesAtStepStart.current = Object.assign({}, attributesRef.current);
|
|
448
|
+
prevStepIdRef.current = renderedStepId;
|
|
449
|
+
const attributionMetadata = buildReadyFunnelAttributionEventMetadata(attributionReady, initialAttributionRef.current);
|
|
450
|
+
if (attributionMetadata === null) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
423
453
|
if (!isPreviewRuntime) {
|
|
424
454
|
(_a = analytics === null || analytics === void 0 ? void 0 : analytics.trackStepStarted) === null || _a === void 0 ? void 0 : _a.call(analytics, {
|
|
425
455
|
userId: currentUserIdRef.current,
|
|
@@ -428,10 +458,15 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
428
458
|
stepName,
|
|
429
459
|
stepType,
|
|
430
460
|
startedAt,
|
|
461
|
+
metadata: attributionMetadata,
|
|
431
462
|
featureFlags: postHogFeatureFlagsRef.current,
|
|
432
463
|
});
|
|
433
464
|
if (!firstStepViewedTrackedRef.current && safeActiveStepId === defaultStepId) {
|
|
434
|
-
firstStepViewedTrackedRef.current
|
|
465
|
+
const initialAttribution = takeInitialFunnelAttributionMetadata(firstStepViewedTrackedRef.current, attributionReady, initialAttributionRef.current);
|
|
466
|
+
firstStepViewedTrackedRef.current = initialAttribution.tracked;
|
|
467
|
+
if (!initialAttribution.metadata) {
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
435
470
|
(_b = analytics === null || analytics === void 0 ? void 0 : analytics.trackFunnelStarted) === null || _b === void 0 ? void 0 : _b.call(analytics, {
|
|
436
471
|
userId: currentUserIdRef.current,
|
|
437
472
|
environment: analyticsRuntimeMode,
|
|
@@ -439,6 +474,7 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
439
474
|
stepName,
|
|
440
475
|
stepType,
|
|
441
476
|
occurredAt: startedAt,
|
|
477
|
+
metadata: initialAttribution.metadata,
|
|
442
478
|
featureFlags: postHogFeatureFlagsRef.current,
|
|
443
479
|
});
|
|
444
480
|
(_c = analytics === null || analytics === void 0 ? void 0 : analytics.trackFirstStepViewed) === null || _c === void 0 ? void 0 : _c.call(analytics, {
|
|
@@ -448,15 +484,15 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
448
484
|
stepName,
|
|
449
485
|
stepType,
|
|
450
486
|
occurredAt: startedAt,
|
|
487
|
+
metadata: initialAttribution.metadata,
|
|
451
488
|
featureFlags: postHogFeatureFlagsRef.current,
|
|
452
489
|
});
|
|
453
490
|
}
|
|
454
491
|
}
|
|
455
|
-
attributesAtStepStart.current = Object.assign({}, attributesRef.current);
|
|
456
|
-
prevStepIdRef.current = renderedStepId;
|
|
457
492
|
}, [
|
|
458
493
|
activeStepId,
|
|
459
494
|
analytics,
|
|
495
|
+
attributionReady,
|
|
460
496
|
defaultStepId,
|
|
461
497
|
isPreviewRuntime,
|
|
462
498
|
recordStepCompletion,
|
|
@@ -512,7 +548,7 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
512
548
|
safeActiveStepId,
|
|
513
549
|
safeInitialStepId,
|
|
514
550
|
]);
|
|
515
|
-
const choiceTargets = getChoiceTargetsForStep(
|
|
551
|
+
const choiceTargets = getChoiceTargetsForStep(renderedStepId);
|
|
516
552
|
const actionBar = (_a = renderedStepMeta === null || renderedStepMeta === void 0 ? void 0 : renderedStepMeta.actionBar) !== null && _a !== void 0 ? _a : activeStepMeta === null || activeStepMeta === void 0 ? void 0 : activeStepMeta.actionBar;
|
|
517
553
|
const isAutoAdvanceStep = typeof (actionBar === null || actionBar === void 0 ? void 0 : actionBar.autoAdvanceMs) === 'number';
|
|
518
554
|
const autoAdvanceMs = actionBar === null || actionBar === void 0 ? void 0 : actionBar.autoAdvanceMs;
|
|
@@ -551,12 +587,12 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
551
587
|
}, [goToStep, isFunnelStepId]);
|
|
552
588
|
const goChoice = useCallback((choice, stepId) => {
|
|
553
589
|
var _a, _b;
|
|
554
|
-
const sourceStepId = (_a = resolveRenderableStepId(stepId)) !== null && _a !== void 0 ? _a :
|
|
590
|
+
const sourceStepId = (_a = resolveRenderableStepId(stepId)) !== null && _a !== void 0 ? _a : renderedStepId;
|
|
555
591
|
setAttributes((prev) => writeStepChoice(prev, sourceStepId, choice));
|
|
556
592
|
const sourceChoiceTargets = getChoiceTargetsForStep(sourceStepId);
|
|
557
593
|
const choiceTarget = (_b = resolveRenderableStepId(sourceChoiceTargets === null || sourceChoiceTargets === void 0 ? void 0 : sourceChoiceTargets[choice])) !== null && _b !== void 0 ? _b : resolveNextStepId(sourceStepId);
|
|
558
594
|
goToStep(choiceTarget);
|
|
559
|
-
}, [getChoiceTargetsForStep, goToStep, resolveNextStepId, resolveRenderableStepId
|
|
595
|
+
}, [getChoiceTargetsForStep, goToStep, renderedStepId, resolveNextStepId, resolveRenderableStepId]);
|
|
560
596
|
usePreviewBridge({
|
|
561
597
|
activeStepId: safeActiveStepId,
|
|
562
598
|
onGoToStep: goToStepFromContext,
|
|
@@ -600,7 +636,7 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
600
636
|
return ((_a = experiment.variants[0]) === null || _a === void 0 ? void 0 : _a.variantKey) || '';
|
|
601
637
|
}, [editorVariantOverrides, postHogReady]);
|
|
602
638
|
const contextValue = useMemo(() => ({
|
|
603
|
-
activeStepId:
|
|
639
|
+
activeStepId: renderedStepId,
|
|
604
640
|
featureFlags: postHogFeatureFlags,
|
|
605
641
|
isBuilder: isPreviewRuntime,
|
|
606
642
|
goToStep: goToStepFromContext,
|
|
@@ -608,7 +644,7 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
608
644
|
goChoice,
|
|
609
645
|
getChoiceTargets: (stepId) => {
|
|
610
646
|
var _a;
|
|
611
|
-
const sourceStepId = (_a = resolveRenderableStepId(stepId)) !== null && _a !== void 0 ? _a :
|
|
647
|
+
const sourceStepId = (_a = resolveRenderableStepId(stepId)) !== null && _a !== void 0 ? _a : renderedStepId;
|
|
612
648
|
return getChoiceTargetsForStep(sourceStepId);
|
|
613
649
|
},
|
|
614
650
|
setAnswer,
|
|
@@ -630,8 +666,8 @@ export function useFunnelFlowController({ analytics, initialStepId, initialAttri
|
|
|
630
666
|
goToStepFromContext,
|
|
631
667
|
isPreviewRuntime,
|
|
632
668
|
postHogFeatureFlags,
|
|
669
|
+
renderedStepId,
|
|
633
670
|
resolveRenderableStepId,
|
|
634
|
-
safeActiveStepId,
|
|
635
671
|
setAnswer,
|
|
636
672
|
setAttribute,
|
|
637
673
|
user,
|