Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

parrableIdSystem: Read legacy ID and optout cookies and migrate to new cookie storage implementation #5219

Merged
merged 31 commits into from
Jun 8, 2020
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
0540240
Add unit coverage for parrableIdSystem getId callback
icflournoy Apr 28, 2020
4af9a6f
PBID-14: Pass uspString to Parrable as us_privacy query parameter
icflournoy Apr 29, 2020
8c84fa3
Merge pull request #6 from Parrable/parrableIdSystem/better-unit-tests
icflournoy Apr 29, 2020
11b457b
PBID-14: Simplify parrableIdSystem us_privacy test
icflournoy Apr 30, 2020
914503e
PBID-14: Only send us_privacy to Parrable when a value exists
icflournoy Apr 30, 2020
82dba43
Merge pull request #7 from Parrable/parrableIdSystem/us-privacy
icflournoy May 1, 2020
1e2ee99
Merge remote-tracking branch 'upstream/master' into parrableIdSystem/…
icflournoy May 5, 2020
98835fa
PBID-11: Read new Parrable compound cookie _parrable_id
icflournoy May 5, 2020
43724a3
Remove path check from parrableIdSystem url test
icflournoy May 5, 2020
e88c929
PBID-11: Integrate Parrable compound cookie, consolidating old cookies
icflournoy May 7, 2020
1286adc
PBID-11: Update parrableIdSystem requestBids hook test to support com…
icflournoy May 7, 2020
2be1fb3
PBID-11: Small refactor to parrableIdSystem spec to support compound …
icflournoy May 7, 2020
a9d67ee
PBID-11: Handle legacy ibaOptout as truthy value when migrating to co…
icflournoy May 7, 2020
b71f7fd
PBID-11: Add parrableIdSystem spec tests covering migration of legacy…
icflournoy May 7, 2020
742e3d9
PBID-11: Remove storage documentation from test pages and userId modu…
icflournoy May 7, 2020
16dd083
PBID-11: Remove SUBMODULES_THAT_ALWAYS_REFRESH_ID feature from userId…
icflournoy May 7, 2020
2f80f58
Merge branch 'parrableIdSystem/base' into parrableIdSystem/PBID-11
icflournoy May 7, 2020
7bf438b
PBID-11: Use better serialize implementation for Parrable compound co…
icflournoy May 8, 2020
527303e
PBID-11: Update parrableIdSystem interface documentation
icflournoy May 8, 2020
8f717da
Add missing extension to mock xhr import
icflournoy May 11, 2020
af77318
Merge remote-tracking branch 'origin/parrableIdSystem/base' into parr…
icflournoy May 11, 2020
5d972c0
Merge pull request #9 from Parrable/parrableIdSystem/PBID-11
icflournoy May 12, 2020
39a7ad4
Merge remote-tracking branch 'upstream/master' into parrableIdSystem/…
icflournoy May 12, 2020
6ba511b
PBID-11: Try to access eid property only when parrableId object exists
icflournoy May 13, 2020
8e084ab
PBID-11: Construct parrableId from legacy cookies in same manner as c…
icflournoy May 13, 2020
e34e55f
Use hardcoded expiration date for legacy cookies
icflournoy May 13, 2020
253a8ec
Merge remote-tracking branch 'origin/master' into parrableIdSystem/base
icflournoy May 15, 2020
2486d2d
Merge remote-tracking branch 'upstream/master' into parrableIdSystem/…
icflournoy May 18, 2020
373075f
parrableIdSystem: Relocate new unit test from upstream
icflournoy May 18, 2020
df73ab9
PBID-39: Fallback to cookie values when backend response is missing c…
icflournoy May 19, 2020
50dc9ef
Merge remote-tracking branch 'upstream/master' into parrableIdSystem/…
icflournoy May 26, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions integrationExamples/gpt/audigentSegments_example.html
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,6 @@
params: {
// change to Parrable Partner Client ID(s) you received from the Parrable Partners you are using
partner: '30182847-e426-4ff9-b2b5-9ca1324ea09b'
},
storage: {
type: "cookie",
name: "_parrable_eid", // create a cookie with this name
expires: 365 // cookie can last for a year
}
}, {
name: "pubCommonId",
Expand Down
5 changes: 0 additions & 5 deletions integrationExamples/gpt/userId_example.html
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,6 @@
params: {
// change to Parrable Partner Client ID(s) you received from the Parrable Partners you are using
partner: '30182847-e426-4ff9-b2b5-9ca1324ea09b'
},
storage: {
type: "cookie",
name: "_parrable_eid", // create a cookie with this name
expires: 365 // cookie can last for a year
}
}, {
name: "pubCommonId",
Expand Down
131 changes: 120 additions & 11 deletions modules/parrableIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,50 @@ import { ajax } from '../src/ajax.js';
import { submodule } from '../src/hook.js';
import { getRefererInfo } from '../src/refererDetection.js';
import { uspDataHandler } from '../src/adapterManager.js';
import { getStorageManager } from '../src/storageManager.js';

const PARRABLE_URL = 'https://h.parrable.com/prebid';
const PARRABLE_COOKIE_NAME = '_parrable_id';
const LEGACY_ID_COOKIE_NAME = '_parrable_eid';
const LEGACY_OPTOUT_COOKIE_NAME = '_parrable_optout';
const ONE_YEAR_MS = 364 * 24 * 60 * 60 * 1000;
const EXPIRE_COOKIE_DATE = 'Thu, 01 Jan 1970 00:00:00 GMT';

const storage = getStorageManager();

function getExpirationDate() {
const oneYearFromNow = new Date(utils.timestamp() + ONE_YEAR_MS);
return oneYearFromNow.toGMTString();
}

function deserializeParrableId(parrableIdStr) {
const parrableId = {};
const values = parrableIdStr.split(',');

values.forEach(function(value) {
const pair = value.split(':');
// unpack a value of 1 as true
parrableId[pair[0]] = +pair[1] === 1 ? true : pair[1];
});

return parrableId;
}

function serializeParrableId(parrableId) {
let components = [];

if (parrableId.eid) {
components.push('eid:' + parrableId.eid);
}
if (parrableId.ibaOptout) {
components.push('ibaOptout:1');
}
if (parrableId.ccpaOptout) {
components.push('ccpaOptout:1');
}

return components.join(',');
}

function isValidConfig(configParams) {
if (!configParams) {
Expand All @@ -22,17 +64,68 @@ function isValidConfig(configParams) {
utils.logError('User ID - parrableId submodule requires partner list');
return false;
}
if (configParams.storage) {
utils.logWarn('User ID - parrableId submodule does not require a storage config');
}
return true;
}

function fetchId(configParams, currentStoredId) {
function readCookie() {
const parrableIdStr = storage.getCookie(PARRABLE_COOKIE_NAME);
if (parrableIdStr) {
return deserializeParrableId(decodeURIComponent(parrableIdStr));
}
return null;
}

function writeCookie(parrableId) {
if (parrableId) {
const parrableIdStr = encodeURIComponent(serializeParrableId(parrableId));
storage.setCookie(PARRABLE_COOKIE_NAME, parrableIdStr, getExpirationDate(), 'lax');
}
}

function readLegacyCookies() {
const eid = storage.getCookie(LEGACY_ID_COOKIE_NAME);
const ibaOptout = (storage.getCookie(LEGACY_OPTOUT_COOKIE_NAME) === 'true');
if (eid || ibaOptout) {
const parrableId = {};
if (eid) {
parrableId.eid = eid;
}
if (ibaOptout) {
parrableId.ibaOptout = ibaOptout;
}
return parrableId;
}
return null;
}

function migrateLegacyCookies(parrableId) {
writeCookie(parrableId);
if (parrableId.eid) {
storage.setCookie(LEGACY_ID_COOKIE_NAME, '', EXPIRE_COOKIE_DATE);
}
if (parrableId.ibaOptout) {
storage.setCookie(LEGACY_OPTOUT_COOKIE_NAME, '', EXPIRE_COOKIE_DATE);
}
}

function fetchId(configParams) {
if (!isValidConfig(configParams)) return;

let parrableId = readCookie();
if (!parrableId) {
parrableId = readLegacyCookies();
migrateLegacyCookies(parrableId);
}

const eid = (parrableId) ? parrableId.eid : null;
const refererInfo = getRefererInfo();
const uspString = uspDataHandler.getConsentData();

const data = {
eid: currentStoredId || null,
eid,
trackers: configParams.partner.split(','),
url: refererInfo.referer
};
Expand All @@ -53,21 +146,34 @@ function fetchId(configParams, currentStoredId) {

const callback = function (cb) {
const onSuccess = (response) => {
let eid;
let parrableId = {};
if (response) {
try {
let responseObj = JSON.parse(response);
eid = responseObj ? responseObj.eid : undefined;
if (responseObj) {
if (responseObj.ccpaOptout !== true) {
parrableId.eid = responseObj.eid;
} else {
parrableId.ccpaOptout = true;
}
if (responseObj.ibaOptout === true) {
parrableId.ibaOptout = true;
}
writeCookie(responseObj);
}
} catch (error) {
utils.logError(error);
}
}
cb(eid);
cb(parrableId);
};
ajax(PARRABLE_URL, onSuccess, searchParams, options);
};

return { callback };
return {
callback,
id: parrableId
};
};

/** @type {Submodule} */
Expand All @@ -80,22 +186,25 @@ export const parrableIdSubmodule = {
/**
* decode the stored id value for passing to bid requests
* @function
* @param {Object|string} value
* @param {ParrableId} parrableId
* @return {(Object|undefined}
*/
decode(value) {
return (value && typeof value === 'string') ? { 'parrableid': value } : undefined;
decode(parrableId) {
if (parrableId && utils.isPlainObject(parrableId)) {
return { 'parrableid': parrableId.eid };
}
return undefined;
},

/**
* performs action to obtain id and return a value in the callback's response argument
* @function
* @param {SubmoduleParams} [configParams]
* @param {ConsentData} [consentData]
* @returns {function(callback:function)}
* @returns {function(callback:function), id:ParrableId}
*/
getId(configParams, gdprConsentData, currentStoredId) {
return fetchId(configParams, currentStoredId);
return fetchId(configParams);
}
};

Expand Down
4 changes: 0 additions & 4 deletions modules/userId/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -426,10 +426,6 @@ function initSubmodules(submodules, consentData) {
refreshNeeded = storedDate && (Date.now() - storedDate.getTime() > submodule.config.storage.refreshInSeconds * 1000);
}

if (CONSTANTS.SUBMODULES_THAT_ALWAYS_REFRESH_ID[submodule.config.name] === true) {
refreshNeeded = true;
}

if (!storedId || refreshNeeded) {
// No previously saved id. Request one from submodule.
response = submodule.submodule.getId(submodule.config.params, consentData, storedId);
Expand Down
5 changes: 0 additions & 5 deletions modules/userId/userId.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,6 @@ pbjs.setConfig({
params: {
// Replace partner with comma-separated (if more than one) Parrable Partner Client ID(s) for Parrable-aware bid adapters in use
partner: "30182847-e426-4ff9-b2b5-9ca1324ea09b"
},
storage: {
type: 'cookie',
name: '_parrable_eid',
expires: 365
}
}, {
name: 'identityLink',
Expand Down
3 changes: 0 additions & 3 deletions src/constants.json
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,5 @@
"BID_TARGETING_SET": "targetingSet",
"RENDERED": "rendered",
"BID_REJECTED": "bidRejected"
},
"SUBMODULES_THAT_ALWAYS_REFRESH_ID": {
"parrableId": true
}
}
Loading