@funnelsgrove/runtime 0.7.12 → 0.7.14
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/env.config.d.ts +2 -0
- package/dist/config/env.config.js +4 -0
- package/dist/runtime/funnel-attribution.js +19 -1
- package/dist/runtime/posthog-flags.d.ts +1 -0
- package/dist/runtime/posthog-flags.js +18 -1
- package/dist/runtime/use-funnel-flow-controller.js +12 -3
- package/dist/services/project-env.d.ts +2 -0
- package/dist/services/project-env.js +4 -0
- package/dist/services/public-env.d.ts +4 -0
- package/dist/services/public-env.js +5 -0
- package/package.json +1 -1
|
@@ -7,6 +7,8 @@ export declare const RUNTIME_ENV_KEYS: {
|
|
|
7
7
|
readonly projectId: "NEXT_PUBLIC_PROJECT_ID";
|
|
8
8
|
readonly funnelVersionId: "NEXT_PUBLIC_FUNNEL_VERSION_ID";
|
|
9
9
|
readonly posthogProjectApiKey: "NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY";
|
|
10
|
+
readonly posthogSessionReplayEnabled: "NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_ENABLED";
|
|
11
|
+
readonly posthogSessionReplaySampleRate: "NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_SAMPLE_RATE";
|
|
10
12
|
readonly supportEmail: "NEXT_PUBLIC_FUNNEL_SUPPORT_EMAIL";
|
|
11
13
|
readonly iosAppStoreUrl: "NEXT_PUBLIC_IOS_APP_STORE_URL";
|
|
12
14
|
readonly androidPlayStoreUrl: "NEXT_PUBLIC_ANDROID_PLAY_STORE_URL";
|
|
@@ -18,6 +18,8 @@ export const RUNTIME_ENV_KEYS = {
|
|
|
18
18
|
projectId: 'NEXT_PUBLIC_PROJECT_ID',
|
|
19
19
|
funnelVersionId: 'NEXT_PUBLIC_FUNNEL_VERSION_ID',
|
|
20
20
|
posthogProjectApiKey: 'NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY',
|
|
21
|
+
posthogSessionReplayEnabled: 'NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_ENABLED',
|
|
22
|
+
posthogSessionReplaySampleRate: 'NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_SAMPLE_RATE',
|
|
21
23
|
supportEmail: 'NEXT_PUBLIC_FUNNEL_SUPPORT_EMAIL',
|
|
22
24
|
iosAppStoreUrl: 'NEXT_PUBLIC_IOS_APP_STORE_URL',
|
|
23
25
|
androidPlayStoreUrl: 'NEXT_PUBLIC_ANDROID_PLAY_STORE_URL',
|
|
@@ -79,6 +81,8 @@ const RUNTIME_ENV_VALUES = {
|
|
|
79
81
|
NEXT_PUBLIC_FUNNEL_VERSION_ID: readRuntimeEnv(() => process.env.NEXT_PUBLIC_FUNNEL_VERSION_ID),
|
|
80
82
|
NEXT_PUBLIC_PROJECT_ID: readRuntimeEnv(() => process.env.NEXT_PUBLIC_PROJECT_ID),
|
|
81
83
|
NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY: readRuntimeEnv(() => process.env.NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY),
|
|
84
|
+
NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_ENABLED: readRuntimeEnv(() => process.env.NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_ENABLED),
|
|
85
|
+
NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_SAMPLE_RATE: readRuntimeEnv(() => process.env.NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_SAMPLE_RATE),
|
|
82
86
|
NEXT_PUBLIC_FUNNEL_SUPPORT_EMAIL: readRuntimeEnv(() => process.env.NEXT_PUBLIC_FUNNEL_SUPPORT_EMAIL),
|
|
83
87
|
NEXT_PUBLIC_IOS_APP_STORE_URL: readRuntimeEnv(() => process.env.NEXT_PUBLIC_IOS_APP_STORE_URL),
|
|
84
88
|
NEXT_PUBLIC_ANDROID_PLAY_STORE_URL: readRuntimeEnv(() => process.env.NEXT_PUBLIC_ANDROID_PLAY_STORE_URL),
|
|
@@ -28,7 +28,25 @@ const EVENT_ATTRIBUTION_FILTER_KEYS = new Set([
|
|
|
28
28
|
'utm_campaign',
|
|
29
29
|
'utm_content',
|
|
30
30
|
'utm_term',
|
|
31
|
+
'utm_id',
|
|
32
|
+
'utm_ad',
|
|
33
|
+
'utm_adset',
|
|
34
|
+
'campaign_id',
|
|
35
|
+
'campaign_name',
|
|
36
|
+
'facebook_campaign_id',
|
|
31
37
|
'adset_id',
|
|
38
|
+
'adset_name',
|
|
39
|
+
'ad_set_id',
|
|
40
|
+
'facebook_adset_id',
|
|
41
|
+
'ad_id',
|
|
42
|
+
'ad_name',
|
|
43
|
+
'facebook_ad_id',
|
|
44
|
+
'creative_id',
|
|
45
|
+
'creative_name',
|
|
46
|
+
'facebook_creative_id',
|
|
47
|
+
'placement',
|
|
48
|
+
'site_source_name',
|
|
49
|
+
'media_source',
|
|
32
50
|
]);
|
|
33
51
|
const MAX_EVENT_ATTRIBUTION_FILTER_VALUE_CODE_POINTS = 256;
|
|
34
52
|
const POSTHOG_CONTEXT_MAPPINGS = {
|
|
@@ -257,7 +275,7 @@ export const mergeFunnelUserAttribution = (current, incoming) => {
|
|
|
257
275
|
context: deepMergeRecords(currentContext, nextContext),
|
|
258
276
|
};
|
|
259
277
|
};
|
|
260
|
-
export const buildFunnelAttributionEventMetadata = (attribution) => normalizeEventAttributionTouch(attribution === null || attribution === void 0 ? void 0 : attribution.
|
|
278
|
+
export const buildFunnelAttributionEventMetadata = (attribution) => normalizeEventAttributionTouch(attribution === null || attribution === void 0 ? void 0 : attribution.lastTouch);
|
|
261
279
|
export const getFunnelUserAttribution = (document) => {
|
|
262
280
|
if (!isRecord(document) || !isRecord(document.attribution)) {
|
|
263
281
|
return null;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { PostHog } from 'posthog-js';
|
|
2
2
|
export declare const POSTHOG_FEATURE_FLAG_READY_TIMEOUT_MS = 2500;
|
|
3
3
|
export declare const POSTHOG_SCOPED_FLAG_RELOAD_RETRY_MS = 300;
|
|
4
|
+
export declare const shouldRecordPostHogSession: (distinctId: string, sampleRate: number) => boolean;
|
|
4
5
|
type BootstrapConfig = {
|
|
5
6
|
apiKey: string;
|
|
6
7
|
apiHost: string;
|
|
@@ -5,6 +5,15 @@ let readyPromise = null;
|
|
|
5
5
|
export const POSTHOG_FEATURE_FLAG_READY_TIMEOUT_MS = 2500;
|
|
6
6
|
export const POSTHOG_SCOPED_FLAG_RELOAD_RETRY_MS = 300;
|
|
7
7
|
const STORED_PERSON_PROPERTIES_KEY = '$stored_person_properties';
|
|
8
|
+
export const shouldRecordPostHogSession = (distinctId, sampleRate) => {
|
|
9
|
+
const normalizedRate = Math.min(100, Math.max(0, Math.round(sampleRate)));
|
|
10
|
+
let hash = 2166136261;
|
|
11
|
+
for (let index = 0; index < distinctId.length; index += 1) {
|
|
12
|
+
hash ^= distinctId.charCodeAt(index);
|
|
13
|
+
hash = Math.imul(hash, 16777619);
|
|
14
|
+
}
|
|
15
|
+
return (hash >>> 0) % 100 < normalizedRate;
|
|
16
|
+
};
|
|
8
17
|
const buildFlagScopeProperties = (config) => {
|
|
9
18
|
var _a, _b;
|
|
10
19
|
const properties = {};
|
|
@@ -76,6 +85,8 @@ export const bootstrapPostHog = (config) => {
|
|
|
76
85
|
};
|
|
77
86
|
readyTimeoutId = setTimeout(markReady, POSTHOG_FEATURE_FLAG_READY_TIMEOUT_MS);
|
|
78
87
|
const scopeProperties = buildFlagScopeProperties(config);
|
|
88
|
+
const sessionReplayEnabled = runtimePublicConfig.posthogSessionReplayEnabled
|
|
89
|
+
&& shouldRecordPostHogSession(config.distinctId, runtimePublicConfig.posthogSessionReplaySampleRate);
|
|
79
90
|
primePostHogFlagScopePersistence(config.apiKey, scopeProperties);
|
|
80
91
|
posthog.init(config.apiKey, {
|
|
81
92
|
api_host: config.apiHost,
|
|
@@ -89,11 +100,17 @@ export const bootstrapPostHog = (config) => {
|
|
|
89
100
|
capture_exceptions: false,
|
|
90
101
|
capture_heatmaps: false,
|
|
91
102
|
capture_performance: false,
|
|
92
|
-
disable_session_recording:
|
|
103
|
+
disable_session_recording: !sessionReplayEnabled,
|
|
104
|
+
session_recording: {
|
|
105
|
+
maskAllInputs: true,
|
|
106
|
+
},
|
|
93
107
|
disable_surveys: true,
|
|
94
108
|
advanced_disable_feature_flags_on_first_load: true,
|
|
95
109
|
bootstrap: { distinctID: config.distinctId },
|
|
96
110
|
loaded: () => {
|
|
111
|
+
if (Object.keys(scopeProperties).length > 0) {
|
|
112
|
+
posthog.register(scopeProperties);
|
|
113
|
+
}
|
|
97
114
|
let unsubscribe = null;
|
|
98
115
|
let scopedReloadRetried = false;
|
|
99
116
|
unsubscribe = posthog.onFeatureFlags((flags) => {
|
|
@@ -8,7 +8,7 @@ import { buildHostedStepLocation, dispatchFunnelLocationChange, dispatchWindowCu
|
|
|
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 { buildFunnelAttributionEventMetadata, collectCurrentFunnelAttribution, getFunnelUserAttribution, } from './funnel-attribution.js';
|
|
11
|
+
import { buildFunnelAttributionEventMetadata, collectCurrentFunnelAttribution, getFunnelUserAttribution, mergeFunnelUserAttribution, } 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';
|
|
@@ -24,8 +24,17 @@ const isTerminalCompletion = (stepMeta, outcome) => {
|
|
|
24
24
|
&& Boolean(stepMeta && ((_a = FUNNEL_STEP_CONTRACTS[stepMeta.type]) === null || _a === void 0 ? void 0 : _a.terminal) === true));
|
|
25
25
|
};
|
|
26
26
|
export function resolveFunnelEventAttribution(document, provisionalAttribution) {
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
const persistedAttribution = getFunnelUserAttribution(document);
|
|
28
|
+
if (!persistedAttribution) {
|
|
29
|
+
return provisionalAttribution;
|
|
30
|
+
}
|
|
31
|
+
if (!provisionalAttribution) {
|
|
32
|
+
return persistedAttribution;
|
|
33
|
+
}
|
|
34
|
+
return Object.assign(Object.assign({}, mergeFunnelUserAttribution(persistedAttribution, provisionalAttribution)), {
|
|
35
|
+
// This event describes the page load happening now. An empty current URL is
|
|
36
|
+
// intentionally direct; never revive a paid click from an older visit.
|
|
37
|
+
lastTouch: Object.assign({}, provisionalAttribution.lastTouch) });
|
|
29
38
|
}
|
|
30
39
|
export function buildReadyFunnelAttributionEventMetadata(attributionReady, attribution) {
|
|
31
40
|
return attributionReady ? buildFunnelAttributionEventMetadata(attribution) : null;
|
|
@@ -4,6 +4,8 @@ export declare const PROJECT_ENV_STANDARD_KEYS: {
|
|
|
4
4
|
readonly funnelVersionId: "NEXT_PUBLIC_FUNNEL_VERSION_ID";
|
|
5
5
|
readonly projectId: "NEXT_PUBLIC_PROJECT_ID";
|
|
6
6
|
readonly posthogProjectApiKey: "NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY";
|
|
7
|
+
readonly posthogSessionReplayEnabled: "NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_ENABLED";
|
|
8
|
+
readonly posthogSessionReplaySampleRate: "NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_SAMPLE_RATE";
|
|
7
9
|
readonly stripeEnabled: "STRIPE_ENABLED";
|
|
8
10
|
readonly stripeActiveMode: "NEXT_PUBLIC_STRIPE_ACTIVE_MODE";
|
|
9
11
|
readonly stripeTestPublishableKey: "NEXT_PUBLIC_STRIPE_TEST_PUBLISHABLE_KEY";
|
|
@@ -4,6 +4,8 @@ export const PROJECT_ENV_STANDARD_KEYS = {
|
|
|
4
4
|
funnelVersionId: 'NEXT_PUBLIC_FUNNEL_VERSION_ID',
|
|
5
5
|
projectId: 'NEXT_PUBLIC_PROJECT_ID',
|
|
6
6
|
posthogProjectApiKey: 'NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY',
|
|
7
|
+
posthogSessionReplayEnabled: 'NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_ENABLED',
|
|
8
|
+
posthogSessionReplaySampleRate: 'NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_SAMPLE_RATE',
|
|
7
9
|
stripeEnabled: 'STRIPE_ENABLED',
|
|
8
10
|
stripeActiveMode: 'NEXT_PUBLIC_STRIPE_ACTIVE_MODE',
|
|
9
11
|
stripeTestPublishableKey: 'NEXT_PUBLIC_STRIPE_TEST_PUBLISHABLE_KEY',
|
|
@@ -78,6 +80,8 @@ const buildProjectStandardValues = (envMap) => {
|
|
|
78
80
|
funnelVersionId: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.funnelVersionId),
|
|
79
81
|
projectId: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.projectId),
|
|
80
82
|
posthogProjectApiKey: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.posthogProjectApiKey),
|
|
83
|
+
posthogSessionReplayEnabled: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.posthogSessionReplayEnabled),
|
|
84
|
+
posthogSessionReplaySampleRate: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.posthogSessionReplaySampleRate),
|
|
81
85
|
stripeEnabled: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.stripeEnabled),
|
|
82
86
|
stripeActiveMode: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.stripeActiveMode),
|
|
83
87
|
stripeTestPublishableKey: getProjectEnvValue(envMap, PROJECT_ENV_STANDARD_KEYS.stripeTestPublishableKey),
|
|
@@ -7,6 +7,8 @@ export declare const RUNTIME_PUBLIC_ENV_KEYS: {
|
|
|
7
7
|
readonly funnelVersionId: "NEXT_PUBLIC_FUNNEL_VERSION_ID";
|
|
8
8
|
readonly projectId: "NEXT_PUBLIC_PROJECT_ID";
|
|
9
9
|
readonly posthogProjectApiKey: "NEXT_PUBLIC_POSTHOG_PROJECT_API_KEY";
|
|
10
|
+
readonly posthogSessionReplayEnabled: "NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_ENABLED";
|
|
11
|
+
readonly posthogSessionReplaySampleRate: "NEXT_PUBLIC_POSTHOG_SESSION_REPLAY_SAMPLE_RATE";
|
|
10
12
|
readonly supportEmail: "NEXT_PUBLIC_FUNNEL_SUPPORT_EMAIL";
|
|
11
13
|
readonly iosAppStoreUrl: "NEXT_PUBLIC_IOS_APP_STORE_URL";
|
|
12
14
|
readonly androidPlayStoreUrl: "NEXT_PUBLIC_ANDROID_PLAY_STORE_URL";
|
|
@@ -34,6 +36,8 @@ export type RuntimePublicConfig = {
|
|
|
34
36
|
funnelVersionId: string;
|
|
35
37
|
projectId: string;
|
|
36
38
|
posthogProjectApiKey: string;
|
|
39
|
+
posthogSessionReplayEnabled: boolean;
|
|
40
|
+
posthogSessionReplaySampleRate: number;
|
|
37
41
|
supportEmail: string;
|
|
38
42
|
iosAppStoreUrl: string | null;
|
|
39
43
|
androidPlayStoreUrl: string | null;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
var _a, _b;
|
|
1
2
|
import { RUNTIME_ENV_KEYS, isDevelopmentRuntime, readRuntimeEnv, runtimeEnvConfig, } from '../config/env.config.js';
|
|
2
3
|
import { PROJECT_ENV_STANDARD_KEYS } from './project-env.js';
|
|
3
4
|
export { isDevelopmentRuntime, readRuntimeEnv };
|
|
@@ -30,6 +31,8 @@ export const RUNTIME_PUBLIC_ENV_KEYS = {
|
|
|
30
31
|
funnelVersionId: RUNTIME_ENV_KEYS.funnelVersionId,
|
|
31
32
|
projectId: RUNTIME_ENV_KEYS.projectId,
|
|
32
33
|
posthogProjectApiKey: RUNTIME_ENV_KEYS.posthogProjectApiKey,
|
|
34
|
+
posthogSessionReplayEnabled: RUNTIME_ENV_KEYS.posthogSessionReplayEnabled,
|
|
35
|
+
posthogSessionReplaySampleRate: RUNTIME_ENV_KEYS.posthogSessionReplaySampleRate,
|
|
33
36
|
supportEmail: RUNTIME_ENV_KEYS.supportEmail,
|
|
34
37
|
iosAppStoreUrl: RUNTIME_ENV_KEYS.iosAppStoreUrl,
|
|
35
38
|
androidPlayStoreUrl: RUNTIME_ENV_KEYS.androidPlayStoreUrl,
|
|
@@ -59,6 +62,8 @@ export const runtimePublicConfig = Object.freeze({
|
|
|
59
62
|
funnelVersionId: readRequiredRuntimeValue(runtimeEnvConfig.funnelVersionId, ''),
|
|
60
63
|
projectId: readRequiredRuntimeValue(runtimeEnvConfig.projectId, ''),
|
|
61
64
|
posthogProjectApiKey: readRequiredRuntimeValue(runtimeEnvConfig.posthogProjectApiKey, ''),
|
|
65
|
+
posthogSessionReplayEnabled: ((_a = runtimeEnvConfig.posthogSessionReplayEnabled) === null || _a === void 0 ? void 0 : _a.trim()) === 'true',
|
|
66
|
+
posthogSessionReplaySampleRate: Math.min(100, Math.max(1, Number.parseInt(((_b = runtimeEnvConfig.posthogSessionReplaySampleRate) === null || _b === void 0 ? void 0 : _b.trim()) || '10', 10) || 10)),
|
|
62
67
|
supportEmail: readRequiredRuntimeValue(runtimeEnvConfig.supportEmail, DEFAULT_SUPPORT_EMAIL),
|
|
63
68
|
iosAppStoreUrl: toOptionalEnv(runtimeEnvConfig.iosAppStoreUrl) || toIosAppStoreUrlFromId(appStoreId),
|
|
64
69
|
androidPlayStoreUrl: toOptionalEnv(runtimeEnvConfig.androidPlayStoreUrl) ||
|