@funnelsgrove/runtime 0.1.29 → 0.1.31

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.
@@ -3,6 +3,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useMemo, useState } from 'react';
4
4
  import { clearPaywallStateValue } from '../services/funnel-state.service.js';
5
5
  import { RUNTIME_PUBLIC_ENV_KEYS, runtimePublicConfig, } from '../services/public-env.js';
6
+ import { isPreviewFrameRuntimeSearch } from '../services/preview-frame.service.js';
6
7
  const normalizeDisplayValue = (value) => {
7
8
  if (value === null || typeof value === 'undefined' || value === '') {
8
9
  return '(empty)';
@@ -19,6 +20,19 @@ const runtimePublicConfigEntries = () => {
19
20
  const canUseDom = () => {
20
21
  return typeof window !== 'undefined';
21
22
  };
23
+ const isRuntimeDevInfoHidden = () => {
24
+ if (!canUseDom()) {
25
+ return false;
26
+ }
27
+ try {
28
+ const search = window.location.search;
29
+ return (new URLSearchParams(search).get('hideRuntimeDevTools') === '1' ||
30
+ isPreviewFrameRuntimeSearch(search));
31
+ }
32
+ catch (_a) {
33
+ return false;
34
+ }
35
+ };
22
36
  export const copyRuntimeDevInfoValue = async (value) => {
23
37
  var _a, _b;
24
38
  if (!value || value === '(empty)') {
@@ -65,7 +79,7 @@ export function RuntimeDevInfoBox({ runtimeMode, user, onSwitchToLiveMode, confi
65
79
  const [copiedKey, setCopiedKey] = useState(null);
66
80
  const [resetDone, setResetDone] = useState(false);
67
81
  const configItems = useMemo(() => [...configValues, ...runtimePublicConfigEntries()], [configValues]);
68
- if (runtimeMode !== 'test') {
82
+ if (runtimeMode !== 'test' || isRuntimeDevInfoHidden()) {
69
83
  return null;
70
84
  }
71
85
  const markCopied = (key) => {
@@ -4,6 +4,8 @@ type BootstrapConfig = {
4
4
  apiKey: string;
5
5
  apiHost: string;
6
6
  distinctId: string;
7
+ projectId?: string;
8
+ funnelId?: string;
7
9
  };
8
10
  export declare const bootstrapPostHog: (config: BootstrapConfig) => Promise<void>;
9
11
  export declare const isPostHogReady: () => boolean;
@@ -2,6 +2,19 @@ import posthog from 'posthog-js';
2
2
  let initialized = false;
3
3
  let readyPromise = null;
4
4
  export const POSTHOG_FEATURE_FLAG_READY_TIMEOUT_MS = 2500;
5
+ const buildFlagScopeProperties = (config) => {
6
+ var _a, _b;
7
+ const properties = {};
8
+ const projectId = (_a = config.projectId) === null || _a === void 0 ? void 0 : _a.trim();
9
+ const funnelId = (_b = config.funnelId) === null || _b === void 0 ? void 0 : _b.trim();
10
+ if (projectId) {
11
+ properties.project_id = projectId;
12
+ }
13
+ if (funnelId) {
14
+ properties.funnel_id = funnelId;
15
+ }
16
+ return properties;
17
+ };
5
18
  export const bootstrapPostHog = (config) => {
6
19
  if (readyPromise) {
7
20
  return readyPromise;
@@ -27,13 +40,19 @@ export const bootstrapPostHog = (config) => {
27
40
  api_host: config.apiHost,
28
41
  persistence: 'localStorage+cookie',
29
42
  person_profiles: 'identified_only',
43
+ advanced_disable_feature_flags_on_first_load: true,
30
44
  bootstrap: { distinctID: config.distinctId },
31
45
  loaded: () => {
46
+ const scopeProperties = buildFlagScopeProperties(config);
47
+ if (Object.keys(scopeProperties).length > 0) {
48
+ posthog.setPersonPropertiesForFlags(scopeProperties, false);
49
+ }
32
50
  let unsubscribe = null;
33
51
  unsubscribe = posthog.onFeatureFlags(() => {
34
52
  unsubscribe === null || unsubscribe === void 0 ? void 0 : unsubscribe();
35
53
  markReady();
36
54
  });
55
+ posthog.reloadFeatureFlags();
37
56
  },
38
57
  });
39
58
  });
@@ -275,6 +275,8 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
275
275
  apiKey: POSTHOG_PROJECT_API_KEY,
276
276
  apiHost: POSTHOG_API_HOST,
277
277
  distinctId: localUserId,
278
+ projectId: PROJECT_ID,
279
+ funnelId: FUNNEL_ID,
278
280
  })
279
281
  .then(() => setPostHogReady(true))
280
282
  .catch((error) => {
@@ -352,6 +354,7 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
352
354
  completedAt: new Date().toISOString(),
353
355
  choices,
354
356
  };
357
+ const stepType = meta.type;
355
358
  const startedAt = stepStartedAtByIdRef.current[meta.id] || record.completedAt;
356
359
  const durationMs = Math.max(0, new Date(record.completedAt).getTime() - new Date(startedAt).getTime());
357
360
  dispatchWindowCustomEvent('funnel:step-completed', record);
@@ -360,11 +363,12 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
360
363
  userId: currentUserIdRef.current,
361
364
  stepId: record.stepId,
362
365
  stepName: record.stepName,
366
+ stepType,
363
367
  startedAt,
364
368
  endedAt: record.completedAt,
365
369
  selected: record.choices,
366
370
  });
367
- 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)));
371
+ 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, step_type: stepType, started_at: startedAt, ended_at: record.completedAt, duration_ms: Number.isFinite(durationMs) ? durationMs : undefined, selected: record.choices }, buildFeatureFlagProperties(postHogFeatureFlagsRef.current)));
368
372
  }
