@coframe/sdk 1.1.14 → 1.1.21
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/README.md +28 -1
- package/dist/pkg/cf.cjs.js +283 -113
- package/dist/pkg/cf.esm.mjs +283 -113
- package/dist/pkg/react.cjs.js +2 -1
- package/dist/pkg/react.esm.mjs +2 -1
- package/dist/pkg/server.cjs.js +26 -5
- package/dist/pkg/server.esm.mjs +26 -5
- package/dist/pkg/types/index.d.ts +7 -0
- package/dist/pkg/types/react.d.ts +7 -0
- package/dist/pkg/types/server.d.ts +5 -0
- package/package.json +1 -1
package/dist/pkg/cf.esm.mjs
CHANGED
|
@@ -22,6 +22,19 @@ if (!Array.prototype.find) {
|
|
|
22
22
|
enumerable: false,
|
|
23
23
|
});
|
|
24
24
|
}
|
|
25
|
+
if (!Array.prototype.includes) {
|
|
26
|
+
Object.defineProperty(Array.prototype, 'includes', {
|
|
27
|
+
value: function (searchElement) {
|
|
28
|
+
if (this == null) {
|
|
29
|
+
throw new TypeError('Array.prototype.includes called on null or undefined');
|
|
30
|
+
}
|
|
31
|
+
return Array.prototype.indexOf.call(this, searchElement) !== -1;
|
|
32
|
+
},
|
|
33
|
+
writable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
enumerable: false,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
25
38
|
if (!Array.prototype.flatMap) {
|
|
26
39
|
Object.defineProperty(Array.prototype, 'flatMap', {
|
|
27
40
|
value: function (callback, thisArg) {
|
|
@@ -1064,10 +1077,41 @@ function warnEventsNotSent() {
|
|
|
1064
1077
|
}
|
|
1065
1078
|
}
|
|
1066
1079
|
|
|
1067
|
-
const SDK_VERSION = '2.
|
|
1080
|
+
const SDK_VERSION = '2.7.0';
|
|
1068
1081
|
const queuedEvents = [];
|
|
1069
1082
|
const queuedMonitoringEvents = [];
|
|
1070
1083
|
const queuedSessions = [];
|
|
1084
|
+
let ingestUrl;
|
|
1085
|
+
const COMPILED_INGEST_BASE = "https://ingest.app.coframe.com/ingest/v2";
|
|
1086
|
+
function configureIngestUrl(url) {
|
|
1087
|
+
const trimmed = url === null || url === void 0 ? void 0 : url.trim().replace(/\/+$/, '');
|
|
1088
|
+
ingestUrl = trimmed || undefined;
|
|
1089
|
+
}
|
|
1090
|
+
function resolveIngestUrl(defaultUrl) {
|
|
1091
|
+
if (!ingestUrl || !defaultUrl.startsWith(COMPILED_INGEST_BASE))
|
|
1092
|
+
return defaultUrl;
|
|
1093
|
+
return ingestUrl + defaultUrl.slice(COMPILED_INGEST_BASE.length);
|
|
1094
|
+
}
|
|
1095
|
+
const MAX_BEACON_BATCH_BYTES = 48 * 1024;
|
|
1096
|
+
function getBeaconPayloadBytes(data) {
|
|
1097
|
+
return new Blob([JSON.stringify(data)]).size;
|
|
1098
|
+
}
|
|
1099
|
+
function chunkEventsByByteLimit(events) {
|
|
1100
|
+
const chunks = [];
|
|
1101
|
+
let current = [];
|
|
1102
|
+
for (const event of events) {
|
|
1103
|
+
if (current.length > 0 &&
|
|
1104
|
+
getBeaconPayloadBytes([...current, event]) > MAX_BEACON_BATCH_BYTES) {
|
|
1105
|
+
chunks.push(current);
|
|
1106
|
+
current = [];
|
|
1107
|
+
}
|
|
1108
|
+
current.push(event);
|
|
1109
|
+
}
|
|
1110
|
+
if (current.length > 0) {
|
|
1111
|
+
chunks.push(current);
|
|
1112
|
+
}
|
|
1113
|
+
return chunks;
|
|
1114
|
+
}
|
|
1071
1115
|
function queueMonitoringEvent(coframe, data) {
|
|
1072
1116
|
queuedMonitoringEvents.push(data);
|
|
1073
1117
|
if (queuedMonitoringEvents.length >= coframe.batchSize) {
|
|
@@ -1120,11 +1164,15 @@ function flushQueuedEvents(projectId) {
|
|
|
1120
1164
|
return;
|
|
1121
1165
|
}
|
|
1122
1166
|
if (queuedEvents.length > 0) {
|
|
1123
|
-
|
|
1167
|
+
for (const chunk of chunkEventsByByteLimit(queuedEvents)) {
|
|
1168
|
+
sendEventToBackend(projectId, chunk, 'batched_events');
|
|
1169
|
+
}
|
|
1124
1170
|
queuedEvents.length = 0;
|
|
1125
1171
|
}
|
|
1126
1172
|
if (queuedMonitoringEvents.length > 0) {
|
|
1127
|
-
|
|
1173
|
+
for (const chunk of chunkEventsByByteLimit(queuedMonitoringEvents)) {
|
|
1174
|
+
sendEventToBackend(projectId, chunk, 'batched_monitoring');
|
|
1175
|
+
}
|
|
1128
1176
|
queuedMonitoringEvents.length = 0;
|
|
1129
1177
|
}
|
|
1130
1178
|
if (queuedSessions.length > 0) {
|
|
@@ -1226,7 +1274,7 @@ function sendPageEngagementEvent(coframe, eventType, event, { projectId, session
|
|
|
1226
1274
|
}
|
|
1227
1275
|
}
|
|
1228
1276
|
function sendEventToBackend(projectId, data, eventCategory = 'events') {
|
|
1229
|
-
const eventsEndpoint = `${"https://ingest.app.coframe.com/ingest/v2"}/${eventCategory}/${projectId}
|
|
1277
|
+
const eventsEndpoint = resolveIngestUrl(`${"https://ingest.app.coframe.com/ingest/v2"}/${eventCategory}/${projectId}/`);
|
|
1230
1278
|
if (navigator.sendBeacon) {
|
|
1231
1279
|
const textData = JSON.stringify(data);
|
|
1232
1280
|
const blob = new Blob([textData], { type: 'text/plain' });
|
|
@@ -1239,7 +1287,7 @@ function sendEventToBackend(projectId, data, eventCategory = 'events') {
|
|
|
1239
1287
|
}
|
|
1240
1288
|
}
|
|
1241
1289
|
function createSession(data) {
|
|
1242
|
-
const sessionApiUrl = `${"https://ingest.app.coframe.com/ingest/v2"}/session_result
|
|
1290
|
+
const sessionApiUrl = resolveIngestUrl(`${"https://ingest.app.coframe.com/ingest/v2"}/session_result/`);
|
|
1243
1291
|
if (navigator.sendBeacon) {
|
|
1244
1292
|
const textData = JSON.stringify(data);
|
|
1245
1293
|
const blob = new Blob([textData], { type: 'text/plain' });
|
|
@@ -1251,11 +1299,14 @@ function createSession(data) {
|
|
|
1251
1299
|
console.warn('[Coframe] cannot send event beacon, feature unavailable');
|
|
1252
1300
|
}
|
|
1253
1301
|
}
|
|
1254
|
-
async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers) {
|
|
1302
|
+
async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers, referrer) {
|
|
1255
1303
|
const payload = { projectId, currentUrl };
|
|
1256
1304
|
if (previewVariantId) {
|
|
1257
1305
|
payload.previewVariantId = previewVariantId;
|
|
1258
1306
|
}
|
|
1307
|
+
if (referrer !== undefined) {
|
|
1308
|
+
payload.referrer = referrer;
|
|
1309
|
+
}
|
|
1259
1310
|
const safe = sanitizeUserContext(userContext);
|
|
1260
1311
|
if (safe) {
|
|
1261
1312
|
payload.userContext = safe;
|
|
@@ -1276,6 +1327,26 @@ async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext,
|
|
|
1276
1327
|
return null;
|
|
1277
1328
|
}
|
|
1278
1329
|
}
|
|
1330
|
+
async function fetchProject(projectUrl, projectId, currentUrl, signal, userContext, previewVariantId, headers, referrer) {
|
|
1331
|
+
if (!projectUrl) {
|
|
1332
|
+
return fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers, referrer);
|
|
1333
|
+
}
|
|
1334
|
+
try {
|
|
1335
|
+
const response = await fetch(projectUrl, { headers, signal });
|
|
1336
|
+
if (!response.ok)
|
|
1337
|
+
return null;
|
|
1338
|
+
return {
|
|
1339
|
+
project: (await response.json()),
|
|
1340
|
+
personalizationHeaders: {},
|
|
1341
|
+
};
|
|
1342
|
+
}
|
|
1343
|
+
catch (error) {
|
|
1344
|
+
if (error instanceof DOMException && error.name === 'AbortError') {
|
|
1345
|
+
return null;
|
|
1346
|
+
}
|
|
1347
|
+
return null;
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1279
1350
|
|
|
1280
1351
|
const isPageElement = (element) => {
|
|
1281
1352
|
return (element === document.body ||
|
|
@@ -2127,6 +2198,78 @@ function resolveLaneWinners(claims, reachableByLane, lanes, userToken) {
|
|
|
2127
2198
|
return excluded;
|
|
2128
2199
|
}
|
|
2129
2200
|
|
|
2201
|
+
var CoInspectorMessageType;
|
|
2202
|
+
(function (CoInspectorMessageType) {
|
|
2203
|
+
CoInspectorMessageType["onReady"] = "onReady";
|
|
2204
|
+
CoInspectorMessageType["onHoverElement"] = "onHoverElement";
|
|
2205
|
+
CoInspectorMessageType["onClickElement"] = "onClickElement";
|
|
2206
|
+
CoInspectorMessageType["onPageUrlChange"] = "onPageUrlChange";
|
|
2207
|
+
CoInspectorMessageType["onCreateNewElement"] = "onCreateNewElement";
|
|
2208
|
+
CoInspectorMessageType["onCancelNewElement"] = "onCancelNewElement";
|
|
2209
|
+
CoInspectorMessageType["onCopy"] = "onCopy";
|
|
2210
|
+
CoInspectorMessageType["onCloseDomInspectorPanel"] = "onCloseDomInspectorPanel";
|
|
2211
|
+
CoInspectorMessageType["onEditElement"] = "onEditElement";
|
|
2212
|
+
CoInspectorMessageType["onDeleteElement"] = "onDeleteElement";
|
|
2213
|
+
CoInspectorMessageType["onScroll"] = "onScroll";
|
|
2214
|
+
CoInspectorMessageType["setAllRects"] = "setAllRects";
|
|
2215
|
+
CoInspectorMessageType["onUpdateRects"] = "onUpdateRects";
|
|
2216
|
+
CoInspectorMessageType["DisableMouseTracking"] = "DisableMouseTracking";
|
|
2217
|
+
CoInspectorMessageType["EnableMouseTracking"] = "EnableMouseTracking";
|
|
2218
|
+
CoInspectorMessageType["onLeaveElement"] = "onLeaveElement";
|
|
2219
|
+
})(CoInspectorMessageType || (CoInspectorMessageType = {}));
|
|
2220
|
+
var CoMainSiteMessageType;
|
|
2221
|
+
(function (CoMainSiteMessageType) {
|
|
2222
|
+
CoMainSiteMessageType["ActiveInspect"] = "ActiveInspect";
|
|
2223
|
+
CoMainSiteMessageType["FreezeInspect"] = "FreezeInspect";
|
|
2224
|
+
CoMainSiteMessageType["SetElementChanges"] = "SetElementChanges";
|
|
2225
|
+
CoMainSiteMessageType["ShowDomInspector"] = "ShowDomInspector";
|
|
2226
|
+
CoMainSiteMessageType["RestoreOriginal"] = "RestoreOriginal";
|
|
2227
|
+
CoMainSiteMessageType["CreateNewElement"] = "CreateNewElement";
|
|
2228
|
+
CoMainSiteMessageType["ClickHoverElement"] = "ClickHoverElement";
|
|
2229
|
+
CoMainSiteMessageType["ReloadIframe"] = "ReloadIframe";
|
|
2230
|
+
})(CoMainSiteMessageType || (CoMainSiteMessageType = {}));
|
|
2231
|
+
|
|
2232
|
+
const COFRAME_PREVIEW_SESSION_STORAGE_KEY = 'coframe.preview_variant';
|
|
2233
|
+
const COFRAME_PREVIEW_VARIANT_QUERY_PARAM = 'coframe_variant_id';
|
|
2234
|
+
const ROLLOUTS_PREVIEW_ID = 'rollouts';
|
|
2235
|
+
function splitPreviewVariantIds(raw) {
|
|
2236
|
+
var _a;
|
|
2237
|
+
return ((_a = raw === null || raw === void 0 ? void 0 : raw.split(',').map((id) => id.trim()).filter(Boolean)) !== null && _a !== void 0 ? _a : []);
|
|
2238
|
+
}
|
|
2239
|
+
function isPreviewSentinel(id) {
|
|
2240
|
+
return id === GLOBAL_HOLDOUT || id === ROLLOUTS_PREVIEW_ID;
|
|
2241
|
+
}
|
|
2242
|
+
function normalizePreviewVariantId(raw) {
|
|
2243
|
+
const ids = splitPreviewVariantIds(raw);
|
|
2244
|
+
return ids.length > 0 ? ids.join(',') : null;
|
|
2245
|
+
}
|
|
2246
|
+
function readPreviewVariantIdFromUrl(url = window.location.href) {
|
|
2247
|
+
try {
|
|
2248
|
+
return normalizePreviewVariantId(getUrlSearchParams(url).get(COFRAME_PREVIEW_VARIANT_QUERY_PARAM));
|
|
2249
|
+
}
|
|
2250
|
+
catch (_a) {
|
|
2251
|
+
return null;
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
function readStoredPreviewVariantId() {
|
|
2255
|
+
try {
|
|
2256
|
+
return normalizePreviewVariantId(window.sessionStorage.getItem(COFRAME_PREVIEW_SESSION_STORAGE_KEY));
|
|
2257
|
+
}
|
|
2258
|
+
catch (_a) {
|
|
2259
|
+
return null;
|
|
2260
|
+
}
|
|
2261
|
+
}
|
|
2262
|
+
function resolvePreviewSource(url = window.location.href) {
|
|
2263
|
+
const urlVariantId = readPreviewVariantIdFromUrl(url);
|
|
2264
|
+
const storedVariantId = readStoredPreviewVariantId();
|
|
2265
|
+
return {
|
|
2266
|
+
effectiveVariantId: urlVariantId || storedVariantId,
|
|
2267
|
+
isKeptForSession: Boolean(storedVariantId && storedVariantId === (urlVariantId || storedVariantId)),
|
|
2268
|
+
storedVariantId,
|
|
2269
|
+
urlVariantId,
|
|
2270
|
+
};
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2130
2273
|
function isElementVisible(el) {
|
|
2131
2274
|
const rect = el.getBoundingClientRect();
|
|
2132
2275
|
return rect.top >= 0 && rect.bottom <= window.innerHeight;
|
|
@@ -2166,11 +2309,11 @@ function checkActivationCondition(condition, personalizationHeaders, currentUrl,
|
|
|
2166
2309
|
}
|
|
2167
2310
|
if (condition.url &&
|
|
2168
2311
|
condition.url !== '*' &&
|
|
2169
|
-
!
|
|
2312
|
+
!urlConditionMatches(condition.url, currentUrl, false, logger)) {
|
|
2170
2313
|
return false;
|
|
2171
2314
|
}
|
|
2172
2315
|
if (condition.base_url_matches &&
|
|
2173
|
-
!
|
|
2316
|
+
!urlConditionMatches(condition.base_url_matches, currentUrl, true, logger)) {
|
|
2174
2317
|
return false;
|
|
2175
2318
|
}
|
|
2176
2319
|
if (condition.url_regex) {
|
|
@@ -2284,6 +2427,18 @@ const normalizeUrl = (url, baseUrlMatch) => {
|
|
|
2284
2427
|
}
|
|
2285
2428
|
return `${hostname}${pathname}${parsedUrl.search}${parsedUrl.hash}`;
|
|
2286
2429
|
};
|
|
2430
|
+
function urlConditionMatches(conditionUrl, currentUrl, baseUrlMatch, logger) {
|
|
2431
|
+
try {
|
|
2432
|
+
return urlsMatch(conditionUrl, currentUrl, baseUrlMatch);
|
|
2433
|
+
}
|
|
2434
|
+
catch (_a) {
|
|
2435
|
+
logger.error('Error parsing URL condition', 'url_condition_error', {
|
|
2436
|
+
conditionUrl,
|
|
2437
|
+
currentUrl,
|
|
2438
|
+
});
|
|
2439
|
+
return false;
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2287
2442
|
function urlsMatch(conditionUrl, currentUrl, baseUrlMatch) {
|
|
2288
2443
|
if (currentUrl.includes('localhost') || currentUrl.includes('0.0.0.0')) {
|
|
2289
2444
|
const conditionUrlObj = new URL(conditionUrl);
|
|
@@ -2394,15 +2549,15 @@ const inRange = (bins, scale, seed, uid) => {
|
|
|
2394
2549
|
}
|
|
2395
2550
|
return false;
|
|
2396
2551
|
};
|
|
2397
|
-
function checkAllAudiences(metadata,
|
|
2552
|
+
function checkAllAudiences(metadata, ctx) {
|
|
2398
2553
|
var _a;
|
|
2399
2554
|
const audienceIds = (_a = metadata.activation_condition.audience_ids) !== null && _a !== void 0 ? _a : [];
|
|
2400
2555
|
let result = true;
|
|
2401
2556
|
for (const audienceId of audienceIds) {
|
|
2402
|
-
const audience = project.audiences[audienceId];
|
|
2557
|
+
const audience = ctx.project.audiences[audienceId];
|
|
2403
2558
|
if (!audience)
|
|
2404
2559
|
continue;
|
|
2405
|
-
const activated = checkActivationCondition(audience.selector, personalizationHeaders, currentPageUrl, languages, browserPlatform, userToken, userVisitCount, (js, args) => executeJs(js, args, { isExpression: true, nonce }), logger);
|
|
2560
|
+
const activated = checkActivationCondition(audience.selector, ctx.personalizationHeaders, ctx.currentPageUrl, ctx.languages, ctx.browserPlatform, ctx.userToken, ctx.userVisitCount, (js, args) => executeJs(js, args, { isExpression: true, nonce: ctx.nonce }), ctx.logger);
|
|
2406
2561
|
if (activated === false)
|
|
2407
2562
|
return false;
|
|
2408
2563
|
if (activated !== true)
|
|
@@ -2411,9 +2566,8 @@ function checkAllAudiences(metadata, project, personalizationHeaders, currentPag
|
|
|
2411
2566
|
return result;
|
|
2412
2567
|
}
|
|
2413
2568
|
async function getVariantsAndElements(personalizationHeaders, project, previewVariantId, userToken, currentPageUrl, languages, browserPlatform, logger, nonce, laneClaims = {}, silentFallback = false) {
|
|
2414
|
-
var _a
|
|
2569
|
+
var _a;
|
|
2415
2570
|
const experimentsInfo = [];
|
|
2416
|
-
const variantsAndElements = [];
|
|
2417
2571
|
const cloakBot = !!((_a = project.settings) === null || _a === void 0 ? void 0 : _a.bot_cloaking_enabled) &&
|
|
2418
2572
|
personalizationHeaders['x-is-bot'] === 'true';
|
|
2419
2573
|
const buildResponse = ({ variantsAndElements, experimentsInfo, hasActivatedFrames: frameActivated = false, laneClaims: meClaims = laneClaims, }) => {
|
|
@@ -2424,39 +2578,30 @@ async function getVariantsAndElements(personalizationHeaders, project, previewVa
|
|
|
2424
2578
|
laneClaims: meClaims,
|
|
2425
2579
|
};
|
|
2426
2580
|
};
|
|
2427
|
-
const
|
|
2581
|
+
const userVisitCount = Number.parseInt(getCookie(VISIT_COUNT_COOKIE_KEY) || '0', 10);
|
|
2582
|
+
const ctx = {
|
|
2583
|
+
project,
|
|
2584
|
+
personalizationHeaders,
|
|
2585
|
+
userToken,
|
|
2586
|
+
currentPageUrl,
|
|
2587
|
+
languages,
|
|
2588
|
+
browserPlatform,
|
|
2589
|
+
userVisitCount,
|
|
2590
|
+
nonce,
|
|
2591
|
+
logger,
|
|
2592
|
+
};
|
|
2593
|
+
const validatedClaims = validateClaims(laneClaims, project.lanes);
|
|
2594
|
+
const previewVariantIds = splitPreviewVariantIds(previewVariantId);
|
|
2428
2595
|
if (previewVariantIds.length > 0) {
|
|
2429
|
-
const
|
|
2430
|
-
|
|
2431
|
-
variant,
|
|
2432
|
-
elements: frame.elements,
|
|
2433
|
-
}))))
|
|
2434
|
-
.filter((item) => previewVariantIds.includes(item.variant.id));
|
|
2435
|
-
const skipAlert = previewVariantIds.some((id) => id === project.holdout_info.holdout_variant_id || id === GLOBAL_HOLDOUT);
|
|
2436
|
-
if (filteredVariantsAndElements.length > 0) {
|
|
2596
|
+
const variantsAndElements = previewVariants(previewVariantIds, validatedClaims, ctx, silentFallback);
|
|
2597
|
+
if (variantsAndElements) {
|
|
2437
2598
|
return buildResponse({
|
|
2438
|
-
variantsAndElements
|
|
2439
|
-
hasActivatedFrames:
|
|
2599
|
+
variantsAndElements,
|
|
2600
|
+
hasActivatedFrames: variantsAndElements.length > 0,
|
|
2440
2601
|
});
|
|
2441
2602
|
}
|
|
2442
|
-
if (!skipAlert && !silentFallback) {
|
|
2443
|
-
window.alert(`[Coframe] Variant preview unavailable: ${previewVariantId}.`);
|
|
2444
|
-
}
|
|
2445
|
-
if (silentFallback) ;
|
|
2446
|
-
else {
|
|
2447
|
-
return buildResponse({});
|
|
2448
|
-
}
|
|
2449
2603
|
}
|
|
2450
|
-
const
|
|
2451
|
-
const validatedClaims = validateClaims(laneClaims, project.lanes);
|
|
2452
|
-
const activeFrames = project.frames.filter((frame) => {
|
|
2453
|
-
if (!frame.experiments)
|
|
2454
|
-
return false;
|
|
2455
|
-
const frameActivated = checkActivationCondition(frame.activation_condition, personalizationHeaders, currentPageUrl, languages, browserPlatform, userToken, userVisitCount, (js, args) => executeJs(js, args, { isExpression: true, nonce }), logger);
|
|
2456
|
-
if (!frameActivated)
|
|
2457
|
-
return false;
|
|
2458
|
-
return true;
|
|
2459
|
-
});
|
|
2604
|
+
const activeFrames = activateFrames(ctx);
|
|
2460
2605
|
if (activeFrames.length === 0) {
|
|
2461
2606
|
return buildResponse({ laneClaims: validatedClaims });
|
|
2462
2607
|
}
|
|
@@ -2474,7 +2619,6 @@ async function getVariantsAndElements(personalizationHeaders, project, previewVa
|
|
|
2474
2619
|
level: GLOBAL_HOLDOUT,
|
|
2475
2620
|
});
|
|
2476
2621
|
return buildResponse({
|
|
2477
|
-
variantsAndElements,
|
|
2478
2622
|
experimentsInfo,
|
|
2479
2623
|
hasActivatedFrames: true,
|
|
2480
2624
|
laneClaims: validatedClaims,
|
|
@@ -2489,7 +2633,27 @@ async function getVariantsAndElements(personalizationHeaders, project, previewVa
|
|
|
2489
2633
|
final_state: false,
|
|
2490
2634
|
level: GLOBAL_HOLDOUT,
|
|
2491
2635
|
});
|
|
2492
|
-
const
|
|
2636
|
+
const assignment = assignFrames(activeFrames, validatedClaims, ctx);
|
|
2637
|
+
return buildResponse({
|
|
2638
|
+
...assignment,
|
|
2639
|
+
experimentsInfo: [...experimentsInfo, ...assignment.experimentsInfo],
|
|
2640
|
+
});
|
|
2641
|
+
}
|
|
2642
|
+
function activateFrames(ctx) {
|
|
2643
|
+
return ctx.project.frames.filter((frame) => {
|
|
2644
|
+
if (!frame.experiments)
|
|
2645
|
+
return false;
|
|
2646
|
+
const frameActivated = checkActivationCondition(frame.activation_condition, ctx.personalizationHeaders, ctx.currentPageUrl, ctx.languages, ctx.browserPlatform, ctx.userToken, ctx.userVisitCount, (js, args) => executeJs(js, args, { isExpression: true, nonce: ctx.nonce }), ctx.logger);
|
|
2647
|
+
if (!frameActivated)
|
|
2648
|
+
return false;
|
|
2649
|
+
return true;
|
|
2650
|
+
});
|
|
2651
|
+
}
|
|
2652
|
+
function assignFrames(activeFrames, validatedClaims, ctx) {
|
|
2653
|
+
const { project, userToken, logger } = ctx;
|
|
2654
|
+
const experimentsInfo = [];
|
|
2655
|
+
const variantsAndElements = [];
|
|
2656
|
+
const evalAudiences = (metadata) => checkAllAudiences(metadata, ctx) !== false;
|
|
2493
2657
|
const audiencePass = new Map();
|
|
2494
2658
|
const reachableByLane = {};
|
|
2495
2659
|
for (const frame of activeFrames) {
|
|
@@ -2582,50 +2746,49 @@ async function getVariantsAndElements(personalizationHeaders, project, previewVa
|
|
|
2582
2746
|
variantsAndElements.push({ variant, elements });
|
|
2583
2747
|
}
|
|
2584
2748
|
}
|
|
2585
|
-
return
|
|
2749
|
+
return {
|
|
2586
2750
|
variantsAndElements,
|
|
2587
2751
|
experimentsInfo,
|
|
2588
2752
|
hasActivatedFrames,
|
|
2589
2753
|
laneClaims: updatedClaims,
|
|
2590
|
-
}
|
|
2754
|
+
};
|
|
2591
2755
|
}
|
|
2592
|
-
|
|
2593
|
-
const
|
|
2594
|
-
const
|
|
2595
|
-
|
|
2596
|
-
|
|
2756
|
+
function previewVariants(previewVariantIds, validatedClaims, ctx, silentFallback) {
|
|
2757
|
+
const previewRollouts = previewVariantIds.includes(ROLLOUTS_PREVIEW_ID);
|
|
2758
|
+
const requestedVariantIds = previewVariantIds.filter((id) => !isPreviewSentinel(id));
|
|
2759
|
+
const requestedVariants = findVariants(ctx.project.frames, requestedVariantIds);
|
|
2760
|
+
const requestedVariantsMissing = requestedVariantIds.length > 0 && requestedVariants.length === 0;
|
|
2761
|
+
if (requestedVariantsMissing && !previewRollouts && silentFallback) {
|
|
2597
2762
|
return null;
|
|
2598
|
-
const ids = raw
|
|
2599
|
-
.split(',')
|
|
2600
|
-
.map((id) => id.trim())
|
|
2601
|
-
.filter(Boolean);
|
|
2602
|
-
return ids.length > 0 ? ids.join(',') : null;
|
|
2603
|
-
}
|
|
2604
|
-
function readPreviewVariantIdFromUrl(url = window.location.href) {
|
|
2605
|
-
try {
|
|
2606
|
-
return normalizePreviewVariantId(getUrlSearchParams(url).get(COFRAME_PREVIEW_VARIANT_QUERY_PARAM));
|
|
2607
2763
|
}
|
|
2608
|
-
|
|
2609
|
-
|
|
2764
|
+
const requestedHoldout = requestedVariantIds.includes(ctx.project.holdout_info.holdout_variant_id);
|
|
2765
|
+
if (requestedVariantsMissing && !requestedHoldout && !silentFallback) {
|
|
2766
|
+
window.alert(`[Coframe] Variant preview unavailable: ${previewVariantIds.join(',')}.`);
|
|
2610
2767
|
}
|
|
2768
|
+
const rolledOutVariants = previewRollouts && !previewVariantIds.includes(GLOBAL_HOLDOUT)
|
|
2769
|
+
? assignFrames(keepRolledOutExperiments(activateFrames(ctx)), validatedClaims, ctx).variantsAndElements
|
|
2770
|
+
: [];
|
|
2771
|
+
return uniqueByVariantId([...rolledOutVariants, ...requestedVariants]);
|
|
2611
2772
|
}
|
|
2612
|
-
function
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
catch (_a) {
|
|
2617
|
-
return null;
|
|
2618
|
-
}
|
|
2773
|
+
function findVariants(frames, variantIds) {
|
|
2774
|
+
return frames.flatMap((frame) => frame.experiments.flatMap((experiment) => experiment.variants
|
|
2775
|
+
.filter((variant) => variantIds.includes(variant.id))
|
|
2776
|
+
.map((variant) => ({ variant, elements: frame.elements }))));
|
|
2619
2777
|
}
|
|
2620
|
-
function
|
|
2621
|
-
const
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
|
|
2778
|
+
function uniqueByVariantId(items) {
|
|
2779
|
+
const seen = {};
|
|
2780
|
+
return items.filter(({ variant }) => {
|
|
2781
|
+
if (seen[variant.id])
|
|
2782
|
+
return false;
|
|
2783
|
+
seen[variant.id] = true;
|
|
2784
|
+
return true;
|
|
2785
|
+
});
|
|
2786
|
+
}
|
|
2787
|
+
function keepRolledOutExperiments(frames) {
|
|
2788
|
+
return frames.map((frame) => ({
|
|
2789
|
+
...frame,
|
|
2790
|
+
experiments: frame.experiments.filter((experiment) => experiment.metadata.serving_mode === 'winner'),
|
|
2791
|
+
}));
|
|
2629
2792
|
}
|
|
2630
2793
|
|
|
2631
2794
|
function buildSessionContext(isInitialApply) {
|
|
@@ -2911,29 +3074,27 @@ function createTreatmentAnalytics(Coframe, previewVariantId) {
|
|
|
2911
3074
|
});
|
|
2912
3075
|
}
|
|
2913
3076
|
}
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2928
|
-
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
});
|
|
2936
|
-
}
|
|
3077
|
+
const previewIds = splitPreviewVariantIds(previewVariantId).filter((id) => !isPreviewSentinel(id));
|
|
3078
|
+
for (const id of previewIds) {
|
|
3079
|
+
treatmentsData.push({
|
|
3080
|
+
impressionId: sessionId,
|
|
3081
|
+
userToken,
|
|
3082
|
+
experimentId: `preview_id_${id}`,
|
|
3083
|
+
holdoutExperimentId: `preview_holdout_id_${id}`,
|
|
3084
|
+
variantId: id,
|
|
3085
|
+
inGlobalHoldout: false,
|
|
3086
|
+
isBaseline: false,
|
|
3087
|
+
});
|
|
3088
|
+
treatmentsDataV2.push({
|
|
3089
|
+
coframe_experiment_id: `preview_id_${id}`,
|
|
3090
|
+
coframe_experiment_slug: `preview_id_${id}`,
|
|
3091
|
+
coframe_variant_id: id,
|
|
3092
|
+
coframe_variant_slug: id,
|
|
3093
|
+
coframe_user_token: userToken,
|
|
3094
|
+
coframe_impression_id: sessionId,
|
|
3095
|
+
coframe_in_global_holdout: false,
|
|
3096
|
+
coframe_in_exp_baseline: false,
|
|
3097
|
+
});
|
|
2937
3098
|
}
|
|
2938
3099
|
Coframe.treatmentsData = treatmentsData;
|
|
2939
3100
|
Coframe.treatmentsDataV2 = treatmentsDataV2;
|
|
@@ -3178,12 +3339,12 @@ async function ensureBody(Coframe, cdnProject, timeoutMs, nonce) {
|
|
|
3178
3339
|
}
|
|
3179
3340
|
const FLUSH_EVENTS_TIME = 1000 * 3;
|
|
3180
3341
|
let flushInterval = null;
|
|
3181
|
-
function setupFlushInterval(
|
|
3182
|
-
flushQueuedEvents(projectId);
|
|
3342
|
+
function setupFlushInterval(Coframe) {
|
|
3343
|
+
flushQueuedEvents(Coframe.projectId);
|
|
3183
3344
|
if (flushInterval !== null) {
|
|
3184
3345
|
clearInterval(flushInterval);
|
|
3185
3346
|
}
|
|
3186
|
-
flushInterval = setInterval(() => flushQueuedEvents(projectId), FLUSH_EVENTS_TIME);
|
|
3347
|
+
flushInterval = setInterval(() => flushQueuedEvents(Coframe.projectId), FLUSH_EVENTS_TIME);
|
|
3187
3348
|
}
|
|
3188
3349
|
function setupSPANavigation(Coframe, project, config, previewVariantId, isSessionVariant, applyVariants) {
|
|
3189
3350
|
var _a;
|
|
@@ -3211,6 +3372,7 @@ function setupSPANavigation(Coframe, project, config, previewVariantId, isSessio
|
|
|
3211
3372
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
3212
3373
|
let navigationAbortController = null;
|
|
3213
3374
|
observeUrlChanges(false, async (newPageUrl, _oldPageUrl) => {
|
|
3375
|
+
var _a;
|
|
3214
3376
|
await new Promise((resolve) => requestAnimationFrame(resolve));
|
|
3215
3377
|
infiniteLoopProtection = 0;
|
|
3216
3378
|
if (navigationAbortController)
|
|
@@ -3218,27 +3380,33 @@ function setupSPANavigation(Coframe, project, config, previewVariantId, isSessio
|
|
|
3218
3380
|
navigationAbortController = new AbortController();
|
|
3219
3381
|
const { signal } = navigationAbortController;
|
|
3220
3382
|
let pageProject = project;
|
|
3383
|
+
let pagePersonalizationHeaders = Coframe.personalizationHeaders;
|
|
3221
3384
|
const cached = getCachedFrames(newPageUrl);
|
|
3222
3385
|
if (cached) {
|
|
3223
3386
|
pageProject = cached.project;
|
|
3387
|
+
pagePersonalizationHeaders = {
|
|
3388
|
+
...cached.personalizationHeaders,
|
|
3389
|
+
'x-visit-url': newPageUrl,
|
|
3390
|
+
};
|
|
3224
3391
|
}
|
|
3225
3392
|
else {
|
|
3226
3393
|
try {
|
|
3227
3394
|
const preview = resolvePreview(newPageUrl, previewVariantId, isSessionVariant);
|
|
3228
|
-
const result = await
|
|
3395
|
+
const result = await fetchProject(config.projectUrl, Coframe.projectId, newPageUrl, signal, config.userContext, preview.previewVariantId || undefined, undefined, (_a = config.referrer) !== null && _a !== void 0 ? _a : getBrowserReferrer());
|
|
3229
3396
|
if (signal.aborted)
|
|
3230
3397
|
return;
|
|
3231
3398
|
if (result) {
|
|
3232
3399
|
pageProject = result.project;
|
|
3400
|
+
pagePersonalizationHeaders = result.personalizationHeaders;
|
|
3233
3401
|
cacheFrames(newPageUrl, result);
|
|
3234
3402
|
}
|
|
3235
3403
|
}
|
|
3236
|
-
catch (
|
|
3404
|
+
catch (_b) {
|
|
3237
3405
|
}
|
|
3238
3406
|
}
|
|
3239
3407
|
if (signal.aborted)
|
|
3240
3408
|
return;
|
|
3241
|
-
await applyVariants(newPageUrl, pageProject);
|
|
3409
|
+
await applyVariants(newPageUrl, pageProject, pagePersonalizationHeaders);
|
|
3242
3410
|
});
|
|
3243
3411
|
}
|
|
3244
3412
|
function readLaneClaims() {
|
|
@@ -3269,13 +3437,14 @@ function persistLaneClaims(claims, logger) {
|
|
|
3269
3437
|
setCookie(LANE_COOKIE_KEY, encodeURIComponent(serialized), logger);
|
|
3270
3438
|
}
|
|
3271
3439
|
}
|
|
3272
|
-
function createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics,
|
|
3440
|
+
function createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics, laneStore) {
|
|
3273
3441
|
let isFirstApply = true;
|
|
3274
|
-
return async (pageUrl, pageProject) => {
|
|
3442
|
+
return async (pageUrl, pageProject, personalizationHeaders) => {
|
|
3275
3443
|
const sessionId = isFirstApply ? Coframe.sessionId : generateUUID();
|
|
3276
3444
|
const sessionContext = buildSessionContext(isFirstApply);
|
|
3277
3445
|
isFirstApply = false;
|
|
3278
3446
|
Coframe.sessionId = sessionId;
|
|
3447
|
+
Coframe.personalizationHeaders = personalizationHeaders;
|
|
3279
3448
|
const preview = resolvePreview(pageUrl, previewVariantId, isSessionVariant);
|
|
3280
3449
|
setIsPreviewVariant(!!preview.previewVariantId);
|
|
3281
3450
|
const { variantsAndElements, experimentsInfo, hasActivatedFrames, laneClaims, } = await getVariantsAndElements(personalizationHeaders, pageProject, preview.previewVariantId, Coframe.userToken, pageUrl, getBrowserLanguages(), getBrowserPlatform(), Coframe.logger, config.nonce, laneStore.claims, preview.isSessionVariant);
|
|
@@ -3312,8 +3481,8 @@ async function modifyPage(Coframe, configResult, projectResult, analytics) {
|
|
|
3312
3481
|
if (!(await ensureBody(Coframe, cdnProject, timeoutMs, config.nonce)))
|
|
3313
3482
|
return;
|
|
3314
3483
|
const laneStore = { claims: readLaneClaims() };
|
|
3315
|
-
const applyVariants = createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics,
|
|
3316
|
-
await applyVariants(getCurrentPageUrl(), cdnProject);
|
|
3484
|
+
const applyVariants = createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics, laneStore);
|
|
3485
|
+
await applyVariants(getCurrentPageUrl(), cdnProject, personalizationHeaders);
|
|
3317
3486
|
if (!Coframe.variantsAndElements ||
|
|
3318
3487
|
Coframe.variantsAndElements.length === 0) {
|
|
3319
3488
|
revealPage();
|
|
@@ -3321,7 +3490,7 @@ async function modifyPage(Coframe, configResult, projectResult, analytics) {
|
|
|
3321
3490
|
}
|
|
3322
3491
|
reportInitTiming(Coframe, cdnProject, integrationStartTime, executionStartTime);
|
|
3323
3492
|
setupSPANavigation(Coframe, cdnProject, config, previewVariantId, isSessionVariant, applyVariants);
|
|
3324
|
-
setupFlushInterval(Coframe
|
|
3493
|
+
setupFlushInterval(Coframe);
|
|
3325
3494
|
}
|
|
3326
3495
|
|
|
3327
3496
|
const TIMEOUT_MAX_MS = 5000;
|
|
@@ -3357,6 +3526,7 @@ async function resolveConfig(Coframe, revealPage) {
|
|
|
3357
3526
|
: null;
|
|
3358
3527
|
const executionStartTime = new Date();
|
|
3359
3528
|
Coframe.batchSize = config.batchSize || 32;
|
|
3529
|
+
configureIngestUrl(config.ingestUrl);
|
|
3360
3530
|
const gracefulExit = (msg) => {
|
|
3361
3531
|
console.warn(`[Coframe] ${msg}`);
|
|
3362
3532
|
revealPage();
|
|
@@ -3478,13 +3648,13 @@ async function resolveIdentity(config, Coframe, timeoutMs, gracefulExit) {
|
|
|
3478
3648
|
}
|
|
3479
3649
|
|
|
3480
3650
|
async function resolveProject(Coframe, previewVariantId, isSessionVariant, config) {
|
|
3481
|
-
var _a;
|
|
3651
|
+
var _a, _b;
|
|
3482
3652
|
const logger = Coframe.logger;
|
|
3483
3653
|
const projectData = (_a = findLastCmd((c) => !!c.projectData)) === null || _a === void 0 ? void 0 : _a.projectData;
|
|
3484
3654
|
let personalizationHeaders = (projectData === null || projectData === void 0 ? void 0 : projectData.personalizationHeaders) || null;
|
|
3485
3655
|
let project = isSessionVariant ? undefined : projectData === null || projectData === void 0 ? void 0 : projectData.project;
|
|
3486
3656
|
if (!project) {
|
|
3487
|
-
const edgeResult = await
|
|
3657
|
+
const edgeResult = await fetchProject(config.projectUrl, Coframe.projectId, config.currentUrl || getCurrentPageUrl(), undefined, config.userContext, previewVariantId || undefined, undefined, (_b = config.referrer) !== null && _b !== void 0 ? _b : getBrowserReferrer());
|
|
3488
3658
|
personalizationHeaders = (edgeResult === null || edgeResult === void 0 ? void 0 : edgeResult.personalizationHeaders) || null;
|
|
3489
3659
|
project = (edgeResult === null || edgeResult === void 0 ? void 0 : edgeResult.project) || undefined;
|
|
3490
3660
|
}
|
package/dist/pkg/react.cjs.js
CHANGED
|
@@ -8,7 +8,7 @@ const CoframeContext = React.createContext({ treatments: null });
|
|
|
8
8
|
function CoframeProvider({ projectConfig, projectData, onTreatmentApplied: onTreatmentAppliedProp, onTreatmentAppliedBulk: onTreatmentAppliedBulkProp, onTreatmentAppliedBulkV2, onTreatmentAppliedBulkV2WithoutConsent, onLog: onLogProp, children, }) {
|
|
9
9
|
const [treatments, setTreatments] = React.useState(null);
|
|
10
10
|
React.useEffect(() => {
|
|
11
|
-
var _a, _b;
|
|
11
|
+
var _a, _b, _c;
|
|
12
12
|
if (/cf_disable/.test(window.location.search)) {
|
|
13
13
|
sdk.init().catch((e) => {
|
|
14
14
|
console.error('[Coframe] Error disabling SDK', e);
|
|
@@ -33,6 +33,7 @@ function CoframeProvider({ projectConfig, projectData, onTreatmentApplied: onTre
|
|
|
33
33
|
...projectConfig,
|
|
34
34
|
startTime: (_a = projectConfig.startTime) !== null && _a !== void 0 ? _a : Date.now(),
|
|
35
35
|
currentUrl: (_b = projectConfig.currentUrl) !== null && _b !== void 0 ? _b : window.location.href,
|
|
36
|
+
referrer: (_c = projectConfig.referrer) !== null && _c !== void 0 ? _c : document.referrer,
|
|
36
37
|
},
|
|
37
38
|
...(projectData ? { projectData } : {}),
|
|
38
39
|
})
|
package/dist/pkg/react.esm.mjs
CHANGED
|
@@ -7,7 +7,7 @@ const CoframeContext = createContext({ treatments: null });
|
|
|
7
7
|
function CoframeProvider({ projectConfig, projectData, onTreatmentApplied: onTreatmentAppliedProp, onTreatmentAppliedBulk: onTreatmentAppliedBulkProp, onTreatmentAppliedBulkV2, onTreatmentAppliedBulkV2WithoutConsent, onLog: onLogProp, children, }) {
|
|
8
8
|
const [treatments, setTreatments] = useState(null);
|
|
9
9
|
useEffect(() => {
|
|
10
|
-
var _a, _b;
|
|
10
|
+
var _a, _b, _c;
|
|
11
11
|
if (/cf_disable/.test(window.location.search)) {
|
|
12
12
|
init().catch((e) => {
|
|
13
13
|
console.error('[Coframe] Error disabling SDK', e);
|
|
@@ -32,6 +32,7 @@ function CoframeProvider({ projectConfig, projectData, onTreatmentApplied: onTre
|
|
|
32
32
|
...projectConfig,
|
|
33
33
|
startTime: (_a = projectConfig.startTime) !== null && _a !== void 0 ? _a : Date.now(),
|
|
34
34
|
currentUrl: (_b = projectConfig.currentUrl) !== null && _b !== void 0 ? _b : window.location.href,
|
|
35
|
+
referrer: (_c = projectConfig.referrer) !== null && _c !== void 0 ? _c : document.referrer,
|
|
35
36
|
},
|
|
36
37
|
...(projectData ? { projectData } : {}),
|
|
37
38
|
})
|