@blotoutio/edgetag-sdk-js 1.57.0 → 1.57.1

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/index.cjs.js CHANGED
@@ -507,6 +507,74 @@ const usStates = new Map([
507
507
  ['US-VI', 'Virgin Islands, U.S.'],
508
508
  ]);
509
509
  new Set([...isoCountries.keys(), ...usStates.keys()]);
510
+ /**
511
+ * ISO 3166-1 alpha-2 codes for EU member states (as of 2024)
512
+ */
513
+ const EU_COUNTRY_CODES = new Set([
514
+ 'AT', // Austria
515
+ 'BE', // Belgium
516
+ 'BG', // Bulgaria
517
+ 'CY', // Cyprus
518
+ 'CZ', // Czech Republic
519
+ 'DE', // Germany
520
+ 'DK', // Denmark
521
+ 'EE', // Estonia
522
+ 'ES', // Spain
523
+ 'FI', // Finland
524
+ 'FR', // France
525
+ 'GR', // Greece
526
+ 'HR', // Croatia
527
+ 'HU', // Hungary
528
+ 'IE', // Ireland
529
+ 'IT', // Italy
530
+ 'LT', // Lithuania
531
+ 'LU', // Luxembourg
532
+ 'LV', // Latvia
533
+ 'MT', // Malta
534
+ 'NL', // Netherlands
535
+ 'PL', // Poland
536
+ 'PT', // Portugal
537
+ 'RO', // Romania
538
+ 'SE', // Sweden
539
+ 'SI', // Slovenia
540
+ 'SK', // Slovakia
541
+ ]);
542
+ /**
543
+ * Returns true if the request originates from the EU or the UK (GB).
544
+ * Cloudflare's isEUCountry flag excludes the UK post-Brexit, so GB is
545
+ * checked explicitly alongside the EU member set.
546
+ *
547
+ * Fails closed: when the country cannot be resolved, the request is treated
548
+ * as EU/UK. This is the safe default for the compliance-sensitive Grey Switch
549
+ * (an unknown visitor may be in the EU/UK, so it must not slip through when
550
+ * the EU/UK toggle is off).
551
+ */
552
+ const isEuUkRegion = (country, isEURequest) => {
553
+ if (isEURequest) {
554
+ return true;
555
+ }
556
+ if (!country) {
557
+ return true;
558
+ }
559
+ const upper = country.toUpperCase();
560
+ return upper === 'GB' || EU_COUNTRY_CODES.has(upper);
561
+ };
562
+ /**
563
+ * Grey Switch fire rule, shared by the SDK and the CDN worker so both stay in
564
+ * sync. When Grey Switch is on, EdgeTag fires server-side events for
565
+ * non-consented users. The EU/UK toggle is off by default, which keeps EU/UK
566
+ * visitors on normal consent unless the merchant explicitly opts those regions
567
+ * in. Returns whether a server-side event should fire for a non-consented user.
568
+ */
569
+ const greySwitchAllowsServerEvent = ({ greySwitch, greySwitchEuUk, country, isEURequest, }) => {
570
+ if (!greySwitch) {
571
+ return false;
572
+ }
573
+ if (greySwitchEuUk) {
574
+ return true;
575
+ }
576
+ return !isEuUkRegion(country, isEURequest);
577
+ };
510
578
  const parseCache = new Map();
511
579
  const parseRegions = (regionString) => {
512
580
  const include = new Set();
@@ -1224,7 +1292,7 @@ const generateEventId = (name) => {
1224
1292
  time = perf.toFixed(4);
1225
1293
  }
1226
1294
  }
1227
- return `${encodeString(name)}-${generateUUID()}-${time}`;
1295
+ return `${encodeString(name).replace(/[^a-zA-Z0-9]/g, '')}-${generateUUID()}-${time}`;
1228
1296
  };
1229
1297
 
