@funnelsgrove/runtime 0.1.17 → 0.1.19
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/dist/config/builder-preview.protocol.d.ts +5 -0
- package/dist/config/builder-preview.protocol.js +1 -0
- package/dist/runtime/preview-bridge.d.ts +4 -0
- package/dist/runtime/preview-bridge.js +36 -4
- package/dist/runtime/use-funnel-flow-controller.d.ts +10 -1
- package/dist/runtime/use-funnel-flow-controller.js +16 -4
- package/dist/services/api.service.d.ts +7 -0
- package/dist/services/api.service.js +52 -1
- package/package.json +1 -1
|
@@ -5,6 +5,7 @@ export declare const BUILDER_PREVIEW_RUNTIME_MODE_CHANGED = "builder.preview.run
|
|
|
5
5
|
export declare const BUILDER_PREVIEW_DEFINITION_PATCH = "builder.preview.definitionPatch";
|
|
6
6
|
export declare const BUILDER_PREVIEW_VARIABLE_VALUES_CHANGED = "builder.preview.variableValuesChanged";
|
|
7
7
|
export declare const BUILDER_PREVIEW_PAYWALL_PLANS_CHANGED = "builder.preview.paywallPlansChanged";
|
|
8
|
+
export declare const BUILDER_PREVIEW_THEME_CHANGED = "builder.preview.themeChanged";
|
|
8
9
|
export type BuilderPreviewReadyMessage = {
|
|
9
10
|
type: typeof BUILDER_PREVIEW_READY;
|
|
10
11
|
stepId: string;
|
|
@@ -75,3 +76,7 @@ export type BuilderPreviewPaywallPlansChangedMessage = {
|
|
|
75
76
|
stepId: string;
|
|
76
77
|
plans: BuilderPreviewPaywallPlan[];
|
|
77
78
|
};
|
|
79
|
+
export type BuilderPreviewThemeChangedMessage = {
|
|
80
|
+
type: typeof BUILDER_PREVIEW_THEME_CHANGED;
|
|
81
|
+
cssVariables: Record<string, string>;
|
|
82
|
+
};
|
|
@@ -5,3 +5,4 @@ export const BUILDER_PREVIEW_RUNTIME_MODE_CHANGED = 'builder.preview.runtimeMode
|
|
|
5
5
|
export const BUILDER_PREVIEW_DEFINITION_PATCH = 'builder.preview.definitionPatch';
|
|
6
6
|
export const BUILDER_PREVIEW_VARIABLE_VALUES_CHANGED = 'builder.preview.variableValuesChanged';
|
|
7
7
|
export const BUILDER_PREVIEW_PAYWALL_PLANS_CHANGED = 'builder.preview.paywallPlansChanged';
|
|
8
|
+
export const BUILDER_PREVIEW_THEME_CHANGED = 'builder.preview.themeChanged';
|
|
@@ -41,12 +41,16 @@ type PreviewBridgeMessage = {
|
|
|
41
41
|
kind: 'paywallPlansChanged';
|
|
42
42
|
stepId: string;
|
|
43
43
|
plans: BuilderPreviewPaywallPlan[];
|
|
44
|
+
} | {
|
|
45
|
+
kind: 'themeChanged';
|
|
46
|
+
cssVariables: Record<string, string>;
|
|
44
47
|
} | {
|
|
45
48
|
kind: 'goToStep';
|
|
46
49
|
stepId: string;
|
|
47
50
|
};
|
|
48
51
|
export declare const parsePreviewQuickEditPatch: (value: unknown) => PreviewQuickEditPatch | null;
|
|
49
52
|
export declare const parsePreviewBridgeMessage: (value: unknown) => PreviewBridgeMessage | null;
|
|
53
|
+
export declare const applyPreviewThemeVariables: (cssVariables: Record<string, string>) => void;
|
|
50
54
|
export declare const applyPreviewQuickEditPatch: (patch: PreviewQuickEditPatch) => void;
|
|
51
55
|
export declare function emitPreviewVariableValues(stepId: FunnelStepId, values: Record<string, string>): void;
|
|
52
56
|
export declare function usePreviewVariableValues(stepId: FunnelStepId, values: Record<string, string>): void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { useEffect, useRef } from 'react';
|
|
3
|
-
import { BUILDER_PREVIEW_ACTIVE_STEP_CHANGED, BUILDER_PREVIEW_DEFINITION_PATCH, BUILDER_PREVIEW_GO_TO_STEP, BUILDER_PREVIEW_PAYWALL_PLANS_CHANGED, BUILDER_PREVIEW_READY, BUILDER_PREVIEW_RUNTIME_MODE_CHANGED, BUILDER_PREVIEW_VARIABLE_VALUES_CHANGED, } from '../config/builder-preview.protocol.js';
|
|
3
|
+
import { BUILDER_PREVIEW_ACTIVE_STEP_CHANGED, BUILDER_PREVIEW_DEFINITION_PATCH, BUILDER_PREVIEW_GO_TO_STEP, BUILDER_PREVIEW_PAYWALL_PLANS_CHANGED, BUILDER_PREVIEW_READY, BUILDER_PREVIEW_RUNTIME_MODE_CHANGED, BUILDER_PREVIEW_THEME_CHANGED, BUILDER_PREVIEW_VARIABLE_VALUES_CHANGED, } from '../config/builder-preview.protocol.js';
|
|
4
4
|
import { isPreviewFrameRuntime } from '../services/preview-frame.service.js';
|
|
5
5
|
import { logger } from '../services/logger.js';
|
|
6
6
|
import { applyPreviewDefinitionPatch, applyPreviewPaywallPlansPatch } from './preview-definition-overrides.js';
|
|
@@ -107,6 +107,13 @@ export const parsePreviewQuickEditPatch = (value) => {
|
|
|
107
107
|
}
|
|
108
108
|
return null;
|
|
109
109
|
};
|
|
110
|
+
const parseThemeCssVariables = (value) => {
|
|
111
|
+
if (!isRecord(value)) {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
const cssVariables = Object.fromEntries(Object.entries(value).filter((entry) => entry[0].startsWith('--') && typeof entry[1] === 'string'));
|
|
115
|
+
return Object.keys(cssVariables).length > 0 ? cssVariables : null;
|
|
116
|
+
};
|
|
110
117
|
export const parsePreviewBridgeMessage = (value) => {
|
|
111
118
|
if (!isRecord(value)) {
|
|
112
119
|
return null;
|
|
@@ -149,12 +156,33 @@ export const parsePreviewBridgeMessage = (value) => {
|
|
|
149
156
|
}
|
|
150
157
|
: null;
|
|
151
158
|
}
|
|
159
|
+
if (messageType === BUILDER_PREVIEW_THEME_CHANGED) {
|
|
160
|
+
const cssVariables = parseThemeCssVariables(value.cssVariables);
|
|
161
|
+
return cssVariables ? { kind: 'themeChanged', cssVariables } : null;
|
|
162
|
+
}
|
|
152
163
|
if (messageType === BUILDER_PREVIEW_GO_TO_STEP) {
|
|
153
164
|
const stepId = typeof value.stepId === 'string' ? value.stepId.trim() : '';
|
|
154
165
|
return stepId ? { kind: 'goToStep', stepId } : null;
|
|
155
166
|
}
|
|
156
167
|
return null;
|
|
157
168
|
};
|
|
169
|
+
export const applyPreviewThemeVariables = (cssVariables) => {
|
|
170
|
+
if (typeof document === 'undefined') {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const targets = [
|
|
174
|
+
document.documentElement,
|
|
175
|
+
document.body,
|
|
176
|
+
...Array.from(document.querySelectorAll('.page-root')),
|
|
177
|
+
].filter((target) => Boolean(target));
|
|
178
|
+
for (const target of targets) {
|
|
179
|
+
for (const [key, value] of Object.entries(cssVariables)) {
|
|
180
|
+
if (key.startsWith('--')) {
|
|
181
|
+
target.style.setProperty(key, value);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
};
|
|
158
186
|
export const applyPreviewQuickEditPatch = (patch) => {
|
|
159
187
|
if (typeof document === 'undefined') {
|
|
160
188
|
return;
|
|
@@ -271,9 +299,6 @@ export function usePreviewBridge({ activeStepId, onGoToStep, resolveRenderableSt
|
|
|
271
299
|
emitPreviewReady(activeStepId);
|
|
272
300
|
}, [activeStepId]);
|
|
273
301
|
useEffect(() => {
|
|
274
|
-
if (shouldLockToInitialStep) {
|
|
275
|
-
return;
|
|
276
|
-
}
|
|
277
302
|
const handlePreviewMessage = (event) => {
|
|
278
303
|
const action = parsePreviewBridgeMessage(event.data);
|
|
279
304
|
if (!action) {
|
|
@@ -294,10 +319,17 @@ export function usePreviewBridge({ activeStepId, onGoToStep, resolveRenderableSt
|
|
|
294
319
|
applyPreviewPaywallPlansPatch(action.stepId, action.plans);
|
|
295
320
|
return;
|
|
296
321
|
}
|
|
322
|
+
if (action.kind === 'themeChanged') {
|
|
323
|
+
applyPreviewThemeVariables(action.cssVariables);
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
297
326
|
if (action.kind === 'runtimeModeChanged') {
|
|
298
327
|
setRuntimeMode(action.mode);
|
|
299
328
|
return;
|
|
300
329
|
}
|
|
330
|
+
if (shouldLockToInitialStep) {
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
301
333
|
const targetStepId = resolveRenderableStepId(action.stepId);
|
|
302
334
|
if (!targetStepId) {
|
|
303
335
|
logger.warn({
|
|
@@ -9,7 +9,16 @@ export type FunnelFlowControllerExperiment<StepId extends string> = FunnelManife
|
|
|
9
9
|
})[];
|
|
10
10
|
};
|
|
11
11
|
type StepComponentRegistry = Record<string, unknown>;
|
|
12
|
+
type FunnelFlowAnalyticsAdapter = {
|
|
13
|
+
trackFirstStepViewed?: (input: {
|
|
14
|
+
stepId: string;
|
|
15
|
+
stepName: string;
|
|
16
|
+
occurredAt: string;
|
|
17
|
+
featureFlags?: Record<string, string>;
|
|
18
|
+
}) => string | null;
|
|
19
|
+
};
|
|
12
20
|
type UseFunnelFlowControllerInput<StepId extends string> = {
|
|
21
|
+
analytics?: FunnelFlowAnalyticsAdapter;
|
|
13
22
|
initialStepId?: StepId;
|
|
14
23
|
lockToInitialStep?: boolean;
|
|
15
24
|
defaultStepId: StepId;
|
|
@@ -63,5 +72,5 @@ export declare function computeRenderSuspended(input: {
|
|
|
63
72
|
}>;
|
|
64
73
|
isPreviewRuntime?: boolean;
|
|
65
74
|
}): boolean;
|
|
66
|
-
export declare function useFunnelFlowController<StepId extends string>({ initialStepId, lockToInitialStep, defaultStepId, stepSequence, stepById, stepComponentById, funnelExperiments, getPathForStep, getStepIdFromPath, getSequentialNextStepId, getChoiceTargetsForStep, isFunnelStepId, resolveConfiguredNextStep, resolveRuntimeInitialStepId, }: UseFunnelFlowControllerInput<StepId>): UseFunnelFlowControllerResult<StepId>;
|
|
75
|
+
export declare function useFunnelFlowController<StepId extends string>({ analytics, initialStepId, lockToInitialStep, defaultStepId, stepSequence, stepById, stepComponentById, funnelExperiments, getPathForStep, getStepIdFromPath, getSequentialNextStepId, getChoiceTargetsForStep, isFunnelStepId, resolveConfiguredNextStep, resolveRuntimeInitialStepId, }: UseFunnelFlowControllerInput<StepId>): UseFunnelFlowControllerResult<StepId>;
|
|
67
76
|
export {};
|
|
@@ -54,7 +54,7 @@ export function computeRenderSuspended(input) {
|
|
|
54
54
|
}
|
|
55
55
|
return input.experiments.some((experiment) => experiment.stepId === input.activeStepId);
|
|
56
56
|
}
|
|
57
|
-
export function useFunnelFlowController({ initialStepId, lockToInitialStep = false, defaultStepId, stepSequence, stepById, stepComponentById, funnelExperiments, getPathForStep, getStepIdFromPath, getSequentialNextStepId, getChoiceTargetsForStep, isFunnelStepId, resolveConfiguredNextStep, resolveRuntimeInitialStepId, }) {
|
|
57
|
+
export function useFunnelFlowController({ analytics, initialStepId, lockToInitialStep = false, defaultStepId, stepSequence, stepById, stepComponentById, funnelExperiments, getPathForStep, getStepIdFromPath, getSequentialNextStepId, getChoiceTargetsForStep, isFunnelStepId, resolveConfiguredNextStep, resolveRuntimeInitialStepId, }) {
|
|
58
58
|
var _a, _b;
|
|
59
59
|
const [runtimeMode, setRuntimeMode] = useRuntimeMode();
|
|
60
60
|
const [editorModeEnabled, setEditorModeEnabled] = useState(false);
|
|
@@ -106,6 +106,7 @@ export function useFunnelFlowController({ initialStepId, lockToInitialStep = fal
|
|
|
106
106
|
const attributesRef = useRef(attributes);
|
|
107
107
|
const postHogFeatureFlagsRef = useRef({});
|
|
108
108
|
const prevStepIdRef = useRef(null);
|
|
109
|
+
const firstStepViewedTrackedRef = useRef(false);
|
|
109
110
|
const stepStartedAtByIdRef = useRef({});
|
|
110
111
|
const engagedStepIdsRef = useRef(new Set());
|
|
111
112
|
const currentUserIdRef = useRef(user.id);
|
|
@@ -340,7 +341,7 @@ export function useFunnelFlowController({ initialStepId, lockToInitialStep = fal
|
|
|
340
341
|
endedAt: record.completedAt,
|
|
341
342
|
selected: record.choices,
|
|
342
343
|
});
|
|
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)));
|
|
344
|
+
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
345
|
}
|
|
345
346
|
setUser((prev) => {
|
|
346
347
|
var _a, _b;
|
|
@@ -368,6 +369,7 @@ export function useFunnelFlowController({ initialStepId, lockToInitialStep = fal
|
|
|
368
369
|
recordStepCompletion(stepId, choices);
|
|
369
370
|
}, [recordStepCompletion]);
|
|
370
371
|
useEffect(() => {
|
|
372
|
+
var _a;
|
|
371
373
|
if (safeActiveStepId !== activeStepId) {
|
|
372
374
|
logger.warn(`[FunnelFlow] Unknown or non-renderable step "${activeStepId}", falling back to "${safeActiveStepId}".`);
|
|
373
375
|
setActiveStepId(safeActiveStepId);
|
|
@@ -390,7 +392,16 @@ export function useFunnelFlowController({ initialStepId, lockToInitialStep = fal
|
|
|
390
392
|
stepName,
|
|
391
393
|
startedAt,
|
|
392
394
|
});
|
|
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)));
|
|
395
|
+
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)));
|
|
396
|
+
if (!firstStepViewedTrackedRef.current && safeActiveStepId === defaultStepId) {
|
|
397
|
+
firstStepViewedTrackedRef.current = true;
|
|
398
|
+
(_a = analytics === null || analytics === void 0 ? void 0 : analytics.trackFirstStepViewed) === null || _a === void 0 ? void 0 : _a.call(analytics, {
|
|
399
|
+
stepId: renderedStepId,
|
|
400
|
+
stepName,
|
|
401
|
+
occurredAt: startedAt,
|
|
402
|
+
featureFlags: postHogFeatureFlagsRef.current,
|
|
403
|
+
});
|
|
404
|
+
}
|
|
394
405
|
}
|
|
395
406
|
attributesAtStepStart.current = Object.assign({}, attributesRef.current);
|
|
396
407
|
prevStepIdRef.current = renderedStepId;
|
|
@@ -420,11 +431,12 @@ export function useFunnelFlowController({ initialStepId, lockToInitialStep = fal
|
|
|
420
431
|
engagementThresholdMs: FIRST_STEP_ENGAGEMENT_THRESHOLD_MS,
|
|
421
432
|
},
|
|
422
433
|
});
|
|
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)));
|
|
434
|
+
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
435
|
}, FIRST_STEP_ENGAGEMENT_THRESHOLD_MS);
|
|
425
436
|
return () => window.clearTimeout(timer);
|
|
426
437
|
}, [
|
|
427
438
|
activeStepId,
|
|
439
|
+
analytics,
|
|
428
440
|
defaultStepId,
|
|
429
441
|
isPreviewRuntime,
|
|
430
442
|
recordStepCompletion,
|
|
@@ -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
|
}),
|