@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/smart-canvas.js
CHANGED
|
@@ -3581,16 +3581,19 @@ var SyntrologieSDK = (() => {
|
|
|
3581
3581
|
const opacity = Math.min(Math.max(opts?.scrimOpacity ?? 0.55, 0), 1);
|
|
3582
3582
|
const ringColor = opts?.ringColor ?? "var(--syntro-ring, #5b8cff)";
|
|
3583
3583
|
const blocking = opts?.blocking ?? false;
|
|
3584
|
+
const onClickOutside = opts?.onClickOutside ?? true;
|
|
3585
|
+
const onEsc = opts?.onEsc ?? true;
|
|
3584
3586
|
const rootStyles = getComputedStyle(document.documentElement);
|
|
3585
3587
|
const tokenScrim = rootStyles.getPropertyValue("--syntro-spotlight-backdrop").trim();
|
|
3586
3588
|
const tokenRing = rootStyles.getPropertyValue("--syntro-ring").trim();
|
|
3587
3589
|
const scrim = document.createElement("div");
|
|
3588
3590
|
scrim.className = "syntro-spotlight-scrim";
|
|
3591
|
+
const needsPointerEvents = blocking || onClickOutside;
|
|
3589
3592
|
Object.assign(scrim.style, {
|
|
3590
3593
|
position: "fixed",
|
|
3591
3594
|
inset: "0",
|
|
3592
3595
|
zIndex: "2147483646",
|
|
3593
|
-
pointerEvents:
|
|
3596
|
+
pointerEvents: needsPointerEvents ? "auto" : "none",
|
|
3594
3597
|
background: tokenScrim || `rgba(2, 6, 23, ${opacity})`,
|
|
3595
3598
|
transition: "opacity 220ms ease",
|
|
3596
3599
|
opacity: "0"
|
|
@@ -3678,15 +3681,17 @@ var SyntrologieSDK = (() => {
|
|
|
3678
3681
|
window.addEventListener("scroll", onScroll, true);
|
|
3679
3682
|
window.addEventListener("resize", onResize);
|
|
3680
3683
|
const onKey = (e2) => {
|
|
3681
|
-
if (e2.key === "Escape") handle.destroy();
|
|
3684
|
+
if (e2.key === "Escape" && onEsc) handle.destroy();
|
|
3682
3685
|
};
|
|
3683
|
-
|
|
3686
|
+
if (onEsc) {
|
|
3687
|
+
window.addEventListener("keydown", onKey);
|
|
3688
|
+
}
|
|
3684
3689
|
const onClick = (event) => {
|
|
3685
|
-
if (
|
|
3686
|
-
handle.destroy();
|
|
3687
|
-
} else {
|
|
3690
|
+
if (blocking) {
|
|
3688
3691
|
event.preventDefault();
|
|
3689
3692
|
event.stopPropagation();
|
|
3693
|
+
} else if (onClickOutside) {
|
|
3694
|
+
handle.destroy();
|
|
3690
3695
|
}
|
|
3691
3696
|
};
|
|
3692
3697
|
scrim.addEventListener("click", onClick);
|
|
@@ -3695,7 +3700,9 @@ var SyntrologieSDK = (() => {
|
|
|
3695
3700
|
ro2.disconnect();
|
|
3696
3701
|
window.removeEventListener("scroll", onScroll, true);
|
|
3697
3702
|
window.removeEventListener("resize", onResize);
|
|
3698
|
-
|
|
3703
|
+
if (onEsc) {
|
|
3704
|
+
window.removeEventListener("keydown", onKey);
|
|
3705
|
+
}
|
|
3699
3706
|
scrim.removeEventListener("click", onClick);
|
|
3700
3707
|
scrim.style.opacity = "0";
|
|
3701
3708
|
setTimeout(() => {
|
|
@@ -4119,7 +4126,9 @@ var SyntrologieSDK = (() => {
|
|
|
4119
4126
|
radiusPx: step.ring?.radiusPx,
|
|
4120
4127
|
scrimOpacity: step.scrim?.opacity,
|
|
4121
4128
|
ringColor: step.ringColor,
|
|
4122
|
-
blocking: step.blocking
|
|
4129
|
+
blocking: step.blocking,
|
|
4130
|
+
onClickOutside: step.dismiss?.onClickOutside ?? true,
|
|
4131
|
+
onEsc: step.dismiss?.onEsc ?? true
|
|
4123
4132
|
});
|
|
4124
4133
|
ctx.onEvent?.("syntro_overlay_exposed", { kind: "highlight", stepId: step.id, recipeId: ctx.recipeId });
|
|
4125
4134
|
const timers = [];
|
|
@@ -24545,6 +24554,7 @@ var SyntrologieSDK = (() => {
|
|
|
24545
24554
|
CanvasRecipeZ: () => CanvasRecipeZ,
|
|
24546
24555
|
HighlightStepZ: () => HighlightStepZ,
|
|
24547
24556
|
SelectorZ: () => SelectorZ,
|
|
24557
|
+
SessionMetricTracker: () => SessionMetricTracker,
|
|
24548
24558
|
ShadowCanvasOverlay: () => ShadowCanvasOverlay,
|
|
24549
24559
|
SmartCanvasApp: () => SmartCanvasApp,
|
|
24550
24560
|
SmartCanvasController: () => SmartCanvasController,
|
|
@@ -24558,6 +24568,7 @@ var SyntrologieSDK = (() => {
|
|
|
24558
24568
|
createGrowthBookClient: () => createGrowthBookClient,
|
|
24559
24569
|
createOverlayRecipeFetcher: () => createOverlayRecipeFetcher,
|
|
24560
24570
|
createPostHogClient: () => createPostHogClient,
|
|
24571
|
+
createSessionMetricTracker: () => createSessionMetricTracker,
|
|
24561
24572
|
createSmartCanvas: () => createSmartCanvas,
|
|
24562
24573
|
createSmartCanvasController: () => createSmartCanvasController,
|
|
24563
24574
|
decodeToken: () => decodeToken,
|
|
@@ -29100,14 +29111,18 @@ var SyntrologieSDK = (() => {
|
|
|
29100
29111
|
constructor(options = {}) {
|
|
29101
29112
|
this.options = options;
|
|
29102
29113
|
__publicField(this, "client");
|
|
29114
|
+
__publicField(this, "featureFlagsCallback");
|
|
29103
29115
|
this.client = options.client;
|
|
29116
|
+
this.featureFlagsCallback = options.onFeatureFlagsLoaded;
|
|
29104
29117
|
if (!this.client && typeof window !== "undefined" && options.apiKey) {
|
|
29105
29118
|
this.client = Uo;
|
|
29119
|
+
const enableFeatureFlags = options.enableFeatureFlags ?? true;
|
|
29106
29120
|
this.client.init(options.apiKey, {
|
|
29107
29121
|
api_host: options.apiHost ?? "https://posthog-dev.syntrologie.com",
|
|
29108
|
-
//
|
|
29109
|
-
|
|
29110
|
-
|
|
29122
|
+
// Feature flags for segment membership (in_segment_* flags)
|
|
29123
|
+
// When enabled, /decide is called to get segment flags
|
|
29124
|
+
advanced_disable_feature_flags: !enableFeatureFlags,
|
|
29125
|
+
advanced_disable_feature_flags_on_first_load: !enableFeatureFlags,
|
|
29111
29126
|
// Full-page tracking - all ON by default
|
|
29112
29127
|
autocapture: options.autocapture ?? true,
|
|
29113
29128
|
capture_pageview: options.capturePageview ?? true,
|
|
@@ -29124,10 +29139,43 @@ var SyntrologieSDK = (() => {
|
|
|
29124
29139
|
// Capture performance metrics
|
|
29125
29140
|
capture_performance: true,
|
|
29126
29141
|
// Enable web vitals
|
|
29127
|
-
enable_recording_console_log: true
|
|
29142
|
+
enable_recording_console_log: true,
|
|
29143
|
+
// Bootstrap callback for when flags are loaded
|
|
29144
|
+
loaded: (ph) => {
|
|
29145
|
+
if (enableFeatureFlags && this.featureFlagsCallback) {
|
|
29146
|
+
ph.onFeatureFlags(() => {
|
|
29147
|
+
const allFlags = this.getAllFeatureFlags();
|
|
29148
|
+
if (allFlags && this.featureFlagsCallback) {
|
|
29149
|
+
this.featureFlagsCallback(allFlags);
|
|
29150
|
+
}
|
|
29151
|
+
});
|
|
29152
|
+
}
|
|
29153
|
+
}
|
|
29128
29154
|
});
|
|
29129
29155
|
}
|
|
29130
29156
|
}
|
|
29157
|
+
/**
|
|
29158
|
+
* Get all feature flags from PostHog.
|
|
29159
|
+
* Used to extract segment membership flags (in_segment_*).
|
|
29160
|
+
*/
|
|
29161
|
+
getAllFeatureFlags() {
|
|
29162
|
+
const flags = this.client?.featureFlags?.getFlagVariants?.();
|
|
29163
|
+
return flags;
|
|
29164
|
+
}
|
|
29165
|
+
/**
|
|
29166
|
+
* Get segment membership flags (in_segment_*) from PostHog.
|
|
29167
|
+
*/
|
|
29168
|
+
getSegmentFlags() {
|
|
29169
|
+
const allFlags = this.getAllFeatureFlags();
|
|
29170
|
+
if (!allFlags) return {};
|
|
29171
|
+
const segmentFlags = {};
|
|
29172
|
+
for (const [key, value] of Object.entries(allFlags)) {
|
|
29173
|
+
if (key.startsWith("in_segment_")) {
|
|
29174
|
+
segmentFlags[key] = value === true;
|
|
29175
|
+
}
|
|
29176
|
+
}
|
|
29177
|
+
return segmentFlags;
|
|
29178
|
+
}
|
|
29131
29179
|
identify(id, props) {
|
|
29132
29180
|
this.client?.identify(id, props);
|
|
29133
29181
|
}
|
|
@@ -29176,6 +29224,9 @@ var SyntrologieSDK = (() => {
|
|
|
29176
29224
|
setPersonPropertiesOnce(properties) {
|
|
29177
29225
|
this.client?.capture("$set", { $set_once: properties });
|
|
29178
29226
|
}
|
|
29227
|
+
getDistinctId() {
|
|
29228
|
+
return this.client?.get_distinct_id?.();
|
|
29229
|
+
}
|
|
29179
29230
|
};
|
|
29180
29231
|
function createPostHogClient(options = {}) {
|
|
29181
29232
|
return new PostHogAdapter(options);
|
|
@@ -39170,6 +39221,151 @@ var SyntrologieSDK = (() => {
|
|
|
39170
39221
|
};
|
|
39171
39222
|
}
|
|
39172
39223
|
|
|
39224
|
+
// src/metrics/sessionMetrics.ts
|
|
39225
|
+
var STORAGE_KEY = "syntro_session_metrics";
|
|
39226
|
+
var SessionMetricTracker = class {
|
|
39227
|
+
constructor(options = {}) {
|
|
39228
|
+
__publicField(this, "metrics", /* @__PURE__ */ new Map());
|
|
39229
|
+
__publicField(this, "experiments");
|
|
39230
|
+
__publicField(this, "attributePrefix");
|
|
39231
|
+
__publicField(this, "onMetricChange");
|
|
39232
|
+
this.experiments = options.experiments;
|
|
39233
|
+
this.attributePrefix = options.attributePrefix ?? "session_";
|
|
39234
|
+
this.onMetricChange = options.onMetricChange;
|
|
39235
|
+
this.loadFromStorage();
|
|
39236
|
+
}
|
|
39237
|
+
/**
|
|
39238
|
+
* Increment a metric by the specified amount.
|
|
39239
|
+
*
|
|
39240
|
+
* @param metricKey - The metric to increment (e.g., "button_clicks", "page_views")
|
|
39241
|
+
* @param amount - Amount to increment by (default: 1)
|
|
39242
|
+
* @returns The new metric value
|
|
39243
|
+
*/
|
|
39244
|
+
increment(metricKey, amount = 1) {
|
|
39245
|
+
const currentValue = this.metrics.get(metricKey) ?? 0;
|
|
39246
|
+
const newValue = currentValue + amount;
|
|
39247
|
+
this.metrics.set(metricKey, newValue);
|
|
39248
|
+
this.saveToStorage();
|
|
39249
|
+
this.updateExperimentAttributes(metricKey, newValue);
|
|
39250
|
+
this.onMetricChange?.(metricKey, newValue);
|
|
39251
|
+
return newValue;
|
|
39252
|
+
}
|
|
39253
|
+
/**
|
|
39254
|
+
* Set a metric to a specific value.
|
|
39255
|
+
*
|
|
39256
|
+
* @param metricKey - The metric to set
|
|
39257
|
+
* @param value - The value to set
|
|
39258
|
+
*/
|
|
39259
|
+
set(metricKey, value) {
|
|
39260
|
+
this.metrics.set(metricKey, value);
|
|
39261
|
+
this.saveToStorage();
|
|
39262
|
+
this.updateExperimentAttributes(metricKey, value);
|
|
39263
|
+
this.onMetricChange?.(metricKey, value);
|
|
39264
|
+
}
|
|
39265
|
+
/**
|
|
39266
|
+
* Get the current value of a metric.
|
|
39267
|
+
*
|
|
39268
|
+
* @param metricKey - The metric to get
|
|
39269
|
+
* @returns The current value (0 if not set)
|
|
39270
|
+
*/
|
|
39271
|
+
get(metricKey) {
|
|
39272
|
+
return this.metrics.get(metricKey) ?? 0;
|
|
39273
|
+
}
|
|
39274
|
+
/**
|
|
39275
|
+
* Check if a metric meets or exceeds a threshold.
|
|
39276
|
+
*
|
|
39277
|
+
* @param metricKey - The metric to check
|
|
39278
|
+
* @param threshold - The threshold value
|
|
39279
|
+
* @returns True if metric >= threshold
|
|
39280
|
+
*/
|
|
39281
|
+
meetsThreshold(metricKey, threshold) {
|
|
39282
|
+
return this.get(metricKey) >= threshold;
|
|
39283
|
+
}
|
|
39284
|
+
/**
|
|
39285
|
+
* Get all current metric values.
|
|
39286
|
+
*
|
|
39287
|
+
* @returns Record of metric keys to values
|
|
39288
|
+
*/
|
|
39289
|
+
getAll() {
|
|
39290
|
+
return Object.fromEntries(this.metrics);
|
|
39291
|
+
}
|
|
39292
|
+
/**
|
|
39293
|
+
* Reset a specific metric to zero.
|
|
39294
|
+
*
|
|
39295
|
+
* @param metricKey - The metric to reset
|
|
39296
|
+
*/
|
|
39297
|
+
reset(metricKey) {
|
|
39298
|
+
this.metrics.delete(metricKey);
|
|
39299
|
+
this.saveToStorage();
|
|
39300
|
+
this.updateExperimentAttributes(metricKey, 0);
|
|
39301
|
+
this.onMetricChange?.(metricKey, 0);
|
|
39302
|
+
}
|
|
39303
|
+
/**
|
|
39304
|
+
* Reset all metrics (clear the session).
|
|
39305
|
+
*/
|
|
39306
|
+
resetAll() {
|
|
39307
|
+
const keys = Array.from(this.metrics.keys());
|
|
39308
|
+
this.metrics.clear();
|
|
39309
|
+
this.saveToStorage();
|
|
39310
|
+
const attrs = {};
|
|
39311
|
+
for (const key of keys) {
|
|
39312
|
+
attrs[`${this.attributePrefix}${key}`] = 0;
|
|
39313
|
+
this.onMetricChange?.(key, 0);
|
|
39314
|
+
}
|
|
39315
|
+
this.experiments?.setAttributes?.(attrs);
|
|
39316
|
+
}
|
|
39317
|
+
/**
|
|
39318
|
+
* Update the experiment client (useful if experiments client changes).
|
|
39319
|
+
*/
|
|
39320
|
+
setExperiments(experiments) {
|
|
39321
|
+
this.experiments = experiments;
|
|
39322
|
+
this.syncAllToExperiments();
|
|
39323
|
+
}
|
|
39324
|
+
// ==================== Private Methods ====================
|
|
39325
|
+
updateExperimentAttributes(metricKey, value) {
|
|
39326
|
+
if (!this.experiments?.setAttributes) return;
|
|
39327
|
+
const attributeKey = `${this.attributePrefix}${metricKey}`;
|
|
39328
|
+
this.experiments.setAttributes({ [attributeKey]: value });
|
|
39329
|
+
}
|
|
39330
|
+
syncAllToExperiments() {
|
|
39331
|
+
if (!this.experiments?.setAttributes) return;
|
|
39332
|
+
const attrs = {};
|
|
39333
|
+
for (const [key, value] of this.metrics) {
|
|
39334
|
+
attrs[`${this.attributePrefix}${key}`] = value;
|
|
39335
|
+
}
|
|
39336
|
+
this.experiments.setAttributes(attrs);
|
|
39337
|
+
}
|
|
39338
|
+
loadFromStorage() {
|
|
39339
|
+
if (typeof window === "undefined" || typeof sessionStorage === "undefined") return;
|
|
39340
|
+
try {
|
|
39341
|
+
const stored = sessionStorage.getItem(STORAGE_KEY);
|
|
39342
|
+
if (stored) {
|
|
39343
|
+
const data = JSON.parse(stored);
|
|
39344
|
+
for (const [key, value] of Object.entries(data)) {
|
|
39345
|
+
this.metrics.set(key, value.count);
|
|
39346
|
+
}
|
|
39347
|
+
}
|
|
39348
|
+
} catch (err) {
|
|
39349
|
+
console.warn("[SessionMetricTracker] Failed to load from sessionStorage:", err);
|
|
39350
|
+
}
|
|
39351
|
+
}
|
|
39352
|
+
saveToStorage() {
|
|
39353
|
+
if (typeof window === "undefined" || typeof sessionStorage === "undefined") return;
|
|
39354
|
+
try {
|
|
39355
|
+
const data = {};
|
|
39356
|
+
for (const [key, count] of this.metrics) {
|
|
39357
|
+
data[key] = { count, lastUpdated: Date.now() };
|
|
39358
|
+
}
|
|
39359
|
+
sessionStorage.setItem(STORAGE_KEY, JSON.stringify(data));
|
|
39360
|
+
} catch (err) {
|
|
39361
|
+
console.warn("[SessionMetricTracker] Failed to save to sessionStorage:", err);
|
|
39362
|
+
}
|
|
39363
|
+
}
|
|
39364
|
+
};
|
|
39365
|
+
function createSessionMetricTracker(options = {}) {
|
|
39366
|
+
return new SessionMetricTracker(options);
|
|
39367
|
+
}
|
|
39368
|
+
|
|
39173
39369
|
// src/token.ts
|
|
39174
39370
|
var TOKEN_PREFIX = "syn_";
|
|
39175
39371
|
function decodeToken(token) {
|
|
@@ -39421,6 +39617,40 @@ var SyntrologieSDK = (() => {
|
|
|
39421
39617
|
});
|
|
39422
39618
|
return hasToken;
|
|
39423
39619
|
}
|
|
39620
|
+
var SEGMENT_CACHE_KEY = "syntro_segment_attributes";
|
|
39621
|
+
function loadCachedSegmentAttributes() {
|
|
39622
|
+
if (typeof window === "undefined") return {};
|
|
39623
|
+
try {
|
|
39624
|
+
const cached = localStorage.getItem(SEGMENT_CACHE_KEY);
|
|
39625
|
+
if (cached) {
|
|
39626
|
+
const attrs = JSON.parse(cached);
|
|
39627
|
+
console.log("[Syntro Bootstrap] Loaded cached segment attributes:", attrs);
|
|
39628
|
+
return attrs;
|
|
39629
|
+
}
|
|
39630
|
+
} catch (err) {
|
|
39631
|
+
console.warn("[Syntro Bootstrap] Failed to load cached segment attributes:", err);
|
|
39632
|
+
}
|
|
39633
|
+
return {};
|
|
39634
|
+
}
|
|
39635
|
+
function cacheSegmentAttributes(attrs) {
|
|
39636
|
+
if (typeof window === "undefined") return;
|
|
39637
|
+
try {
|
|
39638
|
+
localStorage.setItem(SEGMENT_CACHE_KEY, JSON.stringify(attrs));
|
|
39639
|
+
console.log("[Syntro Bootstrap] Cached segment attributes:", attrs);
|
|
39640
|
+
} catch (err) {
|
|
39641
|
+
console.warn("[Syntro Bootstrap] Failed to cache segment attributes:", err);
|
|
39642
|
+
}
|
|
39643
|
+
}
|
|
39644
|
+
function extractSegmentFlags(allFlags) {
|
|
39645
|
+
if (!allFlags) return {};
|
|
39646
|
+
const segmentFlags = {};
|
|
39647
|
+
for (const [key, value] of Object.entries(allFlags)) {
|
|
39648
|
+
if (key.startsWith("in_segment_")) {
|
|
39649
|
+
segmentFlags[key] = value === true;
|
|
39650
|
+
}
|
|
39651
|
+
}
|
|
39652
|
+
return segmentFlags;
|
|
39653
|
+
}
|
|
39424
39654
|
async function init(options) {
|
|
39425
39655
|
console.log("[Syntro Bootstrap] ====== INIT ======");
|
|
39426
39656
|
console.log("[Syntro Bootstrap] Options:", {
|
|
@@ -39451,20 +39681,41 @@ var SyntrologieSDK = (() => {
|
|
|
39451
39681
|
const experimentHost = getEnvVar("NEXT_PUBLIC_SYNTRO_EXPERIMENT_HOST") || getEnvVar("VITE_SYNTRO_EXPERIMENT_HOST") || payload?.eh;
|
|
39452
39682
|
const telemetryHost = getEnvVar("NEXT_PUBLIC_SYNTRO_TELEMETRY_HOST") || getEnvVar("VITE_SYNTRO_TELEMETRY_HOST") || payload?.th;
|
|
39453
39683
|
const editorUrl = getEnvVar("NEXT_PUBLIC_SYNTRO_EDITOR_URL") || getEnvVar("VITE_SYNTRO_EDITOR_URL") || options.canvas?.editorUrl;
|
|
39684
|
+
const cachedSegmentAttrs = loadCachedSegmentAttributes();
|
|
39685
|
+
console.log("[Syntro Bootstrap] Phase 1: Using cached segment attributes:", cachedSegmentAttrs);
|
|
39686
|
+
let experiments;
|
|
39687
|
+
const onFeatureFlagsLoaded = (allFlags) => {
|
|
39688
|
+
console.log("[Syntro Bootstrap] Phase 2: PostHog feature flags loaded");
|
|
39689
|
+
const segmentFlags = extractSegmentFlags(allFlags);
|
|
39690
|
+
console.log("[Syntro Bootstrap] Segment flags from PostHog:", segmentFlags);
|
|
39691
|
+
cacheSegmentAttributes(segmentFlags);
|
|
39692
|
+
if (experiments) {
|
|
39693
|
+
const sessionAttrs = sessionMetrics?.getAll?.() ?? {};
|
|
39694
|
+
const updatedAttrs = { ...sessionAttrs, ...segmentFlags };
|
|
39695
|
+
console.log("[Syntro Bootstrap] Updating GrowthBook with attributes:", updatedAttrs);
|
|
39696
|
+
experiments.setAttributes?.(updatedAttrs);
|
|
39697
|
+
}
|
|
39698
|
+
};
|
|
39454
39699
|
let telemetry;
|
|
39455
39700
|
if (payload?.t) {
|
|
39456
39701
|
telemetry = createTelemetryClient("posthog", {
|
|
39457
39702
|
apiKey: payload.t,
|
|
39458
|
-
apiHost: telemetryHost
|
|
39703
|
+
apiHost: telemetryHost,
|
|
39459
39704
|
// undefined falls back to adapter default
|
|
39705
|
+
// Enable PostHog feature flags for segment membership
|
|
39706
|
+
enableFeatureFlags: true,
|
|
39707
|
+
// Wire up callback for when flags are loaded (Phase 2)
|
|
39708
|
+
onFeatureFlagsLoaded
|
|
39460
39709
|
});
|
|
39461
39710
|
}
|
|
39462
|
-
let
|
|
39711
|
+
let sessionMetrics;
|
|
39463
39712
|
if (payload?.e) {
|
|
39464
39713
|
experiments = createExperimentClient("growthbook", {
|
|
39465
39714
|
clientKey: payload.e,
|
|
39466
39715
|
apiHost: experimentHost,
|
|
39467
39716
|
// undefined falls back to adapter default
|
|
39717
|
+
// Phase 1: Use cached segment attributes for instant evaluation
|
|
39718
|
+
attributes: cachedSegmentAttrs,
|
|
39468
39719
|
// Wire experiment tracking to telemetry provider
|
|
39469
39720
|
onExperimentViewed: telemetry?.trackExperiment ? (key, variationId, variationName) => {
|
|
39470
39721
|
telemetry.trackExperiment(key, variationId, variationName);
|
|
@@ -39486,13 +39737,22 @@ var SyntrologieSDK = (() => {
|
|
|
39486
39737
|
} else if (experiments) {
|
|
39487
39738
|
fetcher = createCanvasConfigFetcher({ experiments });
|
|
39488
39739
|
}
|
|
39740
|
+
if (options.enableSessionMetrics) {
|
|
39741
|
+
sessionMetrics = createSessionMetricTracker({
|
|
39742
|
+
experiments,
|
|
39743
|
+
onMetricChange: (key, value) => {
|
|
39744
|
+
console.log(`[Syntro Bootstrap] Session metric changed: ${key} = ${value}`);
|
|
39745
|
+
}
|
|
39746
|
+
});
|
|
39747
|
+
console.log("[Syntro Bootstrap] SessionMetricTracker created");
|
|
39748
|
+
}
|
|
39489
39749
|
const canvas = await createSmartCanvas({
|
|
39490
39750
|
...options.canvas,
|
|
39491
39751
|
fetcher,
|
|
39492
39752
|
integrations: { experiments, telemetry },
|
|
39493
39753
|
editorUrl
|
|
39494
39754
|
});
|
|
39495
|
-
return { canvas, experiments, telemetry };
|
|
39755
|
+
return { canvas, experiments, telemetry, sessionMetrics };
|
|
39496
39756
|
}
|
|
39497
39757
|
var Syntro = {
|
|
39498
39758
|
init,
|