From 53e479cfddfa4618f84e3be861d805f1abeba1d3 Mon Sep 17 00:00:00 2001 From: Mo Mustafa Date: Fri, 4 Oct 2024 12:59:51 -0700 Subject: [PATCH] fix: send default and update consent payloads on kit init --- packages/GA4Client/src/common.js | 36 ++++++++++++ packages/GA4Client/src/consent.js | 6 -- packages/GA4Client/src/event-handler.js | 36 +++--------- packages/GA4Client/src/initialization.js | 20 ++++--- packages/GA4Client/test/src/tests.js | 70 +++++++++++++++++------- 5 files changed, 105 insertions(+), 63 deletions(-) diff --git a/packages/GA4Client/src/common.js b/packages/GA4Client/src/common.js index 52a59b8..638c6eb 100644 --- a/packages/GA4Client/src/common.js +++ b/packages/GA4Client/src/common.js @@ -139,6 +139,42 @@ Common.prototype.limitProductAttributes = function (attributes) { return this.mergeObjects(limitedProductAttributes, reservedAttributes); }; +Common.prototype.getEventConsentState = function (eventConsentState) { + return eventConsentState && eventConsentState.getGDPRConsentState + ? eventConsentState.getGDPRConsentState() + : {}; +}; + +Common.prototype.maybeSendConsentUpdateToGoogle = function (consentState) { + // If consent payload is empty, + // we never sent an initial default consent state + // so we shouldn't send an update. + if ( + this.consentPayloadAsString && + this.consentMappings && + !this.isEmpty(consentState) + ) { + var updatedConsentPayload = + this.consentHandler.generateConsentStatePayloadFromMappings( + consentState, + this.consentMappings + ); + + var eventConsentAsString = JSON.stringify(updatedConsentPayload); + + if (eventConsentAsString !== this.consentPayloadAsString) { + gtag('consent', 'update', updatedConsentPayload); + this.consentPayloadAsString = eventConsentAsString; + } + } +}; + +Common.prototype.sendDefaultConsentPayloadToGoogle = function (consentPayload) { + this.consentPayloadAsString = JSON.stringify(consentPayload); + + gtag('consent', 'default', consentPayload); +}; + Common.prototype.truncateEventName = function (eventName) { return truncateString(eventName, EVENT_NAME_MAX_LENGTH); }; diff --git a/packages/GA4Client/src/consent.js b/packages/GA4Client/src/consent.js index 5ef2626..7f78106 100644 --- a/packages/GA4Client/src/consent.js +++ b/packages/GA4Client/src/consent.js @@ -46,12 +46,6 @@ ConsentHandler.prototype.getUserConsentState = function () { return userConsentState; }; -ConsentHandler.prototype.getEventConsentState = function (eventConsentState) { - return eventConsentState && eventConsentState.getGDPRConsentState - ? eventConsentState.getGDPRConsentState() - : {}; -}; - ConsentHandler.prototype.getConsentSettings = function () { var consentSettings = {}; diff --git a/packages/GA4Client/src/event-handler.js b/packages/GA4Client/src/event-handler.js index 847fafb..c29c446 100644 --- a/packages/GA4Client/src/event-handler.js +++ b/packages/GA4Client/src/event-handler.js @@ -2,32 +2,6 @@ function EventHandler(common) { this.common = common || {}; } -EventHandler.prototype.maybeSendConsentUpdateToGa4 = function (event) { - // If consent payload is empty, - // we never sent an initial default consent state - // so we shouldn't send an update. - if (this.common.consentPayloadAsString && this.common.consentMappings) { - var eventConsentState = this.common.consentHandler.getEventConsentState( - event.ConsentState - ); - - if (!this.common.isEmpty(eventConsentState)) { - var updatedConsentPayload = - this.common.consentHandler.generateConsentStatePayloadFromMappings( - eventConsentState, - this.common.consentMappings - ); - - var eventConsentAsString = JSON.stringify(updatedConsentPayload); - - if (eventConsentAsString !== this.common.consentPayloadAsString) { - gtag('consent', 'update', updatedConsentPayload); - this.common.consentPayloadAsString = eventConsentAsString; - } - } - } -}; - // TODO: https://mparticle-eng.atlassian.net/browse/SQDSDKS-5715 EventHandler.prototype.sendEventToGA4 = function (eventName, eventAttributes) { var standardizedEventName; @@ -58,7 +32,10 @@ EventHandler.prototype.sendEventToGA4 = function (eventName, eventAttributes) { }; EventHandler.prototype.logEvent = function (event) { - this.maybeSendConsentUpdateToGa4(event); + var eventConsentState = this.common.getEventConsentState( + event.ConsentState + ); + this.common.maybeSendConsentUpdateToGoogle(eventConsentState); this.sendEventToGA4(event.EventName, event.EventAttributes); }; @@ -109,7 +86,10 @@ EventHandler.prototype.logPageView = function (event) { event.EventAttributes ); - this.maybeSendConsentUpdateToGa4(event); + var eventConsentState = this.common.getEventConsentState( + event.ConsentState + ); + this.common.maybeSendConsentUpdateToGoogle(eventConsentState); this.sendEventToGA4('page_view', eventAttributes); return true; diff --git a/packages/GA4Client/src/initialization.js b/packages/GA4Client/src/initialization.js index c263b39..90b9d57 100644 --- a/packages/GA4Client/src/initialization.js +++ b/packages/GA4Client/src/initialization.js @@ -105,22 +105,26 @@ var initialization = { common.consentPayloadDefaults = common.consentHandler.getConsentSettings(); - var initialConsentState = common.consentHandler.getUserConsentState(); - - var defaultConsentPayload = + var defaultConsentPayload = common.cloneObject( + common.consentPayloadDefaults + ); + var updatedConsentState = common.consentHandler.getUserConsentState(); + var updatedDefaultConsentPayload = common.consentHandler.generateConsentStatePayloadFromMappings( - initialConsentState, + updatedConsentState, common.consentMappings ); if (!common.isEmpty(defaultConsentPayload)) { - common.consentPayloadAsString = JSON.stringify( - defaultConsentPayload + common.sendDefaultConsentPayloadToGoogle(defaultConsentPayload); + } else if (!common.isEmpty(updatedDefaultConsentPayload)) { + common.sendDefaultConsentPayloadToGoogle( + updatedDefaultConsentPayload ); - - gtag('consent', 'default', defaultConsentPayload); } + common.maybeSendConsentUpdateToGoogle(updatedConsentState); + return isInitialized; }, }; diff --git a/packages/GA4Client/test/src/tests.js b/packages/GA4Client/test/src/tests.js index 3b222e3..f02163f 100644 --- a/packages/GA4Client/test/src/tests.js +++ b/packages/GA4Client/test/src/tests.js @@ -2628,7 +2628,7 @@ describe('Google Analytics 4 Event', function () { done(); }); - it('should merge Consent Setting Defaults with User Consent State to construct a Default Consent State', (done) => { + it('should construct a Default Consent State Payload from Default Settings and construct an Update Consent State Payload from Mappings', (done) => { mParticle.forwarder.init( { conversionId: 'AW-123123123', @@ -2643,9 +2643,20 @@ describe('Google Analytics 4 Event', function () { true ); - var expectedDataLayer = [ + var expectedDataLayer1 = [ 'consent', 'default', + { + ad_personalization: 'granted', // From Consent Settings + ad_user_data: 'granted', // From Consent Settings + ad_storage: 'granted', // From Consent Settings + analytics_storage: 'granted', // From Consent Settings + }, + ]; + + var expectedDataLayer2 = [ + 'consent', + 'update', { ad_personalization: 'denied', // From User Consent State ad_user_data: 'denied', // From User Consent State @@ -2656,10 +2667,13 @@ describe('Google Analytics 4 Event', function () { // Initial elements of Data Layer are setup for gtag. // Consent state should be on the bottom - window.dataLayer.length.should.eql(4); + window.dataLayer.length.should.eql(5); window.dataLayer[3][0].should.equal('consent'); window.dataLayer[3][1].should.equal('default'); - window.dataLayer[3][2].should.deepEqual(expectedDataLayer[2]); + window.dataLayer[3][2].should.deepEqual(expectedDataLayer1[2]); + window.dataLayer[4][0].should.equal('consent'); + window.dataLayer[4][1].should.equal('update'); + window.dataLayer[4][2].should.deepEqual(expectedDataLayer2[2]); done(); }); @@ -2877,7 +2891,18 @@ describe('Google Analytics 4 Event', function () { true ); - var expectedDataLayerBefore = [ + var expectedDataLayerBefore1 = [ + 'consent', + 'default', + { + ad_personalization: 'granted', // From Consent Settings + ad_user_data: 'granted', // From Consent Settings + ad_storage: 'granted', // From Consent Settings + analytics_storage: 'granted', // From Consent Settings + }, + ]; + + var expectedDataLayerBefore2 = [ 'consent', 'update', { @@ -2890,10 +2915,13 @@ describe('Google Analytics 4 Event', function () { // Initial elements of Data Layer are setup for gtag. // Consent state should be on the bottom - window.dataLayer.length.should.eql(4); + window.dataLayer.length.should.eql(5); window.dataLayer[3][0].should.equal('consent'); window.dataLayer[3][1].should.equal('default'); - window.dataLayer[3][2].should.deepEqual(expectedDataLayerBefore[2]); + window.dataLayer[3][2].should.deepEqual(expectedDataLayerBefore1[2]); + window.dataLayer[4][0].should.equal('consent'); + window.dataLayer[4][1].should.equal('update'); + window.dataLayer[4][2].should.deepEqual(expectedDataLayerBefore2[2]); mParticle.forwarder.process({ EventName: 'Homepage', @@ -2950,12 +2978,12 @@ describe('Google Analytics 4 Event', function () { // Initial elements of Data Layer are setup for gtag. // Consent Default is index 3 - // Consent Update is index 4 - // Event is index 5 - window.dataLayer.length.should.eql(6); - window.dataLayer[4][0].should.equal('consent'); - window.dataLayer[4][1].should.equal('update'); - window.dataLayer[4][2].should.deepEqual(expectedDataLayerAfter[2]); + // Consent Update is index 5 + // Event is index 6 + window.dataLayer.length.should.eql(7); + window.dataLayer[5][0].should.equal('consent'); + window.dataLayer[5][1].should.equal('update'); + window.dataLayer[5][2].should.deepEqual(expectedDataLayerAfter[2]); mParticle.forwarder.process({ EventName: 'Homepage', @@ -3022,14 +3050,14 @@ describe('Google Analytics 4 Event', function () { // Initial elements of Data Layer are setup for gtag. // Consent Default is index 3 - // Consent Update is index 4 - // Event is index 5 - // Consent Update #2 is index 6 - // Event #2 is index 7 - window.dataLayer.length.should.eql(8); - window.dataLayer[6][0].should.equal('consent'); - window.dataLayer[6][1].should.equal('update'); - window.dataLayer[6][2].should.deepEqual(expectedDataLayerFinal[2]); + // Consent Update is index 5 + // Event is index 6 + // Consent Update #2 is index 7 + // Event #2 is index 8 + window.dataLayer.length.should.eql(9); + window.dataLayer[7][0].should.equal('consent'); + window.dataLayer[7][1].should.equal('update'); + window.dataLayer[7][2].should.deepEqual(expectedDataLayerFinal[2]); done(); });