@mparticle/web-google-tag-manager-kit 2.0.3 → 2.1.0

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.
@@ -2,8 +2,125 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
+ var googleConsentValues = {
6
+ // Server Integration uses 'Unspecified' as a value when the setting is 'not set'.
7
+ // However, this is not used by Google's Web SDK. We are referencing it here as a comment
8
+ // as a record of this distinction and for posterity.
9
+ // If Google ever adds this for web, the line can just be uncommented to support this.
10
+ //
11
+ // Docs:
12
+ // Web: https://developers.google.com/tag-platform/gtagjs/reference#consent
13
+ // S2S: https://developers.google.com/google-ads/api/reference/rpc/v15/ConsentStatusEnum.ConsentStatus
14
+ //
15
+ // Unspecified: 'unspecified',
16
+ Denied: 'denied',
17
+ Granted: 'granted',
18
+ };
19
+
20
+ // Declares list of valid Google Consent Properties
21
+ var googleConsentProperties = [
22
+ 'ad_storage',
23
+ 'ad_user_data',
24
+ 'ad_personalization',
25
+ 'analytics_storage',
26
+ ];
27
+
28
+ function ConsentHandler(common) {
29
+ this.common = common || {};
30
+ }
31
+
32
+ ConsentHandler.prototype.getUserConsentState = function () {
33
+ var userConsentState = {};
34
+
35
+ if (mParticle.Identity && mParticle.Identity.getCurrentUser) {
36
+ var currentUser = mParticle.Identity.getCurrentUser();
37
+
38
+ if (!currentUser) {
39
+ return {};
40
+ }
41
+
42
+ var consentState =
43
+ mParticle.Identity.getCurrentUser().getConsentState();
44
+
45
+ if (consentState && consentState.getGDPRConsentState) {
46
+ userConsentState = consentState.getGDPRConsentState();
47
+ }
48
+ }
49
+
50
+ return userConsentState;
51
+ };
52
+
53
+ ConsentHandler.prototype.getEventConsentState = function (eventConsentState) {
54
+ return eventConsentState && eventConsentState.getGDPRConsentState
55
+ ? eventConsentState.getGDPRConsentState()
56
+ : {};
57
+ };
58
+
59
+ ConsentHandler.prototype.getConsentSettings = function () {
60
+ var consentSettings = {};
61
+
62
+ var googleToMpConsentSettingsMapping = {
63
+ ad_user_data: 'defaultAdUserDataConsentWeb',
64
+ ad_personalization: 'defaultAdPersonalizationConsentWeb',
65
+ ad_storage: 'defaultAdStorageConsentWeb',
66
+ analytics_storage: 'defaultAnalyticsStorageConsentWeb',
67
+ };
68
+
69
+ var settings = this.common.settings;
70
+
71
+ Object.keys(googleToMpConsentSettingsMapping).forEach(function (
72
+ googleConsentKey
73
+ ) {
74
+ var mpConsentSettingKey =
75
+ googleToMpConsentSettingsMapping[googleConsentKey];
76
+ var googleConsentValuesKey = settings[mpConsentSettingKey];
77
+
78
+ if (googleConsentValuesKey && mpConsentSettingKey) {
79
+ consentSettings[googleConsentKey] =
80
+ googleConsentValues[googleConsentValuesKey];
81
+ }
82
+ });
83
+
84
+ return consentSettings;
85
+ };
86
+
87
+ ConsentHandler.prototype.generateConsentStatePayloadFromMappings = function (
88
+ consentState,
89
+ mappings
90
+ ) {
91
+ if (!mappings) return {};
92
+
93
+ var payload = this.common.cloneObject(this.common.consentPayloadDefaults);
94
+
95
+ for (var i = 0; i <= mappings.length - 1; i++) {
96
+ var mappingEntry = mappings[i];
97
+ var mpMappedConsentName = mappingEntry.map;
98
+ var googleMappedConsentName = mappingEntry.value;
99
+
100
+ if (
101
+ consentState[mpMappedConsentName] &&
102
+ googleConsentProperties.indexOf(googleMappedConsentName) !== -1
103
+ ) {
104
+ payload[googleMappedConsentName] = consentState[mpMappedConsentName]
105
+ .Consented
106
+ ? googleConsentValues.Granted
107
+ : googleConsentValues.Denied;
108
+ }
109
+ }
110
+
111
+ return payload;
112
+ };
113
+
114
+ var consent = ConsentHandler;
115
+
5
116
  function Common() {
6
117
  this.customDataLayerName = null;
118
+
119
+ this.consentMappings = [];
120
+ this.consentPayloadDefaults = {};
121
+ this.consentPayloadAsString = '';
122
+
123
+ this.consentHandler = new consent(this);
7
124
  }
8
125
 
