@coframe/sdk 1.1.14 → 1.1.16

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.
@@ -1066,10 +1066,30 @@ function warnEventsNotSent() {
1066
1066
  }
1067
1067
  }
1068
1068
 
1069
- const SDK_VERSION = '2.6.0';
1069
+ const SDK_VERSION = '2.7.0';
1070
1070
  const queuedEvents = [];
1071
1071
  const queuedMonitoringEvents = [];
1072
1072
  const queuedSessions = [];
1073
+ const MAX_BEACON_BATCH_BYTES = 48 * 1024;
1074
+ function getBeaconPayloadBytes(data) {
1075
+ return new Blob([JSON.stringify(data)]).size;
1076
+ }
1077
+ function chunkEventsByByteLimit(events) {
1078
+ const chunks = [];
1079
+ let current = [];
1080
+ for (const event of events) {
1081
+ if (current.length > 0 &&
1082
+ getBeaconPayloadBytes([...current, event]) > MAX_BEACON_BATCH_BYTES) {
1083
+ chunks.push(current);
1084
+ current = [];
1085
+ }
1086
+ current.push(event);
1087
+ }
1088
+ if (current.length > 0) {
1089
+ chunks.push(current);
1090
+ }
1091
+ return chunks;
1092
+ }
1073
1093
  function queueMonitoringEvent(coframe, data) {
1074
1094
  queuedMonitoringEvents.push(data);
1075
1095
  if (queuedMonitoringEvents.length >= coframe.batchSize) {
@@ -1122,11 +1142,15 @@ function flushQueuedEvents(projectId) {
1122
1142
  return;
1123
1143
  }
1124
1144
  if (queuedEvents.length > 0) {
1125
- sendEventToBackend(projectId, queuedEvents, 'batched_events');
1145
+ for (const chunk of chunkEventsByByteLimit(queuedEvents)) {
1146
+ sendEventToBackend(projectId, chunk, 'batched_events');
1147
+ }
1126
1148
  queuedEvents.length = 0;
1127
1149
  }
1128
1150
  if (queuedMonitoringEvents.length > 0) {
1129
- sendEventToBackend(projectId, queuedMonitoringEvents, 'batched_monitoring');
1151
+ for (const chunk of chunkEventsByByteLimit(queuedMonitoringEvents)) {
1152
+ sendEventToBackend(projectId, chunk, 'batched_monitoring');
1153
+ }
1130
1154
  queuedMonitoringEvents.length = 0;
1131
1155
  }
1132
1156
  if (queuedSessions.length > 0) {
@@ -1253,11 +1277,14 @@ function createSession(data) {
1253
1277
  console.warn('[Coframe] cannot send event beacon, feature unavailable');
1254
1278
  }
1255
1279
  }
1256
- async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers) {
1280
+ async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers, referrer) {
1257
1281
  const payload = { projectId, currentUrl };
1258
1282
  if (previewVariantId) {
1259
1283
  payload.previewVariantId = previewVariantId;
1260
1284
  }
1285
+ if (referrer !== undefined) {
1286
+ payload.referrer = referrer;
1287
+ }
1261
1288
  const safe = sanitizeUserContext(userContext);
1262
1289
  if (safe) {
1263
1290
  payload.userContext = safe;
@@ -3213,6 +3240,7 @@ function setupSPANavigation(Coframe, project, config, previewVariantId, isSessio
3213
3240
  observer.observe(document.body, { childList: true, subtree: true });
3214
3241
  let navigationAbortController = null;
3215
3242
  observeUrlChanges(false, async (newPageUrl, _oldPageUrl) => {
3243
+ var _a;
3216
3244
  await new Promise((resolve) => requestAnimationFrame(resolve));
3217
3245
  infiniteLoopProtection = 0;
3218
3246
  if (navigationAbortController)
@@ -3220,27 +3248,33 @@ function setupSPANavigation(Coframe, project, config, previewVariantId, isSessio
3220
3248
  navigationAbortController = new AbortController();
3221
3249
  const { signal } = navigationAbortController;
3222
3250
  let pageProject = project;
3251
+ let pagePersonalizationHeaders = Coframe.personalizationHeaders;
3223
3252
  const cached = getCachedFrames(newPageUrl);
3224
3253
  if (cached) {
3225
3254
  pageProject = cached.project;
3255
+ pagePersonalizationHeaders = {
3256
+ ...cached.personalizationHeaders,
3257
+ 'x-visit-url': newPageUrl,
3258
+ };
3226
3259
  }
3227
3260
  else {
3228
3261
  try {
3229
3262
  const preview = resolvePreview(newPageUrl, previewVariantId, isSessionVariant);
3230
- const result = await fetchProjectFromEdge(Coframe.projectId, newPageUrl, signal, config.userContext, preview.previewVariantId || undefined);
3263
+ const result = await fetchProjectFromEdge(Coframe.projectId, newPageUrl, signal, config.userContext, preview.previewVariantId || undefined, undefined, (_a = config.referrer) !== null && _a !== void 0 ? _a : getBrowserReferrer());
3231
3264
  if (signal.aborted)
3232
3265
  return;
3233
3266
  if (result) {
3234
3267
  pageProject = result.project;
3268
+ pagePersonalizationHeaders = result.personalizationHeaders;
3235
3269
  cacheFrames(newPageUrl, result);
3236
3270
  }
3237
3271
  }
3238
- catch (_a) {
3272
+ catch (_b) {
3239
3273
  }
3240
3274
  }
3241
3275
  if (signal.aborted)
3242
3276
  return;
3243
- await applyVariants(newPageUrl, pageProject);
3277
+ await applyVariants(newPageUrl, pageProject, pagePersonalizationHeaders);
3244
3278
  });
3245
3279
  }
3246
3280
  function readLaneClaims() {
@@ -3271,13 +3305,14 @@ function persistLaneClaims(claims, logger) {
3271
3305
  setCookie(LANE_COOKIE_KEY, encodeURIComponent(serialized), logger);
3272
3306
  }
3273
3307
  }
3274
- function createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics, personalizationHeaders, laneStore) {
3308
+ function createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics, laneStore) {
3275
3309
  let isFirstApply = true;
3276
- return async (pageUrl, pageProject) => {
3310
+ return async (pageUrl, pageProject, personalizationHeaders) => {
3277
3311
  const sessionId = isFirstApply ? Coframe.sessionId : generateUUID();
3278
3312
  const sessionContext = buildSessionContext(isFirstApply);
3279
3313
  isFirstApply = false;
3280
3314
  Coframe.sessionId = sessionId;
3315
+ Coframe.personalizationHeaders = personalizationHeaders;
3281
3316
  const preview = resolvePreview(pageUrl, previewVariantId, isSessionVariant);
3282
3317
  setIsPreviewVariant(!!preview.previewVariantId);
3283
3318
  const { variantsAndElements, experimentsInfo, hasActivatedFrames, laneClaims, } = await getVariantsAndElements(personalizationHeaders, pageProject, preview.previewVariantId, Coframe.userToken, pageUrl, getBrowserLanguages(), getBrowserPlatform(), Coframe.logger, config.nonce, laneStore.claims, preview.isSessionVariant);
@@ -3314,8 +3349,8 @@ async function modifyPage(Coframe, configResult, projectResult, analytics) {
3314
3349
  if (!(await ensureBody(Coframe, cdnProject, timeoutMs, config.nonce)))
3315
3350
  return;
3316
3351
  const laneStore = { claims: readLaneClaims() };
3317
- const applyVariants = createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics, personalizationHeaders, laneStore);
3318
- await applyVariants(getCurrentPageUrl(), cdnProject);
3352
+ const applyVariants = createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics, laneStore);
3353
+ await applyVariants(getCurrentPageUrl(), cdnProject, personalizationHeaders);
3319
3354
  if (!Coframe.variantsAndElements ||
3320
3355
  Coframe.variantsAndElements.length === 0) {
3321
3356
  revealPage();
@@ -3480,13 +3515,13 @@ async function resolveIdentity(config, Coframe, timeoutMs, gracefulExit) {
3480
3515
  }
3481
3516
 
3482
3517
  async function resolveProject(Coframe, previewVariantId, isSessionVariant, config) {
3483
- var _a;
3518
+ var _a, _b;
3484
3519
  const logger = Coframe.logger;
3485
3520
  const projectData = (_a = findLastCmd((c) => !!c.projectData)) === null || _a === void 0 ? void 0 : _a.projectData;
3486
3521
  let personalizationHeaders = (projectData === null || projectData === void 0 ? void 0 : projectData.personalizationHeaders) || null;
3487
3522
  let project = isSessionVariant ? undefined : projectData === null || projectData === void 0 ? void 0 : projectData.project;
3488
3523
  if (!project) {
3489
- const edgeResult = await fetchProjectFromEdge(Coframe.projectId, config.currentUrl || getCurrentPageUrl(), undefined, config.userContext, previewVariantId || undefined);
3524
+ const edgeResult = await fetchProjectFromEdge(Coframe.projectId, config.currentUrl || getCurrentPageUrl(), undefined, config.userContext, previewVariantId || undefined, undefined, (_b = config.referrer) !== null && _b !== void 0 ? _b : getBrowserReferrer());
3490
3525
  personalizationHeaders = (edgeResult === null || edgeResult === void 0 ? void 0 : edgeResult.personalizationHeaders) || null;
3491
3526
  project = (edgeResult === null || edgeResult === void 0 ? void 0 : edgeResult.project) || undefined;
3492
3527
  }
@@ -1064,10 +1064,30 @@ function warnEventsNotSent() {
1064
1064
  }
1065
1065
  }
1066
1066
 
1067
- const SDK_VERSION = '2.6.0';
1067
+ const SDK_VERSION = '2.7.0';
1068
1068
  const queuedEvents = [];
1069
1069
  const queuedMonitoringEvents = [];
1070
1070
  const queuedSessions = [];
1071
+ const MAX_BEACON_BATCH_BYTES = 48 * 1024;
1072
+ function getBeaconPayloadBytes(data) {
1073
+ return new Blob([JSON.stringify(data)]).size;
1074
+ }
1075
+ function chunkEventsByByteLimit(events) {
1076
+ const chunks = [];
1077
+ let current = [];
1078
+ for (const event of events) {
1079
+ if (current.length > 0 &&
1080
+ getBeaconPayloadBytes([...current, event]) > MAX_BEACON_BATCH_BYTES) {
1081
+ chunks.push(current);
1082
+ current = [];
1083
+ }
1084
+ current.push(event);
1085
+ }
1086
+ if (current.length > 0) {
1087
+ chunks.push(current);
1088
+ }
1089
+ return chunks;
1090
+ }
1071
1091
  function queueMonitoringEvent(coframe, data) {
1072
1092
  queuedMonitoringEvents.push(data);
1073
1093
  if (queuedMonitoringEvents.length >= coframe.batchSize) {
@@ -1120,11 +1140,15 @@ function flushQueuedEvents(projectId) {
1120
1140
  return;
1121
1141
  }
1122
1142
  if (queuedEvents.length > 0) {
1123
- sendEventToBackend(projectId, queuedEvents, 'batched_events');
1143
+ for (const chunk of chunkEventsByByteLimit(queuedEvents)) {
1144
+ sendEventToBackend(projectId, chunk, 'batched_events');
1145
+ }
1124
1146
  queuedEvents.length = 0;
1125
1147
  }
1126
1148
  if (queuedMonitoringEvents.length > 0) {
1127
- sendEventToBackend(projectId, queuedMonitoringEvents, 'batched_monitoring');
1149
+ for (const chunk of chunkEventsByByteLimit(queuedMonitoringEvents)) {
1150
+ sendEventToBackend(projectId, chunk, 'batched_monitoring');
1151
+ }
1128
1152
  queuedMonitoringEvents.length = 0;
1129
1153
  }
1130
1154
  if (queuedSessions.length > 0) {
@@ -1251,11 +1275,14 @@ function createSession(data) {
1251
1275
  console.warn('[Coframe] cannot send event beacon, feature unavailable');
1252
1276
  }
1253
1277
  }
1254
- async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers) {
1278
+ async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers, referrer) {
1255
1279
  const payload = { projectId, currentUrl };
1256
1280
  if (previewVariantId) {
1257
1281
  payload.previewVariantId = previewVariantId;
1258
1282
  }
1283
+ if (referrer !== undefined) {
1284
+ payload.referrer = referrer;
1285
+ }
1259
1286
  const safe = sanitizeUserContext(userContext);
1260
1287
  if (safe) {
1261
1288
  payload.userContext = safe;
@@ -3211,6 +3238,7 @@ function setupSPANavigation(Coframe, project, config, previewVariantId, isSessio
3211
3238
  observer.observe(document.body, { childList: true, subtree: true });
3212
3239
  let navigationAbortController = null;
3213
3240
  observeUrlChanges(false, async (newPageUrl, _oldPageUrl) => {
3241
+ var _a;
3214
3242
  await new Promise((resolve) => requestAnimationFrame(resolve));
3215
3243
  infiniteLoopProtection = 0;
3216
3244
  if (navigationAbortController)
@@ -3218,27 +3246,33 @@ function setupSPANavigation(Coframe, project, config, previewVariantId, isSessio
3218
3246
  navigationAbortController = new AbortController();
3219
3247
  const { signal } = navigationAbortController;
3220
3248
  let pageProject = project;
3249
+ let pagePersonalizationHeaders = Coframe.personalizationHeaders;
3221
3250
  const cached = getCachedFrames(newPageUrl);
3222
3251
  if (cached) {
3223
3252
  pageProject = cached.project;
3253
+ pagePersonalizationHeaders = {
3254
+ ...cached.personalizationHeaders,
3255
+ 'x-visit-url': newPageUrl,
3256
+ };
3224
3257
  }
3225
3258
  else {
3226
3259
  try {
3227
3260
  const preview = resolvePreview(newPageUrl, previewVariantId, isSessionVariant);
3228
- const result = await fetchProjectFromEdge(Coframe.projectId, newPageUrl, signal, config.userContext, preview.previewVariantId || undefined);
3261
+ const result = await fetchProjectFromEdge(Coframe.projectId, newPageUrl, signal, config.userContext, preview.previewVariantId || undefined, undefined, (_a = config.referrer) !== null && _a !== void 0 ? _a : getBrowserReferrer());
3229
3262
  if (signal.aborted)
3230
3263
  return;
3231
3264
  if (result) {
3232
3265
  pageProject = result.project;
3266
+ pagePersonalizationHeaders = result.personalizationHeaders;
3233
3267
  cacheFrames(newPageUrl, result);
3234
3268
  }
3235
3269
  }
3236
- catch (_a) {
3270
+ catch (_b) {
3237
3271
  }
3238
3272
  }
3239
3273
  if (signal.aborted)
3240
3274
  return;
3241
- await applyVariants(newPageUrl, pageProject);
3275
+ await applyVariants(newPageUrl, pageProject, pagePersonalizationHeaders);
3242
3276
  });
3243
3277
  }
3244
3278
  function readLaneClaims() {
@@ -3269,13 +3303,14 @@ function persistLaneClaims(claims, logger) {
3269
3303
  setCookie(LANE_COOKIE_KEY, encodeURIComponent(serialized), logger);
3270
3304
  }
3271
3305
  }
3272
- function createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics, personalizationHeaders, laneStore) {
3306
+ function createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics, laneStore) {
3273
3307
  let isFirstApply = true;
3274
- return async (pageUrl, pageProject) => {
3308
+ return async (pageUrl, pageProject, personalizationHeaders) => {
3275
3309
  const sessionId = isFirstApply ? Coframe.sessionId : generateUUID();
3276
3310
  const sessionContext = buildSessionContext(isFirstApply);
3277
3311
  isFirstApply = false;
3278
3312
  Coframe.sessionId = sessionId;
3313
+ Coframe.personalizationHeaders = personalizationHeaders;
3279
3314
  const preview = resolvePreview(pageUrl, previewVariantId, isSessionVariant);
3280
3315
  setIsPreviewVariant(!!preview.previewVariantId);
3281
3316
  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 +3347,8 @@ async function modifyPage(Coframe, configResult, projectResult, analytics) {
3312
3347
  if (!(await ensureBody(Coframe, cdnProject, timeoutMs, config.nonce)))
3313
3348
  return;
3314
3349
  const laneStore = { claims: readLaneClaims() };
3315
- const applyVariants = createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics, personalizationHeaders, laneStore);
3316
- await applyVariants(getCurrentPageUrl(), cdnProject);
3350
+ const applyVariants = createApplyVariants(Coframe, config, previewVariantId, isSessionVariant, executionStartTime, analytics, laneStore);
3351
+ await applyVariants(getCurrentPageUrl(), cdnProject, personalizationHeaders);
3317
3352
  if (!Coframe.variantsAndElements ||
3318
3353
  Coframe.variantsAndElements.length === 0) {
3319
3354
  revealPage();
@@ -3478,13 +3513,13 @@ async function resolveIdentity(config, Coframe, timeoutMs, gracefulExit) {
3478
3513
  }
3479
3514
 
3480
3515
  async function resolveProject(Coframe, previewVariantId, isSessionVariant, config) {
3481
- var _a;
3516
+ var _a, _b;
3482
3517
  const logger = Coframe.logger;
3483
3518
  const projectData = (_a = findLastCmd((c) => !!c.projectData)) === null || _a === void 0 ? void 0 : _a.projectData;
3484
3519
  let personalizationHeaders = (projectData === null || projectData === void 0 ? void 0 : projectData.personalizationHeaders) || null;
3485
3520
  let project = isSessionVariant ? undefined : projectData === null || projectData === void 0 ? void 0 : projectData.project;
3486
3521
  if (!project) {
3487
- const edgeResult = await fetchProjectFromEdge(Coframe.projectId, config.currentUrl || getCurrentPageUrl(), undefined, config.userContext, previewVariantId || undefined);
3522
+ const edgeResult = await fetchProjectFromEdge(Coframe.projectId, config.currentUrl || getCurrentPageUrl(), undefined, config.userContext, previewVariantId || undefined, undefined, (_b = config.referrer) !== null && _b !== void 0 ? _b : getBrowserReferrer());
3488
3523
  personalizationHeaders = (edgeResult === null || edgeResult === void 0 ? void 0 : edgeResult.personalizationHeaders) || null;
3489
3524
  project = (edgeResult === null || edgeResult === void 0 ? void 0 : edgeResult.project) || undefined;
3490
3525
  }
@@ -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
  })
@@ -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
  })
@@ -22,8 +22,11 @@ function sanitizeUserContext(userContext) {
22
22
  return userContext;
23
23
  }
24
24
 
25
- async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers) {
25
+ async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers, referrer) {
26
26
  const payload = { projectId, currentUrl };
27
+ if (referrer !== undefined) {
28
+ payload.referrer = referrer;
29
+ }
27
30
  const safe = sanitizeUserContext(userContext);
28
31
  if (safe) {
29
32
  payload.userContext = safe;
@@ -45,9 +48,25 @@ async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext,
45
48
  }
46
49
  }
47
50
 
48
- async function fetchAntiflickerFromEdge(projectId, currentUrl, userContext, antiflickerMode, headers) {
51
+ function getRequestReferrer(headers) {
52
+ const get = headers.get;
53
+ if (typeof get === 'function') {
54
+ const value = get.call(headers, 'referer');
55
+ return typeof value === 'string' ? value : undefined;
56
+ }
57
+ for (const [key, value] of Object.entries(headers)) {
58
+ if (key.toLowerCase() === 'referer') {
59
+ return typeof value === 'string' ? value : undefined;
60
+ }
61
+ }
62
+ return undefined;
63
+ }
64
+ async function fetchAntiflickerFromEdge(projectId, currentUrl, referrer, userContext, antiflickerMode, headers) {
49
65
  try {
50
66
  const payload = { projectId, currentUrl };
67
+ if (referrer !== undefined) {
68
+ payload.referrer = referrer;
69
+ }
51
70
  if (userContext) {
52
71
  payload.userContext = userContext;
53
72
  }
@@ -69,21 +88,23 @@ async function fetchAntiflickerFromEdge(projectId, currentUrl, userContext, anti
69
88
  }
70
89
  }
71
90
  async function getProjectData(options) {
91
+ var _a;
72
92
  try {
73
93
  if (/cf_disable/.test(new URL(options.currentUrl).search)) {
74
94
  return null;
75
95
  }
76
96
  }
77
- catch (_a) {
97
+ catch (_b) {
78
98
  }
79
99
  const includeProject = options.includeProject !== false;
80
100
  const includeCSS = options.includeCSS !== false;
101
+ const referrer = (_a = options.referrer) !== null && _a !== void 0 ? _a : getRequestReferrer(options.headers);
81
102
  const [projectResult, antiflickerCSS] = await Promise.all([
82
103
  includeProject
83
- ? fetchProjectFromEdge(options.projectId, options.currentUrl, undefined, options.userContext, undefined, options.headers)
104
+ ? fetchProjectFromEdge(options.projectId, options.currentUrl, undefined, options.userContext, undefined, options.headers, referrer)
84
105
  : Promise.resolve(null),
85
106
  includeCSS
86
- ? fetchAntiflickerFromEdge(options.projectId, options.currentUrl, options.userContext, options.antiflickerMode, options.headers)
107
+ ? fetchAntiflickerFromEdge(options.projectId, options.currentUrl, referrer, options.userContext, options.antiflickerMode, options.headers)
87
108
  : Promise.resolve(null),
88
109
  ]);
89
110
  const config = {};
@@ -20,8 +20,11 @@ function sanitizeUserContext(userContext) {
20
20
  return userContext;
21
21
  }
22
22
 
23
- async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers) {
23
+ async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext, previewVariantId, headers, referrer) {
24
24
  const payload = { projectId, currentUrl };
25
+ if (referrer !== undefined) {
26
+ payload.referrer = referrer;
27
+ }
25
28
  const safe = sanitizeUserContext(userContext);
26
29
  if (safe) {
27
30
  payload.userContext = safe;
@@ -43,9 +46,25 @@ async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext,
43
46
  }
44
47
  }
45
48
 
46
- async function fetchAntiflickerFromEdge(projectId, currentUrl, userContext, antiflickerMode, headers) {
49
+ function getRequestReferrer(headers) {
50
+ const get = headers.get;
51
+ if (typeof get === 'function') {
52
+ const value = get.call(headers, 'referer');
53
+ return typeof value === 'string' ? value : undefined;
54
+ }
55
+ for (const [key, value] of Object.entries(headers)) {
56
+ if (key.toLowerCase() === 'referer') {
57
+ return typeof value === 'string' ? value : undefined;
58
+ }
59
+ }
60
+ return undefined;
61
+ }
62
+ async function fetchAntiflickerFromEdge(projectId, currentUrl, referrer, userContext, antiflickerMode, headers) {
47
63
  try {
48
64
  const payload = { projectId, currentUrl };
65
+ if (referrer !== undefined) {
66
+ payload.referrer = referrer;
67
+ }
49
68
  if (userContext) {
50
69
  payload.userContext = userContext;
51
70
  }
@@ -67,21 +86,23 @@ async function fetchAntiflickerFromEdge(projectId, currentUrl, userContext, anti
67
86
  }
68
87
  }
69
88
  async function getProjectData(options) {
89
+ var _a;
70
90
  try {
71
91
  if (/cf_disable/.test(new URL(options.currentUrl).search)) {
72
92
  return null;
73
93
  }
74
94
  }
75
- catch (_a) {
95
+ catch (_b) {
76
96
  }
77
97
  const includeProject = options.includeProject !== false;
78
98
  const includeCSS = options.includeCSS !== false;
99
+ const referrer = (_a = options.referrer) !== null && _a !== void 0 ? _a : getRequestReferrer(options.headers);
79
100
  const [projectResult, antiflickerCSS] = await Promise.all([
80
101
  includeProject
81
- ? fetchProjectFromEdge(options.projectId, options.currentUrl, undefined, options.userContext, undefined, options.headers)
102
+ ? fetchProjectFromEdge(options.projectId, options.currentUrl, undefined, options.userContext, undefined, options.headers, referrer)
82
103
  : Promise.resolve(null),
83
104
  includeCSS
84
- ? fetchAntiflickerFromEdge(options.projectId, options.currentUrl, options.userContext, options.antiflickerMode, options.headers)
105
+ ? fetchAntiflickerFromEdge(options.projectId, options.currentUrl, referrer, options.userContext, options.antiflickerMode, options.headers)
85
106
  : Promise.resolve(null),
86
107
  ]);
87
108
  const config = {};
@@ -246,6 +246,7 @@ type CoframeConfig = {
246
246
  timeoutMs?: number;
247
247
  timeoutBehavior?: 'exclude';
248
248
  currentUrl?: string;
249
+ referrer?: string;
249
250
  userContext?: Record<string, unknown>;
250
251
  nonce?: string;
251
252
  enableDebug?: boolean;
@@ -258,6 +259,8 @@ type ConversionEventPayload = {
258
259
  };
259
260
  type BotReason = 'none' | 'cf_bot_score' | 'cf_verified_bot' | 'force_bot_param';
260
261
  type PersonalizationHeaders = {
262
+ 'x-visit-url'?: string;
263
+ 'x-visit-referrer'?: string;
261
264
  'x-device-type': string;
262
265
  'x-is-mobile-viewer': string;
263
266
  'x-viewer-city': string;
@@ -249,12 +249,15 @@ type CoframeConfig = {
249
249
  timeoutMs?: number;
250
250
  timeoutBehavior?: 'exclude';
251
251
  currentUrl?: string;
252
+ referrer?: string;
252
253
  userContext?: Record<string, unknown>;
253
254
  nonce?: string;
254
255
  enableDebug?: boolean;
255
256
  };
256
257
  type BotReason = 'none' | 'cf_bot_score' | 'cf_verified_bot' | 'force_bot_param';
257
258
  type PersonalizationHeaders = {
259
+ 'x-visit-url'?: string;
260
+ 'x-visit-referrer'?: string;
258
261
  'x-device-type': string;
259
262
  'x-is-mobile-viewer': string;
260
263
  'x-viewer-city': string;
@@ -199,6 +199,8 @@ type ActivationCondition = {
199
199
  type AntiflickerMode = 'body' | 'include' | 'exclude';
200
200
  type BotReason = 'none' | 'cf_bot_score' | 'cf_verified_bot' | 'force_bot_param';
201
201
  type PersonalizationHeaders = {
202
+ 'x-visit-url'?: string;
203
+ 'x-visit-referrer'?: string;
202
204
  'x-device-type': string;
203
205
  'x-is-mobile-viewer': string;
204
206
  'x-viewer-city': string;
@@ -214,6 +216,7 @@ type PersonalizationHeaders = {
214
216
  interface GetProjectDataOptions {
215
217
  projectId: string;
216
218
  currentUrl: string;
219
+ referrer?: string;
217
220
  userContext?: Record<string, unknown>;
218
221
  headers: Headers | Record<string, string>;
219
222
  antiflickerMode?: AntiflickerMode;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coframe/sdk",
3
- "version": "1.1.14",
3
+ "version": "1.1.16",
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",