369
373
  setUser((prev) => {
370
374
  var _a, _b;
@@ -410,15 +414,17 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
410
414
  }
411
415
  const startedAt = new Date().toISOString();
412
416
  const stepName = (renderedStepMeta === null || renderedStepMeta === void 0 ? void 0 : renderedStepMeta.name) || (renderedStepMeta === null || renderedStepMeta === void 0 ? void 0 : renderedStepMeta.title) || renderedStepId;
417
+ const stepType = renderedStepMeta === null || renderedStepMeta === void 0 ? void 0 : renderedStepMeta.type;
413
418
  stepStartedAtByIdRef.current[renderedStepId] = startedAt;
414
419
  if (!isPreviewRuntime) {
415
420
  apiService.trackStepStarted({
416
421
  userId: currentUserIdRef.current,
417
422
  stepId: renderedStepId,
418
423
  stepName,
424
+ stepType,
419
425
  startedAt,
420
426
  });
421
- 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)));
427
+ 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, step_type: stepType, started_at: startedAt }, buildFeatureFlagProperties(postHogFeatureFlagsRef.current)));
422
428
  if (!firstStepViewedTrackedRef.current && safeActiveStepId === defaultStepId) {
423
429
  firstStepViewedTrackedRef.current = true;
424
430
  (_a = analytics === null || analytics === void 0 ? void 0 : analytics.trackFirstStepViewed) === null || _a === void 0 ? void 0 : _a.call(analytics, {
@@ -439,6 +445,7 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
439
445
  const engagedStepId = renderedStepId;
440
446
  const engagedStartedAt = startedAt;
441
447
  const engagedStepName = stepName;
448
+ const engagedStepType = stepType;
442
449
  const timer = window.setTimeout(() => {
443
450
  if (prevStepIdRef.current !== engagedStepId || engagedStepIdsRef.current.has(engagedStepId)) {
444
451
  return;
@@ -450,6 +457,7 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
450
457
  eventType: 'step_engaged',
451
458
  stepId: engagedStepId,
452
459
  stepName: engagedStepName,
460
+ stepType: engagedStepType,
453
461
  startedAt: engagedStartedAt,
454
462
  endedAt: engagedAt,
455
463
  metadata: {
@@ -457,7 +465,7 @@ export function useFunnelFlowController({ analytics, initialStepId, lockToInitia
457
465
  engagementThresholdMs: FIRST_STEP_ENGAGEMENT_THRESHOLD_MS,
458
466
  },
459
467
  });
460
- 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)));
468
+ 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, step_type: engagedStepType, started_at: engagedStartedAt, ended_at: engagedAt, duration_ms: FIRST_STEP_ENGAGEMENT_THRESHOLD_MS, engagement_threshold_ms: FIRST_STEP_ENGAGEMENT_THRESHOLD_MS }, buildFeatureFlagProperties(postHogFeatureFlagsRef.current)));
461
469
  }, FIRST_STEP_ENGAGEMENT_THRESHOLD_MS);
462
470
  return () => window.clearTimeout(timer);
463
471
  }, [
@@ -16,6 +16,7 @@ export type FunnelEvent = {
16
16
  eventType: string;
17
17
  stepId?: string;
18
18
  stepName?: string;
19
+ stepType?: string;
19
20
  startedAt?: string;
20
21
  endedAt?: string;
21
22
  selected?: Record<string, unknown>;
@@ -25,6 +26,7 @@ export type StepCompletionEvent = {
25
26
  userId: string;
26
27
  stepId: string;
27
28
  stepName: string;
29
+ stepType?: string;
28
30
  startedAt: string;
29
31
  endedAt: string;
30
32
  selected: Record<string, unknown>;
@@ -104,6 +106,7 @@ declare class ApiService {
104
106
  userId: string;
105
107
  stepId: string;
106
108
  stepName: string;
109
+ stepType?: string;
107
110
  startedAt: string;
108
111
  }): void;
109
112
  trackStepCompleted(event: StepCompletionEvent): void;
@@ -493,6 +493,7 @@ class ApiService {
493
493
  eventType: 'step_start',
494
494
  stepId: input.stepId,
495
495
  stepName: input.stepName,
496
+ stepType: input.stepType,
496
497
  startedAt: input.startedAt,
497
498
  });
498
499
  }
@@ -502,6 +503,7 @@ class ApiService {
502
503
  eventType: 'step_end',
503
504
  stepId: event.stepId,
504
505
  stepName: event.stepName,
506
+ stepType: event.stepType,
505
507
  startedAt: event.startedAt,
506
508
  endedAt: event.endedAt,
507
509
  selected: event.selected,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@funnelsgrove/runtime",
3
- "version": "0.1.29",
3
+ "version": "0.1.31",
4
4
  "type": "module",
5
5
  "private": false,
6
6
  "main": "./dist/index.js",