@blotoutio/edgetag-sdk-browser 1.35.0 → 1.35.2

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.
Files changed (2) hide show
  1. package/index.js +487 -81
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -509,6 +509,306 @@
509
509
  return true;
510
510
  };
511
511
 
512
+ /**
513
+ * Get a nested value from an object using dot notation
514
+ */
515
+ const getNestedValue = (obj, path) => {
516
+ const parts = path.split('.');
517
+ let current = obj;
518
+ for (const part of parts) {
519
+ if (current === null || current === undefined) {
520
+ return undefined;
521
+ }
522
+ if (typeof current !== 'object') {
523
+ return undefined;
524
+ }
525
+ current = current[part];
526
+ }
527
+ return current;
528
+ };
529
+ /**
530
+ * Set a nested value in an object using dot notation
531
+ */
532
+ const setNestedValue = (obj, path, value) => {
533
+ const parts = path.split('.');
534
+ let current = obj;
535
+ for (let i = 0; i < parts.length - 1; i++) {
536
+ const part = parts[i];
537
+ const existing = current[part];
538
+ if (existing === undefined) {
539
+ current[part] = {};
540
+ }
541
+ else if (existing === null || typeof existing === 'object') {
542
+ // null can be overwritten with an object
543
+ // existing objects can be traversed
544
+ current[part] || (current[part] = {});
545
+ }
546
+ else {
547
+ // existing is a primitive type (string, number, boolean, etc.)
548
+ console.log(`Cannot set nested path "${path}": "${parts
549
+ .slice(0, i + 1)
550
+ .join('.')}" is already a ${typeof existing} and cannot be converted to an object`);
551
+ return;
552
+ }
553
+ current = current[part];
554
+ }
555
+ current[parts[parts.length - 1]] = value;
556
+ };
557
+ /**
558
+ * Remove a nested value from an object using dot notation
559
+ */
560
+ const removeNestedValue = (obj, path) => {
561
+ const parts = path.split('.');
562
+ let current = obj;
563
+ for (let i = 0; i < parts.length - 1; i++) {
564
+ const part = parts[i];
565
+ const existing = current[part];
566
+ if (existing !== null && typeof existing === 'object') {
567
+ current = current[part];
568
+ }
569
+ else {
570
+ return;
571
+ }
572
+ }
573
+ delete current[parts[parts.length - 1]];
574
+ };
575
+ /**
576
+ * Evaluate a single condition rule
577
+ */
578
+ const evaluateCondition = (condition, payload, userData = {}) => {
579
+ let fieldValue;
580
+ if (condition.field.startsWith('user.')) {
581
+ const userPath = condition.field.replace('user.', '');
582
+ fieldValue = getNestedValue(userData, userPath);
583
+ }
584
+ else if (condition.field.startsWith('payload.')) {
585
+ const payloadPath = condition.field.replace('payload.', '');
586
+ if (payloadPath.includes('[]')) {
587
+ const [arrayPath, arrayField] = payloadPath.split('[]');
588
+ const arrayValue = getNestedValue(payload, arrayPath);
589
+ if (Array.isArray(arrayValue)) {
590
+ const fieldName = arrayField.startsWith('.')
591
+ ? arrayField.slice(1)
592
+ : arrayField;
593
+ fieldValue = arrayValue.flatMap((item) => typeof item === 'object' && item !== null
594
+ ? item[fieldName]
595
+ : []);
596
+ }
597
+ else {
598
+ fieldValue = undefined;
599
+ }
600
+ }
601
+ else {
602
+ fieldValue = getNestedValue(payload, payloadPath);
603
+ }
604
+ }
605
+ else {
606
+ fieldValue = getNestedValue(payload.data, condition.field);
607
+ }
608
+ const operator = condition.operator;
609
+ const conditionValue = condition.value;
610
+ switch (operator) {
611
+ case 'equals':
612
+ return fieldValue === conditionValue;
613
+ case 'notEquals':
614
+ return fieldValue !== conditionValue;
615
+ case 'greaterThan':
616
+ return (typeof fieldValue === 'number' &&
617
+ typeof conditionValue === 'number' &&
618
+ fieldValue > conditionValue);
619
+ case 'greaterThanOrEqual':
620
+ return (typeof fieldValue === 'number' &&
621
+ typeof conditionValue === 'number' &&
622
+ fieldValue >= conditionValue);
623
+ case 'lessThan':
624
+ return (typeof fieldValue === 'number' &&
625
+ typeof conditionValue === 'number' &&
626
+ fieldValue < conditionValue);
627
+ case 'lessThanOrEqual':
628
+ return (typeof fieldValue === 'number' &&
629
+ typeof conditionValue === 'number' &&
630
+ fieldValue <= conditionValue);
631
+ case 'contains':
632
+ if (Array.isArray(fieldValue)) {
633
+ // For array fields, check if any item in the array contains the condition value
634
+ return (typeof conditionValue === 'string' &&
635
+ fieldValue.some((val) => typeof val === 'string' && val === conditionValue));
636
+ }
637
+ return (typeof fieldValue === 'string' &&
638
+ typeof conditionValue === 'string' &&
639
+ fieldValue.includes(conditionValue));
640
+ case 'notContains':
641
+ if (Array.isArray(fieldValue)) {
642
+ // For array fields, check if no item in the array contains the condition value
643
+ return (typeof conditionValue === 'string' &&
644
+ !fieldValue.some((val) => typeof val === 'string' && val === conditionValue));
645
+ }
646
+ return (typeof fieldValue === 'string' &&
647
+ typeof conditionValue === 'string' &&
648
+ !fieldValue.includes(conditionValue));
649
+ case 'in':
650
+ if (Array.isArray(fieldValue)) {
651
+ return (Array.isArray(conditionValue) &&
652
+ fieldValue.some((val) => conditionValue.includes(val)));
653
+ }
654
+ return (Array.isArray(conditionValue) &&
655
+ conditionValue.some((val) => val === fieldValue));
656
+ case 'notIn':
657
+ if (Array.isArray(fieldValue)) {
658
+ return (Array.isArray(conditionValue) &&
659
+ !fieldValue.some((val) => conditionValue.includes(val)));
660
+ }
661
+ return (Array.isArray(conditionValue) &&
662
+ !conditionValue.some((val) => val === fieldValue));
663
+ case 'startsWith':
664
+ return (typeof fieldValue === 'string' &&
665
+ typeof conditionValue === 'string' &&
666
+ fieldValue.startsWith(conditionValue));
667
+ case 'endsWith':
668
+ return (typeof fieldValue === 'string' &&
669
+ typeof conditionValue === 'string' &&
670
+ fieldValue.endsWith(conditionValue));
671
+ case 'isNull':
672
+ return fieldValue === null || fieldValue === undefined;
673
+ case 'isNotNull':
674
+ return fieldValue !== null && fieldValue !== undefined;
675
+ default:
676
+ return false;
677
+ }
678
+ };
679
+ /**
680
+ * Evaluate conditions for a simplified rule (no nested groups)
681
+ */
682
+ const evaluateConditions = (conditions, logicalOperator, payload, userData = {}) => {
683
+ if (conditions.length === 0) {
684
+ return true;
685
+ }
686
+ if (logicalOperator === 'AND') {
687
+ return conditions.every((condition) => evaluateCondition(condition, payload, userData));
688
+ }
689
+ else {
690
+ return conditions.some((condition) => evaluateCondition(condition, payload, userData));
691
+ }
692
+ };
693
+ /**
694
+ * Apply actions to payload and providers
695
+ * @param actions - Array of actions to apply
696
+ * @param payload - The payload to modify
697
+ * @param providers - Optional separate providers object (if not in payload)
698
+ * @returns Updated payload, providers, skipEvent flag, and additional event names
699
+ */
700
+ const applyActions = (actions, payload, providers) => {
701
+ var _a;
702
+ const updatedPayload = structuredClone(payload);
703
+ if (!updatedPayload.data) {
704
+ updatedPayload.data = {};
705
+ }
706
+ const updatedProviders = ((_a = providers !== null && providers !== void 0 ? providers : updatedPayload.providers) !== null && _a !== void 0 ? _a : { all: true });
707
+ let skipEvent = false;
708
+ let skipBrowserEvent = false;
709
+ const additionalEvents = [];
710
+ for (const action of actions) {
711
+ switch (action.type) {
712
+ case 'skipEvent':
713
+ skipEvent = true;
714
+ break;
715
+ case 'skipBrowserEvent':
716
+ skipBrowserEvent = true;
717
+ break;
718
+ case 'skipProviders':
719
+ if (action.providers && updatedProviders) {
720
+ for (const provider of action.providers) {
721
+ updatedProviders[provider] = false;
722
+ }
723
+ }
724
+ break;
725
+ case 'updatePayloadField':
726
+ if (action.fieldPath && action.fieldValue !== undefined) {
727
+ const path = action.fieldPath.startsWith('data.')
728
+ ? action.fieldPath
729
+ : `data.${action.fieldPath}`;
730
+ setNestedValue(updatedPayload.data, path.replace('data.', ''), action.fieldValue);
731
+ }
732
+ break;
733
+ case 'addPayloadField':
734
+ if (action.fieldPath && action.fieldValue !== undefined) {
735
+ const path = action.fieldPath.startsWith('data.')
736
+ ? action.fieldPath
737
+ : `data.${action.fieldPath}`;
738
+ setNestedValue(updatedPayload.data, path.replace('data.', ''), action.fieldValue);
739
+ }
740
+ break;
741
+ case 'removePayloadField':
742
+ if (action.fieldPath) {
743
+ const path = action.fieldPath.startsWith('data.')
744
+ ? action.fieldPath
745
+ : `data.${action.fieldPath}`;
746
+ removeNestedValue(updatedPayload.data, path.replace('data.', ''));
747
+ }
748
+ break;
749
+ case 'createAdditionalEvents':
750
+ if (action.additionalEvents) {
751
+ additionalEvents.push(...action.additionalEvents);
752
+ }
753
+ break;
754
+ }
755
+ }
756
+ if (updatedProviders !== undefined) {
757
+ updatedPayload.providers = updatedProviders;
758
+ }
759
+ return {
760
+ updatedPayload,
761
+ updatedProviders,
762
+ skipEvent,
763
+ skipBrowserEvent,
764
+ additionalEvents,
765
+ };
766
+ };
767
+ /**
768
+ * Evaluate all event rules and apply actions
769
+ * @param rules - Array of event rules to evaluate
770
+ * @param payload - The payload to evaluate and modify
771
+ * @param providers - Optional separate providers object (if not in payload)
772
+ * @param userData - Optional user data for user.* field access
773
+ * @returns Updated payload, providers, skipEvent flag, and additional event names
774
+ */
775
+ const evaluateEventRules = (rules, payload, providers, userData = {}) => {
776
+ var _a;
777
+ let updatedPayload = payload;
778
+ let updatedProviders = ((_a = providers !== null && providers !== void 0 ? providers : payload.providers) !== null && _a !== void 0 ? _a : { all: true });
779
+ let skipEvent = false;
780
+ let skipBrowserEvent = false;
781
+ const allAdditionalEvents = [];
782
+ try {
783
+ for (const rule of rules) {
784
+ const conditionMatches = evaluateConditions(rule.conditions || [], rule.logicalOperator || 'AND', updatedPayload, userData);
785
+ if (conditionMatches) {
786
+ const actions = rule.actions || [];
787
+ const result = applyActions(actions, updatedPayload, updatedProviders);
788
+ updatedPayload = result.updatedPayload;
789
+ updatedProviders = result.updatedProviders;
790
+ allAdditionalEvents.push(...result.additionalEvents);
791
+ if (result.skipEvent) {
792
+ skipEvent = true;
793
+ }
794
+ if (result.skipBrowserEvent) {
795
+ skipBrowserEvent = true;
796
+ }
797
+ }
798
+ }
799
+ }
800
+ catch (error) {
801
+ console.error('Error evaluating event rules:', error);
802
+ }
803
+ return {
804
+ updatedPayload,
805
+ updatedProviders,
806
+ skipEvent,
807
+ skipBrowserEvent,
808
+ additionalEvents: allAdditionalEvents,
809
+ };
810
+ };
811
+
512
812
  // eslint-disable-next-line @nx/enforce-module-boundaries
