mk9-prebid
Version:
Header Bidding Management Library
142 lines (122 loc) • 4.58 kB
JavaScript
/**
* This module adds Criteo Real Time User Sync to the User ID module
* The {@link module:modules/userId} module is required
* @module modules/criteoIdSystem
* @requires module:modules/userId
*/
import * as utils from '../src/utils.js'
import * as ajax from '../src/ajax.js'
import { getRefererInfo } from '../src/refererDetection.js'
import { submodule } from '../src/hook.js';
import { getStorageManager } from '../src/storageManager.js';
const gvlid = 91;
const bidderCode = 'criteo';
export const storage = getStorageManager(gvlid, bidderCode);
const bididStorageKey = 'cto_bidid';
const bundleStorageKey = 'cto_bundle';
const cookiesMaxAge = 13 * 30 * 24 * 60 * 60 * 1000;
const pastDateString = new Date(0).toString();
const expirationString = new Date(utils.timestamp() + cookiesMaxAge).toString();
function extractProtocolHost (url, returnOnlyHost = false) {
const parsedUrl = utils.parseUrl(url, {noDecodeWholeURL: true})
return returnOnlyHost
? `${parsedUrl.hostname}`
: `${parsedUrl.protocol}://${parsedUrl.hostname}${parsedUrl.port ? ':' + parsedUrl.port : ''}/`;
}
function getFromAllStorages(key) {
return storage.getCookie(key) || storage.getDataFromLocalStorage(key);
}
function saveOnAllStorages(key, value) {
if (key && value) {
storage.setCookie(key, value, expirationString);
storage.setDataInLocalStorage(key, value);
}
}
function deleteFromAllStorages(key) {
storage.setCookie(key, '', pastDateString);
storage.removeDataFromLocalStorage(key);
}
function getCriteoDataFromAllStorages() {
return {
bundle: getFromAllStorages(bundleStorageKey),
bidId: getFromAllStorages(bididStorageKey),
}
}
function buildCriteoUsersyncUrl(topUrl, domain, bundle, areCookiesWriteable, isLocalStorageWritable, isPublishertagPresent, gdprString) {
const url = 'https://gum.criteo.com/sid/json?origin=prebid' +
`${topUrl ? '&topUrl=' + encodeURIComponent(topUrl) : ''}` +
`${domain ? '&domain=' + encodeURIComponent(domain) : ''}` +
`${bundle ? '&bundle=' + encodeURIComponent(bundle) : ''}` +
`${gdprString ? '&gdprString=' + encodeURIComponent(gdprString) : ''}` +
`${areCookiesWriteable ? '&cw=1' : ''}` +
`${isPublishertagPresent ? '&pbt=1' : ''}` +
`${isLocalStorageWritable ? '&lsw=1' : ''}`;
return url;
}
function callCriteoUserSync(parsedCriteoData, gdprString) {
const cw = storage.cookiesAreEnabled();
const lsw = storage.localStorageIsEnabled();
const topUrl = extractProtocolHost(getRefererInfo().referer);
const domain = extractProtocolHost(document.location.href, true);
const isPublishertagPresent = typeof criteo_pubtag !== 'undefined'; // eslint-disable-line camelcase
const url = buildCriteoUsersyncUrl(
topUrl,
domain,
parsedCriteoData.bundle,
cw,
lsw,
isPublishertagPresent,
gdprString
);
ajax.ajaxBuilder()(
url,
response => {
const jsonResponse = JSON.parse(response);
if (jsonResponse.bidId) {
saveOnAllStorages(bididStorageKey, jsonResponse.bidId);
} else {
deleteFromAllStorages(bididStorageKey);
}
if (jsonResponse.acwsUrl) {
const urlsToCall = typeof jsonResponse.acwsUrl === 'string' ? [jsonResponse.acwsUrl] : jsonResponse.acwsUrl;
urlsToCall.forEach(url => utils.triggerPixel(url));
} else if (jsonResponse.bundle) {
saveOnAllStorages(bundleStorageKey, jsonResponse.bundle);
}
},
undefined,
{ method: 'GET', contentType: 'application/json', withCredentials: true }
);
}
/** @type {Submodule} */
export const criteoIdSubmodule = {
/**
* used to link submodule with config
* @type {string}
*/
name: bidderCode,
gvlid: gvlid,
/**
* decode the stored id value for passing to bid requests
* @function
* @returns {{criteoId: string} | undefined}
*/
decode(bidId) {
return bidId;
},
/**
* get the Criteo Id from local storages and initiate a new user sync
* @function
* @param {SubmoduleConfig} [config]
* @param {ConsentData} [consentData]
* @returns {{id: {criteoId: string} | undefined}}}
*/
getId(config, consentData) {
const hasGdprData = consentData && typeof consentData.gdprApplies === 'boolean' && consentData.gdprApplies;
const gdprConsentString = hasGdprData ? consentData.consentString : undefined;
let localData = getCriteoDataFromAllStorages();
callCriteoUserSync(localData, gdprConsentString);
return { id: localData.bidId ? { criteoId: localData.bidId } : undefined }
}
};
submodule('userId', criteoIdSubmodule);