@syntrologie/runtime-sdk 2.15.0 → 2.16.0
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/SmartCanvasApp.d.ts +4 -1
- package/dist/api.d.ts +3 -0
- package/dist/bootstrap-init.d.ts +2 -0
- package/dist/{chunk-CVMZW3II.js → chunk-NVV7IWJC.js} +330 -24
- package/dist/{chunk-CVMZW3II.js.map → chunk-NVV7IWJC.js.map} +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +75 -1
- package/dist/index.js.map +4 -4
- package/dist/platform/PlatformAdapter.d.ts +46 -0
- package/dist/platform/ShopifyAdapter.d.ts +36 -0
- package/dist/platform/ShopifyAnchorResolver.d.ts +31 -0
- package/dist/platform/ShopifyAntiFlicker.d.ts +21 -0
- package/dist/platform/ShopifyPixelBridge.d.ts +37 -0
- package/dist/platform/detect.d.ts +9 -0
- package/dist/platform/index.d.ts +10 -0
- package/dist/platform/shopify-cookie-contract.d.ts +39 -0
- package/dist/react.js +1 -1
- package/dist/shopify-pixel-entry.d.ts +68 -0
- package/dist/shopify-pixel.js +77 -0
- package/dist/shopify-pixel.js.map +7 -0
- package/dist/shopify-pixel.min.js +2 -0
- package/dist/shopify-pixel.min.js.map +7 -0
- package/dist/smart-canvas.esm.js +135 -135
- package/dist/smart-canvas.esm.js.map +4 -4
- package/dist/smart-canvas.js +288 -10
- package/dist/smart-canvas.js.map +4 -4
- package/dist/smart-canvas.min.js +135 -135
- package/dist/smart-canvas.min.js.map +4 -4
- package/dist/version.d.ts +1 -1
- package/package.json +1 -1
package/dist/smart-canvas.js
CHANGED
|
@@ -12645,7 +12645,7 @@ Please report this to https://github.com/markedjs/marked.`, e9) {
|
|
|
12645
12645
|
}
|
|
12646
12646
|
|
|
12647
12647
|
// src/version.ts
|
|
12648
|
-
var SDK_VERSION = "2.
|
|
12648
|
+
var SDK_VERSION = "2.16.0";
|
|
12649
12649
|
|
|
12650
12650
|
// src/types.ts
|
|
12651
12651
|
var SDK_SCHEMA_VERSION = "2.0";
|
|
@@ -22204,12 +22204,8 @@ ${cssRules}
|
|
|
22204
22204
|
if (typeof process !== "undefined" && process.env) {
|
|
22205
22205
|
return process.env[name];
|
|
22206
22206
|
}
|
|
22207
|
-
|
|
22208
|
-
|
|
22209
|
-
if (meta?.env) {
|
|
22210
|
-
return meta.env[name];
|
|
22211
|
-
}
|
|
22212
|
-
} catch {
|
|
22207
|
+
if (false) {
|
|
22208
|
+
return (void 0)[name];
|
|
22213
22209
|
}
|
|
22214
22210
|
return void 0;
|
|
22215
22211
|
}
|
|
@@ -25849,6 +25845,250 @@ ${cssRules}
|
|
|
25849
25845
|
return new SessionMetricTracker(options);
|
|
25850
25846
|
}
|
|
25851
25847
|
|
|
25848
|
+
// src/platform/ShopifyAntiFlicker.ts
|
|
25849
|
+
var ShopifyAntiFlicker = class {
|
|
25850
|
+
constructor(adapter) {
|
|
25851
|
+
this.unsubUnload = null;
|
|
25852
|
+
this.unsubLoad = null;
|
|
25853
|
+
this.destroyed = false;
|
|
25854
|
+
this.adapter = adapter;
|
|
25855
|
+
}
|
|
25856
|
+
activate() {
|
|
25857
|
+
if (this.destroyed) return;
|
|
25858
|
+
this.unsubUnload = this.adapter.onRegionWillUnload((sectionId) => {
|
|
25859
|
+
this.hideContentInSection(sectionId);
|
|
25860
|
+
});
|
|
25861
|
+
this.unsubLoad = this.adapter.onRegionDidLoad((sectionId) => {
|
|
25862
|
+
this.revealContentInSection(sectionId);
|
|
25863
|
+
});
|
|
25864
|
+
}
|
|
25865
|
+
destroy() {
|
|
25866
|
+
this.destroyed = true;
|
|
25867
|
+
this.unsubUnload?.();
|
|
25868
|
+
this.unsubLoad?.();
|
|
25869
|
+
this.unsubUnload = null;
|
|
25870
|
+
this.unsubLoad = null;
|
|
25871
|
+
}
|
|
25872
|
+
hideContentInSection(sectionId) {
|
|
25873
|
+
const selector = this.sectionSelector(sectionId);
|
|
25874
|
+
const elements2 = document.querySelectorAll(`${selector} [data-syntro-action-id]`);
|
|
25875
|
+
for (const el of elements2) {
|
|
25876
|
+
el.style.opacity = "0";
|
|
25877
|
+
el.style.transition = "none";
|
|
25878
|
+
}
|
|
25879
|
+
}
|
|
25880
|
+
revealContentInSection(sectionId) {
|
|
25881
|
+
const selector = this.sectionSelector(sectionId);
|
|
25882
|
+
requestAnimationFrame(() => {
|
|
25883
|
+
if (this.destroyed) return;
|
|
25884
|
+
const elements2 = document.querySelectorAll(
|
|
25885
|
+
`${selector} [data-syntro-action-id]`
|
|
25886
|
+
);
|
|
25887
|
+
for (const el of elements2) {
|
|
25888
|
+
el.style.transition = "opacity 120ms ease-in";
|
|
25889
|
+
el.style.opacity = "1";
|
|
25890
|
+
}
|
|
25891
|
+
});
|
|
25892
|
+
}
|
|
25893
|
+
sectionSelector(sectionId) {
|
|
25894
|
+
const escaped = typeof CSS !== "undefined" ? CSS.escape(sectionId) : sectionId;
|
|
25895
|
+
const byId = document.getElementById(`shopify-section-${sectionId}`);
|
|
25896
|
+
if (byId) return `#shopify-section-${escaped}`;
|
|
25897
|
+
return `.shopify-section[id$="-${escaped}"]`;
|
|
25898
|
+
}
|
|
25899
|
+
};
|
|
25900
|
+
|
|
25901
|
+
// src/platform/ShopifyAdapter.ts
|
|
25902
|
+
var ShopifyAdapter = class {
|
|
25903
|
+
constructor(options) {
|
|
25904
|
+
this.name = "shopify";
|
|
25905
|
+
this.loadCallbacks = /* @__PURE__ */ new Set();
|
|
25906
|
+
this.unloadCallbacks = /* @__PURE__ */ new Set();
|
|
25907
|
+
this.abortController = null;
|
|
25908
|
+
this.antiFlicker = null;
|
|
25909
|
+
this.initTimeoutMs = options?.initTimeoutMs ?? 3e3;
|
|
25910
|
+
}
|
|
25911
|
+
// --------------------------------------------------------------------------
|
|
25912
|
+
// Detection
|
|
25913
|
+
// --------------------------------------------------------------------------
|
|
25914
|
+
detect() {
|
|
25915
|
+
if (typeof window === "undefined" || typeof document === "undefined") {
|
|
25916
|
+
return false;
|
|
25917
|
+
}
|
|
25918
|
+
if ("Shopify" in window && window.Shopify != null) {
|
|
25919
|
+
return true;
|
|
25920
|
+
}
|
|
25921
|
+
if (document.querySelector('meta[name="shopify-checkout-api-token"]')) {
|
|
25922
|
+
return true;
|
|
25923
|
+
}
|
|
25924
|
+
return false;
|
|
25925
|
+
}
|
|
25926
|
+
// --------------------------------------------------------------------------
|
|
25927
|
+
// Initialization
|
|
25928
|
+
// --------------------------------------------------------------------------
|
|
25929
|
+
/**
|
|
25930
|
+
* Wait for Shopify sections to be ready, then attach lifecycle listeners.
|
|
25931
|
+
*
|
|
25932
|
+
* Resolution order:
|
|
25933
|
+
* 1. `.shopify-section` already in DOM -> resolve immediately
|
|
25934
|
+
* 2. `shopify:section:load` fires -> resolve
|
|
25935
|
+
* 3. Timeout (default 3000ms) -> resolve anyway (graceful degradation)
|
|
25936
|
+
*/
|
|
25937
|
+
async onInit() {
|
|
25938
|
+
this.abortController = new AbortController();
|
|
25939
|
+
const { signal } = this.abortController;
|
|
25940
|
+
this.attachSectionListeners(signal);
|
|
25941
|
+
this.antiFlicker = new ShopifyAntiFlicker(this);
|
|
25942
|
+
this.antiFlicker.activate();
|
|
25943
|
+
await this.waitForInitialSections(this.initTimeoutMs, signal);
|
|
25944
|
+
}
|
|
25945
|
+
// --------------------------------------------------------------------------
|
|
25946
|
+
// Region lifecycle subscriptions
|
|
25947
|
+
// --------------------------------------------------------------------------
|
|
25948
|
+
onRegionDidLoad(callback) {
|
|
25949
|
+
this.loadCallbacks.add(callback);
|
|
25950
|
+
return () => {
|
|
25951
|
+
this.loadCallbacks.delete(callback);
|
|
25952
|
+
};
|
|
25953
|
+
}
|
|
25954
|
+
onRegionWillUnload(callback) {
|
|
25955
|
+
this.unloadCallbacks.add(callback);
|
|
25956
|
+
return () => {
|
|
25957
|
+
this.unloadCallbacks.delete(callback);
|
|
25958
|
+
};
|
|
25959
|
+
}
|
|
25960
|
+
onRegionMutated(_regionId) {
|
|
25961
|
+
}
|
|
25962
|
+
// --------------------------------------------------------------------------
|
|
25963
|
+
// Anchor scope
|
|
25964
|
+
// --------------------------------------------------------------------------
|
|
25965
|
+
getAnchorScope(anchor) {
|
|
25966
|
+
const section = anchor.closest(".shopify-section");
|
|
25967
|
+
if (section?.id) {
|
|
25968
|
+
const escaped = typeof CSS !== "undefined" ? CSS.escape(section.id) : section.id;
|
|
25969
|
+
return `#${escaped} `;
|
|
25970
|
+
}
|
|
25971
|
+
return "";
|
|
25972
|
+
}
|
|
25973
|
+
// --------------------------------------------------------------------------
|
|
25974
|
+
// Teardown
|
|
25975
|
+
// --------------------------------------------------------------------------
|
|
25976
|
+
destroy() {
|
|
25977
|
+
this.antiFlicker?.destroy();
|
|
25978
|
+
this.antiFlicker = null;
|
|
25979
|
+
if (this.abortController) {
|
|
25980
|
+
this.abortController.abort();
|
|
25981
|
+
this.abortController = null;
|
|
25982
|
+
}
|
|
25983
|
+
this.loadCallbacks.clear();
|
|
25984
|
+
this.unloadCallbacks.clear();
|
|
25985
|
+
}
|
|
25986
|
+
// --------------------------------------------------------------------------
|
|
25987
|
+
// Private
|
|
25988
|
+
// --------------------------------------------------------------------------
|
|
25989
|
+
attachSectionListeners(signal) {
|
|
25990
|
+
document.addEventListener(
|
|
25991
|
+
"shopify:section:load",
|
|
25992
|
+
(event) => {
|
|
25993
|
+
const sectionId = event.detail?.sectionId;
|
|
25994
|
+
if (sectionId) {
|
|
25995
|
+
for (const cb of this.loadCallbacks) {
|
|
25996
|
+
try {
|
|
25997
|
+
cb(sectionId);
|
|
25998
|
+
} catch {
|
|
25999
|
+
}
|
|
26000
|
+
}
|
|
26001
|
+
}
|
|
26002
|
+
},
|
|
26003
|
+
{ signal }
|
|
26004
|
+
);
|
|
26005
|
+
document.addEventListener(
|
|
26006
|
+
"shopify:section:unload",
|
|
26007
|
+
(event) => {
|
|
26008
|
+
const sectionId = event.detail?.sectionId;
|
|
26009
|
+
if (sectionId) {
|
|
26010
|
+
for (const cb of this.unloadCallbacks) {
|
|
26011
|
+
try {
|
|
26012
|
+
cb(sectionId);
|
|
26013
|
+
} catch {
|
|
26014
|
+
}
|
|
26015
|
+
}
|
|
26016
|
+
}
|
|
26017
|
+
},
|
|
26018
|
+
{ signal }
|
|
26019
|
+
);
|
|
26020
|
+
}
|
|
26021
|
+
waitForInitialSections(timeoutMs, signal) {
|
|
26022
|
+
return new Promise((resolve) => {
|
|
26023
|
+
if (document.querySelector(".shopify-section")) {
|
|
26024
|
+
resolve();
|
|
26025
|
+
return;
|
|
26026
|
+
}
|
|
26027
|
+
let resolved = false;
|
|
26028
|
+
const done = () => {
|
|
26029
|
+
if (resolved) return;
|
|
26030
|
+
resolved = true;
|
|
26031
|
+
resolve();
|
|
26032
|
+
};
|
|
26033
|
+
document.addEventListener("shopify:section:load", () => done(), { once: true, signal });
|
|
26034
|
+
const timer = setTimeout(done, timeoutMs);
|
|
26035
|
+
signal.addEventListener(
|
|
26036
|
+
"abort",
|
|
26037
|
+
() => {
|
|
26038
|
+
clearTimeout(timer);
|
|
26039
|
+
done();
|
|
26040
|
+
},
|
|
26041
|
+
{ once: true }
|
|
26042
|
+
);
|
|
26043
|
+
});
|
|
26044
|
+
}
|
|
26045
|
+
};
|
|
26046
|
+
|
|
26047
|
+
// src/platform/detect.ts
|
|
26048
|
+
var ADAPTERS = [() => new ShopifyAdapter()];
|
|
26049
|
+
function detectPlatform() {
|
|
26050
|
+
for (const create of ADAPTERS) {
|
|
26051
|
+
const adapter = create();
|
|
26052
|
+
if (adapter.detect()) {
|
|
26053
|
+
return adapter;
|
|
26054
|
+
}
|
|
26055
|
+
}
|
|
26056
|
+
return null;
|
|
26057
|
+
}
|
|
26058
|
+
|
|
26059
|
+
// src/platform/shopify-cookie-contract.ts
|
|
26060
|
+
var COOKIE_NAME = "syntro_experiments";
|
|
26061
|
+
var COOKIE_VERSION = 1;
|
|
26062
|
+
|
|
26063
|
+
// src/platform/ShopifyPixelBridge.ts
|
|
26064
|
+
var MAX_AGE_SECONDS = 30 * 24 * 60 * 60;
|
|
26065
|
+
var ShopifyPixelBridge = class {
|
|
26066
|
+
constructor(context) {
|
|
26067
|
+
this.context = { ...context, telemetryHost: context.telemetryHost.replace(/\/$/, "") };
|
|
26068
|
+
this.writeCookie();
|
|
26069
|
+
}
|
|
26070
|
+
/** Update the telemetry context (e.g., after consent is granted and
|
|
26071
|
+
* PostHog finally initializes and a real distinct_id becomes available). */
|
|
26072
|
+
updateContext(context) {
|
|
26073
|
+
this.context = { ...context, telemetryHost: context.telemetryHost.replace(/\/$/, "") };
|
|
26074
|
+
this.writeCookie();
|
|
26075
|
+
}
|
|
26076
|
+
destroy() {
|
|
26077
|
+
document.cookie = `${COOKIE_NAME}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=Lax`;
|
|
26078
|
+
}
|
|
26079
|
+
writeCookie() {
|
|
26080
|
+
const payload = {
|
|
26081
|
+
version: COOKIE_VERSION,
|
|
26082
|
+
distinct_id: this.context.distinctId,
|
|
26083
|
+
telemetry_host: this.context.telemetryHost,
|
|
26084
|
+
telemetry_key: this.context.telemetryKey
|
|
26085
|
+
};
|
|
26086
|
+
const value = encodeURIComponent(JSON.stringify(payload));
|
|
26087
|
+
const cookieString = `${COOKIE_NAME}=${value}; max-age=${MAX_AGE_SECONDS}; path=/; SameSite=Lax`;
|
|
26088
|
+
document.cookie = cookieString;
|
|
26089
|
+
}
|
|
26090
|
+
};
|
|
26091
|
+
|
|
25852
26092
|
// src/context/ContextManager.ts
|
|
25853
26093
|
function createDefaultContext() {
|
|
25854
26094
|
const now = Date.now();
|
|
@@ -33007,6 +33247,8 @@ ${cssRules}
|
|
|
33007
33247
|
true
|
|
33008
33248
|
);
|
|
33009
33249
|
}
|
|
33250
|
+
const platformAdapter = detectPlatform();
|
|
33251
|
+
let shopifyPixelBridge;
|
|
33010
33252
|
const onFeatureFlagsLoaded = (allFlags) => {
|
|
33011
33253
|
debug("Syntro Bootstrap", "Phase 2: PostHog feature flags loaded");
|
|
33012
33254
|
const segmentFlags = extractSegmentFlags(allFlags);
|
|
@@ -33023,6 +33265,16 @@ ${cssRules}
|
|
|
33023
33265
|
debug("Syntro Bootstrap", "Updating GrowthBook with attributes:", updatedAttrs);
|
|
33024
33266
|
experiments.setAttributes?.(updatedAttrs);
|
|
33025
33267
|
}
|
|
33268
|
+
if (shopifyPixelBridge && telemetry?.getDistinctId) {
|
|
33269
|
+
const distinctId = telemetry.getDistinctId();
|
|
33270
|
+
if (distinctId && telemetryHost && payload?.t) {
|
|
33271
|
+
shopifyPixelBridge.updateContext({
|
|
33272
|
+
distinctId,
|
|
33273
|
+
telemetryHost,
|
|
33274
|
+
telemetryKey: payload.t
|
|
33275
|
+
});
|
|
33276
|
+
}
|
|
33277
|
+
}
|
|
33026
33278
|
};
|
|
33027
33279
|
let telemetry;
|
|
33028
33280
|
if (payload?.t) {
|
|
@@ -33054,6 +33306,18 @@ ${cssRules}
|
|
|
33054
33306
|
events.setPosthogCapture((name, props) => {
|
|
33055
33307
|
telemetryForCapture.track?.(name, props);
|
|
33056
33308
|
});
|
|
33309
|
+
if (platformAdapter?.name === "shopify" && telemetryHost) {
|
|
33310
|
+
try {
|
|
33311
|
+
shopifyPixelBridge = new ShopifyPixelBridge({
|
|
33312
|
+
distinctId: telemetry.getDistinctId?.() ?? "",
|
|
33313
|
+
telemetryHost,
|
|
33314
|
+
telemetryKey: payload.t
|
|
33315
|
+
});
|
|
33316
|
+
debug("Syntro Bootstrap", "ShopifyPixelBridge initialized for checkout attribution");
|
|
33317
|
+
} catch (err) {
|
|
33318
|
+
warn("Syntro Bootstrap", "ShopifyPixelBridge init failed", err);
|
|
33319
|
+
}
|
|
33320
|
+
}
|
|
33057
33321
|
}
|
|
33058
33322
|
let sessionMetrics;
|
|
33059
33323
|
if (payload?.e) {
|
|
@@ -33063,7 +33327,11 @@ ${cssRules}
|
|
|
33063
33327
|
// undefined falls back to adapter default
|
|
33064
33328
|
// Phase 1: Use browser metadata + cached segment attributes for instant evaluation
|
|
33065
33329
|
attributes: phaseOneAttrs,
|
|
33066
|
-
// Wire experiment tracking to telemetry provider
|
|
33330
|
+
// Wire experiment tracking to telemetry provider. PostHog registers
|
|
33331
|
+
// the assignment as a super-property + fires `$experiment_started`;
|
|
33332
|
+
// every future event from this distinct_id (including checkout events
|
|
33333
|
+
// posted by the Shopify Web Pixel) is then auto-attributed to the
|
|
33334
|
+
// variant server-side, so the pixel doesn't need to re-transmit.
|
|
33067
33335
|
onExperimentViewed: telemetry?.trackExperiment ? (key, variationId, variationName) => {
|
|
33068
33336
|
telemetry.trackExperiment(key, variationId, variationName);
|
|
33069
33337
|
} : void 0
|
|
@@ -33255,13 +33523,23 @@ ${cssRules}
|
|
|
33255
33523
|
}
|
|
33256
33524
|
return config;
|
|
33257
33525
|
} : void 0;
|
|
33526
|
+
if (platformAdapter) {
|
|
33527
|
+
debug("Syntro Bootstrap", `Detected platform: ${platformAdapter.name}`);
|
|
33528
|
+
try {
|
|
33529
|
+
await platformAdapter.onInit();
|
|
33530
|
+
debug("Syntro Bootstrap", `Platform adapter initialized: ${platformAdapter.name}`);
|
|
33531
|
+
} catch (err) {
|
|
33532
|
+
warn("Syntro Bootstrap", `Platform adapter init failed: ${platformAdapter.name}`, err);
|
|
33533
|
+
}
|
|
33534
|
+
}
|
|
33258
33535
|
const canvas = await createSmartCanvas({
|
|
33259
33536
|
...options.canvas,
|
|
33260
33537
|
fetcher: appLoadingFetcher,
|
|
33261
33538
|
integrations: { experiments, telemetry },
|
|
33262
33539
|
editorUrl,
|
|
33263
|
-
runtime: runtime8
|
|
33540
|
+
runtime: runtime8,
|
|
33264
33541
|
// Pass runtime so actions can be applied
|
|
33542
|
+
platformAdapter: platformAdapter ?? void 0
|
|
33265
33543
|
});
|
|
33266
33544
|
return { canvas, runtime: runtime8, experiments, telemetry, sessionMetrics, appLoader };
|
|
33267
33545
|
}
|
|
@@ -33691,7 +33969,7 @@ ${cssRules}
|
|
|
33691
33969
|
}
|
|
33692
33970
|
|
|
33693
33971
|
// src/index-lit.ts
|
|
33694
|
-
var RUNTIME_SDK_BUILD = true ? `${"2026-04-
|
|
33972
|
+
var RUNTIME_SDK_BUILD = true ? `${"2026-04-24T22:49:55.034Z"} (${"617ec713a54"})` : "dev";
|
|
33695
33973
|
if (typeof window !== "undefined") {
|
|
33696
33974
|
console.log(`[Syntro Runtime] Build: ${RUNTIME_SDK_BUILD} (Lit)`);
|
|
33697
33975
|
const existing = window.SynOS;
|