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] Add GVLID and handle TC Consent data #6283

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
22 changes: 18 additions & 4 deletions modules/parrableIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ import { getStorageManager } from '../src/storageManager.js';

const PARRABLE_URL = 'https://h.parrable.com/prebid';
const PARRABLE_COOKIE_NAME = '_parrable_id';
const PARRABLE_GVLID = 928;
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();
const storage = getStorageManager(PARRABLE_GVLID);

function getExpirationDate() {
const oneYearFromNow = new Date(utils.timestamp() + ONE_YEAR_MS);
Expand Down Expand Up @@ -167,7 +168,7 @@ function shouldFilterImpression(configParams, parrableId) {
return !isAllowed() || isBlocked();
}

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

let parrableId = readCookie();
Expand All @@ -183,6 +184,8 @@ function fetchId(configParams) {
const eid = (parrableId) ? parrableId.eid : null;
const refererInfo = getRefererInfo();
const uspString = uspDataHandler.getConsentData();
const gdprApplies = (gdprConsentData && typeof gdprConsentData.gdprApplies === 'boolean' && gdprConsentData.gdprApplies);
const gdprConsentString = (gdprConsentData && gdprApplies && gdprConsentData.consentString) || '';
Comment on lines +187 to +188
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a tip for future reference, you could have done this in a shorter way.
You could have changed:

typeof gdprConsentData.gdprApplies === 'boolean' && gdprConsentData.gdprApplies

into:

gdprConsentData.gdprApplies === true

Also, for line 188, you don't need to check for gdprConsentData, if that evaluates to false then gdprApplies would be also false. So, for line 188 it's enough just to do:

const gdprConsentString = (gdprApplies && gdprConsentData.consentString) || '';

const partners = configParams.partners || configParams.partner
const trackers = typeof partners === 'string'
? partners.split(',')
Expand All @@ -198,13 +201,18 @@ function fetchId(configParams) {

const searchParams = {
data: encodeBase64UrlSafe(btoa(JSON.stringify(data))),
gdpr: gdprApplies ? 1 : 0,
_rand: Math.random()
};

if (uspString) {
searchParams.us_privacy = uspString;
}

if (gdprApplies) {
searchParams.gdpr_consent = gdprConsentString;
}

const options = {
method: 'GET',
withCredentials: true
Expand Down Expand Up @@ -251,7 +259,7 @@ function fetchId(configParams) {
callback,
id: parrableId
};
};
}

/** @type {Submodule} */
export const parrableIdSubmodule = {
Expand All @@ -260,6 +268,12 @@ export const parrableIdSubmodule = {
* @type {string}
*/
name: 'parrableId',
/**
* Global Vendor List ID
* @type {number}
*/
gvlid: PARRABLE_GVLID,

/**
* decode the stored id value for passing to bid requests
* @function
Expand All @@ -282,7 +296,7 @@ export const parrableIdSubmodule = {
*/
getId(config, gdprConsentData, currentStoredId) {
const configParams = (config && config.params) || {};
return fetchId(configParams);
return fetchId(configParams, gdprConsentData);
}
};

Expand Down
32 changes: 32 additions & 0 deletions test/spec/modules/parrableIdSystem_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,38 @@ describe('Parrable ID System', function() {
removeParrableCookie();
});
});

describe('GDPR consent', () => {
let callbackSpy = sinon.spy();

const config = {
params: {
partner: 'partner'
}
};

const gdprConsentTestCases = [
{ consentData: { gdprApplies: true, consentString: 'expectedConsentString' }, expected: { gdpr: 1, gdpr_consent: 'expectedConsentString' } },
{ consentData: { gdprApplies: false, consentString: 'expectedConsentString' }, expected: { gdpr: 0 } },
{ consentData: { gdprApplies: true, consentString: undefined }, expected: { gdpr: 1, gdpr_consent: '' } },
{ consentData: { gdprApplies: 'yes', consentString: 'expectedConsentString' }, expected: { gdpr: 0 } },
{ consentData: undefined, expected: { gdpr: 0 } }
];

gdprConsentTestCases.forEach((testCase, index) => {
it(`should call user sync url with the gdprConsent - case ${index}`, () => {
parrableIdSubmodule.getId(config, testCase.consentData).callback(callbackSpy);

if (testCase.expected.gdpr === 1) {
expect(server.requests[0].url).to.contain('gdpr=' + testCase.expected.gdpr);
expect(server.requests[0].url).to.contain('gdpr_consent=' + testCase.expected.gdpr_consent);
} else {
expect(server.requests[0].url).to.contain('gdpr=' + testCase.expected.gdpr);
expect(server.requests[0].url).to.not.contain('gdpr_consent');
}
})
});
});
});

describe('parrableIdSystem.decode()', function() {
Expand Down