@coframe/sdk 1.1.8 → 1.1.10

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 CHANGED
@@ -40,6 +40,21 @@ await init({
40
40
 
41
41
  `init()` accepts `config` and optional `projectData`, so npm consumers do not need to manually populate `window.CFQ` first.
42
42
 
43
+ ### URL controls
44
+
45
+ The npm entry uses the same browser URL controls as the script-tag and Edge
46
+ installations:
47
+
48
+ - `cf_disable` skips initialization and reveals any antiflicker state.
49
+ - `coframe_variant_id` previews one or more comma-separated variant IDs.
50
+ - `keep_preview_for_session=true` keeps that preview active for the tab.
51
+ - `coframe_should_send_events=true` allows events during preview for testing.
52
+
53
+ For SSR, pass the complete request URL, including its query string, as
54
+ `currentUrl`. This is required for query-sensitive targeting and allows
55
+ `getProjectData()` to short-circuit before any request when `cf_disable` is
56
+ present.
57
+
43
58
  ### React
44
59
 
45
60
  ```tsx
@@ -60,6 +75,8 @@ export default function App({ children }) {
60
75
  ```
61
76
 
62
77
  Mount the provider once at the root of your app. It initializes the SDK on mount and keeps treatment state available to child components.
78
+ Keep it mounted across client-side route changes; runtime commands and the SDK's
79
+ navigation observer handle subsequent page changes without remounting it.
63
80
 
64
81
  ### Server prefetch
65
82
 
@@ -148,6 +165,10 @@ import { CoframeProvider } from '@coframe/sdk/react'
148
165
  </CoframeProvider>
149
166
  ```
150
167
 
168
+ If your privacy policy permits treatment analytics before cookie consent, use
169
+ `onTreatmentAppliedBulkV2WithoutConsent` instead. It has the same callback
170
+ arguments and does not fire again when consent is later granted.
171
+
151
172
  Outside React, you can also register callbacks from the main entry:
152
173
 
153
174
  ```ts
@@ -159,6 +180,7 @@ import { onLog, onTreatmentApplied } from '@coframe/sdk'
159
180
  - `getProjectData()` is intended for SSR and edge runtimes that can provide a full request URL and request headers.
160
181
  - In Pages Router or Remix, per-request server loaders are the most straightforward place to call it.
161
182
  - In App Router, keep the provider mounted in a persistent shell, but be careful about request URL handling in `layout.tsx` if you need query-sensitive SSR targeting.
183
+ - The npm runtime reveals antiflicker styles but cannot insert them early enough to protect the initial paint. Render `antiflickerCSS` from `getProjectData()` in the server document head, or place equivalent static CSS and a timeout fallback there before application content.
162
184
 
163
185
  ## Package layout
164
186
 
@@ -181,6 +181,12 @@ function getBrowserPlatform() {
181
181
  function getBrowserReferrer() {
182
182
  return document.referrer;
183
183
  }
184
+ function getScreenSize() {
185
+ return {
186
+ width: window.innerWidth,
187
+ height: window.innerHeight,
188
+ };
189
+ }
184
190
  function getBrowserHostname() {
185
191
  return window.location.hostname;
186
192
  }
@@ -926,7 +932,7 @@ function warnEventsNotSent() {
926
932
  }
927
933
  }
928
934
 
929
- const SDK_VERSION = '2.5.0';
935
+ const SDK_VERSION = '2.6.0';
930
936
  const queuedEvents = [];
931
937
  const queuedMonitoringEvents = [];
932
938
  const queuedSessions = [];
@@ -942,7 +948,7 @@ function queueEventForBatchedSending(coframe, data, flushImmediately = false) {
942
948
  flushQueuedEvents(coframe.projectId);
943
949
  }
944
950
  }
945
- function queueCreateSession(coframe, orgId, projectId, sessionId, userToken, experimentsInfo, startTime, referrer, platform, languages, userAgent, url, storageInfo, gaSessionInfo, cfId, personalizationHeaders) {
951
+ function queueCreateSession(coframe, orgId, projectId, sessionId, userToken, experimentsInfo, startTime, referrer, platform, languages, userAgent, url, storageInfo, gaSessionInfo, cfId, personalizationHeaders, sessionContext) {
946
952
  queuedSessions.push({
947
953
  org_id: orgId,
948
954
  project_id: projectId,
@@ -960,6 +966,7 @@ function queueCreateSession(coframe, orgId, projectId, sessionId, userToken, exp
960
966
  session_metadata: JSON.stringify({
961
967
  url,
962
968
  storage_info: storageInfo,
969
+ ...sessionContext,
963
970
  }),
964
971
  ga_session_id: gaSessionInfo === null || gaSessionInfo === void 0 ? void 0 : gaSessionInfo.ga_session_id,
965
972
  ga_session_number: gaSessionInfo === null || gaSessionInfo === void 0 ? void 0 : gaSessionInfo.ga_session_number,
@@ -1816,6 +1823,7 @@ const waitForBody = (timeout = 10000) => {
1816
1823
  function revealPage() {
1817
1824
  document.dispatchEvent(new CustomEvent('coframe:show', {}));
1818
1825
  document.documentElement.style.setProperty('--cf-show', '1');
1826
+ document.documentElement.style.setProperty('--cf-visibility', 'visible');
1819
1827
  }
1820
1828
  async function replaceVariants(variants, orgId, logger, nonce) {
1821
1829
  const failedReplacements = [];
@@ -2480,6 +2488,59 @@ async function getVariantsAndElements(personalizationHeaders, project, previewVa
2480
2488
  });
2481
2489
  }
2482
2490
 
2491
+ function buildSessionContext(isInitialApply) {
2492
+ const context = {};
2493
+ const viewport = getScreenSize();
2494
+ if (isReportedSize(viewport.width) && isReportedSize(viewport.height)) {
2495
+ context.viewport_width = viewport.width;
2496
+ context.viewport_height = viewport.height;
2497
+ }
2498
+ const visitCount = getCookie(VISIT_COUNT_COOKIE_KEY);
2499
+ if (/^[1-9]\d{0,14}$/.test(visitCount)) {
2500
+ context.visit_count = Number(visitCount);
2501
+ }
2502
+ try {
2503
+ context.navigation_type = getNavigationType(isInitialApply);
2504
+ }
2505
+ catch (_a) {
2506
+ }
2507
+ try {
2508
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
2509
+ if (timezone) {
2510
+ context.timezone = timezone;
2511
+ }
2512
+ }
2513
+ catch (_b) {
2514
+ }
2515
+ return context;
2516
+ }
2517
+ function isReportedSize(size) {
2518
+ return (typeof size === 'number' && size > 0 && size !== Number.POSITIVE_INFINITY);
2519
+ }
2520
+ function getNavigationType(isInitialApply) {
2521
+ var _a, _b;
2522
+ if (!isInitialApply) {
2523
+ return 'spa_navigation';
2524
+ }
2525
+ const nav = (_b = (_a = performance.getEntriesByType) === null || _a === void 0 ? void 0 : _a.call(performance, 'navigation')) === null || _b === void 0 ? void 0 : _b[0];
2526
+ if (nav) {
2527
+ if (nav.type === 'reload')
2528
+ return 'reload';
2529
+ if (nav.type === 'back_forward')
2530
+ return 'back_forward';
2531
+ return nav.type === 'navigate' ? 'initial_load' : undefined;
2532
+ }
2533
+ const legacy = performance.navigation;
2534
+ if (legacy) {
2535
+ if (legacy.type === 1)
2536
+ return 'reload';
2537
+ if (legacy.type === 2)
2538
+ return 'back_forward';
2539
+ return legacy.type === 0 ? 'initial_load' : undefined;
2540
+ }
2541
+ return undefined;
2542
+ }
2543
+
2483
2544
  const CACHE_TTL_MS = 60 * 1000;
2484
2545
  const cache = new Map();
2485
2546
  function getCachedFrames(url) {
@@ -2820,7 +2881,7 @@ function observeUrlChanges(baseUrlMatch, onUrlChange) {
2820
2881
  patchHistoryMethod('replaceState');
2821
2882
  }
2822
2883
 
2823
- function startSession(Coframe, cookiesEnabled, executionStartTime, personalizationHeaders) {
2884
+ function startSession(Coframe, cookiesEnabled, executionStartTime, personalizationHeaders, sessionContext) {
2824
2885
  const sessionPayload = [
2825
2886
  Coframe,
2826
2887
  Coframe.orgId,
@@ -2837,7 +2898,7 @@ function startSession(Coframe, cookiesEnabled, executionStartTime, personalizati
2837
2898
  getBrowserFignerprintInfo(),
2838
2899
  ];
2839
2900
  {
2840
- queueCreateSession(...sessionPayload, undefined, undefined, personalizationHeaders);
2901
+ queueCreateSession(...sessionPayload, undefined, undefined, personalizationHeaders, sessionContext);
2841
2902
  }
2842
2903
  queueEvent(Coframe, {
2843
2904
  projectId: Coframe.projectId,
@@ -3284,6 +3345,7 @@ function createApplyVariants(Coframe, config, previewVariantId, isSessionVariant
3284
3345
  let isFirstApply = true;
3285
3346
  return async (pageUrl, pageProject) => {
3286
3347
  const sessionId = isFirstApply ? Coframe.sessionId : generateUUID();
3348
+ const sessionContext = buildSessionContext(isFirstApply);
3287
3349
  isFirstApply = false;
3288
3350
  Coframe.sessionId = sessionId;
3289
3351
  const preview = resolvePreview(pageUrl, previewVariantId, isSessionVariant);
@@ -3307,7 +3369,7 @@ function createApplyVariants(Coframe, config, previewVariantId, isSessionVariant
3307
3369
  else {
3308
3370
  replaceVariants(variantsAndElements, Coframe.orgId, Coframe.logger, config.nonce);
3309
3371
  }
3310
- startSession(Coframe, isCookiesEnabled, executionStartTime, personalizationHeaders);
3372
+ startSession(Coframe, isCookiesEnabled, executionStartTime, personalizationHeaders, sessionContext);
3311
3373
  analytics.resetBroadcasted();
3312
3374
  analytics.sendAnalytics();
3313
3375
  };
@@ -3585,6 +3647,12 @@ const Coframe = {
3585
3647
  };
3586
3648
  Coframe.logger = createLogger(() => Coframe);
3587
3649
  async function init(options) {
3650
+ if (typeof window !== 'undefined' &&
3651
+ /cf_disable/.test(window.location.search)) {
3652
+ console.warn('[Coframe] Disabled via URL parameter');
3653
+ revealPage();
3654
+ return;
3655
+ }
3588
3656
  if (options)
3589
3657
  injectOptions(options);
3590
3658
  const gracefulExit = (msg) => {
@@ -179,6 +179,12 @@ function getBrowserPlatform() {
179
179
  function getBrowserReferrer() {
180
180
  return document.referrer;
181
181
  }
182
+ function getScreenSize() {
183
+ return {
184
+ width: window.innerWidth,
185
+ height: window.innerHeight,
186
+ };
187
+ }
182
188
  function getBrowserHostname() {
183
189
  return window.location.hostname;
184
190
  }
@@ -924,7 +930,7 @@ function warnEventsNotSent() {
924
930
  }
925
931
  }
926
932
 
927
- const SDK_VERSION = '2.5.0';
933
+ const SDK_VERSION = '2.6.0';
928
934
  const queuedEvents = [];
929
935
  const queuedMonitoringEvents = [];
930
936
  const queuedSessions = [];
@@ -940,7 +946,7 @@ function queueEventForBatchedSending(coframe, data, flushImmediately = false) {
940
946
  flushQueuedEvents(coframe.projectId);
941
947
  }
942
948
  }
943
- function queueCreateSession(coframe, orgId, projectId, sessionId, userToken, experimentsInfo, startTime, referrer, platform, languages, userAgent, url, storageInfo, gaSessionInfo, cfId, personalizationHeaders) {
949
+ function queueCreateSession(coframe, orgId, projectId, sessionId, userToken, experimentsInfo, startTime, referrer, platform, languages, userAgent, url, storageInfo, gaSessionInfo, cfId, personalizationHeaders, sessionContext) {
944
950
  queuedSessions.push({
945
951
  org_id: orgId,
946
952
  project_id: projectId,
@@ -958,6 +964,7 @@ function queueCreateSession(coframe, orgId, projectId, sessionId, userToken, exp
958
964
  session_metadata: JSON.stringify({
959
965
  url,
960
966
  storage_info: storageInfo,
967
+ ...sessionContext,
961
968
  }),
962
969
  ga_session_id: gaSessionInfo === null || gaSessionInfo === void 0 ? void 0 : gaSessionInfo.ga_session_id,
963
970
  ga_session_number: gaSessionInfo === null || gaSessionInfo === void 0 ? void 0 : gaSessionInfo.ga_session_number,
@@ -1814,6 +1821,7 @@ const waitForBody = (timeout = 10000) => {
1814
1821
  function revealPage() {
1815
1822
  document.dispatchEvent(new CustomEvent('coframe:show', {}));
1816
1823
  document.documentElement.style.setProperty('--cf-show', '1');
1824
+ document.documentElement.style.setProperty('--cf-visibility', 'visible');
1817
1825
  }
1818
1826
  async function replaceVariants(variants, orgId, logger, nonce) {
1819
1827
  const failedReplacements = [];
@@ -2478,6 +2486,59 @@ async function getVariantsAndElements(personalizationHeaders, project, previewVa
2478
2486
  });
2479
2487
  }
2480
2488
 
2489
+ function buildSessionContext(isInitialApply) {
2490
+ const context = {};
2491
+ const viewport = getScreenSize();
2492
+ if (isReportedSize(viewport.width) && isReportedSize(viewport.height)) {
2493
+ context.viewport_width = viewport.width;
2494
+ context.viewport_height = viewport.height;
2495
+ }
2496
+ const visitCount = getCookie(VISIT_COUNT_COOKIE_KEY);
2497
+ if (/^[1-9]\d{0,14}$/.test(visitCount)) {
2498
+ context.visit_count = Number(visitCount);
2499
+ }
2500
+ try {
2501
+ context.navigation_type = getNavigationType(isInitialApply);
2502
+ }
2503
+ catch (_a) {
2504
+ }
2505
+ try {
2506
+ const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
2507
+ if (timezone) {
2508
+ context.timezone = timezone;
2509
+ }
2510
+ }
2511
+ catch (_b) {
2512
+ }
2513
+ return context;
2514
+ }
2515
+ function isReportedSize(size) {
2516
+ return (typeof size === 'number' && size > 0 && size !== Number.POSITIVE_INFINITY);
2517
+ }
2518
+ function getNavigationType(isInitialApply) {
2519
+ var _a, _b;
2520
+ if (!isInitialApply) {
2521
+ return 'spa_navigation';
2522
+ }
2523
+ const nav = (_b = (_a = performance.getEntriesByType) === null || _a === void 0 ? void 0 : _a.call(performance, 'navigation')) === null || _b === void 0 ? void 0 : _b[0];
2524
+ if (nav) {
2525
+ if (nav.type === 'reload')
2526
+ return 'reload';
2527
+ if (nav.type === 'back_forward')
2528
+ return 'back_forward';
2529
+ return nav.type === 'navigate' ? 'initial_load' : undefined;
2530
+ }
2531
+ const legacy = performance.navigation;
2532
+ if (legacy) {
2533
+ if (legacy.type === 1)
2534
+ return 'reload';
2535
+ if (legacy.type === 2)
2536
+ return 'back_forward';
2537
+ return legacy.type === 0 ? 'initial_load' : undefined;
2538
+ }
2539
+ return undefined;
2540
+ }
2541
+
2481
2542
  const CACHE_TTL_MS = 60 * 1000;
2482
2543
  const cache = new Map();
2483
2544
  function getCachedFrames(url) {
@@ -2818,7 +2879,7 @@ function observeUrlChanges(baseUrlMatch, onUrlChange) {
2818
2879
  patchHistoryMethod('replaceState');
2819
2880
  }
2820
2881
 
2821
- function startSession(Coframe, cookiesEnabled, executionStartTime, personalizationHeaders) {
2882
+ function startSession(Coframe, cookiesEnabled, executionStartTime, personalizationHeaders, sessionContext) {
2822
2883
  const sessionPayload = [
2823
2884
  Coframe,
2824
2885
  Coframe.orgId,
@@ -2835,7 +2896,7 @@ function startSession(Coframe, cookiesEnabled, executionStartTime, personalizati
2835
2896
  getBrowserFignerprintInfo(),
2836
2897
  ];
2837
2898
  {
2838
- queueCreateSession(...sessionPayload, undefined, undefined, personalizationHeaders);
2899
+ queueCreateSession(...sessionPayload, undefined, undefined, personalizationHeaders, sessionContext);
2839
2900
  }
2840
2901
  queueEvent(Coframe, {
2841
2902
  projectId: Coframe.projectId,
@@ -3282,6 +3343,7 @@ function createApplyVariants(Coframe, config, previewVariantId, isSessionVariant
3282
3343
  let isFirstApply = true;
3283
3344
  return async (pageUrl, pageProject) => {
3284
3345
  const sessionId = isFirstApply ? Coframe.sessionId : generateUUID();
3346
+ const sessionContext = buildSessionContext(isFirstApply);
3285
3347
  isFirstApply = false;
3286
3348
  Coframe.sessionId = sessionId;
3287
3349
  const preview = resolvePreview(pageUrl, previewVariantId, isSessionVariant);
@@ -3305,7 +3367,7 @@ function createApplyVariants(Coframe, config, previewVariantId, isSessionVariant
3305
3367
  else {
3306
3368
  replaceVariants(variantsAndElements, Coframe.orgId, Coframe.logger, config.nonce);
3307
3369
  }
3308
- startSession(Coframe, isCookiesEnabled, executionStartTime, personalizationHeaders);
3370
+ startSession(Coframe, isCookiesEnabled, executionStartTime, personalizationHeaders, sessionContext);
3309
3371
  analytics.resetBroadcasted();
3310
3372
  analytics.sendAnalytics();
3311
3373
  };
@@ -3583,6 +3645,12 @@ const Coframe = {
3583
3645
  };
3584
3646
  Coframe.logger = createLogger(() => Coframe);
3585
3647
  async function init(options) {
3648
+ if (typeof window !== 'undefined' &&
3649
+ /cf_disable/.test(window.location.search)) {
3650
+ console.warn('[Coframe] Disabled via URL parameter');
3651
+ revealPage();
3652
+ return;
3653
+ }
3586
3654
  if (options)
3587
3655
  injectOptions(options);
3588
3656
  const gracefulExit = (msg) => {
@@ -5,10 +5,17 @@ var sdk = require('@coframe/sdk');
5
5
  var React = require('react');
6
6
 
7
7
  const CoframeContext = React.createContext({ treatments: null });
8
- function CoframeProvider({ projectConfig, projectData, onTreatmentApplied: onTreatmentAppliedProp, onTreatmentAppliedBulk: onTreatmentAppliedBulkProp, onTreatmentAppliedBulkV2, onLog: onLogProp, children, }) {
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
11
  var _a, _b;
12
+ if (/cf_disable/.test(window.location.search)) {
13
+ sdk.init().catch((e) => {
14
+ console.error('[Coframe] Error disabling SDK', e);
15
+ });
16
+ setTreatments([]);
17
+ return;
18
+ }
12
19
  sdk.onTreatmentApplied({
13
20
  callback: onTreatmentAppliedProp,
14
21
  bulkCallback: (data) => {
@@ -16,6 +23,7 @@ function CoframeProvider({ projectConfig, projectData, onTreatmentApplied: onTre
16
23
  onTreatmentAppliedBulkProp === null || onTreatmentAppliedBulkProp === void 0 ? void 0 : onTreatmentAppliedBulkProp(data);
17
24
  },
18
25
  bulkCallbackV2: onTreatmentAppliedBulkV2,
26
+ bulkCallbackV2WithoutConsent: onTreatmentAppliedBulkV2WithoutConsent,
19
27
  });
20
28
  if (onLogProp) {
21
29
  sdk.onLog(onLogProp);
@@ -1,13 +1,20 @@
1
1
  'use client';
2
- import { onTreatmentApplied, onLog, init } from '@coframe/sdk';
2
+ import { init, onTreatmentApplied, onLog } from '@coframe/sdk';
3
3
  export { init, onLog, onTreatmentApplied, setConsent, setFeatureFlag, setPageHydrated, setUserToken, trackConversion } from '@coframe/sdk';
4
4
  import React, { createContext, useState, useEffect, useContext } from 'react';
5
5
 
6
6
  const CoframeContext = createContext({ treatments: null });
7
- function CoframeProvider({ projectConfig, projectData, onTreatmentApplied: onTreatmentAppliedProp, onTreatmentAppliedBulk: onTreatmentAppliedBulkProp, onTreatmentAppliedBulkV2, onLog: onLogProp, children, }) {
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
10
  var _a, _b;
11
+ if (/cf_disable/.test(window.location.search)) {
12
+ init().catch((e) => {
13
+ console.error('[Coframe] Error disabling SDK', e);
14
+ });
15
+ setTreatments([]);
16
+ return;
17
+ }
11
18
  onTreatmentApplied({
12
19
  callback: onTreatmentAppliedProp,
13
20
  bulkCallback: (data) => {
@@ -15,6 +22,7 @@ function CoframeProvider({ projectConfig, projectData, onTreatmentApplied: onTre
15
22
  onTreatmentAppliedBulkProp === null || onTreatmentAppliedBulkProp === void 0 ? void 0 : onTreatmentAppliedBulkProp(data);
16
23
  },
17
24
  bulkCallbackV2: onTreatmentAppliedBulkV2,
25
+ bulkCallbackV2WithoutConsent: onTreatmentAppliedBulkV2WithoutConsent,
18
26
  });
19
27
  if (onLogProp) {
20
28
  onLog(onLogProp);
@@ -45,14 +45,14 @@ async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext,
45
45
  }
46
46
  }
47
47
 
48
- async function fetchAntiflickerFromEdge(projectId, currentUrl, userContext, enableElementAntiFlicker, headers) {
48
+ async function fetchAntiflickerFromEdge(projectId, currentUrl, userContext, antiflickerMode, headers) {
49
49
  try {
50
50
  const payload = { projectId, currentUrl };
51
51
  if (userContext) {
52
52
  payload.userContext = userContext;
53
53
  }
54
- if (enableElementAntiFlicker) {
55
- payload.enableElementAntiFlicker = enableElementAntiFlicker;
54
+ if (antiflickerMode) {
55
+ payload.antiflickerMode = antiflickerMode;
56
56
  }
57
57
  const config = encodeURIComponent(JSON.stringify(payload));
58
58
  const edgeUrl = new URL(`${"https://edge.cofra.me"}/cf.css`);
@@ -69,6 +69,13 @@ async function fetchAntiflickerFromEdge(projectId, currentUrl, userContext, enab
69
69
  }
70
70
  }
71
71
  async function getProjectData(options) {
72
+ try {
73
+ if (/cf_disable/.test(new URL(options.currentUrl).search)) {
74
+ return null;
75
+ }
76
+ }
77
+ catch (_a) {
78
+ }
72
79
  const includeProject = options.includeProject !== false;
73
80
  const includeCSS = options.includeCSS !== false;
74
81
  const [projectResult, antiflickerCSS] = await Promise.all([
@@ -76,7 +83,7 @@ async function getProjectData(options) {
76
83
  ? fetchProjectFromEdge(options.projectId, options.currentUrl, undefined, options.userContext, undefined, options.headers)
77
84
  : Promise.resolve(null),
78
85
  includeCSS
79
- ? fetchAntiflickerFromEdge(options.projectId, options.currentUrl, options.userContext, options.enableElementAntiFlicker, options.headers)
86
+ ? fetchAntiflickerFromEdge(options.projectId, options.currentUrl, options.userContext, options.antiflickerMode, options.headers)
80
87
  : Promise.resolve(null),
81
88
  ]);
82
89
  const config = {};
@@ -43,14 +43,14 @@ async function fetchProjectFromEdge(projectId, currentUrl, signal, userContext,
43
43
  }
44
44
  }
45
45
 
46
- async function fetchAntiflickerFromEdge(projectId, currentUrl, userContext, enableElementAntiFlicker, headers) {
46
+ async function fetchAntiflickerFromEdge(projectId, currentUrl, userContext, antiflickerMode, headers) {
47
47
  try {
48
48
  const payload = { projectId, currentUrl };
49
49
  if (userContext) {
50
50
  payload.userContext = userContext;
51
51
  }
52
- if (enableElementAntiFlicker) {
53
- payload.enableElementAntiFlicker = enableElementAntiFlicker;
52
+ if (antiflickerMode) {
53
+ payload.antiflickerMode = antiflickerMode;
54
54
  }
55
55
  const config = encodeURIComponent(JSON.stringify(payload));
56
56
  const edgeUrl = new URL(`${"https://edge.cofra.me"}/cf.css`);
@@ -67,6 +67,13 @@ async function fetchAntiflickerFromEdge(projectId, currentUrl, userContext, enab
67
67
  }
68
68
  }
69
69
  async function getProjectData(options) {
70
+ try {
71
+ if (/cf_disable/.test(new URL(options.currentUrl).search)) {
72
+ return null;
73
+ }
74
+ }
75
+ catch (_a) {
76
+ }
70
77
  const includeProject = options.includeProject !== false;
71
78
  const includeCSS = options.includeCSS !== false;
72
79
  const [projectResult, antiflickerCSS] = await Promise.all([
@@ -74,7 +81,7 @@ async function getProjectData(options) {
74
81
  ? fetchProjectFromEdge(options.projectId, options.currentUrl, undefined, options.userContext, undefined, options.headers)
75
82
  : Promise.resolve(null),
76
83
  includeCSS
77
- ? fetchAntiflickerFromEdge(options.projectId, options.currentUrl, options.userContext, options.enableElementAntiFlicker, options.headers)
84
+ ? fetchAntiflickerFromEdge(options.projectId, options.currentUrl, options.userContext, options.antiflickerMode, options.headers)
78
85
  : Promise.resolve(null),
79
86
  ]);
80
87
  const config = {};
@@ -230,12 +230,13 @@ type ActivationCondition = {
230
230
  allocation?: ActivationConditionAllocation;
231
231
  js_function?: string;
232
232
  };
233
+ type AntiflickerMode = 'body' | 'include' | 'exclude';
233
234
  type CoframeConfig = {
234
235
  projectId: string;
235
236
  previewVariantId?: string;
236
237
  trackingOnly?: boolean;
237
238
  enableAntiFlickering?: boolean;
238
- enableElementAntiFlicker?: boolean;
239
+ antiflickerMode?: AntiflickerMode;
239
240
  waitForHydration?: boolean;
240
241
  waitForCookiesEnabled?: boolean;
241
242
  waitForFeatureFlag?: boolean;
@@ -295,6 +296,7 @@ interface TreatmentAppliedHandlers {
295
296
  callback?: (data: TreatmentData) => void;
296
297
  bulkCallback?: (data: TreatmentData[]) => void;
297
298
  bulkCallbackV2?: (data: TreatmentDataV2[], rawIds: ExperimentInfo[]) => void;
299
+ bulkCallbackV2WithoutConsent?: (data: TreatmentDataV2[], rawIds: ExperimentInfo[]) => void;
298
300
  }
299
301
  declare function setConsent(enabled: boolean): void;
300
302
  declare function setUserToken(token: string): void;
@@ -233,12 +233,13 @@ type ActivationCondition = {
233
233
  allocation?: ActivationConditionAllocation;
234
234
  js_function?: string;
235
235
  };
236
+ type AntiflickerMode = 'body' | 'include' | 'exclude';
236
237
  type CoframeConfig = {
237
238
  projectId: string;
238
239
  previewVariantId?: string;
239
240
  trackingOnly?: boolean;
240
241
  enableAntiFlickering?: boolean;
241
- enableElementAntiFlicker?: boolean;
242
+ antiflickerMode?: AntiflickerMode;
242
243
  waitForHydration?: boolean;
243
244
  waitForCookiesEnabled?: boolean;
244
245
  waitForFeatureFlag?: boolean;
@@ -290,13 +291,14 @@ interface CoframeProviderProps {
290
291
  onTreatmentApplied?: (data: TreatmentData) => void;
291
292
  onTreatmentAppliedBulk?: (data: TreatmentData[]) => void;
292
293
  onTreatmentAppliedBulkV2?: (data: TreatmentDataV2[], rawIds: ExperimentInfo[]) => void;
294
+ onTreatmentAppliedBulkV2WithoutConsent?: (data: TreatmentDataV2[], rawIds: ExperimentInfo[]) => void;
293
295
  onLog?: (payload: LogPayload) => void;
294
296
  children: ReactNode;
295
297
  }
296
298
  interface CoframeContextValue {
297
299
  treatments: TreatmentData[] | null;
298
300
  }
299
- declare function CoframeProvider({ projectConfig, projectData, onTreatmentApplied: onTreatmentAppliedProp, onTreatmentAppliedBulk: onTreatmentAppliedBulkProp, onTreatmentAppliedBulkV2, onLog: onLogProp, children, }: CoframeProviderProps): React.FunctionComponentElement<React.ProviderProps<CoframeContextValue>>;
301
+ declare function CoframeProvider({ projectConfig, projectData, onTreatmentApplied: onTreatmentAppliedProp, onTreatmentAppliedBulk: onTreatmentAppliedBulkProp, onTreatmentAppliedBulkV2, onTreatmentAppliedBulkV2WithoutConsent, onLog: onLogProp, children, }: CoframeProviderProps): React.FunctionComponentElement<React.ProviderProps<CoframeContextValue>>;
300
302
  declare function useCoframeTreatments(): TreatmentData[] | null;
301
303
  declare function useCoframeTreatment(experimentId: string): TreatmentData | undefined;
302
304
  declare function useCoframeVariant(experimentId: string): string | undefined;
@@ -196,6 +196,7 @@ type ActivationCondition = {
196
196
  allocation?: ActivationConditionAllocation;
197
197
  js_function?: string;
198
198
  };
199
+ type AntiflickerMode = 'body' | 'include' | 'exclude';
199
200
  type BotReason = 'none' | 'cf_bot_score' | 'cf_verified_bot' | 'force_bot_param';
200
201
  type PersonalizationHeaders = {
201
202
  'x-device-type': string;
@@ -215,7 +216,7 @@ interface GetProjectDataOptions {
215
216
  currentUrl: string;
216
217
  userContext?: Record<string, unknown>;
217
218
  headers: Headers | Record<string, string>;
218
- enableElementAntiFlicker?: boolean;
219
+ antiflickerMode?: AntiflickerMode;
219
220
  includeProject?: boolean;
220
221
  includeCSS?: boolean;
221
222
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coframe/sdk",
3
- "version": "1.1.8",
3
+ "version": "1.1.10",
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",
@@ -28,6 +28,7 @@
28
28
  "scripts": {
29
29
  "test:jest": "jest --maxWorkers=2",
30
30
  "test:playwright": "npx playwright test --retries=5 --reporter=list",
31
+ "test:package": "node ./tests/package/scripts/test-package.mjs",
31
32
  "test:browserstack:full": "jest --config jest.browserstack.config.js --suite=full",
32
33
  "test:browserstack:small": "jest --config jest.browserstack.config.js --suite=small",
33
34
  "test": "npm run test:jest && npm run test:playwright",