@coframe/sdk 1.1.3 → 1.1.5
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/pkg/cf.cjs.js +276 -20
- package/dist/pkg/cf.esm.mjs +276 -20
- package/dist/pkg/server.cjs.js +2 -2
- package/dist/pkg/server.esm.mjs +2 -2
- package/dist/pkg/types/index.d.ts +1 -0
- package/dist/pkg/types/react.d.ts +1 -0
- package/package.json +1 -1
package/dist/pkg/cf.cjs.js
CHANGED
|
@@ -1105,8 +1105,11 @@ function createSession(data) {
|
|
|
1105
1105
|
console.warn('[Coframe] cannot send event beacon, feature unavailable');
|
|
1106
1106
|
}
|
|
1107
1107
|
}
|
|
1108
|
-
async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, headers) {
|
|
1108
|
+
async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers) {
|
|
1109
1109
|
const payload = { projectId, currentUrl };
|
|
1110
|
+
if (previewVariantId) {
|
|
1111
|
+
payload.previewVariantId = previewVariantId;
|
|
1112
|
+
}
|
|
1110
1113
|
const safe = sanitizeUserContext(userContext);
|
|
1111
1114
|
if (safe) {
|
|
1112
1115
|
payload.userContext = safe;
|
|
@@ -2296,7 +2299,7 @@ function checkAllAudiences(metadata, project, personalizationHeaders, currentPag
|
|
|
2296
2299
|
}
|
|
2297
2300
|
return result;
|
|
2298
2301
|
}
|
|
2299
|
-
async function getVariantsAndElements(personalizationHeaders, project, previewVariantId, userToken, currentPageUrl, languages, browserPlatform, logger, nonce, laneClaims = {}) {
|
|
2302
|
+
async function getVariantsAndElements(personalizationHeaders, project, previewVariantId, userToken, currentPageUrl, languages, browserPlatform, logger, nonce, laneClaims = {}, silentFallback = false) {
|
|
2300
2303
|
var _a, _b;
|
|
2301
2304
|
const experimentsInfo = [];
|
|
2302
2305
|
const variantsAndElements = [];
|
|
@@ -2325,10 +2328,13 @@ async function getVariantsAndElements(personalizationHeaders, project, previewVa
|
|
|
2325
2328
|
hasActivatedFrames: true,
|
|
2326
2329
|
});
|
|
2327
2330
|
}
|
|
2328
|
-
if (!skipAlert) {
|
|
2331
|
+
if (!skipAlert && !silentFallback) {
|
|
2329
2332
|
window.alert(`[Coframe] Variant preview unavailable: ${previewVariantId}.`);
|
|
2330
2333
|
}
|
|
2331
|
-
|
|
2334
|
+
if (silentFallback) ;
|
|
2335
|
+
else {
|
|
2336
|
+
return buildResponse({});
|
|
2337
|
+
}
|
|
2332
2338
|
}
|
|
2333
2339
|
const userVisitCount = Number.parseInt(getCookie(VISIT_COUNT_COOKIE_KEY) || '0', 10);
|
|
2334
2340
|
const validatedClaims = validateClaims(laneClaims, project.lanes);
|
|
@@ -2573,6 +2579,220 @@ function rebindMetrics(coframe, logger, metrics, nonce) {
|
|
|
2573
2579
|
}
|
|
2574
2580
|
}
|
|
2575
2581
|
|
|
2582
|
+
function getActivePreviewModes(sessionPreview) {
|
|
2583
|
+
if (!sessionPreview.isSessionPreviewActive ||
|
|
2584
|
+
!sessionPreview.previewVariantId) {
|
|
2585
|
+
return [];
|
|
2586
|
+
}
|
|
2587
|
+
return [
|
|
2588
|
+
{
|
|
2589
|
+
id: 'session-preview',
|
|
2590
|
+
label: 'Preview on',
|
|
2591
|
+
title: `Session preview is active for ${sessionPreview.previewVariantId}`,
|
|
2592
|
+
variantIds: sessionPreview.previewVariantId
|
|
2593
|
+
.split(',')
|
|
2594
|
+
.map((id) => id.trim())
|
|
2595
|
+
.filter(Boolean),
|
|
2596
|
+
},
|
|
2597
|
+
];
|
|
2598
|
+
}
|
|
2599
|
+
|
|
2600
|
+
const PREVIEW_UI_PROTOCOL_VERSION = 1;
|
|
2601
|
+
|
|
2602
|
+
const SESSION_VARIANT_KEY = 'coframe.preview_variant';
|
|
2603
|
+
const PREVIEW_VARIANT_QUERY_PARAM = 'coframe_variant_id';
|
|
2604
|
+
const KEEP_PREVIEW_FOR_SESSION_QUERY_PARAM = 'keep_preview_for_session';
|
|
2605
|
+
let previewDismissed = false;
|
|
2606
|
+
function dismissSessionPreview() {
|
|
2607
|
+
previewDismissed = true;
|
|
2608
|
+
clearPreviewVariantId();
|
|
2609
|
+
const url = new URL(window.location.href);
|
|
2610
|
+
url.searchParams.delete(PREVIEW_VARIANT_QUERY_PARAM);
|
|
2611
|
+
url.searchParams.delete(KEEP_PREVIEW_FOR_SESSION_QUERY_PARAM);
|
|
2612
|
+
window.history.replaceState(window.history.state, '', url);
|
|
2613
|
+
window.location.reload();
|
|
2614
|
+
}
|
|
2615
|
+
function normalizeVariantIds(raw) {
|
|
2616
|
+
if (!raw)
|
|
2617
|
+
return null;
|
|
2618
|
+
const ids = raw
|
|
2619
|
+
.split(',')
|
|
2620
|
+
.map((id) => id.trim())
|
|
2621
|
+
.filter(Boolean);
|
|
2622
|
+
return ids.length > 0 ? ids.join(',') : null;
|
|
2623
|
+
}
|
|
2624
|
+
function readPreviewVariantId() {
|
|
2625
|
+
try {
|
|
2626
|
+
return sessionStorage.getItem(SESSION_VARIANT_KEY);
|
|
2627
|
+
}
|
|
2628
|
+
catch (_a) {
|
|
2629
|
+
return null;
|
|
2630
|
+
}
|
|
2631
|
+
}
|
|
2632
|
+
function persistPreviewVariantId(variantId) {
|
|
2633
|
+
const normalized = normalizeVariantIds(variantId);
|
|
2634
|
+
if (!normalized)
|
|
2635
|
+
return;
|
|
2636
|
+
try {
|
|
2637
|
+
sessionStorage.setItem(SESSION_VARIANT_KEY, normalized);
|
|
2638
|
+
}
|
|
2639
|
+
catch (_a) {
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
function clearPreviewVariantId() {
|
|
2643
|
+
try {
|
|
2644
|
+
sessionStorage.removeItem(SESSION_VARIANT_KEY);
|
|
2645
|
+
}
|
|
2646
|
+
catch (_a) {
|
|
2647
|
+
}
|
|
2648
|
+
}
|
|
2649
|
+
function resolvePreviewSource(urlParams = getCurrentUrlSearchParams()) {
|
|
2650
|
+
return {
|
|
2651
|
+
urlVariantId: urlParams.get(PREVIEW_VARIANT_QUERY_PARAM),
|
|
2652
|
+
storedVariantId: readPreviewVariantId(),
|
|
2653
|
+
keepForSession: urlParams.get(KEEP_PREVIEW_FOR_SESSION_QUERY_PARAM) === 'true',
|
|
2654
|
+
};
|
|
2655
|
+
}
|
|
2656
|
+
function resolveSessionPreviewState() {
|
|
2657
|
+
if (previewDismissed) {
|
|
2658
|
+
return { isSessionPreviewActive: false, previewVariantId: null };
|
|
2659
|
+
}
|
|
2660
|
+
const previewSource = resolvePreviewSource();
|
|
2661
|
+
const urlVariantId = normalizeVariantIds(previewSource.urlVariantId);
|
|
2662
|
+
if (urlVariantId && previewSource.keepForSession) {
|
|
2663
|
+
return {
|
|
2664
|
+
isSessionPreviewActive: true,
|
|
2665
|
+
previewVariantId: urlVariantId,
|
|
2666
|
+
};
|
|
2667
|
+
}
|
|
2668
|
+
if (urlVariantId) {
|
|
2669
|
+
return { isSessionPreviewActive: false, previewVariantId: null };
|
|
2670
|
+
}
|
|
2671
|
+
const storedVariantId = normalizeVariantIds(previewSource.storedVariantId);
|
|
2672
|
+
return {
|
|
2673
|
+
isSessionPreviewActive: !!storedVariantId,
|
|
2674
|
+
previewVariantId: storedVariantId,
|
|
2675
|
+
};
|
|
2676
|
+
}
|
|
2677
|
+
|
|
2678
|
+
const PREVIEW_UI_SCRIPT_ID = 'coframe-preview-ui-script';
|
|
2679
|
+
const PREVIEW_UI_URL = "https://edge.cofra.me/preview-ui/latest.js";
|
|
2680
|
+
let loadPromise = null;
|
|
2681
|
+
let latestState = { modes: [] };
|
|
2682
|
+
let nonce;
|
|
2683
|
+
let logger;
|
|
2684
|
+
let mounted = false;
|
|
2685
|
+
function reportError(message, error) {
|
|
2686
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2687
|
+
if (logger) {
|
|
2688
|
+
logger.warn(message, 'preview_ui_unavailable', { error: errorMessage });
|
|
2689
|
+
return;
|
|
2690
|
+
}
|
|
2691
|
+
console.warn(`[Coframe] ${message}`, error);
|
|
2692
|
+
}
|
|
2693
|
+
function getPreviewUI() {
|
|
2694
|
+
const api = window.CoframePreviewUI;
|
|
2695
|
+
return (api === null || api === void 0 ? void 0 : api.protocolVersion) === PREVIEW_UI_PROTOCOL_VERSION ? api : undefined;
|
|
2696
|
+
}
|
|
2697
|
+
function loadPreviewUI() {
|
|
2698
|
+
const existing = getPreviewUI();
|
|
2699
|
+
if (existing)
|
|
2700
|
+
return Promise.resolve(existing);
|
|
2701
|
+
if (loadPromise)
|
|
2702
|
+
return loadPromise;
|
|
2703
|
+
loadPromise = new Promise((resolve, reject) => {
|
|
2704
|
+
const script = document.createElement('script');
|
|
2705
|
+
script.id = PREVIEW_UI_SCRIPT_ID;
|
|
2706
|
+
script.async = true;
|
|
2707
|
+
script.src = PREVIEW_UI_URL;
|
|
2708
|
+
if (nonce)
|
|
2709
|
+
script.nonce = nonce;
|
|
2710
|
+
script.onload = () => {
|
|
2711
|
+
const api = getPreviewUI();
|
|
2712
|
+
if (!api) {
|
|
2713
|
+
reject(new Error('Preview UI protocol is missing or incompatible'));
|
|
2714
|
+
return;
|
|
2715
|
+
}
|
|
2716
|
+
resolve(api);
|
|
2717
|
+
};
|
|
2718
|
+
script.onerror = () => {
|
|
2719
|
+
reject(new Error('Preview UI script failed to load'));
|
|
2720
|
+
};
|
|
2721
|
+
document.head.appendChild(script);
|
|
2722
|
+
});
|
|
2723
|
+
return loadPromise;
|
|
2724
|
+
}
|
|
2725
|
+
function renderPreviewUI(api) {
|
|
2726
|
+
try {
|
|
2727
|
+
if (latestState.modes.length === 0) {
|
|
2728
|
+
api.unmount();
|
|
2729
|
+
mounted = false;
|
|
2730
|
+
}
|
|
2731
|
+
else if (mounted) {
|
|
2732
|
+
api.update(latestState);
|
|
2733
|
+
}
|
|
2734
|
+
else {
|
|
2735
|
+
api.mount({ state: latestState, nonce, onDismiss: dismissPreviewPanel });
|
|
2736
|
+
mounted = true;
|
|
2737
|
+
}
|
|
2738
|
+
}
|
|
2739
|
+
catch (error) {
|
|
2740
|
+
reportError('Preview UI could not be rendered', error);
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2743
|
+
function dismissPreviewPanel() {
|
|
2744
|
+
dismissSessionPreview();
|
|
2745
|
+
latestState = { modes: [] };
|
|
2746
|
+
const api = getPreviewUI();
|
|
2747
|
+
if (api)
|
|
2748
|
+
renderPreviewUI(api);
|
|
2749
|
+
}
|
|
2750
|
+
function modesWithVariants(sessionPreview, variantsAndElements, applied = true) {
|
|
2751
|
+
const activeModes = getActivePreviewModes(sessionPreview);
|
|
2752
|
+
if (activeModes.length === 0)
|
|
2753
|
+
return [];
|
|
2754
|
+
const currentPageVariantIds = new Set((variantsAndElements === null || variantsAndElements === void 0 ? void 0 : variantsAndElements.map(({ variant }) => variant.id)) || []);
|
|
2755
|
+
const slugById = new Map((variantsAndElements === null || variantsAndElements === void 0 ? void 0 : variantsAndElements.map(({ variant }) => [variant.id, variant.slug])) || []);
|
|
2756
|
+
return activeModes.map((mode) => ({
|
|
2757
|
+
id: mode.id,
|
|
2758
|
+
label: mode.label,
|
|
2759
|
+
title: mode.title,
|
|
2760
|
+
variants: mode.variantIds.map((id) => ({
|
|
2761
|
+
id,
|
|
2762
|
+
slug: slugById.get(id) || null,
|
|
2763
|
+
status: variantsAndElements
|
|
2764
|
+
? applied && currentPageVariantIds.has(id)
|
|
2765
|
+
? 'active'
|
|
2766
|
+
: 'inactive'
|
|
2767
|
+
: 'pending',
|
|
2768
|
+
})),
|
|
2769
|
+
}));
|
|
2770
|
+
}
|
|
2771
|
+
function resolveSessionPreviewPanel(sessionPreview, previewNonce, previewLogger) {
|
|
2772
|
+
const modes = modesWithVariants(sessionPreview);
|
|
2773
|
+
if (modes.length === 0)
|
|
2774
|
+
return;
|
|
2775
|
+
nonce = previewNonce;
|
|
2776
|
+
logger = previewLogger;
|
|
2777
|
+
latestState = { modes };
|
|
2778
|
+
const existing = getPreviewUI();
|
|
2779
|
+
if (existing) {
|
|
2780
|
+
renderPreviewUI(existing);
|
|
2781
|
+
return;
|
|
2782
|
+
}
|
|
2783
|
+
void loadPreviewUI()
|
|
2784
|
+
.then(renderPreviewUI)
|
|
2785
|
+
.catch((error) => reportError('Preview UI could not be loaded', error));
|
|
2786
|
+
}
|
|
2787
|
+
function updatePreviewPanel(variantsAndElements, sessionPreview, applied = true) {
|
|
2788
|
+
latestState = {
|
|
2789
|
+
modes: modesWithVariants(sessionPreview, variantsAndElements, applied),
|
|
2790
|
+
};
|
|
2791
|
+
const api = getPreviewUI();
|
|
2792
|
+
if (api)
|
|
2793
|
+
renderPreviewUI(api);
|
|
2794
|
+
}
|
|
2795
|
+
|
|
2576
2796
|
let lastUrl = null;
|
|
2577
2797
|
function observeUrlChanges(baseUrlMatch, onUrlChange) {
|
|
2578
2798
|
const tryTrack = () => {
|
|
@@ -2910,6 +3130,23 @@ function setupTracking(Coframe, projectResult, previewVariantId, executionStartT
|
|
|
2910
3130
|
return analytics;
|
|
2911
3131
|
}
|
|
2912
3132
|
|
|
3133
|
+
function resolvePreview(pageUrl, previewVariantId, isSessionVariant) {
|
|
3134
|
+
let urlPreviewVariantId = null;
|
|
3135
|
+
try {
|
|
3136
|
+
urlPreviewVariantId = new URL(pageUrl).searchParams.get('coframe_variant_id');
|
|
3137
|
+
}
|
|
3138
|
+
catch (_a) {
|
|
3139
|
+
urlPreviewVariantId = getCurrentUrlSearchParams().get('coframe_variant_id');
|
|
3140
|
+
}
|
|
3141
|
+
if (urlPreviewVariantId) {
|
|
3142
|
+
return { previewVariantId: urlPreviewVariantId, isSessionVariant: false };
|
|
3143
|
+
}
|
|
3144
|
+
if (previewVariantId) {
|
|
3145
|
+
return { previewVariantId, isSessionVariant };
|
|
3146
|
+
}
|
|
3147
|
+
const stored = readPreviewVariantId();
|
|
3148
|
+
return { previewVariantId: stored, isSessionVariant: !!stored };
|
|
3149
|
+
}
|
|
2913
3150
|
async function awaitHydration(config, Coframe, project) {
|
|
2914
3151
|
var _a, _b;
|
|
2915
3152
|
if (!config.waitForHydration)
|
|
@@ -2942,7 +3179,7 @@ function setupFlushInterval(projectId) {
|
|
|
2942
3179
|
}
|
|
2943
3180
|
flushInterval = setInterval(() => flushQueuedEvents(projectId), FLUSH_EVENTS_TIME);
|
|
2944
3181
|
}
|
|
2945
|
-
function setupSPANavigation(Coframe, project, config, applyVariants) {
|
|
3182
|
+
function setupSPANavigation(Coframe, project, config, previewVariantId, isSessionVariant, applyVariants) {
|
|
2946
3183
|
var _a;
|
|
2947
3184
|
if (!((_a = project === null || project === void 0 ? void 0 : project.settings) === null || _a === void 0 ? void 0 : _a.mutation_observer_active))
|
|
2948
3185
|
return;
|
|
@@ -2981,7 +3218,8 @@ function setupSPANavigation(Coframe, project, config, applyVariants) {
|
|
|
2981
3218
|
}
|
|
2982
3219
|
else {
|
|
2983
3220
|
try {
|
|
2984
|
-
const
|
|
3221
|
+
const preview = resolvePreview(newPageUrl, previewVariantId, isSessionVariant);
|
|
3222
|
+
const result = await fetchProjectFromEdge(Coframe.projectId, newPageUrl, signal, config.userContext, preview.previewVariantId || undefined);
|
|
2985
3223
|
if (signal.aborted)
|
|
2986
3224
|
return;
|
|
2987
3225
|
if (result) {
|
|
@@ -3025,22 +3263,22 @@ function persistLaneClaims(claims, logger) {
|
|
|
3025
3263
|
setCookie(LANE_COOKIE_KEY, encodeURIComponent(serialized), logger);
|
|
3026
3264
|
}
|
|
3027
3265
|
}
|
|
3028
|
-
function createApplyVariants(Coframe, config, previewVariantId, executionStartTime, analytics, personalizationHeaders, laneStore) {
|
|
3266
|
+
function createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics, personalizationHeaders, laneStore) {
|
|
3029
3267
|
let isFirstApply = true;
|
|
3030
3268
|
return async (pageUrl, pageProject) => {
|
|
3031
3269
|
const sessionId = isFirstApply ? Coframe.sessionId : generateUUID();
|
|
3032
3270
|
isFirstApply = false;
|
|
3033
3271
|
Coframe.sessionId = sessionId;
|
|
3034
|
-
const
|
|
3035
|
-
|
|
3036
|
-
|
|
3037
|
-
: previewVariantId;
|
|
3038
|
-
const { variantsAndElements, experimentsInfo, hasActivatedFrames, laneClaims, } = await getVariantsAndElements(personalizationHeaders, pageProject, updatedPreviewVariantId, Coframe.userToken, pageUrl, getBrowserLanguages(), getBrowserPlatform(), Coframe.logger, config.nonce, laneStore.claims);
|
|
3272
|
+
const preview = resolvePreview(pageUrl, previewVariantId, isSessionVariant);
|
|
3273
|
+
setIsPreviewVariant(!!preview.previewVariantId);
|
|
3274
|
+
const { variantsAndElements, experimentsInfo, hasActivatedFrames, laneClaims, } = await getVariantsAndElements(personalizationHeaders, pageProject, preview.previewVariantId, Coframe.userToken, pageUrl, getBrowserLanguages(), getBrowserPlatform(), Coframe.logger, config.nonce, laneStore.claims, preview.isSessionVariant);
|
|
3039
3275
|
laneStore.claims = laneClaims;
|
|
3040
3276
|
persistLaneClaims(laneClaims, Coframe.logger);
|
|
3041
3277
|
Coframe.experimentInfo = experimentsInfo;
|
|
3042
3278
|
Coframe.variantsAndElements = variantsAndElements;
|
|
3043
3279
|
setFrameActivated(hasActivatedFrames);
|
|
3280
|
+
const sessionPreview = resolveSessionPreviewState();
|
|
3281
|
+
updatePreviewPanel(variantsAndElements, sessionPreview, !config.trackingOnly);
|
|
3044
3282
|
if (Coframe.debug) {
|
|
3045
3283
|
Coframe.debug.project = pageProject;
|
|
3046
3284
|
Coframe.debug.frames = pageProject.frames;
|
|
@@ -3058,8 +3296,13 @@ function createApplyVariants(Coframe, config, previewVariantId, executionStartTi
|
|
|
3058
3296
|
};
|
|
3059
3297
|
}
|
|
3060
3298
|
async function modifyPage(Coframe, configResult, projectResult, analytics) {
|
|
3061
|
-
const { config, timeoutMs, previewVariantId, integrationStartTime, executionStartTime, } = configResult;
|
|
3299
|
+
const { config, timeoutMs, previewVariantId, isSessionVariant, integrationStartTime, executionStartTime, } = configResult;
|
|
3062
3300
|
const { project: cdnProject, personalizationHeaders } = projectResult;
|
|
3301
|
+
if (resolveSessionPreviewState().isSessionPreviewActive) {
|
|
3302
|
+
waitForBody(timeoutMs)
|
|
3303
|
+
.then(() => resolveSessionPreviewPanel(resolveSessionPreviewState(), config.nonce, Coframe.logger))
|
|
3304
|
+
.catch(() => { });
|
|
3305
|
+
}
|
|
3063
3306
|
if (!(await awaitHydration(config, Coframe, cdnProject)))
|
|
3064
3307
|
return;
|
|
3065
3308
|
if (cdnProject.tags) {
|
|
@@ -3069,7 +3312,7 @@ async function modifyPage(Coframe, configResult, projectResult, analytics) {
|
|
|
3069
3312
|
if (!(await ensureBody(Coframe, cdnProject, timeoutMs, config.nonce)))
|
|
3070
3313
|
return;
|
|
3071
3314
|
const laneStore = { claims: readLaneClaims() };
|
|
3072
|
-
const applyVariants = createApplyVariants(Coframe, config, previewVariantId, executionStartTime, analytics, personalizationHeaders, laneStore);
|
|
3315
|
+
const applyVariants = createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics, personalizationHeaders, laneStore);
|
|
3073
3316
|
await applyVariants(getCurrentPageUrl(), cdnProject);
|
|
3074
3317
|
if (!Coframe.variantsAndElements ||
|
|
3075
3318
|
Coframe.variantsAndElements.length === 0) {
|
|
@@ -3077,7 +3320,7 @@ async function modifyPage(Coframe, configResult, projectResult, analytics) {
|
|
|
3077
3320
|
variantRendered();
|
|
3078
3321
|
}
|
|
3079
3322
|
reportInitTiming(Coframe, cdnProject, integrationStartTime, executionStartTime);
|
|
3080
|
-
setupSPANavigation(Coframe, cdnProject, config, applyVariants);
|
|
3323
|
+
setupSPANavigation(Coframe, cdnProject, config, previewVariantId, isSessionVariant, applyVariants);
|
|
3081
3324
|
setupFlushInterval(Coframe.projectId);
|
|
3082
3325
|
}
|
|
3083
3326
|
|
|
@@ -3152,8 +3395,20 @@ async function resolveConfig(Coframe, revealPage) {
|
|
|
3152
3395
|
}
|
|
3153
3396
|
Coframe.projectId = projectId;
|
|
3154
3397
|
const urlParams = getCurrentUrlSearchParams();
|
|
3155
|
-
const
|
|
3398
|
+
const previewSource = resolvePreviewSource(urlParams);
|
|
3156
3399
|
const shouldSendEventsParam = urlParams.get('coframe_should_send_events');
|
|
3400
|
+
let previewVariantId = null;
|
|
3401
|
+
let isSessionVariant = false;
|
|
3402
|
+
if (previewSource.urlVariantId) {
|
|
3403
|
+
previewVariantId = previewSource.urlVariantId;
|
|
3404
|
+
if (previewSource.keepForSession) {
|
|
3405
|
+
persistPreviewVariantId(previewSource.urlVariantId);
|
|
3406
|
+
}
|
|
3407
|
+
}
|
|
3408
|
+
else if (previewSource.storedVariantId) {
|
|
3409
|
+
previewVariantId = previewSource.storedVariantId;
|
|
3410
|
+
isSessionVariant = true;
|
|
3411
|
+
}
|
|
3157
3412
|
setForceSendEvents(shouldSendEventsParam === 'true');
|
|
3158
3413
|
setIsPreviewVariant(!!previewVariantId);
|
|
3159
3414
|
setWaitingForCookies(!!config.waitForCookiesEnabled);
|
|
@@ -3162,6 +3417,7 @@ async function resolveConfig(Coframe, revealPage) {
|
|
|
3162
3417
|
timeoutMs,
|
|
3163
3418
|
projectId,
|
|
3164
3419
|
previewVariantId,
|
|
3420
|
+
isSessionVariant,
|
|
3165
3421
|
integrationStartTime,
|
|
3166
3422
|
executionStartTime,
|
|
3167
3423
|
};
|
|
@@ -3223,14 +3479,14 @@ async function resolveIdentity(config, Coframe, timeoutMs, gracefulExit) {
|
|
|
3223
3479
|
return { userToken, applyCookieConsent, onConsentChange };
|
|
3224
3480
|
}
|
|
3225
3481
|
|
|
3226
|
-
async function resolveProject(Coframe, previewVariantId, config) {
|
|
3482
|
+
async function resolveProject(Coframe, previewVariantId, isSessionVariant, config) {
|
|
3227
3483
|
var _a;
|
|
3228
3484
|
const logger = Coframe.logger;
|
|
3229
3485
|
const projectData = (_a = findLastCmd((c) => !!c.projectData)) === null || _a === void 0 ? void 0 : _a.projectData;
|
|
3230
3486
|
let personalizationHeaders = (projectData === null || projectData === void 0 ? void 0 : projectData.personalizationHeaders) || null;
|
|
3231
|
-
let project = projectData === null || projectData === void 0 ? void 0 : projectData.project;
|
|
3487
|
+
let project = isSessionVariant ? undefined : projectData === null || projectData === void 0 ? void 0 : projectData.project;
|
|
3232
3488
|
if (!project) {
|
|
3233
|
-
const edgeResult = await fetchProjectFromEdge(Coframe.projectId, config.currentUrl || getCurrentPageUrl(), undefined, config.userContext);
|
|
3489
|
+
const edgeResult = await fetchProjectFromEdge(Coframe.projectId, config.currentUrl || getCurrentPageUrl(), undefined, config.userContext, previewVariantId || undefined);
|
|
3234
3490
|
personalizationHeaders = (edgeResult === null || edgeResult === void 0 ? void 0 : edgeResult.personalizationHeaders) || null;
|
|
3235
3491
|
project = (edgeResult === null || edgeResult === void 0 ? void 0 : edgeResult.project) || undefined;
|
|
3236
3492
|
}
|
|
@@ -3322,7 +3578,7 @@ async function init(options) {
|
|
|
3322
3578
|
const configResult = await resolveConfig(Coframe, revealPage);
|
|
3323
3579
|
if (!configResult)
|
|
3324
3580
|
return;
|
|
3325
|
-
const projectResult = await resolveProject(Coframe, configResult.previewVariantId, configResult.config);
|
|
3581
|
+
const projectResult = await resolveProject(Coframe, configResult.previewVariantId, configResult.isSessionVariant, configResult.config);
|
|
3326
3582
|
if (!projectResult)
|
|
3327
3583
|
return;
|
|
3328
3584
|
Coframe.orgId = projectResult.project.org_id || '';
|
package/dist/pkg/cf.esm.mjs
CHANGED
|
@@ -1103,8 +1103,11 @@ function createSession(data) {
|
|
|
1103
1103
|
console.warn('[Coframe] cannot send event beacon, feature unavailable');
|
|
1104
1104
|
}
|
|
1105
1105
|
}
|
|
1106
|
-
async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, headers) {
|
|
1106
|
+
async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers) {
|
|
1107
1107
|
const payload = { projectId, currentUrl };
|
|
1108
|
+
if (previewVariantId) {
|
|
1109
|
+
payload.previewVariantId = previewVariantId;
|
|
1110
|
+
}
|
|
1108
1111
|
const safe = sanitizeUserContext(userContext);
|
|
1109
1112
|
if (safe) {
|
|
1110
1113
|
payload.userContext = safe;
|
|
@@ -2294,7 +2297,7 @@ function checkAllAudiences(metadata, project, personalizationHeaders, currentPag
|
|
|
2294
2297
|
}
|
|
2295
2298
|
return result;
|
|
2296
2299
|
}
|
|
2297
|
-
async function getVariantsAndElements(personalizationHeaders, project, previewVariantId, userToken, currentPageUrl, languages, browserPlatform, logger, nonce, laneClaims = {}) {
|
|
2300
|
+
async function getVariantsAndElements(personalizationHeaders, project, previewVariantId, userToken, currentPageUrl, languages, browserPlatform, logger, nonce, laneClaims = {}, silentFallback = false) {
|
|
2298
2301
|
var _a, _b;
|
|
2299
2302
|
const experimentsInfo = [];
|
|
2300
2303
|
const variantsAndElements = [];
|
|
@@ -2323,10 +2326,13 @@ async function getVariantsAndElements(personalizationHeaders, project, previewVa
|
|
|
2323
2326
|
hasActivatedFrames: true,
|
|
2324
2327
|
});
|
|
2325
2328
|
}
|
|
2326
|
-
if (!skipAlert) {
|
|
2329
|
+
if (!skipAlert && !silentFallback) {
|
|
2327
2330
|
window.alert(`[Coframe] Variant preview unavailable: ${previewVariantId}.`);
|
|
2328
2331
|
}
|
|
2329
|
-
|
|
2332
|
+
if (silentFallback) ;
|
|
2333
|
+
else {
|
|
2334
|
+
return buildResponse({});
|
|
2335
|
+
}
|
|
2330
2336
|
}
|
|
2331
2337
|
const userVisitCount = Number.parseInt(getCookie(VISIT_COUNT_COOKIE_KEY) || '0', 10);
|
|
2332
2338
|
const validatedClaims = validateClaims(laneClaims, project.lanes);
|
|
@@ -2571,6 +2577,220 @@ function rebindMetrics(coframe, logger, metrics, nonce) {
|
|
|
2571
2577
|
}
|
|
2572
2578
|
}
|
|
2573
2579
|
|
|
2580
|
+
function getActivePreviewModes(sessionPreview) {
|
|
2581
|
+
if (!sessionPreview.isSessionPreviewActive ||
|
|
2582
|
+
!sessionPreview.previewVariantId) {
|
|
2583
|
+
return [];
|
|
2584
|
+
}
|
|
2585
|
+
return [
|
|
2586
|
+
{
|
|
2587
|
+
id: 'session-preview',
|
|
2588
|
+
label: 'Preview on',
|
|
2589
|
+
title: `Session preview is active for ${sessionPreview.previewVariantId}`,
|
|
2590
|
+
variantIds: sessionPreview.previewVariantId
|
|
2591
|
+
.split(',')
|
|
2592
|
+
.map((id) => id.trim())
|
|
2593
|
+
.filter(Boolean),
|
|
2594
|
+
},
|
|
2595
|
+
];
|
|
2596
|
+
}
|
|
2597
|
+
|
|
2598
|
+
const PREVIEW_UI_PROTOCOL_VERSION = 1;
|
|
2599
|
+
|
|
2600
|
+
const SESSION_VARIANT_KEY = 'coframe.preview_variant';
|
|
2601
|
+
const PREVIEW_VARIANT_QUERY_PARAM = 'coframe_variant_id';
|
|
2602
|
+
const KEEP_PREVIEW_FOR_SESSION_QUERY_PARAM = 'keep_preview_for_session';
|
|
2603
|
+
let previewDismissed = false;
|
|
2604
|
+
function dismissSessionPreview() {
|
|
2605
|
+
previewDismissed = true;
|
|
2606
|
+
clearPreviewVariantId();
|
|
2607
|
+
const url = new URL(window.location.href);
|
|
2608
|
+
url.searchParams.delete(PREVIEW_VARIANT_QUERY_PARAM);
|
|
2609
|
+
url.searchParams.delete(KEEP_PREVIEW_FOR_SESSION_QUERY_PARAM);
|
|
2610
|
+
window.history.replaceState(window.history.state, '', url);
|
|
2611
|
+
window.location.reload();
|
|
2612
|
+
}
|
|
2613
|
+
function normalizeVariantIds(raw) {
|
|
2614
|
+
if (!raw)
|
|
2615
|
+
return null;
|
|
2616
|
+
const ids = raw
|
|
2617
|
+
.split(',')
|
|
2618
|
+
.map((id) => id.trim())
|
|
2619
|
+
.filter(Boolean);
|
|
2620
|
+
return ids.length > 0 ? ids.join(',') : null;
|
|
2621
|
+
}
|
|
2622
|
+
function readPreviewVariantId() {
|
|
2623
|
+
try {
|
|
2624
|
+
return sessionStorage.getItem(SESSION_VARIANT_KEY);
|
|
2625
|
+
}
|
|
2626
|
+
catch (_a) {
|
|
2627
|
+
return null;
|
|
2628
|
+
}
|
|
2629
|
+
}
|
|
2630
|
+
function persistPreviewVariantId(variantId) {
|
|
2631
|
+
const normalized = normalizeVariantIds(variantId);
|
|
2632
|
+
if (!normalized)
|
|
2633
|
+
return;
|
|
2634
|
+
try {
|
|
2635
|
+
sessionStorage.setItem(SESSION_VARIANT_KEY, normalized);
|
|
2636
|
+
}
|
|
2637
|
+
catch (_a) {
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
function clearPreviewVariantId() {
|
|
2641
|
+
try {
|
|
2642
|
+
sessionStorage.removeItem(SESSION_VARIANT_KEY);
|
|
2643
|
+
}
|
|
2644
|
+
catch (_a) {
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
function resolvePreviewSource(urlParams = getCurrentUrlSearchParams()) {
|
|
2648
|
+
return {
|
|
2649
|
+
urlVariantId: urlParams.get(PREVIEW_VARIANT_QUERY_PARAM),
|
|
2650
|
+
storedVariantId: readPreviewVariantId(),
|
|
2651
|
+
keepForSession: urlParams.get(KEEP_PREVIEW_FOR_SESSION_QUERY_PARAM) === 'true',
|
|
2652
|
+
};
|
|
2653
|
+
}
|
|
2654
|
+
function resolveSessionPreviewState() {
|
|
2655
|
+
if (previewDismissed) {
|
|
2656
|
+
return { isSessionPreviewActive: false, previewVariantId: null };
|
|
2657
|
+
}
|
|
2658
|
+
const previewSource = resolvePreviewSource();
|
|
2659
|
+
const urlVariantId = normalizeVariantIds(previewSource.urlVariantId);
|
|
2660
|
+
if (urlVariantId && previewSource.keepForSession) {
|
|
2661
|
+
return {
|
|
2662
|
+
isSessionPreviewActive: true,
|
|
2663
|
+
previewVariantId: urlVariantId,
|
|
2664
|
+
};
|
|
2665
|
+
}
|
|
2666
|
+
if (urlVariantId) {
|
|
2667
|
+
return { isSessionPreviewActive: false, previewVariantId: null };
|
|
2668
|
+
}
|
|
2669
|
+
const storedVariantId = normalizeVariantIds(previewSource.storedVariantId);
|
|
2670
|
+
return {
|
|
2671
|
+
isSessionPreviewActive: !!storedVariantId,
|
|
2672
|
+
previewVariantId: storedVariantId,
|
|
2673
|
+
};
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
const PREVIEW_UI_SCRIPT_ID = 'coframe-preview-ui-script';
|
|
2677
|
+
const PREVIEW_UI_URL = "https://edge.cofra.me/preview-ui/latest.js";
|
|
2678
|
+
let loadPromise = null;
|
|
2679
|
+
let latestState = { modes: [] };
|
|
2680
|
+
let nonce;
|
|
2681
|
+
let logger;
|
|
2682
|
+
let mounted = false;
|
|
2683
|
+
function reportError(message, error) {
|
|
2684
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2685
|
+
if (logger) {
|
|
2686
|
+
logger.warn(message, 'preview_ui_unavailable', { error: errorMessage });
|
|
2687
|
+
return;
|
|
2688
|
+
}
|
|
2689
|
+
console.warn(`[Coframe] ${message}`, error);
|
|
2690
|
+
}
|
|
2691
|
+
function getPreviewUI() {
|
|
2692
|
+
const api = window.CoframePreviewUI;
|
|
2693
|
+
return (api === null || api === void 0 ? void 0 : api.protocolVersion) === PREVIEW_UI_PROTOCOL_VERSION ? api : undefined;
|
|
2694
|
+
}
|
|
2695
|
+
function loadPreviewUI() {
|
|
2696
|
+
const existing = getPreviewUI();
|
|
2697
|
+
if (existing)
|
|
2698
|
+
return Promise.resolve(existing);
|
|
2699
|
+
if (loadPromise)
|
|
2700
|
+
return loadPromise;
|
|
2701
|
+
loadPromise = new Promise((resolve, reject) => {
|
|
2702
|
+
const script = document.createElement('script');
|
|
2703
|
+
script.id = PREVIEW_UI_SCRIPT_ID;
|
|
2704
|
+
script.async = true;
|
|
2705
|
+
script.src = PREVIEW_UI_URL;
|
|
2706
|
+
if (nonce)
|
|
2707
|
+
script.nonce = nonce;
|
|
2708
|
+
script.onload = () => {
|
|
2709
|
+
const api = getPreviewUI();
|
|
2710
|
+
if (!api) {
|
|
2711
|
+
reject(new Error('Preview UI protocol is missing or incompatible'));
|
|
2712
|
+
return;
|
|
2713
|
+
}
|
|
2714
|
+
resolve(api);
|
|
2715
|
+
};
|
|
2716
|
+
script.onerror = () => {
|
|
2717
|
+
reject(new Error('Preview UI script failed to load'));
|
|
2718
|
+
};
|
|
2719
|
+
document.head.appendChild(script);
|
|
2720
|
+
});
|
|
2721
|
+
return loadPromise;
|
|
2722
|
+
}
|
|
2723
|
+
function renderPreviewUI(api) {
|
|
2724
|
+
try {
|
|
2725
|
+
if (latestState.modes.length === 0) {
|
|
2726
|
+
api.unmount();
|
|
2727
|
+
mounted = false;
|
|
2728
|
+
}
|
|
2729
|
+
else if (mounted) {
|
|
2730
|
+
api.update(latestState);
|
|
2731
|
+
}
|
|
2732
|
+
else {
|
|
2733
|
+
api.mount({ state: latestState, nonce, onDismiss: dismissPreviewPanel });
|
|
2734
|
+
mounted = true;
|
|
2735
|
+
}
|
|
2736
|
+
}
|
|
2737
|
+
catch (error) {
|
|
2738
|
+
reportError('Preview UI could not be rendered', error);
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2741
|
+
function dismissPreviewPanel() {
|
|
2742
|
+
dismissSessionPreview();
|
|
2743
|
+
latestState = { modes: [] };
|
|
2744
|
+
const api = getPreviewUI();
|
|
2745
|
+
if (api)
|
|
2746
|
+
renderPreviewUI(api);
|
|
2747
|
+
}
|
|
2748
|
+
function modesWithVariants(sessionPreview, variantsAndElements, applied = true) {
|
|
2749
|
+
const activeModes = getActivePreviewModes(sessionPreview);
|
|
2750
|
+
if (activeModes.length === 0)
|
|
2751
|
+
return [];
|
|
2752
|
+
const currentPageVariantIds = new Set((variantsAndElements === null || variantsAndElements === void 0 ? void 0 : variantsAndElements.map(({ variant }) => variant.id)) || []);
|
|
2753
|
+
const slugById = new Map((variantsAndElements === null || variantsAndElements === void 0 ? void 0 : variantsAndElements.map(({ variant }) => [variant.id, variant.slug])) || []);
|
|
2754
|
+
return activeModes.map((mode) => ({
|
|
2755
|
+
id: mode.id,
|
|
2756
|
+
label: mode.label,
|
|
2757
|
+
title: mode.title,
|
|
2758
|
+
variants: mode.variantIds.map((id) => ({
|
|
2759
|
+
id,
|
|
2760
|
+
slug: slugById.get(id) || null,
|
|
2761
|
+
status: variantsAndElements
|
|
2762
|
+
? applied && currentPageVariantIds.has(id)
|
|
2763
|
+
? 'active'
|
|
2764
|
+
: 'inactive'
|
|
2765
|
+
: 'pending',
|
|
2766
|
+
})),
|
|
2767
|
+
}));
|
|
2768
|
+
}
|
|
2769
|
+
function resolveSessionPreviewPanel(sessionPreview, previewNonce, previewLogger) {
|
|
2770
|
+
const modes = modesWithVariants(sessionPreview);
|
|
2771
|
+
if (modes.length === 0)
|
|
2772
|
+
return;
|
|
2773
|
+
nonce = previewNonce;
|
|
2774
|
+
logger = previewLogger;
|
|
2775
|
+
latestState = { modes };
|
|
2776
|
+
const existing = getPreviewUI();
|
|
2777
|
+
if (existing) {
|
|
2778
|
+
renderPreviewUI(existing);
|
|
2779
|
+
return;
|
|
2780
|
+
}
|
|
2781
|
+
void loadPreviewUI()
|
|
2782
|
+
.then(renderPreviewUI)
|
|
2783
|
+
.catch((error) => reportError('Preview UI could not be loaded', error));
|
|
2784
|
+
}
|
|
2785
|
+
function updatePreviewPanel(variantsAndElements, sessionPreview, applied = true) {
|
|
2786
|
+
latestState = {
|
|
2787
|
+
modes: modesWithVariants(sessionPreview, variantsAndElements, applied),
|
|
2788
|
+
};
|
|
2789
|
+
const api = getPreviewUI();
|
|
2790
|
+
if (api)
|
|
2791
|
+
renderPreviewUI(api);
|
|
2792
|
+
}
|
|
2793
|
+
|
|
2574
2794
|
let lastUrl = null;
|
|
2575
2795
|
function observeUrlChanges(baseUrlMatch, onUrlChange) {
|
|
2576
2796
|
const tryTrack = () => {
|
|
@@ -2908,6 +3128,23 @@ function setupTracking(Coframe, projectResult, previewVariantId, executionStartT
|
|
|
2908
3128
|
return analytics;
|
|
2909
3129
|
}
|
|
2910
3130
|
|
|
3131
|
+
function resolvePreview(pageUrl, previewVariantId, isSessionVariant) {
|
|
3132
|
+
let urlPreviewVariantId = null;
|
|
3133
|
+
try {
|
|
3134
|
+
urlPreviewVariantId = new URL(pageUrl).searchParams.get('coframe_variant_id');
|
|
3135
|
+
}
|
|
3136
|
+
catch (_a) {
|
|
3137
|
+
urlPreviewVariantId = getCurrentUrlSearchParams().get('coframe_variant_id');
|
|
3138
|
+
}
|
|
3139
|
+
if (urlPreviewVariantId) {
|
|
3140
|
+
return { previewVariantId: urlPreviewVariantId, isSessionVariant: false };
|
|
3141
|
+
}
|
|
3142
|
+
if (previewVariantId) {
|
|
3143
|
+
return { previewVariantId, isSessionVariant };
|
|
3144
|
+
}
|
|
3145
|
+
const stored = readPreviewVariantId();
|
|
3146
|
+
return { previewVariantId: stored, isSessionVariant: !!stored };
|
|
3147
|
+
}
|
|
2911
3148
|
async function awaitHydration(config, Coframe, project) {
|
|
2912
3149
|
var _a, _b;
|
|
2913
3150
|
if (!config.waitForHydration)
|
|
@@ -2940,7 +3177,7 @@ function setupFlushInterval(projectId) {
|
|
|
2940
3177
|
}
|
|
2941
3178
|
flushInterval = setInterval(() => flushQueuedEvents(projectId), FLUSH_EVENTS_TIME);
|
|
2942
3179
|
}
|
|
2943
|
-
function setupSPANavigation(Coframe, project, config, applyVariants) {
|
|
3180
|
+
function setupSPANavigation(Coframe, project, config, previewVariantId, isSessionVariant, applyVariants) {
|
|
2944
3181
|
var _a;
|
|
2945
3182
|
if (!((_a = project === null || project === void 0 ? void 0 : project.settings) === null || _a === void 0 ? void 0 : _a.mutation_observer_active))
|
|
2946
3183
|
return;
|
|
@@ -2979,7 +3216,8 @@ function setupSPANavigation(Coframe, project, config, applyVariants) {
|
|
|
2979
3216
|
}
|
|
2980
3217
|
else {
|
|
2981
3218
|
try {
|
|
2982
|
-
const
|
|
3219
|
+
const preview = resolvePreview(newPageUrl, previewVariantId, isSessionVariant);
|
|
3220
|
+
const result = await fetchProjectFromEdge(Coframe.projectId, newPageUrl, signal, config.userContext, preview.previewVariantId || undefined);
|
|
2983
3221
|
if (signal.aborted)
|
|
2984
3222
|
return;
|
|
2985
3223
|
if (result) {
|
|
@@ -3023,22 +3261,22 @@ function persistLaneClaims(claims, logger) {
|
|
|
3023
3261
|
setCookie(LANE_COOKIE_KEY, encodeURIComponent(serialized), logger);
|
|
3024
3262
|
}
|
|
3025
3263
|
}
|
|
3026
|
-
function createApplyVariants(Coframe, config, previewVariantId, executionStartTime, analytics, personalizationHeaders, laneStore) {
|
|
3264
|
+
function createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics, personalizationHeaders, laneStore) {
|
|
3027
3265
|
let isFirstApply = true;
|
|
3028
3266
|
return async (pageUrl, pageProject) => {
|
|
3029
3267
|
const sessionId = isFirstApply ? Coframe.sessionId : generateUUID();
|
|
3030
3268
|
isFirstApply = false;
|
|
3031
3269
|
Coframe.sessionId = sessionId;
|
|
3032
|
-
const
|
|
3033
|
-
|
|
3034
|
-
|
|
3035
|
-
: previewVariantId;
|
|
3036
|
-
const { variantsAndElements, experimentsInfo, hasActivatedFrames, laneClaims, } = await getVariantsAndElements(personalizationHeaders, pageProject, updatedPreviewVariantId, Coframe.userToken, pageUrl, getBrowserLanguages(), getBrowserPlatform(), Coframe.logger, config.nonce, laneStore.claims);
|
|
3270
|
+
const preview = resolvePreview(pageUrl, previewVariantId, isSessionVariant);
|
|
3271
|
+
setIsPreviewVariant(!!preview.previewVariantId);
|
|
3272
|
+
const { variantsAndElements, experimentsInfo, hasActivatedFrames, laneClaims, } = await getVariantsAndElements(personalizationHeaders, pageProject, preview.previewVariantId, Coframe.userToken, pageUrl, getBrowserLanguages(), getBrowserPlatform(), Coframe.logger, config.nonce, laneStore.claims, preview.isSessionVariant);
|
|
3037
3273
|
laneStore.claims = laneClaims;
|
|
3038
3274
|
persistLaneClaims(laneClaims, Coframe.logger);
|
|
3039
3275
|
Coframe.experimentInfo = experimentsInfo;
|
|
3040
3276
|
Coframe.variantsAndElements = variantsAndElements;
|
|
3041
3277
|
setFrameActivated(hasActivatedFrames);
|
|
3278
|
+
const sessionPreview = resolveSessionPreviewState();
|
|
3279
|
+
updatePreviewPanel(variantsAndElements, sessionPreview, !config.trackingOnly);
|
|
3042
3280
|
if (Coframe.debug) {
|
|
3043
3281
|
Coframe.debug.project = pageProject;
|
|
3044
3282
|
Coframe.debug.frames = pageProject.frames;
|
|
@@ -3056,8 +3294,13 @@ function createApplyVariants(Coframe, config, previewVariantId, executionStartTi
|
|
|
3056
3294
|
};
|
|
3057
3295
|
}
|
|
3058
3296
|
async function modifyPage(Coframe, configResult, projectResult, analytics) {
|
|
3059
|
-
const { config, timeoutMs, previewVariantId, integrationStartTime, executionStartTime, } = configResult;
|
|
3297
|
+
const { config, timeoutMs, previewVariantId, isSessionVariant, integrationStartTime, executionStartTime, } = configResult;
|
|
3060
3298
|
const { project: cdnProject, personalizationHeaders } = projectResult;
|
|
3299
|
+
if (resolveSessionPreviewState().isSessionPreviewActive) {
|
|
3300
|
+
waitForBody(timeoutMs)
|
|
3301
|
+
.then(() => resolveSessionPreviewPanel(resolveSessionPreviewState(), config.nonce, Coframe.logger))
|
|
3302
|
+
.catch(() => { });
|
|
3303
|
+
}
|
|
3061
3304
|
if (!(await awaitHydration(config, Coframe, cdnProject)))
|
|
3062
3305
|
return;
|
|
3063
3306
|
if (cdnProject.tags) {
|
|
@@ -3067,7 +3310,7 @@ async function modifyPage(Coframe, configResult, projectResult, analytics) {
|
|
|
3067
3310
|
if (!(await ensureBody(Coframe, cdnProject, timeoutMs, config.nonce)))
|
|
3068
3311
|
return;
|
|
3069
3312
|
const laneStore = { claims: readLaneClaims() };
|
|
3070
|
-
const applyVariants = createApplyVariants(Coframe, config, previewVariantId, executionStartTime, analytics, personalizationHeaders, laneStore);
|
|
3313
|
+
const applyVariants = createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics, personalizationHeaders, laneStore);
|
|
3071
3314
|
await applyVariants(getCurrentPageUrl(), cdnProject);
|
|
3072
3315
|
if (!Coframe.variantsAndElements ||
|
|
3073
3316
|
Coframe.variantsAndElements.length === 0) {
|
|
@@ -3075,7 +3318,7 @@ async function modifyPage(Coframe, configResult, projectResult, analytics) {
|
|
|
3075
3318
|
variantRendered();
|
|
3076
3319
|
}
|
|
3077
3320
|
reportInitTiming(Coframe, cdnProject, integrationStartTime, executionStartTime);
|
|
3078
|
-
setupSPANavigation(Coframe, cdnProject, config, applyVariants);
|
|
3321
|
+
setupSPANavigation(Coframe, cdnProject, config, previewVariantId, isSessionVariant, applyVariants);
|
|
3079
3322
|
setupFlushInterval(Coframe.projectId);
|
|
3080
3323
|
}
|
|
3081
3324
|
|
|
@@ -3150,8 +3393,20 @@ async function resolveConfig(Coframe, revealPage) {
|
|
|
3150
3393
|
}
|
|
3151
3394
|
Coframe.projectId = projectId;
|
|
3152
3395
|
const urlParams = getCurrentUrlSearchParams();
|
|
3153
|
-
const
|
|
3396
|
+
const previewSource = resolvePreviewSource(urlParams);
|
|
3154
3397
|
const shouldSendEventsParam = urlParams.get('coframe_should_send_events');
|
|
3398
|
+
let previewVariantId = null;
|
|
3399
|
+
let isSessionVariant = false;
|
|
3400
|
+
if (previewSource.urlVariantId) {
|
|
3401
|
+
previewVariantId = previewSource.urlVariantId;
|
|
3402
|
+
if (previewSource.keepForSession) {
|
|
3403
|
+
persistPreviewVariantId(previewSource.urlVariantId);
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
else if (previewSource.storedVariantId) {
|
|
3407
|
+
previewVariantId = previewSource.storedVariantId;
|
|
3408
|
+
isSessionVariant = true;
|
|
3409
|
+
}
|
|
3155
3410
|
setForceSendEvents(shouldSendEventsParam === 'true');
|
|
3156
3411
|
setIsPreviewVariant(!!previewVariantId);
|
|
3157
3412
|
setWaitingForCookies(!!config.waitForCookiesEnabled);
|
|
@@ -3160,6 +3415,7 @@ async function resolveConfig(Coframe, revealPage) {
|
|
|
3160
3415
|
timeoutMs,
|
|
3161
3416
|
projectId,
|
|
3162
3417
|
previewVariantId,
|
|
3418
|
+
isSessionVariant,
|
|
3163
3419
|
integrationStartTime,
|
|
3164
3420
|
executionStartTime,
|
|
3165
3421
|
};
|
|
@@ -3221,14 +3477,14 @@ async function resolveIdentity(config, Coframe, timeoutMs, gracefulExit) {
|
|
|
3221
3477
|
return { userToken, applyCookieConsent, onConsentChange };
|
|
3222
3478
|
}
|
|
3223
3479
|
|
|
3224
|
-
async function resolveProject(Coframe, previewVariantId, config) {
|
|
3480
|
+
async function resolveProject(Coframe, previewVariantId, isSessionVariant, config) {
|
|
3225
3481
|
var _a;
|
|
3226
3482
|
const logger = Coframe.logger;
|
|
3227
3483
|
const projectData = (_a = findLastCmd((c) => !!c.projectData)) === null || _a === void 0 ? void 0 : _a.projectData;
|
|
3228
3484
|
let personalizationHeaders = (projectData === null || projectData === void 0 ? void 0 : projectData.personalizationHeaders) || null;
|
|
3229
|
-
let project = projectData === null || projectData === void 0 ? void 0 : projectData.project;
|
|
3485
|
+
let project = isSessionVariant ? undefined : projectData === null || projectData === void 0 ? void 0 : projectData.project;
|
|
3230
3486
|
if (!project) {
|
|
3231
|
-
const edgeResult = await fetchProjectFromEdge(Coframe.projectId, config.currentUrl || getCurrentPageUrl(), undefined, config.userContext);
|
|
3487
|
+
const edgeResult = await fetchProjectFromEdge(Coframe.projectId, config.currentUrl || getCurrentPageUrl(), undefined, config.userContext, previewVariantId || undefined);
|
|
3232
3488
|
personalizationHeaders = (edgeResult === null || edgeResult === void 0 ? void 0 : edgeResult.personalizationHeaders) || null;
|
|
3233
3489
|
project = (edgeResult === null || edgeResult === void 0 ? void 0 : edgeResult.project) || undefined;
|
|
3234
3490
|
}
|
|
@@ -3320,7 +3576,7 @@ async function init(options) {
|
|
|
3320
3576
|
const configResult = await resolveConfig(Coframe, revealPage);
|
|
3321
3577
|
if (!configResult)
|
|
3322
3578
|
return;
|
|
3323
|
-
const projectResult = await resolveProject(Coframe, configResult.previewVariantId, configResult.config);
|
|
3579
|
+
const projectResult = await resolveProject(Coframe, configResult.previewVariantId, configResult.isSessionVariant, configResult.config);
|
|
3324
3580
|
if (!projectResult)
|
|
3325
3581
|
return;
|
|
3326
3582
|
Coframe.orgId = projectResult.project.org_id || '';
|
package/dist/pkg/server.cjs.js
CHANGED
|
@@ -22,7 +22,7 @@ function sanitizeUserContext(userContext) {
|
|
|
22
22
|
return userContext;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, headers) {
|
|
25
|
+
async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers) {
|
|
26
26
|
const payload = { projectId, currentUrl };
|
|
27
27
|
const safe = sanitizeUserContext(userContext);
|
|
28
28
|
if (safe) {
|
|
@@ -73,7 +73,7 @@ async function getProjectData(options) {
|
|
|
73
73
|
const includeCSS = options.includeCSS !== false;
|
|
74
74
|
const [projectResult, antiflickerCSS] = await Promise.all([
|
|
75
75
|
includeProject
|
|
76
|
-
? fetchProjectFromEdge(options.projectId, options.currentUrl, undefined, options.userContext, options.headers)
|
|
76
|
+
? fetchProjectFromEdge(options.projectId, options.currentUrl, undefined, options.userContext, undefined, options.headers)
|
|
77
77
|
: Promise.resolve(null),
|
|
78
78
|
includeCSS
|
|
79
79
|
? fetchAntiflickerFromEdge(options.projectId, options.currentUrl, options.userContext, options.enableElementAntiFlicker, options.headers)
|
package/dist/pkg/server.esm.mjs
CHANGED
|
@@ -20,7 +20,7 @@ function sanitizeUserContext(userContext) {
|
|
|
20
20
|
return userContext;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, headers) {
|
|
23
|
+
async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers) {
|
|
24
24
|
const payload = { projectId, currentUrl };
|
|
25
25
|
const safe = sanitizeUserContext(userContext);
|
|
26
26
|
if (safe) {
|
|
@@ -71,7 +71,7 @@ async function getProjectData(options) {
|
|
|
71
71
|
const includeCSS = options.includeCSS !== false;
|
|
72
72
|
const [projectResult, antiflickerCSS] = await Promise.all([
|
|
73
73
|
includeProject
|
|
74
|
-
? fetchProjectFromEdge(options.projectId, options.currentUrl, undefined, options.userContext, options.headers)
|
|
74
|
+
? fetchProjectFromEdge(options.projectId, options.currentUrl, undefined, options.userContext, undefined, options.headers)
|
|
75
75
|
: Promise.resolve(null),
|
|
76
76
|
includeCSS
|
|
77
77
|
? fetchAntiflickerFromEdge(options.projectId, options.currentUrl, options.userContext, options.enableElementAntiFlicker, options.headers)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coframe/sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "Coframe optimizes your website using generative AI to deliver maximum impact to your audience and allow your site to improve itself as you sleep. Learn more at coframe.com.",
|
|
5
5
|
"main": "dist/pkg/cf.cjs.js",
|
|
6
6
|
"module": "dist/pkg/cf.esm.mjs",
|