Skip to content

Commit

Permalink
feat: Add support for Consent State
Browse files Browse the repository at this point in the history
  • Loading branch information
alexs-mparticle committed Sep 23, 2024
1 parent 3e4d042 commit 4c4fc48
Show file tree
Hide file tree
Showing 4 changed files with 807 additions and 25 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"before": true,
"beforeEach": true,
"after": true,
"afterEach": true,
"uetq": true,
"UET": true
},
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"lint:fix": "eslint src/ test/src/ --fix",
"test": "npm run build && npm run build:test && DEBUG=false karma start test/karma.config.js",
"test:debug": "npm run build && npm run build:test && DEBUG=true karma start test/karma.config.js",
"watch": "ENVIRONMENT=production rollup --config rollup.config.js -w"
"watch": "ENVIRONMENT=production rollup --config rollup.config.js -w",
"watch:tests": "ENVIRONMENT=production rollup --config rollup.test.config.js -w"

},
"devDependencies": {
"@semantic-release/changelog": "^5.0.1",
Expand Down
167 changes: 165 additions & 2 deletions src/BingAdsEventForwarder.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,52 @@ var MessageType = {
Commerce: 16,
};

var bingConsentValues = { Denied: 'denied', Granted: 'granted' };
var bingConsentProperties = ['ad_storage'];
var bingToMpConsentSettingsMapping = {
ad_storage: 'defaultAdStorageConsentSDK',
};

var constructor = function() {
var self = this;
var isInitialized = false;
var forwarderSettings = null;
var reportingService = null;

self.consentMappings = [];
self.consentPayloadAsString = '';
self.consentPayloadDefaults = {};

self.name = name;

function initForwarder(settings, service, testMode) {
console.warn('BING Local DEV');

forwarderSettings = settings;
reportingService = service;

if (forwarderSettings.consentMapingWeb) {
self.consentMappings = parseSettingsString(
forwarderSettings.consentMapingWeb
);
}
self.consentPayloadDefaults = getConsentSettings(forwarderSettings);

var initialConsentPayload = cloneObject(self.consentPayloadDefaults);
var userConsentState = getUserConsentState();

var updatedConsentPayload = generateConsentPayload(
userConsentState,
self.consentMappings
);

var consentPayload;
if (!isEmpty(initialConsentPayload)) {
consentPayload = initialConsentPayload;
} else if (!isEmpty(updatedConsentPayload)) {
consentPayload = updatedConsentPayload;
}

try {
if (!testMode) {
(function(window, document, tag, url, queue) {
Expand All @@ -47,14 +81,16 @@ var constructor = function() {
var i;
(window[queue] = window[queue] || []),
(window.uetq = window.uetq || []),
sendConsentDefaultToBing(consentPayload),
(f = function() {
var obj = {
ti: forwarderSettings.tagId,
q: window.uetq,
};
(obj.q = window[queue]),
(window[queue] = new UET(obj)),
window[queue].push('pageLoad');
maybeSendConsentUpdateToBing(consentPayload);
window[queue].push('pageLoad');
}),
(n = document.createElement(tag)),
(n.src = url),
Expand Down Expand Up @@ -86,6 +122,7 @@ var constructor = function() {
isInitialized = true;
return 'Successfully initialized: ' + name;
} catch (e) {
console.log('error?');
return "Can't initialize forwarder: " + name + ': ' + e;
}
}
Expand Down Expand Up @@ -128,10 +165,13 @@ var constructor = function() {
"Can't log event on forwarder: " + name + ', not initialized'
);
}

try {
var obj = createUetObject(event, 'pageLoad');

var eventConsentState = getEventConsentState(event.ConsentState);

maybeSendConsentUpdateToBing(eventConsentState);

window.uetq.push(obj);
} catch (e) {
return "Can't log event on forwarder: " + name + ': ' + e;
Expand Down Expand Up @@ -180,10 +220,125 @@ var constructor = function() {
return obj;
}

function getEventConsentState(eventConsentState) {
return eventConsentState && eventConsentState.getGDPRConsentState
? eventConsentState.getGDPRConsentState()
: {};
}

function generateConsentPayload(consentState, mappings) {
if (!mappings) {
return {};
}

var payload = cloneObject(self.consentPayloadDefaults);
if (mappings && mappings.length > 0) {
for (var i = 0; i < mappings.length; i++) {
var mappingEntry = mappings[i];
var mpMappedConsentName = mappingEntry.map.toLowerCase();
var bingMappedConsentName = mappingEntry.value;

if (
consentState[mpMappedConsentName] &&
bingConsentProperties.indexOf(bingMappedConsentName) !== -1
) {
payload[bingMappedConsentName] = consentState[
mpMappedConsentName
].Consented
? bingConsentValues.Granted
: bingConsentValues.Denied;
}
}
}

return payload;
}

function maybeSendConsentUpdateToBing(consentState) {
// If consent payload is empty,
// we never sent an initial default consent state
// so we shouldn't send an update.
if (
self.consentPayloadAsString &&
self.consentMappings &&
!isEmpty(consentState)
) {
var updatedConsentPayload = generateConsentPayload(
consentState,
self.consentMappings
);

var eventConsentAsString = JSON.stringify(updatedConsentPayload);

if (eventConsentAsString !== self.consentPayloadAsString) {
window.uetq.push('consent', 'update', updatedConsentPayload);
self.consentPayloadAsString = JSON.stringify(
updatedConsentPayload
);
}
}
}

function sendConsentDefaultToBing(consentPayload) {
self.consentPayloadAsString = JSON.stringify(consentPayload);

window.uetq.push('consent', 'default', consentPayload);
}

this.init = initForwarder;
this.process = processEvent;
};

function getUserConsentState() {
var userConsentState = {};

if (mParticle.Identity && mParticle.Identity.getCurrentUser) {
var currentUser = mParticle.Identity.getCurrentUser();

if (!currentUser) {
return {};
}

var consentState = mParticle.Identity.getCurrentUser().getConsentState();

if (consentState && consentState.getGDPRConsentState) {
userConsentState = consentState.getGDPRConsentState();
}
}

return userConsentState;
}

function getConsentSettings(settings) {
var consentSettings = {};

Object.keys(bingToMpConsentSettingsMapping).forEach(function(
bingConsentKey
) {
var mpConsentSettingKey =
bingToMpConsentSettingsMapping[bingConsentKey];
var bingConsentValuesKey = settings[mpConsentSettingKey];

// Microsoft recommends that for most countries, we should default to 'Granted'
// if a default value is not provided
if (bingConsentValuesKey && mpConsentSettingKey) {
consentSettings[bingConsentKey] = bingConsentValues[
bingConsentValuesKey
]
? bingConsentValues[bingConsentValuesKey]
: bingConsentValues.Granted;
} else {
consentSettings[bingConsentKey] = bingConsentValues.Granted;
}
});

return consentSettings;
}

function parseSettingsString(settingsString) {
return JSON.parse(settingsString.replace(/&quot;/g, '"'));
}

function getId() {
return moduleId;
}
Expand Down Expand Up @@ -228,6 +383,14 @@ if (typeof window !== 'undefined') {
}
}

function isEmpty(value) {
return value == null || !(Object.keys(value) || value).length;
}

function cloneObject(obj) {
return JSON.parse(JSON.stringify(obj));
}

module.exports = {
register: register,
};
Loading

0 comments on commit 4c4fc48

Please sign in to comment.