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 17a7b15 commit fa9ebf2
Show file tree
Hide file tree
Showing 4 changed files with 820 additions and 35 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
190 changes: 178 additions & 12 deletions src/BingAdsEventForwarder.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,45 +27,83 @@ var MessageType = {
Commerce: 16,
};

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

var constructor = function () {

Check failure on line 36 in src/BingAdsEventForwarder.js

View workflow job for this annotation

GitHub Actions / Run Web Kit PR Workflow / Build and Test

Delete `·`
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) {
(function (window, document, tag, url, queue) {

Check failure on line 78 in src/BingAdsEventForwarder.js

View workflow job for this annotation

GitHub Actions / Run Web Kit PR Workflow / Build and Test

Delete `·`
var f;
var n;
var i;
(window[queue] = window[queue] || []),
(window.uetq = window.uetq || []),
(f = function() {
sendConsentDefaultToBing(consentPayload),
(f = function () {

Check failure on line 85 in src/BingAdsEventForwarder.js

View workflow job for this annotation

GitHub Actions / Run Web Kit PR Workflow / Build and Test

Delete `·`
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),
(n.async = 1),
(n.onload = n.onreadystatechange = function() {
var state = this.readyState;
(state &&
state !== 'loaded' &&
state !== 'complete') ||
(f(), (n.onload = n.onreadystatechange = null));
}),
(n.onload = n.onreadystatechange =

Check failure on line 98 in src/BingAdsEventForwarder.js

View workflow job for this annotation

GitHub Actions / Run Web Kit PR Workflow / Build and Test

Replace `⏎····························function·` with `·function`
function () {
var state = this.readyState;

Check failure on line 100 in src/BingAdsEventForwarder.js

View workflow job for this annotation

GitHub Actions / Run Web Kit PR Workflow / Build and Test

Delete `····`
(state &&

Check failure on line 101 in src/BingAdsEventForwarder.js

View workflow job for this annotation

GitHub Actions / Run Web Kit PR Workflow / Build and Test

Delete `····`
state !== 'loaded' &&

Check failure on line 102 in src/BingAdsEventForwarder.js

View workflow job for this annotation

GitHub Actions / Run Web Kit PR Workflow / Build and Test

Delete `····`
state !== 'complete') ||

Check failure on line 103 in src/BingAdsEventForwarder.js

View workflow job for this annotation

GitHub Actions / Run Web Kit PR Workflow / Build and Test

Replace `····································` with `································`
(f(),

Check failure on line 104 in src/BingAdsEventForwarder.js

View workflow job for this annotation

GitHub Actions / Run Web Kit PR Workflow / Build and Test

Replace `····(f(),⏎···································` with `(f(),`
(n.onload = n.onreadystatechange = null));
}),

Check failure on line 106 in src/BingAdsEventForwarder.js

View workflow job for this annotation

GitHub Actions / Run Web Kit PR Workflow / Build and Test

Delete `····`
(i = document.getElementsByTagName(tag)[0]),
i.parentNode.insertBefore(n, i);
})(window, document, 'script', '//bat.bing.com/bat.js', 'uetq');
Expand All @@ -86,6 +124,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 +167,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 +222,126 @@ 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 +386,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 fa9ebf2

Please sign in to comment.