1230
1298
  const getCookieValue = (key) => {
@@ -1470,7 +1538,7 @@ const getStandardPayload = (destination, payload) => {
1470
1538
  referrer: getReferrer(destination),
1471
1539
  search: getSearch(destination),
1472
1540
  locale: getLocale(),
1473
- sdkVersion: "1.57.0" ,
1541
+ sdkVersion: "1.57.1" ,
1474
1542
  ...(payload || {}),
1475
1543
  };
1476
1544
  let storage = {};
@@ -1746,6 +1814,15 @@ const processTag = async (destination, eventName, data = {}, providers, options)
1746
1814
  const consentCategory = getConsentCategories(destination);
1747
1815
  const consentSettings = getSetting(destination, 'consentSetting');
1748
1816
  const userConsent = { consentChannel, consentCategory, consentSettings };
1817
+ // Grey Switch: when enabled, still send the event to the server for
1818
+ // non-consented users. Browser pixels remain gated by hasUserConsent below,
1819
+ // so nothing fires client-side.
1820
+ const greySwitchAllows = greySwitchAllowsServerEvent({
1821
+ greySwitch: getSetting(destination, 'greySwitch') || false,
1822
+ greySwitchEuUk: getSetting(destination, 'greySwitchEuUk') || false,
1823
+ country: requestCountry,
1824
+ isEURequest,
1825
+ });
1749
1826
  const ip = getSetting(destination, 'ip') || null;
1750
1827
  const userProperties = getSetting(destination, 'userProperties');
1751
1828
  if (skipZeroPurchaseEvent && isZeroPurchaseEvent({ eventName, data })) {
@@ -1902,7 +1979,8 @@ const processTag = async (destination, eventName, data = {}, providers, options)
1902
1979
  else {
1903
1980
  logger.log('Browser events skipped by event rules, sending tag to server only');
1904
1981
  }
1905
- if (!hasAllowedManifestTags(configuredTags, userConsent, providers)) {
1982
+ if (!hasAllowedManifestTags(configuredTags, userConsent, providers) &&
1983
+ !greySwitchAllows) {
1906
1984
  return;
1907
1985
  }
1908
1986
  sendTag(destination, {
@@ -2473,6 +2551,8 @@ const handleInit = (preferences) => {
2473
2551
  storageId: result.storageId,
2474
2552
  currency: result.currency,
2475
2553
  skipZeroPurchaseEvent: result.skipZeroPurchaseEvent,
2554
+ greySwitch: result.greySwitch,
2555
+ greySwitchEuUk: result.greySwitchEuUk,
2476
2556
  geoCountry: result.geoCountry,
2477
2557
  geoRegion: result.geoRegion,
2478
2558
  isEURequest: result.isEURequest,
package/index.mjs CHANGED
@@ -505,6 +505,74 @@ const usStates = new Map([
505
505
  ['US-VI', 'Virgin Islands, U.S.'],
506
506
  ]);
507
507
  new Set([...isoCountries.keys(), ...usStates.keys()]);
508
+ /**
509
+ * ISO 3166-1 alpha-2 codes for EU member states (as of 2024)
510
+ */
511
+ const EU_COUNTRY_CODES = new Set([
512
+ 'AT', // Austria
513
+ 'BE', // Belgium
514
+ 'BG', // Bulgaria
515
+ 'CY', // Cyprus
516
+ 'CZ', // Czech Republic
517
+ 'DE', // Germany
518
+ 'DK', // Denmark
519
+ 'EE', // Estonia
520
+ 'ES', // Spain
521
+ 'FI', // Finland
522
+ 'FR', // France
523
+ 'GR', // Greece
524
+ 'HR', // Croatia
525
+ 'HU', // Hungary
526
+ 'IE', // Ireland
527
+ 'IT', // Italy
528
+ 'LT', // Lithuania
529
+ 'LU', // Luxembourg
530
+ 'LV', // Latvia
531
+ 'MT', // Malta
532
+ 'NL', // Netherlands
533
+ 'PL', // Poland
534
+ 'PT', // Portugal
535
+ 'RO', // Romania
536
+ 'SE', // Sweden
537
+ 'SI', // Slovenia
538
+ 'SK', // Slovakia
539
+ ]);
540
+ /**
541
+ * Returns true if the request originates from the EU or the UK (GB).
542
+ * Cloudflare's isEUCountry flag excludes the UK post-Brexit, so GB is
543
+ * checked explicitly alongside the EU member set.
544
+ *
545
+ * Fails closed: when the country cannot be resolved, the request is treated
546
+ * as EU/UK. This is the safe default for the compliance-sensitive Grey Switch
547
+ * (an unknown visitor may be in the EU/UK, so it must not slip through when
548
+ * the EU/UK toggle is off).
549
+ */
550
+ const isEuUkRegion = (country, isEURequest) => {
551
+ if (isEURequest) {
552
+ return true;
553
+ }
554
+ if (!country) {
555
+ return true;
556
+ }
557
+ const upper = country.toUpperCase();
558
+ return upper === 'GB' || EU_COUNTRY_CODES.has(upper);
559
+ };
560
+ /**
561
+ * Grey Switch fire rule, shared by the SDK and the CDN worker so both stay in
562
+ * sync. When Grey Switch is on, EdgeTag fires server-side events for
563
+ * non-consented users. The EU/UK toggle is off by default, which keeps EU/UK
564
+ * visitors on normal consent unless the merchant explicitly opts those regions
565
+ * in. Returns whether a server-side event should fire for a non-consented user.
566
+ */
567
+ const greySwitchAllowsServerEvent = ({ greySwitch, greySwitchEuUk, country, isEURequest, }) => {
568
+ if (!greySwitch) {
569
+ return false;
570
+ }
571
+ if (greySwitchEuUk) {
572
+ return true;
573
+ }
574
+ return !isEuUkRegion(country, isEURequest);
575
+ };
508
576
  const parseCache = new Map();
509
577
  const parseRegions = (regionString) => {
510
578
  const include = new Set();
@@ -1222,7 +1290,7 @@ const generateEventId = (name) => {
1222
1290
  time = perf.toFixed(4);
1223
1291
  }
1224
1292
  }
1225
- return `${encodeString(name)}-${generateUUID()}-${time}`;
1293
+ return `${encodeString(name).replace(/[^a-zA-Z0-9]/g, '')}-${generateUUID()}-${time}`;
1226
1294
  };
1227
1295
 
1228
1296
  const getCookieValue = (key) => {
@@ -1468,7 +1536,7 @@ const getStandardPayload = (destination, payload) => {
1468
1536
  referrer: getReferrer(destination),
1469
1537
  search: getSearch(destination),
1470
1538
  locale: getLocale(),
1471
- sdkVersion: "1.57.0" ,
1539
+ sdkVersion: "1.57.1" ,
1472
1540
  ...(payload || {}),
1473
1541
  };
1474
1542
  let storage = {};
@@ -1744,6 +1812,15 @@ const processTag = async (destination, eventName, data = {}, providers, options)
1744
1812
  const consentCategory = getConsentCategories(destination);
1745
1813
  const consentSettings = getSetting(destination, 'consentSetting');
1746
1814
  const userConsent = { consentChannel, consentCategory, consentSettings };
1815
+ // Grey Switch: when enabled, still send the event to the server for
1816
+ // non-consented users. Browser pixels remain gated by hasUserConsent below,
1817
+ // so nothing fires client-side.
1818
+ const greySwitchAllows = greySwitchAllowsServerEvent({
1819
+ greySwitch: getSetting(destination, 'greySwitch') || false,
1820
+ greySwitchEuUk: getSetting(destination, 'greySwitchEuUk') || false,
1821
+ country: requestCountry,
1822
+ isEURequest,
1823
+ });
1747
1824
  const ip = getSetting(destination, 'ip') || null;
1748
1825
  const userProperties = getSetting(destination, 'userProperties');
1749
1826
  if (skipZeroPurchaseEvent && isZeroPurchaseEvent({ eventName, data })) {
@@ -1900,7 +1977,8 @@ const processTag = async (destination, eventName, data = {}, providers, options)
1900
1977
  else {
1901
1978
  logger.log('Browser events skipped by event rules, sending tag to server only');
1902
1979
  }
1903
- if (!hasAllowedManifestTags(configuredTags, userConsent, providers)) {
1980
+ if (!hasAllowedManifestTags(configuredTags, userConsent, providers) &&
1981
+ !greySwitchAllows) {
1904
1982
  return;
1905
1983
  }
1906
1984
  sendTag(destination, {
@@ -2471,6 +2549,8 @@ const handleInit = (preferences) => {
2471
2549
  storageId: result.storageId,
2472
2550
  currency: result.currency,
2473
2551
  skipZeroPurchaseEvent: result.skipZeroPurchaseEvent,
2552
+ greySwitch: result.greySwitch,
2553
+ greySwitchEuUk: result.greySwitchEuUk,
2474
2554
  geoCountry: result.geoCountry,
2475
2555
  geoRegion: result.geoRegion,
2476
2556
  isEURequest: result.isEURequest,
package/internal.d.ts CHANGED
@@ -67,6 +67,8 @@ type InitResponse = {
67
67
  rates: { from: string; to: string; value: number }[]
68
68
  }
69
69
  skipZeroPurchaseEvent?: boolean
70
+ greySwitch?: boolean
71
+ greySwitchEuUk?: boolean
70
72
  geoCountry: string | null
71
73
  geoRegion: string | null
72
74
  isEURequest: boolean
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blotoutio/edgetag-sdk-js",
3
- "version": "1.57.0",
3
+ "version": "1.57.1",
4
4
  "description": "JS SDK for EdgeTag",
5
5
  "author": "Blotout",
6
6
  "license": "MIT",