@syntrologie/runtime-sdk 0.2.13 → 0.2.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/bootstrap.d.ts +14 -0
- package/dist/bootstrap.js +102 -4
- package/dist/bootstrap.js.map +1 -1
- package/dist/experiments/registry.d.ts +5 -0
- package/dist/experiments/registry.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/metrics/index.d.ts +4 -0
- package/dist/metrics/index.js +5 -0
- package/dist/metrics/index.js.map +1 -0
- package/dist/metrics/sessionMetrics.d.ts +101 -0
- package/dist/metrics/sessionMetrics.js +178 -0
- package/dist/metrics/sessionMetrics.js.map +1 -0
- package/dist/overlays/runtime/overlay/highlight.d.ts +2 -0
- package/dist/overlays/runtime/overlay/highlight.js +17 -9
- package/dist/overlays/runtime/overlay/highlight.js.map +1 -1
- package/dist/overlays/runtime/overlay/runner.js +5 -3
- package/dist/overlays/runtime/overlay/runner.js.map +1 -1
- package/dist/smart-canvas.esm.js +11 -11
- package/dist/smart-canvas.esm.js.map +4 -4
- package/dist/smart-canvas.js +275 -15
- package/dist/smart-canvas.js.map +3 -3
- package/dist/smart-canvas.min.js +11 -11
- package/dist/smart-canvas.min.js.map +4 -4
- package/dist/telemetry/adapters/posthog.d.ts +24 -0
- package/dist/telemetry/adapters/posthog.js +58 -9
- package/dist/telemetry/adapters/posthog.js.map +1 -1
- package/dist/telemetry/registry.d.ts +9 -4
- package/dist/telemetry/registry.js.map +1 -1
- package/dist/telemetry/types.d.ts +15 -0
- package/package.json +1 -1
package/dist/bootstrap.d.ts
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { decodeToken, encodeToken } from "./token";
|
|
14
14
|
import { SmartCanvasConfig, SmartCanvasHandle } from "./api";
|
|
15
|
+
import { SessionMetricTracker } from "./metrics";
|
|
15
16
|
import type { ExperimentClient } from "./experiments/types";
|
|
16
17
|
import type { TelemetryClient } from "./telemetry/types";
|
|
17
18
|
import type { CanvasConfigFetcher } from "./types";
|
|
@@ -35,6 +36,14 @@ export interface SyntroInitOptions {
|
|
|
35
36
|
* The token's telemetry credentials (t field) are still used if present.
|
|
36
37
|
*/
|
|
37
38
|
fetcher?: CanvasConfigFetcher;
|
|
39
|
+
/**
|
|
40
|
+
* Enable session-based metric tracking.
|
|
41
|
+
* When true, a SessionMetricTracker is created that tracks metrics during
|
|
42
|
+
* the user's session and updates GrowthBook attributes in real-time.
|
|
43
|
+
*
|
|
44
|
+
* @default false
|
|
45
|
+
*/
|
|
46
|
+
enableSessionMetrics?: boolean;
|
|
38
47
|
}
|
|
39
48
|
export interface SyntroInitResult {
|
|
40
49
|
/**
|
|
@@ -49,6 +58,11 @@ export interface SyntroInitResult {
|
|
|
49
58
|
* The telemetry client, if telemetry is configured in the token.
|
|
50
59
|
*/
|
|
51
60
|
telemetry?: TelemetryClient;
|
|
61
|
+
/**
|
|
62
|
+
* The session metric tracker, if enableSessionMetrics is true.
|
|
63
|
+
* Use this to track session-based metrics for real-time targeting.
|
|
64
|
+
*/
|
|
65
|
+
sessionMetrics?: SessionMetricTracker;
|
|
52
66
|
}
|
|
53
67
|
/**
|
|
54
68
|
* Initialize the Syntro SDK with a single token.
|
package/dist/bootstrap.js
CHANGED
|
@@ -16,6 +16,7 @@ import { createTelemetryClient } from "./telemetry/registry";
|
|
|
16
16
|
import { createConfigFetcher } from "./fetchers/registry";
|
|
17
17
|
import { createCanvasConfigFetcher } from "./configFetcher";
|
|
18
18
|
import { createSmartCanvas } from "./api";
|
|
19
|
+
import { createSessionMetricTracker } from "./metrics";
|
|
19
20
|
/**
|
|
20
21
|
* Get environment variable, supporting both Vite and Next.js patterns.
|
|
21
22
|
*/
|
|
@@ -54,6 +55,58 @@ function isEditorMode() {
|
|
|
54
55
|
});
|
|
55
56
|
return hasToken;
|
|
56
57
|
}
|
|
58
|
+
// ============================================================================
|
|
59
|
+
// Segment Attribute Caching (localStorage)
|
|
60
|
+
// ============================================================================
|
|
61
|
+
const SEGMENT_CACHE_KEY = 'syntro_segment_attributes';
|
|
62
|
+
/**
|
|
63
|
+
* Load cached segment attributes from localStorage.
|
|
64
|
+
* Returns cached values for instant Phase 1 evaluation.
|
|
65
|
+
*/
|
|
66
|
+
function loadCachedSegmentAttributes() {
|
|
67
|
+
if (typeof window === 'undefined')
|
|
68
|
+
return {};
|
|
69
|
+
try {
|
|
70
|
+
const cached = localStorage.getItem(SEGMENT_CACHE_KEY);
|
|
71
|
+
if (cached) {
|
|
72
|
+
const attrs = JSON.parse(cached);
|
|
73
|
+
console.log('[Syntro Bootstrap] Loaded cached segment attributes:', attrs);
|
|
74
|
+
return attrs;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
console.warn('[Syntro Bootstrap] Failed to load cached segment attributes:', err);
|
|
79
|
+
}
|
|
80
|
+
return {};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Save segment attributes to localStorage for faster future loads.
|
|
84
|
+
*/
|
|
85
|
+
function cacheSegmentAttributes(attrs) {
|
|
86
|
+
if (typeof window === 'undefined')
|
|
87
|
+
return;
|
|
88
|
+
try {
|
|
89
|
+
localStorage.setItem(SEGMENT_CACHE_KEY, JSON.stringify(attrs));
|
|
90
|
+
console.log('[Syntro Bootstrap] Cached segment attributes:', attrs);
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
console.warn('[Syntro Bootstrap] Failed to cache segment attributes:', err);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Extract segment flags (in_segment_*) from PostHog feature flags.
|
|
98
|
+
*/
|
|
99
|
+
function extractSegmentFlags(allFlags) {
|
|
100
|
+
if (!allFlags)
|
|
101
|
+
return {};
|
|
102
|
+
const segmentFlags = {};
|
|
103
|
+
for (const [key, value] of Object.entries(allFlags)) {
|
|
104
|
+
if (key.startsWith('in_segment_')) {
|
|
105
|
+
segmentFlags[key] = value === true;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return segmentFlags;
|
|
109
|
+
}
|
|
57
110
|
/**
|
|
58
111
|
* Initialize the Syntro SDK with a single token.
|
|
59
112
|
*
|
|
@@ -116,20 +169,55 @@ async function init(options) {
|
|
|
116
169
|
const editorUrl = getEnvVar("NEXT_PUBLIC_SYNTRO_EDITOR_URL")
|
|
117
170
|
|| getEnvVar("VITE_SYNTRO_EDITOR_URL")
|
|
118
171
|
|| ((_b = options.canvas) === null || _b === void 0 ? void 0 : _b.editorUrl);
|
|
119
|
-
//
|
|
172
|
+
// ============================================================================
|
|
173
|
+
// PHASE 1: Load cached segment attributes for instant evaluation
|
|
174
|
+
// ============================================================================
|
|
175
|
+
const cachedSegmentAttrs = loadCachedSegmentAttributes();
|
|
176
|
+
console.log('[Syntro Bootstrap] Phase 1: Using cached segment attributes:', cachedSegmentAttrs);
|
|
177
|
+
// Will be set when experiments client is created
|
|
178
|
+
let experiments;
|
|
179
|
+
// Callback for when PostHog feature flags are loaded (Phase 2)
|
|
180
|
+
const onFeatureFlagsLoaded = (allFlags) => {
|
|
181
|
+
var _a, _b, _c;
|
|
182
|
+
console.log('[Syntro Bootstrap] Phase 2: PostHog feature flags loaded');
|
|
183
|
+
// Extract segment flags (in_segment_*)
|
|
184
|
+
const segmentFlags = extractSegmentFlags(allFlags);
|
|
185
|
+
console.log('[Syntro Bootstrap] Segment flags from PostHog:', segmentFlags);
|
|
186
|
+
// Cache for next page load
|
|
187
|
+
cacheSegmentAttributes(segmentFlags);
|
|
188
|
+
// Update GrowthBook with fresh segment attributes
|
|
189
|
+
if (experiments) {
|
|
190
|
+
// Get current session metrics if available
|
|
191
|
+
const sessionAttrs = (_b = (_a = sessionMetrics === null || sessionMetrics === void 0 ? void 0 : sessionMetrics.getAll) === null || _a === void 0 ? void 0 : _a.call(sessionMetrics)) !== null && _b !== void 0 ? _b : {};
|
|
192
|
+
// Merge session metrics + segment flags and update GrowthBook
|
|
193
|
+
const updatedAttrs = { ...sessionAttrs, ...segmentFlags };
|
|
194
|
+
console.log('[Syntro Bootstrap] Updating GrowthBook with attributes:', updatedAttrs);
|
|
195
|
+
(_c = experiments.setAttributes) === null || _c === void 0 ? void 0 : _c.call(experiments, updatedAttrs);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
// Initialize telemetry client with feature flags callback
|
|
120
199
|
let telemetry;
|
|
121
200
|
if (payload === null || payload === void 0 ? void 0 : payload.t) {
|
|
122
201
|
telemetry = createTelemetryClient("posthog", {
|
|
123
202
|
apiKey: payload.t,
|
|
124
203
|
apiHost: telemetryHost, // undefined falls back to adapter default
|
|
204
|
+
// Enable PostHog feature flags for segment membership
|
|
205
|
+
enableFeatureFlags: true,
|
|
206
|
+
// Wire up callback for when flags are loaded (Phase 2)
|
|
207
|
+
onFeatureFlagsLoaded,
|
|
125
208
|
});
|
|
126
209
|
}
|
|
127
|
-
//
|
|
128
|
-
|
|
210
|
+
// ============================================================================
|
|
211
|
+
// Initialize experiment client with CACHED attributes (Phase 1)
|
|
212
|
+
// PostHog will update these when /decide returns (Phase 2)
|
|
213
|
+
// ============================================================================
|
|
214
|
+
let sessionMetrics;
|
|
129
215
|
if (payload === null || payload === void 0 ? void 0 : payload.e) {
|
|
130
216
|
experiments = createExperimentClient("growthbook", {
|
|
131
217
|
clientKey: payload.e,
|
|
132
218
|
apiHost: experimentHost, // undefined falls back to adapter default
|
|
219
|
+
// Phase 1: Use cached segment attributes for instant evaluation
|
|
220
|
+
attributes: cachedSegmentAttrs,
|
|
133
221
|
// Wire experiment tracking to telemetry provider
|
|
134
222
|
onExperimentViewed: (telemetry === null || telemetry === void 0 ? void 0 : telemetry.trackExperiment)
|
|
135
223
|
? (key, variationId, variationName) => {
|
|
@@ -161,6 +249,16 @@ async function init(options) {
|
|
|
161
249
|
// Default: use experiments-based fetcher (GrowthBook config or URI)
|
|
162
250
|
fetcher = createCanvasConfigFetcher({ experiments });
|
|
163
251
|
}
|
|
252
|
+
// Create session metric tracker if enabled
|
|
253
|
+
if (options.enableSessionMetrics) {
|
|
254
|
+
sessionMetrics = createSessionMetricTracker({
|
|
255
|
+
experiments,
|
|
256
|
+
onMetricChange: (key, value) => {
|
|
257
|
+
console.log(`[Syntro Bootstrap] Session metric changed: ${key} = ${value}`);
|
|
258
|
+
},
|
|
259
|
+
});
|
|
260
|
+
console.log('[Syntro Bootstrap] SessionMetricTracker created');
|
|
261
|
+
}
|
|
164
262
|
// Create canvas with integrations
|
|
165
263
|
const canvas = await createSmartCanvas({
|
|
166
264
|
...options.canvas,
|
|
@@ -168,7 +266,7 @@ async function init(options) {
|
|
|
168
266
|
integrations: { experiments, telemetry },
|
|
169
267
|
editorUrl,
|
|
170
268
|
});
|
|
171
|
-
return { canvas, experiments, telemetry };
|
|
269
|
+
return { canvas, experiments, telemetry, sessionMetrics };
|
|
172
270
|
}
|
|
173
271
|
/**
|
|
174
272
|
* The Syntro namespace for single-token initialization.
|
package/dist/bootstrap.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,WAAW,EAAE,WAAW,EAAsB,MAAM,SAAS,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAwC,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../src/bootstrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,6 +10,11 @@ import type { ExperimentClient } from "./types";
|
|
|
10
10
|
export interface CreateExperimentClientConfig {
|
|
11
11
|
clientKey: string;
|
|
12
12
|
apiHost?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Initial user attributes for targeting.
|
|
15
|
+
* Used for segment-based targeting.
|
|
16
|
+
*/
|
|
17
|
+
attributes?: Record<string, unknown>;
|
|
13
18
|
/**
|
|
14
19
|
* Callback fired when a user is assigned to an experiment.
|
|
15
20
|
* Use this to send experiment data to your analytics provider.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/experiments/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,sBAAsB,GAGvB,MAAM,uBAAuB,CAAC;AAK/B,MAAM,QAAQ,GAAmC;IAC/C,UAAU,EAAE,CAAC,MAAgC,EAAE,EAAE,CAC/C,sBAAsB,CAAC;QACrB,GAAG,MAAM;QACT,QAAQ,EAAE,IAAI;KACf,CAAC;CACL,CAAC;
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/experiments/registry.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EACL,sBAAsB,GAGvB,MAAM,uBAAuB,CAAC;AAK/B,MAAM,QAAQ,GAAmC;IAC/C,UAAU,EAAE,CAAC,MAAgC,EAAE,EAAE,CAC/C,sBAAsB,CAAC;QACrB,GAAG,MAAM;QACT,QAAQ,EAAE,IAAI;KACf,CAAC;CACL,CAAC;AAiBF;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CACpC,QAAgB,EAChB,MAAoC;IAEpC,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,gCAAgC,QAAQ,gBAAgB,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAC3F,CAAC;IACJ,CAAC;IACD,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC;AACzB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export * from "./configFetcher";
|
|
|
14
14
|
export * from "./overlays/types";
|
|
15
15
|
export * from "./overlays/schema";
|
|
16
16
|
export * from "./overlays/fetcher";
|
|
17
|
+
export * from "./metrics";
|
|
17
18
|
export { Syntro } from "./bootstrap";
|
|
18
19
|
export type { SyntroInitOptions, SyntroInitResult } from "./bootstrap";
|
|
19
20
|
export { encodeToken, decodeToken } from "./token";
|
package/dist/index.js
CHANGED
|
@@ -14,6 +14,8 @@ export * from "./configFetcher";
|
|
|
14
14
|
export * from "./overlays/types";
|
|
15
15
|
export * from "./overlays/schema";
|
|
16
16
|
export * from "./overlays/fetcher";
|
|
17
|
+
// Metrics for session-based targeting
|
|
18
|
+
export * from "./metrics";
|
|
17
19
|
// Single-token initialization
|
|
18
20
|
export { Syntro } from "./bootstrap";
|
|
19
21
|
export { encodeToken, decodeToken } from "./token";
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,OAAO,CAAC;AACtB,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AAEnC,8BAA8B;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC;AACtC,cAAc,kCAAkC,CAAC;AACjD,cAAc,wBAAwB,CAAC;AACvC,cAAc,cAAc,CAAC;AAC7B,cAAc,kBAAkB,CAAC;AACjC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,OAAO,CAAC;AACtB,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,mBAAmB,CAAC;AAClC,cAAc,oBAAoB,CAAC;AAEnC,sCAAsC;AACtC,cAAc,WAAW,CAAC;AAE1B,8BAA8B;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,oBAAoB,EACpB,0BAA0B,GAE3B,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SessionMetricTracker - Real-time session-based metrics for segment targeting.
|
|
3
|
+
*
|
|
4
|
+
* This module tracks metrics during a user's session and updates GrowthBook
|
|
5
|
+
* attributes in real-time, enabling instant segment targeting without waiting
|
|
6
|
+
* for batch PostHog cohort computation.
|
|
7
|
+
*
|
|
8
|
+
* Use cases:
|
|
9
|
+
* - "Show action plan after 3+ button clicks in this session"
|
|
10
|
+
* - "Target users who viewed 5+ products this session"
|
|
11
|
+
* - "Trigger intervention when user hovers a CTA 2+ times"
|
|
12
|
+
*/
|
|
13
|
+
import type { ExperimentClient } from "../experiments/types";
|
|
14
|
+
/**
|
|
15
|
+
* Options for creating a SessionMetricTracker.
|
|
16
|
+
*/
|
|
17
|
+
export interface SessionMetricTrackerOptions {
|
|
18
|
+
/**
|
|
19
|
+
* The experiment client to update attributes on.
|
|
20
|
+
* When a metric changes, the session_${metricKey} attribute is updated.
|
|
21
|
+
*/
|
|
22
|
+
experiments?: ExperimentClient;
|
|
23
|
+
/**
|
|
24
|
+
* Prefix for attribute keys sent to GrowthBook.
|
|
25
|
+
* @default "session_"
|
|
26
|
+
*/
|
|
27
|
+
attributePrefix?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Callback fired when any metric value changes.
|
|
30
|
+
* Useful for debugging or custom integrations.
|
|
31
|
+
*/
|
|
32
|
+
onMetricChange?: (key: string, newValue: number) => void;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Tracks session-based metrics for real-time segment targeting.
|
|
36
|
+
*/
|
|
37
|
+
export declare class SessionMetricTracker {
|
|
38
|
+
private metrics;
|
|
39
|
+
private experiments?;
|
|
40
|
+
private attributePrefix;
|
|
41
|
+
private onMetricChange?;
|
|
42
|
+
constructor(options?: SessionMetricTrackerOptions);
|
|
43
|
+
/**
|
|
44
|
+
* Increment a metric by the specified amount.
|
|
45
|
+
*
|
|
46
|
+
* @param metricKey - The metric to increment (e.g., "button_clicks", "page_views")
|
|
47
|
+
* @param amount - Amount to increment by (default: 1)
|
|
48
|
+
* @returns The new metric value
|
|
49
|
+
*/
|
|
50
|
+
increment(metricKey: string, amount?: number): number;
|
|
51
|
+
/**
|
|
52
|
+
* Set a metric to a specific value.
|
|
53
|
+
*
|
|
54
|
+
* @param metricKey - The metric to set
|
|
55
|
+
* @param value - The value to set
|
|
56
|
+
*/
|
|
57
|
+
set(metricKey: string, value: number): void;
|
|
58
|
+
/**
|
|
59
|
+
* Get the current value of a metric.
|
|
60
|
+
*
|
|
61
|
+
* @param metricKey - The metric to get
|
|
62
|
+
* @returns The current value (0 if not set)
|
|
63
|
+
*/
|
|
64
|
+
get(metricKey: string): number;
|
|
65
|
+
/**
|
|
66
|
+
* Check if a metric meets or exceeds a threshold.
|
|
67
|
+
*
|
|
68
|
+
* @param metricKey - The metric to check
|
|
69
|
+
* @param threshold - The threshold value
|
|
70
|
+
* @returns True if metric >= threshold
|
|
71
|
+
*/
|
|
72
|
+
meetsThreshold(metricKey: string, threshold: number): boolean;
|
|
73
|
+
/**
|
|
74
|
+
* Get all current metric values.
|
|
75
|
+
*
|
|
76
|
+
* @returns Record of metric keys to values
|
|
77
|
+
*/
|
|
78
|
+
getAll(): Record<string, number>;
|
|
79
|
+
/**
|
|
80
|
+
* Reset a specific metric to zero.
|
|
81
|
+
*
|
|
82
|
+
* @param metricKey - The metric to reset
|
|
83
|
+
*/
|
|
84
|
+
reset(metricKey: string): void;
|
|
85
|
+
/**
|
|
86
|
+
* Reset all metrics (clear the session).
|
|
87
|
+
*/
|
|
88
|
+
resetAll(): void;
|
|
89
|
+
/**
|
|
90
|
+
* Update the experiment client (useful if experiments client changes).
|
|
91
|
+
*/
|
|
92
|
+
setExperiments(experiments: ExperimentClient): void;
|
|
93
|
+
private updateExperimentAttributes;
|
|
94
|
+
private syncAllToExperiments;
|
|
95
|
+
private loadFromStorage;
|
|
96
|
+
private saveToStorage;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Create a SessionMetricTracker instance.
|
|
100
|
+
*/
|
|
101
|
+
export declare function createSessionMetricTracker(options?: SessionMetricTrackerOptions): SessionMetricTracker;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SessionMetricTracker - Real-time session-based metrics for segment targeting.
|
|
3
|
+
*
|
|
4
|
+
* This module tracks metrics during a user's session and updates GrowthBook
|
|
5
|
+
* attributes in real-time, enabling instant segment targeting without waiting
|
|
6
|
+
* for batch PostHog cohort computation.
|
|
7
|
+
*
|
|
8
|
+
* Use cases:
|
|
9
|
+
* - "Show action plan after 3+ button clicks in this session"
|
|
10
|
+
* - "Target users who viewed 5+ products this session"
|
|
11
|
+
* - "Trigger intervention when user hovers a CTA 2+ times"
|
|
12
|
+
*/
|
|
13
|
+
const STORAGE_KEY = "syntro_session_metrics";
|
|
14
|
+
/**
|
|
15
|
+
* Tracks session-based metrics for real-time segment targeting.
|
|
16
|
+
*/
|
|
17
|
+
export class SessionMetricTracker {
|
|
18
|
+
constructor(options = {}) {
|
|
19
|
+
var _a;
|
|
20
|
+
this.metrics = new Map();
|
|
21
|
+
this.experiments = options.experiments;
|
|
22
|
+
this.attributePrefix = (_a = options.attributePrefix) !== null && _a !== void 0 ? _a : "session_";
|
|
23
|
+
this.onMetricChange = options.onMetricChange;
|
|
24
|
+
// Restore metrics from sessionStorage
|
|
25
|
+
this.loadFromStorage();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Increment a metric by the specified amount.
|
|
29
|
+
*
|
|
30
|
+
* @param metricKey - The metric to increment (e.g., "button_clicks", "page_views")
|
|
31
|
+
* @param amount - Amount to increment by (default: 1)
|
|
32
|
+
* @returns The new metric value
|
|
33
|
+
*/
|
|
34
|
+
increment(metricKey, amount = 1) {
|
|
35
|
+
var _a, _b;
|
|
36
|
+
const currentValue = (_a = this.metrics.get(metricKey)) !== null && _a !== void 0 ? _a : 0;
|
|
37
|
+
const newValue = currentValue + amount;
|
|
38
|
+
this.metrics.set(metricKey, newValue);
|
|
39
|
+
this.saveToStorage();
|
|
40
|
+
// Update GrowthBook attributes for real-time targeting
|
|
41
|
+
this.updateExperimentAttributes(metricKey, newValue);
|
|
42
|
+
// Fire callback if configured
|
|
43
|
+
(_b = this.onMetricChange) === null || _b === void 0 ? void 0 : _b.call(this, metricKey, newValue);
|
|
44
|
+
return newValue;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Set a metric to a specific value.
|
|
48
|
+
*
|
|
49
|
+
* @param metricKey - The metric to set
|
|
50
|
+
* @param value - The value to set
|
|
51
|
+
*/
|
|
52
|
+
set(metricKey, value) {
|
|
53
|
+
var _a;
|
|
54
|
+
this.metrics.set(metricKey, value);
|
|
55
|
+
this.saveToStorage();
|
|
56
|
+
this.updateExperimentAttributes(metricKey, value);
|
|
57
|
+
(_a = this.onMetricChange) === null || _a === void 0 ? void 0 : _a.call(this, metricKey, value);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Get the current value of a metric.
|
|
61
|
+
*
|
|
62
|
+
* @param metricKey - The metric to get
|
|
63
|
+
* @returns The current value (0 if not set)
|
|
64
|
+
*/
|
|
65
|
+
get(metricKey) {
|
|
66
|
+
var _a;
|
|
67
|
+
return (_a = this.metrics.get(metricKey)) !== null && _a !== void 0 ? _a : 0;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Check if a metric meets or exceeds a threshold.
|
|
71
|
+
*
|
|
72
|
+
* @param metricKey - The metric to check
|
|
73
|
+
* @param threshold - The threshold value
|
|
74
|
+
* @returns True if metric >= threshold
|
|
75
|
+
*/
|
|
76
|
+
meetsThreshold(metricKey, threshold) {
|
|
77
|
+
return this.get(metricKey) >= threshold;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get all current metric values.
|
|
81
|
+
*
|
|
82
|
+
* @returns Record of metric keys to values
|
|
83
|
+
*/
|
|
84
|
+
getAll() {
|
|
85
|
+
return Object.fromEntries(this.metrics);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Reset a specific metric to zero.
|
|
89
|
+
*
|
|
90
|
+
* @param metricKey - The metric to reset
|
|
91
|
+
*/
|
|
92
|
+
reset(metricKey) {
|
|
93
|
+
var _a;
|
|
94
|
+
this.metrics.delete(metricKey);
|
|
95
|
+
this.saveToStorage();
|
|
96
|
+
this.updateExperimentAttributes(metricKey, 0);
|
|
97
|
+
(_a = this.onMetricChange) === null || _a === void 0 ? void 0 : _a.call(this, metricKey, 0);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Reset all metrics (clear the session).
|
|
101
|
+
*/
|
|
102
|
+
resetAll() {
|
|
103
|
+
var _a, _b, _c;
|
|
104
|
+
const keys = Array.from(this.metrics.keys());
|
|
105
|
+
this.metrics.clear();
|
|
106
|
+
this.saveToStorage();
|
|
107
|
+
// Update all attributes to 0
|
|
108
|
+
const attrs = {};
|
|
109
|
+
for (const key of keys) {
|
|
110
|
+
attrs[`${this.attributePrefix}${key}`] = 0;
|
|
111
|
+
(_a = this.onMetricChange) === null || _a === void 0 ? void 0 : _a.call(this, key, 0);
|
|
112
|
+
}
|
|
113
|
+
(_c = (_b = this.experiments) === null || _b === void 0 ? void 0 : _b.setAttributes) === null || _c === void 0 ? void 0 : _c.call(_b, attrs);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Update the experiment client (useful if experiments client changes).
|
|
117
|
+
*/
|
|
118
|
+
setExperiments(experiments) {
|
|
119
|
+
this.experiments = experiments;
|
|
120
|
+
// Sync all current metrics to the new experiment client
|
|
121
|
+
this.syncAllToExperiments();
|
|
122
|
+
}
|
|
123
|
+
// ==================== Private Methods ====================
|
|
124
|
+
updateExperimentAttributes(metricKey, value) {
|
|
125
|
+
var _a;
|
|
126
|
+
if (!((_a = this.experiments) === null || _a === void 0 ? void 0 : _a.setAttributes))
|
|
127
|
+
return;
|
|
128
|
+
const attributeKey = `${this.attributePrefix}${metricKey}`;
|
|
129
|
+
this.experiments.setAttributes({ [attributeKey]: value });
|
|
130
|
+
}
|
|
131
|
+
syncAllToExperiments() {
|
|
132
|
+
var _a;
|
|
133
|
+
if (!((_a = this.experiments) === null || _a === void 0 ? void 0 : _a.setAttributes))
|
|
134
|
+
return;
|
|
135
|
+
const attrs = {};
|
|
136
|
+
for (const [key, value] of this.metrics) {
|
|
137
|
+
attrs[`${this.attributePrefix}${key}`] = value;
|
|
138
|
+
}
|
|
139
|
+
this.experiments.setAttributes(attrs);
|
|
140
|
+
}
|
|
141
|
+
loadFromStorage() {
|
|
142
|
+
if (typeof window === "undefined" || typeof sessionStorage === "undefined")
|
|
143
|
+
return;
|
|
144
|
+
try {
|
|
145
|
+
const stored = sessionStorage.getItem(STORAGE_KEY);
|
|
146
|
+
if (stored) {
|
|
147
|
+
const data = JSON.parse(stored);
|
|
148
|
+
for (const [key, value] of Object.entries(data)) {
|
|
149
|
+
this.metrics.set(key, value.count);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
catch (err) {
|
|
154
|
+
console.warn("[SessionMetricTracker] Failed to load from sessionStorage:", err);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
saveToStorage() {
|
|
158
|
+
if (typeof window === "undefined" || typeof sessionStorage === "undefined")
|
|
159
|
+
return;
|
|
160
|
+
try {
|
|
161
|
+
const data = {};
|
|
162
|
+
for (const [key, count] of this.metrics) {
|
|
163
|
+
data[key] = { count, lastUpdated: Date.now() };
|
|
164
|
+
}
|
|
165
|
+
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(data));
|
|
166
|
+
}
|
|
167
|
+
catch (err) {
|
|
168
|
+
console.warn("[SessionMetricTracker] Failed to save to sessionStorage:", err);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Create a SessionMetricTracker instance.
|
|
174
|
+
*/
|
|
175
|
+
export function createSessionMetricTracker(options = {}) {
|
|
176
|
+
return new SessionMetricTracker(options);
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=sessionMetrics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessionMetrics.js","sourceRoot":"","sources":["../../src/metrics/sessionMetrics.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
var _a;
|
|
2
2
|
const supportsPathClip = typeof CSS !== "undefined" && ((_a = CSS.supports) === null || _a === void 0 ? void 0 : _a.call(CSS, "clip-path", "path('M0 0 H1 V1 Z')"));
|
|
3
3
|
export function showHighlight(anchorEl, overlayRoot, opts) {
|
|
4
|
-
var _a, _b, _c, _d, _e;
|
|
4
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
5
5
|
const padding = (_a = opts === null || opts === void 0 ? void 0 : opts.paddingPx) !== null && _a !== void 0 ? _a : 12;
|
|
6
6
|
const radius = (_b = opts === null || opts === void 0 ? void 0 : opts.radiusPx) !== null && _b !== void 0 ? _b : 12;
|
|
7
7
|
const opacity = Math.min(Math.max((_c = opts === null || opts === void 0 ? void 0 : opts.scrimOpacity) !== null && _c !== void 0 ? _c : 0.55, 0), 1);
|
|
8
8
|
const ringColor = (_d = opts === null || opts === void 0 ? void 0 : opts.ringColor) !== null && _d !== void 0 ? _d : "var(--syntro-ring, #5b8cff)";
|
|
9
9
|
const blocking = (_e = opts === null || opts === void 0 ? void 0 : opts.blocking) !== null && _e !== void 0 ? _e : false;
|
|
10
|
+
const onClickOutside = (_f = opts === null || opts === void 0 ? void 0 : opts.onClickOutside) !== null && _f !== void 0 ? _f : true; // Default to true for backwards compat
|
|
11
|
+
const onEsc = (_g = opts === null || opts === void 0 ? void 0 : opts.onEsc) !== null && _g !== void 0 ? _g : true; // Default to true for backwards compat
|
|
10
12
|
const rootStyles = getComputedStyle(document.documentElement);
|
|
11
13
|
const tokenScrim = rootStyles.getPropertyValue("--syntro-spotlight-backdrop").trim();
|
|
12
14
|
const tokenRing = rootStyles.getPropertyValue("--syntro-ring").trim();
|
|
13
15
|
const scrim = document.createElement("div");
|
|
14
16
|
scrim.className = "syntro-spotlight-scrim";
|
|
17
|
+
// Enable pointer events if blocking OR if we want to dismiss on click outside
|
|
18
|
+
const needsPointerEvents = blocking || onClickOutside;
|
|
15
19
|
Object.assign(scrim.style, {
|
|
16
20
|
position: "fixed",
|
|
17
21
|
inset: "0",
|
|
18
22
|
zIndex: "2147483646",
|
|
19
|
-
pointerEvents:
|
|
23
|
+
pointerEvents: needsPointerEvents ? "auto" : "none",
|
|
20
24
|
background: tokenScrim || `rgba(2, 6, 23, ${opacity})`,
|
|
21
25
|
transition: "opacity 220ms ease",
|
|
22
26
|
opacity: "0",
|
|
@@ -118,18 +122,20 @@ export function showHighlight(anchorEl, overlayRoot, opts) {
|
|
|
118
122
|
window.addEventListener("scroll", onScroll, true);
|
|
119
123
|
window.addEventListener("resize", onResize);
|
|
120
124
|
const onKey = (e) => {
|
|
121
|
-
if (e.key === "Escape")
|
|
125
|
+
if (e.key === "Escape" && onEsc)
|
|
122
126
|
handle.destroy();
|
|
123
127
|
};
|
|
124
|
-
|
|
128
|
+
if (onEsc) {
|
|
129
|
+
window.addEventListener("keydown", onKey);
|
|
130
|
+
}
|
|
125
131
|
const onClick = (event) => {
|
|
126
|
-
if (
|
|
127
|
-
handle.destroy();
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
132
|
+
if (blocking) {
|
|
130
133
|
event.preventDefault();
|
|
131
134
|
event.stopPropagation();
|
|
132
135
|
}
|
|
136
|
+
else if (onClickOutside) {
|
|
137
|
+
handle.destroy();
|
|
138
|
+
}
|
|
133
139
|
};
|
|
134
140
|
scrim.addEventListener("click", onClick);
|
|
135
141
|
const handle = {
|
|
@@ -137,7 +143,9 @@ export function showHighlight(anchorEl, overlayRoot, opts) {
|
|
|
137
143
|
ro.disconnect();
|
|
138
144
|
window.removeEventListener("scroll", onScroll, true);
|
|
139
145
|
window.removeEventListener("resize", onResize);
|
|
140
|
-
|
|
146
|
+
if (onEsc) {
|
|
147
|
+
window.removeEventListener("keydown", onKey);
|
|
148
|
+
}
|
|
141
149
|
scrim.removeEventListener("click", onClick);
|
|
142
150
|
scrim.style.opacity = "0";
|
|
143
151
|
setTimeout(() => {
|