513
813
  const getGlobalSettings = () => {
514
814
  var _a;
@@ -665,6 +965,15 @@
665
965
  }
666
966
  return true;
667
967
  };
968
+ const getInitData = (edgeURL, manifestResult) => ({
969
+ destination: edgeURL,
970
+ userId: manifestResult.userId,
971
+ isNewUser: manifestResult.isNewUser,
972
+ consent: manifestResult.consent,
973
+ consentCategories: manifestResult.consentCategories,
974
+ consentSetting: manifestResult.consentSetting,
975
+ session: manifestResult.session,
976
+ });
668
977
 
669
978
  const tagStorage = 'edgeTag';
670
979
  const consentKey = 'consent';
@@ -956,7 +1265,7 @@
956
1265
  referrer: getReferrer(destination),
957
1266
  search: getSearch(destination),
958
1267
  locale: getLocale(),
959
- sdkVersion: "1.35.0" ,
1268
+ sdkVersion: "1.35.2" ,
960
1269
  ...(payload || {}),
961
1270
  };
962
1271
  let storage = {};
@@ -1130,13 +1439,14 @@
1130
1439
  processGetData(instances[0], keys, callback);
1131
1440
  };
1132
1441
 
1133
- const sendTag = (destination, { eventName, eventId, data, providerData, providers, options }) => {
1442
+ const sendTag = (destination, { eventName, eventId, data, providerData, providers, options, configuratorProcessed, }) => {
1134
1443
  const payload = {
1135
1444
  eventName,
1136
1445
  eventId,
1137
1446
  timestamp: Date.now(),
1138
1447
  data,
1139
1448
  providerData,
1449
+ configuratorProcessed,
1140
1450
  };
1141
1451
  if (providers) {
1142
1452
  payload.providers = providers;
@@ -1169,64 +1479,93 @@
1169
1479
  const consentCategory = getConsentCategories(destination);
1170
1480
  const consentSettings = getSetting(destination, 'consentSetting');
1171
1481
  const userConsent = { consentChannel, consentCategory, consentSettings };
1482
+ const userProperties = getSetting(destination, 'userProperties');
1172
1483
  if (skipZeroPurchaseEvent && isZeroPurchaseEvent({ eventName, data })) {
1173
1484
  return;
1174
1485
  }
1175
- const conversion = preparePayloadWithConversion(JSON.parse(JSON.stringify(data)), getSetting(destination, 'currency'));
1176
- for (const pkg of providerPackages) {
1177
- if (!pkg || !pkg.name || !pkg.tag) {
1178
- continue;
1486
+ const originalData = structuredClone(data);
1487
+ const originalProviders = structuredClone(providers);
1488
+ const rules = (getSetting(destination, 'configuratorSetting') ||
1489
+ []);
1490
+ const rulesResult = evaluateEventRules(rules, structuredClone({ eventName, data }), providers !== null && providers !== void 0 ? providers : undefined, userProperties || {});
1491
+ if (!rulesResult.skipEvent) {
1492
+ if (rulesResult.updatedPayload) {
1493
+ // eslint-disable-next-line no-param-reassign
1494
+ data = rulesResult.updatedPayload.data;
1179
1495
  }
1180
- if (!configuredTags.has(pkg.name)) {
1181
- logger.log(`Provider ${pkg.name} is not in allow list`);
1182
- continue;
1496
+ if (rulesResult.updatedProviders) {
1497
+ // eslint-disable-next-line no-param-reassign
1498
+ providers = rulesResult.updatedProviders;
1183
1499
  }
1184
- const variables = getProviderVariables(destination, pkg.name);
1185
- const result = {};
1186
- const executionContext = new Map();
1187
- for (const variable of variables) {
1188
- if (!isProviderInstanceAllowed(providers, pkg.name, variable.tagName)) {
1189
- logger.log(`Provider instance is not allowed (${pkg.name}: ${variable.tagName})`);
1190
- continue;
1191
- }
1192
- if (!hasUserConsent(userConsent, pkg.name, variable.tagName)) {
1193
- logger.log(`Consent is missing (${pkg.name}: ${variable.tagName})`);
1194
- continue;
1195
- }
1196
- if (!doesGeoRequestMatchList(requestCountry, requestRegion, isEURequest, variable.geoRegions)) {
1197
- logger.log('GEO request region does not match the filter, skiping');
1198
- continue;
1500
+ if (!rulesResult.skipBrowserEvent) {
1501
+ const conversion = preparePayloadWithConversion(JSON.parse(JSON.stringify(data)), getSetting(destination, 'currency'));
1502
+ for (const pkg of providerPackages) {
1503
+ if (!pkg || !pkg.name || !pkg.tag) {
1504
+ continue;
1505
+ }
1506
+ if (!configuredTags.has(pkg.name)) {
1507
+ logger.log(`Provider ${pkg.name} is not in allow list`);
1508
+ continue;
1509
+ }
1510
+ const variables = getProviderVariables(destination, pkg.name);
1511
+ const result = {};
1512
+ const executionContext = new Map();
1513
+ for (const variable of variables) {
1514
+ if (!isProviderInstanceAllowed(providers, pkg.name, variable.tagName)) {
1515
+ logger.log(`Provider instance is not allowed (${pkg.name}: ${variable.tagName})`);
1516
+ continue;
1517
+ }
1518
+ if (!hasUserConsent(userConsent, pkg.name, variable.tagName)) {
1519
+ logger.log(`Consent is missing (${pkg.name}: ${variable.tagName})`);
1520
+ continue;
1521
+ }
1522
+ if (!doesGeoRequestMatchList(requestCountry, requestRegion, isEURequest, variable.geoRegions)) {
1523
+ logger.log('GEO request region does not match the filter, skiping');
1524
+ continue;
1525
+ }
1526
+ const payload = ((_a = conversion === null || conversion === void 0 ? void 0 : conversion.providers) === null || _a === void 0 ? void 0 : _a.length) === 0 ||
1527
+ ((_b = conversion === null || conversion === void 0 ? void 0 : conversion.providers) === null || _b === void 0 ? void 0 : _b.includes(pkg.name))
1528
+ ? conversion.payload
1529
+ : data;
1530
+ result[variable.tagName] = pkg.tag({
1531
+ userId,
1532
+ sessionId,
1533
+ eventName,
1534
+ eventId,
1535
+ data: JSON.parse(JSON.stringify(payload)),
1536
+ sendTag: sendTag.bind(null, destination),
1537
+ getEdgeData: processGetData.bind(null, destination),
1538
+ manifestVariables: variable.variableSet,
1539
+ executionContext,
1540
+ destination,
1541
+ });
1542
+ }
1543
+ providerData[pkg.name] = result;
1199
1544
  }
1200
- const payload = ((_a = conversion === null || conversion === void 0 ? void 0 : conversion.providers) === null || _a === void 0 ? void 0 : _a.length) === 0 ||
1201
- ((_b = conversion === null || conversion === void 0 ? void 0 : conversion.providers) === null || _b === void 0 ? void 0 : _b.includes(pkg.name))
1202
- ? conversion.payload
1203
- : data;
1204
- result[variable.tagName] = pkg.tag({
1205
- userId,
1206
- sessionId,
1207
- eventName,
1208
- eventId,
1209
- data: JSON.parse(JSON.stringify(payload)),
1210
- sendTag: sendTag.bind(null, destination),
1211
- getEdgeData: processGetData.bind(null, destination),
1212
- manifestVariables: variable.variableSet,
1213
- executionContext,
1214
- destination,
1215
- });
1216
1545
  }
1217
- providerData[pkg.name] = result;
1546
+ else {
1547
+ logger.log('Browser events skipped by event rules, sending tag to server only');
1548
+ }
1549
+ if (!hasAllowedManifestTags(configuredTags, userConsent, providers)) {
1550
+ return;
1551
+ }
1552
+ sendTag(destination, {
1553
+ configuratorProcessed: true,
1554
+ eventName,
1555
+ eventId,
1556
+ data,
1557
+ providerData,
1558
+ providers,
1559
+ options,
1560
+ });
1218
1561
  }
1219
- if (!hasAllowedManifestTags(configuredTags, userConsent, providers)) {
1220
- return;
1562
+ else {
1563
+ logger.log('Event skipped by event rules');
1564
+ }
1565
+ const additionalEvents = rulesResult.additionalEvents || [];
1566
+ for (const additionalEventName of additionalEvents) {
1567
+ handleTag(additionalEventName, structuredClone(originalData || {}), originalProviders, options);
1221
1568
  }
1222
- sendTag(destination, {
1223
- eventName,
1224
- eventId,
1225
- data,
1226
- providerData,
1227
- providers,
1228
- options,
1229
- });
1230
1569
  };
1231
1570
  const handleTag = (eventName, data = {}, providers, options) => {
1232
1571
  if (options === null || options === void 0 ? void 0 : options.destination) {
@@ -1623,6 +1962,17 @@
1623
1962
  setSetting(destination, {
1624
1963
  initialized: true,
1625
1964
  });
1965
+ // we fire this event to process the initial consent settings before firing
1966
+ // the rest of the stubs. this will provide the ability to enqueue the consent
1967
+ // call before the rest of the events so that consent is applied correctly for
1968
+ // queued events.
1969
+ try {
1970
+ const detail = getInitData(destination, response);
1971
+ window.dispatchEvent(new CustomEvent('edgetag-boot', { detail }));
1972
+ }
1973
+ catch {
1974
+ // do nothing
1975
+ }
1626
1976
  processStubs(destination);
1627
1977
  };
1628
1978
 
@@ -1747,24 +2097,16 @@
1747
2097
  geoRegion: result.geoRegion,
1748
2098
  isEURequest: result.isEURequest,
1749
2099
  consentSetting: result.consentSetting,
2100
+ configuratorSetting: result.configuratorSetting,
2101
+ userProperties: result.userProperties,
1750
2102
  });
1751
2103
  if (result.storageId != null) {
1752
2104
  savePerKey(preferences.edgeURL, 'local', tagStorage, result.storageId, storageIdKey);
1753
2105
  }
1754
2106
  handleManifest(preferences.edgeURL, result);
1755
2107
  try {
1756
- const detail = {
1757
- destination: preferences.edgeURL,
1758
- userId: result.userId,
1759
- isNewUser: result.isNewUser,
1760
- consent: result.consent,
1761
- consentCategories: result.consentCategories,
1762
- consentSetting: result.consentSetting,
1763
- session: result.session,
1764
- };
1765
- window.dispatchEvent(new CustomEvent('edgetag-initialized', {
1766
- detail,
1767
- }));
2108
+ const detail = getInitData(preferences.edgeURL, result);
2109
+ window.dispatchEvent(new CustomEvent('edgetag-initialized', { detail }));
1768
2110
  onReady(detail);
1769
2111
  }
1770
2112
  catch {
@@ -2054,6 +2396,21 @@
2054
2396
  });
2055
2397
  };
2056
2398
 
2399
+ const addConsentToDestination = (destination, consent) => {
2400
+ if (!window.edgetag.destinations[destination]) {
2401
+ window.edgetag.destinations[destination] = {};
2402
+ }
2403
+
2404
+ if (!window.edgetag.destinations[destination].consents) {
2405
+ window.edgetag.destinations[destination].consents = [];
2406
+ }
2407
+
2408
+ window.edgetag.destinations[destination].consents.push({
2409
+ name: 'consent',
2410
+ arguments: consent,
2411
+ });
2412
+ };
2413
+
2057
2414
  const handleInit = (args) => {
2058
2415
  if (!args?.length) {
2059
2416
  console.error('EdgeTag SDK: Init event is missing arguments');
@@ -2072,26 +2429,38 @@
2072
2429
  }
2073
2430
 
2074
2431
  const tags = [];
2432
+ const consents = [];
2433
+
2434
+ window.edgetag.destinations['all'] =
2435
+ window.edgetag.destinations['all'] || {};
2436
+
2437
+ if (!window.edgetag.destinations['all'].resolvedInits?.has(destination)) {
2438
+ if (window.edgetag.destinations?.['all']?.tags) {
2439
+ const destinationTags = window.edgetag.destinations['all'].tags.map(
2440
+ (tag) => {
2441
+ const newTag = structuredClone(tag);
2442
+ newTag['arguments'][3] = { ...newTag['arguments'][3], destination };
2443
+ return newTag
2444
+ }
2445
+ );
2446
+ tags.push(...destinationTags);
2447
+ }
2448
+
2449
+ if (window.edgetag.destinations?.['all']?.consents) {
2450
+ const destinationConsents = window.edgetag.destinations[
2451
+ 'all'
2452
+ ].consents.map((consent) => {
2453
+ const newConsent = structuredClone(consent);
2454
+ newConsent.arguments[2] = { ...newConsent.arguments[2], destination };
2455
+ return newConsent
2456
+ });
2457
+ consents.push(...destinationConsents);
2458
+ }
2075
2459
 
2076
- if (
2077
- window.edgetag.destinations?.['all']?.tags &&
2078
- !window.edgetag.destinations['all']?.resolvedInits?.has(destination)
2079
- ) {
2080
- const destinationTags = window.edgetag.destinations['all'].tags.map(
2081
- (tag) => {
2082
- const newTag = structuredClone(tag);
2083
- newTag['arguments'][3] = {
2084
- ...newTag['arguments'][3],
2085
- destination,
2086
- };
2087
-
2088
- return newTag
2089
- }
2090
- );
2091
- tags.push(...destinationTags);
2092
2460
  if (!window.edgetag.destinations['all'].resolvedInits) {
2093
2461
  window.edgetag.destinations['all'].resolvedInits = new Set();
2094
2462
  }
2463
+
2095
2464
  window.edgetag.destinations['all'].resolvedInits.add(destination);
2096
2465
  }
2097
2466
 
@@ -2100,8 +2469,13 @@
2100
2469
  window.edgetag.destinations[destination].tags = [];
2101
2470
  }
2102
2471
 
2103
- if (tags.length) {
2104
- args[0]['afterManifestEvents'] = tags;
2472
+ if (window.edgetag.destinations[destination].consents) {
2473
+ consents.push(...window.edgetag.destinations[destination].consents);
2474
+ window.edgetag.destinations[destination].consents = [];
2475
+ }
2476
+
2477
+ if (consents.length + tags.length > 0) {
2478
+ args[0]['afterManifestEvents'] = [...consents, ...tags];
2105
2479
  }
2106
2480
 
2107
2481
  library.init(...args);
@@ -2188,6 +2562,7 @@
2188
2562
 
2189
2563
  const inits = [];
2190
2564
  const tags = [];
2565
+ const consents = [];
2191
2566
  const otherStubs = [];
2192
2567
 
2193
2568
  stubs.forEach((stub) => {
@@ -2211,6 +2586,11 @@
2211
2586
  return
2212
2587
  }
2213
2588
 
2589
+ if (name === 'consent') {
2590
+ consents.push(args);
2591
+ return
2592
+ }
2593
+
2214
2594
  if (name === 'tag') {
2215
2595
  tags.push(args);
2216
2596
  return
@@ -2232,6 +2612,7 @@
2232
2612
  if (!window.edgetag.destinations['all']) {
2233
2613
  window.edgetag.destinations['all'] = {
2234
2614
  tags: [],
2615
+ consents: [],
2235
2616
  resolvedInits: new Set(),
2236
2617
  };
2237
2618
  }
@@ -2242,6 +2623,31 @@
2242
2623
  });
2243
2624
  });
2244
2625
 
2626
+ consents.forEach((consent) => {
2627
+ const destination = getTagDestination(consent);
2628
+ if (destination) {
2629
+ addConsentToDestination(destination, consent);
2630
+ return
2631
+ }
2632
+
2633
+ if (!window.edgetag.destinations['all']) {
2634
+ window.edgetag.destinations['all'] = {
2635
+ tags: [],
2636
+ consents: [],
2637
+ resolvedInits: new Set(),
2638
+ };
2639
+ }
2640
+
2641
+ if (!window.edgetag.destinations['all'].consents) {
2642
+ window.edgetag.destinations['all'].consents = [];
2643
+ }
2644
+
2645
+ window.edgetag.destinations['all'].consents.push({
2646
+ name: 'consent',
2647
+ arguments: consent,
2648
+ });
2649
+ });
2650
+
2245
2651
  inits.forEach((init) => {
2246
2652
  window.edgetag.stubs.push(['init', ...init]);
2247
2653
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blotoutio/edgetag-sdk-browser",
3
- "version": "1.35.0",
3
+ "version": "1.35.2",
4
4
  "description": "Browser SDK for EdgeTag",
5
5
  "author": "Blotout",
6
6
  "license": "MIT",