9
126
  Common.prototype.buildMPID = function(event, user) {
@@ -122,6 +239,26 @@ Common.prototype.send = function(_attributes) {
122
239
  window[this.customDataLayerName].push(payload);
123
240
  };
124
241
 
242
+ Common.prototype.sendConsent = function (type, payload) {
243
+ // Google Tag Manager doesn't directly use the gtag function
244
+ // but recommends pushing directly into the dataLayer
245
+ // https://developers.google.com/tag-manager/devguide
246
+ var customDataLayerName = this.customDataLayerName;
247
+ function customDataLayer() {
248
+ window[customDataLayerName].push(arguments);
249
+ }
250
+
251
+ customDataLayer('consent', type, payload);
252
+ };
253
+
254
+ Common.prototype.cloneObject = function (obj) {
255
+ return JSON.parse(JSON.stringify(obj));
256
+ };
257
+
258
+ Common.prototype.isEmpty = function isEmpty(value) {
259
+ return value == null || !(Object.keys(value) || value).length;
260
+ };
261
+
125
262
  var common = Common;
126
263
 
127
264
  var ProductActionTypes = {
@@ -439,9 +576,36 @@ function EventHandler(common) {
439
576
  this.common = common || {};
440
577
  }
441
578
 
442
- EventHandler.prototype.logEvent = function(event) {
579
+ EventHandler.prototype.maybeSendConsentUpdateToGoogle = function (event) {
580
+ // If consent payload is empty,
581
+ // we never sent an initial default consent state
582
+ // so we shouldn't send an update.
583
+ if (this.common.consentPayloadAsString && this.common.consentMappings) {
584
+ var eventConsentState = this.common.consentHandler.getEventConsentState(
585
+ event.ConsentState
586
+ );
587
+
588
+ if (!this.common.isEmpty(eventConsentState)) {
589
+ var updatedConsentPayload =
590
+ this.common.consentHandler.generateConsentStatePayloadFromMappings(
591
+ eventConsentState,
592
+ this.common.consentMappings
593
+ );
594
+
595
+ var eventConsentAsString = JSON.stringify(updatedConsentPayload);
596
+
597
+ if (eventConsentAsString !== this.common.consentPayloadAsString) {
598
+ this.common.sendConsent('update', updatedConsentPayload);
599
+ this.common.consentPayloadAsString = eventConsentAsString;
600
+ }
601
+ }
602
+ }
603
+ };
604
+
605
+ EventHandler.prototype.logEvent = function (event) {
606
+ this.maybeSendConsentUpdateToGoogle(event);
443
607
  this.common.send({
444
- event: event
608
+ event: event,
445
609
  });
446
610
 
447
611
  return true;
@@ -449,7 +613,8 @@ EventHandler.prototype.logEvent = function(event) {
449
613
 
450
614
  EventHandler.prototype.logError = function() {};
451
615
 
452
- EventHandler.prototype.logPageView = function(event) {
616
+ EventHandler.prototype.logPageView = function (event) {
617
+ this.maybeSendConsentUpdateToGoogle(event);
453
618
  this.common.send({
454
619
  event: event,
455
620
  eventType: 'screen_view'
@@ -562,6 +727,20 @@ var initialization = {
562
727
  isInitialized,
563
728
  common
564
729
  ) {
730
+ common.settings = settings;
731
+
732
+ if (common.settings.consentMappingWeb) {
733
+ common.consentMappings = parseSettingsString(
734
+ common.settings.consentMappingWeb
735
+ );
736
+ } else {
737
+ // Ensures consent mappings is an empty array
738
+ // for future use
739
+ common.consentMappings = [];
740
+ common.consentPayloadDefaults = {};
741
+ common.consentPayloadAsString = '';
742
+ }
743
+
565
744
  var containerId = sanitizeContainerId(settings.containerId);
566
745
 
567
746
  if (!containerId) {
@@ -596,15 +775,32 @@ var initialization = {
596
775
 
597
776
  if (testMode || !includeContainer) {
598
777
  isInitialized = true;
599
- return;
778
+ } else {
779
+ isInitialized = initializeContainer(
780
+ containerId,
781
+ common.customDataLayerName,
782
+ previewUrl
783
+ );
600
784
  }
601
785
 
602
- isInitialized = initializeContainer(
603
- containerId,
604
- common.customDataLayerName,
605
- previewUrl
606
- );
607
- }
786
+ common.consentPayloadDefaults =
787
+ common.consentHandler.getConsentSettings();
788
+ var initialConsentState = common.consentHandler.getUserConsentState();
789
+
790
+ var defaultConsentPayload =
791
+ common.consentHandler.generateConsentStatePayloadFromMappings(
792
+ initialConsentState,
793
+ common.consentMappings
794
+ );
795
+
796
+ if (!common.isEmpty(defaultConsentPayload)) {
797
+ common.consentPayloadAsString = JSON.stringify(
798
+ defaultConsentPayload
799
+ );
800
+
801
+ common.sendConsent('default', defaultConsentPayload);
802
+ }
803
+ },
608
804
  };
609
805
 
610
806
  function initializeContainer(containerId, dataLayerName, previewUrl) {
@@ -680,10 +876,15 @@ function sanitizeDataLayerName(_dataLayerName) {
680
876
 
681
877
  function sanitizePreviewUrl(_previewUrl) {
682
878
  var previewUrl = _previewUrl || '';
683
- var regex = /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/gm;
879
+ var regex =
880
+ /^(?:http(s)?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]+$/gm;
684
881
  return previewUrl.trim().match(regex) ? previewUrl.trim() : '';
685
882
  }
686
883
 
884
+ function parseSettingsString(settingsString) {
885
+ return JSON.parse(settingsString.replace(/&quot;/g, '"'));
886
+ }
887
+
687
888
  var initialization_1 = initialization;
688
889
 
689
890
  var sessionHandler = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mparticle/web-google-tag-manager-kit",
3
- "version": "2.0.3",
3
+ "version": "2.1.0",
4
4
  "repository": "https://github.com/mparticle-integrations/mparticle-javascript-integration-google-tag-manager",
5
5
  "main": "dist/GoogleTagManager-Kit.common.js",
6
6
  "browser": "dist/GoogleTagManager-Kit.common.js",
@@ -8,6 +8,8 @@
8
8
  "dist/GoogleTagManager-Kit.common.js"
9
9
  ],
10
10
  "scripts": {
11
+ "test": "npm run build && npm run test:karma",
12
+ "test:karma": "npm run testKarma",
11
13
  "testKarma": "node test/boilerplate/test-karma.js",
12
14
  "build": "ENVIRONMENT=production rollup --config rollup.config.js",
13
15
  "watch": "ENVIRONMENT=production rollup --config rollup.config.js -w",