@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.
- package/index.js +487 -81
- 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.
|
|
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
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
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 (
|
|
1181
|
-
|
|
1182
|
-
|
|
1496
|
+
if (rulesResult.updatedProviders) {
|
|
1497
|
+
// eslint-disable-next-line no-param-reassign
|
|
1498
|
+
providers = rulesResult.updatedProviders;
|
|
1183
1499
|
}
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1220
|
-
|
|
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
|
-
|
|
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 (
|
|
2104
|
-
|
|
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
|
});
|