@coframe/sdk 1.1.38 → 1.1.40

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.
@@ -3937,21 +3937,31 @@ async function modifyPage(Coframe, configResult, projectResult, analytics) {
3937
3937
  let startRequested = false;
3938
3938
  let replayScriptUrl;
3939
3939
  const COMPILED_REPLAY_SCRIPT_URL = `${"https://edge.cofra.me"}/replay/latest.js`;
3940
+ const CONSENT_POLL_MS = 100;
3941
+ const CONSENT_WAIT_MS = 5000;
3940
3942
  function configureReplayScriptUrl(url) {
3941
3943
  replayScriptUrl = (url === null || url === void 0 ? void 0 : url.trim()) || undefined;
3942
3944
  }
3943
- function replayConsentAllowed() {
3944
- var _a;
3945
+ function readReplayConsent() {
3945
3946
  try {
3946
- const privacy = (_a = window.Shopify) === null || _a === void 0 ? void 0 : _a.customerPrivacy;
3947
- const analyticsAllowed = !privacy ||
3948
- typeof privacy.analyticsProcessingAllowed !== 'function' ||
3949
- privacy.analyticsProcessingAllowed() === true;
3950
- return (navigator
3951
- .globalPrivacyControl !== true && analyticsAllowed);
3947
+ if (navigator
3948
+ .globalPrivacyControl === true) {
3949
+ return { state: 'denied', reason: 'gpc' };
3950
+ }
3951
+ const shopify = window.Shopify;
3952
+ if (shopify === undefined)
3953
+ return { state: 'allowed', source: 'none' };
3954
+ const customerPrivacy = shopify.customerPrivacy;
3955
+ const analyticsProcessingAllowed = customerPrivacy === null || customerPrivacy === void 0 ? void 0 : customerPrivacy.analyticsProcessingAllowed;
3956
+ if (typeof analyticsProcessingAllowed === 'function') {
3957
+ return analyticsProcessingAllowed.call(customerPrivacy) === true
3958
+ ? { state: 'allowed', source: 'shopify' }
3959
+ : { state: 'denied', reason: 'consent_denied' };
3960
+ }
3961
+ return { state: 'pending' };
3952
3962
  }
3953
- catch (_b) {
3954
- return false;
3963
+ catch (_a) {
3964
+ return { state: 'denied', reason: 'consent_unavailable' };
3955
3965
  }
3956
3966
  }
3957
3967
  function createMonitoringPayload(coframe, monitoringType, metadata) {
@@ -3972,16 +3982,23 @@ function reportStartFailure(coframe, reason) {
3972
3982
  }
3973
3983
  catch (_a) { }
3974
3984
  }
3975
- function createStartContext(coframe, settings, forceSample) {
3985
+ function reportReplaySkipped(coframe, reason) {
3986
+ try {
3987
+ queueMonitoringEvent(coframe, createMonitoringPayload(coframe, 'replay_skipped', { reason }));
3988
+ }
3989
+ catch (_a) { }
3990
+ }
3991
+ function createStartContext(coframe, settings, forceSample, consentSource) {
3976
3992
  return {
3977
3993
  projectId: coframe.projectId,
3978
3994
  ingestUrl: resolveIngestUrl("https://ingest.app.coframe.com/ingest/v2"),
3979
3995
  settings,
3980
3996
  forceSample,
3997
+ consentSource,
3981
3998
  getPageViewId: () => coframe.sessionId,
3982
3999
  getUserToken: () => coframe.userToken,
3983
4000
  getVariantIds: () => { var _a; return ((_a = coframe.experimentInfo) !== null && _a !== void 0 ? _a : []).map((experiment) => experiment.variant_id); },
3984
- canSend: () => shouldSendEvents() && replayConsentAllowed(),
4001
+ canSend: () => shouldSendEvents() && readReplayConsent().state === 'allowed',
3985
4002
  onEventsFlushed: (callback) => {
3986
4003
  if (queuedEvents.length === 0 && queuedSessions.length === 0) {
3987
4004
  callback();
@@ -3993,22 +4010,13 @@ function createStartContext(coframe, settings, forceSample) {
3993
4010
  report: (type, metadata) => queueMonitoringEvent(coframe, createMonitoringPayload(coframe, type, metadata)),
3994
4011
  };
3995
4012
  }
3996
- function startReplayIfEnabled(coframe, project, nonce) {
3997
- var _a;
4013
+ function insertReplayScript(coframe, settings, consentSource, nonce) {
3998
4014
  try {
3999
- const settings = (_a = project.settings) === null || _a === void 0 ? void 0 : _a.session_replay;
4000
- if ((settings === null || settings === void 0 ? void 0 : settings.enabled) !== true ||
4001
- typeof CompressionStream !== 'function' ||
4002
- !shouldSendEvents() ||
4003
- !replayConsentAllowed() ||
4004
- startRequested) {
4005
- return;
4006
- }
4007
4015
  let forceSample = false;
4008
4016
  try {
4009
4017
  forceSample = localStorage.getItem('coframe.enableRecording') === 'true';
4010
4018
  }
4011
- catch (_b) { }
4019
+ catch (_a) { }
4012
4020
  const script = document.createElement('script');
4013
4021
  script.id = 'coframe-replay-script';
4014
4022
  script.async = true;
@@ -4019,7 +4027,7 @@ function startReplayIfEnabled(coframe, project, nonce) {
4019
4027
  try {
4020
4028
  const replay = window.CoframeReplay;
4021
4029
  if ((replay === null || replay === void 0 ? void 0 : replay.protocolVersion) === 1) {
4022
- replay.start(createStartContext(coframe, settings, forceSample));
4030
+ replay.start(createStartContext(coframe, settings, forceSample, consentSource));
4023
4031
  }
4024
4032
  else {
4025
4033
  reportStartFailure(coframe, 'incompatible_protocol');
@@ -4032,13 +4040,56 @@ function startReplayIfEnabled(coframe, project, nonce) {
4032
4040
  script.onerror = () => {
4033
4041
  reportStartFailure(coframe, 'script_load_failed');
4034
4042
  };
4035
- startRequested = true;
4036
4043
  document.head.appendChild(script);
4037
4044
  }
4038
4045
  catch (error) {
4039
4046
  reportStartFailure(coframe, error instanceof Error ? error.message : String(error));
4040
4047
  }
4041
4048
  }
4049
+ function startReplayIfEnabled(coframe, project, nonce) {
4050
+ var _a;
4051
+ try {
4052
+ const settings = (_a = project.settings) === null || _a === void 0 ? void 0 : _a.session_replay;
4053
+ if ((settings === null || settings === void 0 ? void 0 : settings.enabled) !== true ||
4054
+ typeof CompressionStream !== 'function' ||
4055
+ !shouldSendEvents() ||
4056
+ startRequested) {
4057
+ return;
4058
+ }
4059
+ startRequested = true;
4060
+ let waited = 0;
4061
+ const decide = () => {
4062
+ var _a;
4063
+ const consent = readReplayConsent();
4064
+ if (consent.state === 'allowed') {
4065
+ insertReplayScript(coframe, settings, consent.source, nonce);
4066
+ }
4067
+ else if (consent.state === 'denied') {
4068
+ reportReplaySkipped(coframe, consent.reason);
4069
+ }
4070
+ else if (waited >= CONSENT_WAIT_MS) {
4071
+ reportReplaySkipped(coframe, 'consent_unavailable');
4072
+ }
4073
+ else {
4074
+ if (waited === 0) {
4075
+ try {
4076
+ const loadFeatures = (_a = window.Shopify) === null || _a === void 0 ? void 0 : _a.loadFeatures;
4077
+ if (typeof loadFeatures === 'function') {
4078
+ loadFeatures.call(window.Shopify, [{ name: 'consent-tracking-api', version: '0.1' }], () => { });
4079
+ }
4080
+ }
4081
+ catch (_b) { }
4082
+ }
4083
+ waited += CONSENT_POLL_MS;
4084
+ window.setTimeout(decide, CONSENT_POLL_MS);
4085
+ }
4086
+ };
4087
+ decide();
4088
+ }
4089
+ catch (error) {
4090
+ reportStartFailure(coframe, error instanceof Error ? error.message : String(error));
4091
+ }
4092
+ }
4042
4093
 
4043
4094
  const TIMEOUT_MAX_MS = 5000;
4044
4095
  const MAX_NOT_RENDERED_REASON_CHARS = 200;
@@ -3935,21 +3935,31 @@ async function modifyPage(Coframe, configResult, projectResult, analytics) {
3935
3935
  let startRequested = false;
3936
3936
  let replayScriptUrl;
3937
3937
  const COMPILED_REPLAY_SCRIPT_URL = `${"https://edge.cofra.me"}/replay/latest.js`;
3938
+ const CONSENT_POLL_MS = 100;
3939
+ const CONSENT_WAIT_MS = 5000;
3938
3940
  function configureReplayScriptUrl(url) {
3939
3941
  replayScriptUrl = (url === null || url === void 0 ? void 0 : url.trim()) || undefined;
3940
3942
  }
3941
- function replayConsentAllowed() {
3942
- var _a;
3943
+ function readReplayConsent() {
3943
3944
  try {
3944
- const privacy = (_a = window.Shopify) === null || _a === void 0 ? void 0 : _a.customerPrivacy;
3945
- const analyticsAllowed = !privacy ||
3946
- typeof privacy.analyticsProcessingAllowed !== 'function' ||
3947
- privacy.analyticsProcessingAllowed() === true;
3948
- return (navigator
3949
- .globalPrivacyControl !== true && analyticsAllowed);
3945
+ if (navigator
3946
+ .globalPrivacyControl === true) {
3947
+ return { state: 'denied', reason: 'gpc' };
3948
+ }
3949
+ const shopify = window.Shopify;
3950
+ if (shopify === undefined)
3951
+ return { state: 'allowed', source: 'none' };
3952
+ const customerPrivacy = shopify.customerPrivacy;
3953
+ const analyticsProcessingAllowed = customerPrivacy === null || customerPrivacy === void 0 ? void 0 : customerPrivacy.analyticsProcessingAllowed;
3954
+ if (typeof analyticsProcessingAllowed === 'function') {
3955
+ return analyticsProcessingAllowed.call(customerPrivacy) === true
3956
+ ? { state: 'allowed', source: 'shopify' }
3957
+ : { state: 'denied', reason: 'consent_denied' };
3958
+ }
3959
+ return { state: 'pending' };
3950
3960
  }
3951
- catch (_b) {
3952
- return false;
3961
+ catch (_a) {
3962
+ return { state: 'denied', reason: 'consent_unavailable' };
3953
3963
  }
3954
3964
  }
3955
3965
  function createMonitoringPayload(coframe, monitoringType, metadata) {
@@ -3970,16 +3980,23 @@ function reportStartFailure(coframe, reason) {
3970
3980
  }
3971
3981
  catch (_a) { }
3972
3982
  }
3973
- function createStartContext(coframe, settings, forceSample) {
3983
+ function reportReplaySkipped(coframe, reason) {
3984
+ try {
3985
+ queueMonitoringEvent(coframe, createMonitoringPayload(coframe, 'replay_skipped', { reason }));
3986
+ }
3987
+ catch (_a) { }
3988
+ }
3989
+ function createStartContext(coframe, settings, forceSample, consentSource) {
3974
3990
  return {
3975
3991
  projectId: coframe.projectId,
3976
3992
  ingestUrl: resolveIngestUrl("https://ingest.app.coframe.com/ingest/v2"),
3977
3993
  settings,
3978
3994
  forceSample,
3995
+ consentSource,
3979
3996
  getPageViewId: () => coframe.sessionId,
3980
3997
  getUserToken: () => coframe.userToken,
3981
3998
  getVariantIds: () => { var _a; return ((_a = coframe.experimentInfo) !== null && _a !== void 0 ? _a : []).map((experiment) => experiment.variant_id); },
3982
- canSend: () => shouldSendEvents() && replayConsentAllowed(),
3999
+ canSend: () => shouldSendEvents() && readReplayConsent().state === 'allowed',
3983
4000
  onEventsFlushed: (callback) => {
3984
4001
  if (queuedEvents.length === 0 && queuedSessions.length === 0) {
3985
4002
  callback();
@@ -3991,22 +4008,13 @@ function createStartContext(coframe, settings, forceSample) {
3991
4008
  report: (type, metadata) => queueMonitoringEvent(coframe, createMonitoringPayload(coframe, type, metadata)),
3992
4009
  };
3993
4010
  }
3994
- function startReplayIfEnabled(coframe, project, nonce) {
3995
- var _a;
4011
+ function insertReplayScript(coframe, settings, consentSource, nonce) {
3996
4012
  try {
3997
- const settings = (_a = project.settings) === null || _a === void 0 ? void 0 : _a.session_replay;
3998
- if ((settings === null || settings === void 0 ? void 0 : settings.enabled) !== true ||
3999
- typeof CompressionStream !== 'function' ||
4000
- !shouldSendEvents() ||
4001
- !replayConsentAllowed() ||
4002
- startRequested) {
4003
- return;
4004
- }
4005
4013
  let forceSample = false;
4006
4014
  try {
4007
4015
  forceSample = localStorage.getItem('coframe.enableRecording') === 'true';
4008
4016
  }
4009
- catch (_b) { }
4017
+ catch (_a) { }
4010
4018
  const script = document.createElement('script');
4011
4019
  script.id = 'coframe-replay-script';
4012
4020
  script.async = true;
@@ -4017,7 +4025,7 @@ function startReplayIfEnabled(coframe, project, nonce) {
4017
4025
  try {
4018
4026
  const replay = window.CoframeReplay;
4019
4027
  if ((replay === null || replay === void 0 ? void 0 : replay.protocolVersion) === 1) {
4020
- replay.start(createStartContext(coframe, settings, forceSample));
4028
+ replay.start(createStartContext(coframe, settings, forceSample, consentSource));
4021
4029
  }
4022
4030
  else {
4023
4031
  reportStartFailure(coframe, 'incompatible_protocol');
@@ -4030,13 +4038,56 @@ function startReplayIfEnabled(coframe, project, nonce) {
4030
4038
  script.onerror = () => {
4031
4039
  reportStartFailure(coframe, 'script_load_failed');
4032
4040
  };
4033
- startRequested = true;
4034
4041
  document.head.appendChild(script);
4035
4042
  }
4036
4043
  catch (error) {
4037
4044
  reportStartFailure(coframe, error instanceof Error ? error.message : String(error));
4038
4045
  }
4039
4046
  }
4047
+ function startReplayIfEnabled(coframe, project, nonce) {
4048
+ var _a;
4049
+ try {
4050
+ const settings = (_a = project.settings) === null || _a === void 0 ? void 0 : _a.session_replay;
4051
+ if ((settings === null || settings === void 0 ? void 0 : settings.enabled) !== true ||
4052
+ typeof CompressionStream !== 'function' ||
4053
+ !shouldSendEvents() ||
4054
+ startRequested) {
4055
+ return;
4056
+ }
4057
+ startRequested = true;
4058
+ let waited = 0;
4059
+ const decide = () => {
4060
+ var _a;
4061
+ const consent = readReplayConsent();
4062
+ if (consent.state === 'allowed') {
4063
+ insertReplayScript(coframe, settings, consent.source, nonce);
4064
+ }
4065
+ else if (consent.state === 'denied') {
4066
+ reportReplaySkipped(coframe, consent.reason);
4067
+ }
4068
+ else if (waited >= CONSENT_WAIT_MS) {
4069
+ reportReplaySkipped(coframe, 'consent_unavailable');
4070
+ }
4071
+ else {
4072
+ if (waited === 0) {
4073
+ try {
4074
+ const loadFeatures = (_a = window.Shopify) === null || _a === void 0 ? void 0 : _a.loadFeatures;
4075
+ if (typeof loadFeatures === 'function') {
4076
+ loadFeatures.call(window.Shopify, [{ name: 'consent-tracking-api', version: '0.1' }], () => { });
4077
+ }
4078
+ }
4079
+ catch (_b) { }
4080
+ }
4081
+ waited += CONSENT_POLL_MS;
4082
+ window.setTimeout(decide, CONSENT_POLL_MS);
4083
+ }
4084
+ };
4085
+ decide();
4086
+ }
4087
+ catch (error) {
4088
+ reportStartFailure(coframe, error instanceof Error ? error.message : String(error));
4089
+ }
4090
+ }
4040
4091
 
4041
4092
  const TIMEOUT_MAX_MS = 5000;
4042
4093
  const MAX_NOT_RENDERED_REASON_CHARS = 200;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coframe/sdk",
3
- "version": "1.1.38",
3
+ "version": "1.1.40",
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",