Skip to content

Commit

Permalink
Prebid Core: Adding support for a global return of consent metadata. (#…
Browse files Browse the repository at this point in the history
…8043)

* Adding support for a global return of consent metadata with light test coverage.

* removing duplicate test

* updates for code consistency, timestamp naming

* move tcstring check down, return a zero if not a string

* forgot util import!
  • Loading branch information
decaffeinatedio authored Feb 22, 2022
1 parent 3e55124 commit 334e32f
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 3 deletions.
29 changes: 26 additions & 3 deletions src/adapterManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import {
logMessage,
logWarn,
shuffle,
timestamp
timestamp,
isStr
} from './utils.js';
import { getLabels, resolveStatus } from './sizeMapping.js';
import { decorateAdUnitsWithNativeParams, nativeAdapters } from './native.js';
Expand Down Expand Up @@ -173,21 +174,43 @@ function getAdUnitCopyForClientAdapters(adUnits) {

export let gdprDataHandler = {
consentData: null,
setConsentData: function(consentInfo) {
generatedTime: null,
setConsentData: function(consentInfo, time = timestamp()) {
gdprDataHandler.consentData = consentInfo;
gdprDataHandler.generatedTime = time;
},
getConsentData: function() {
return gdprDataHandler.consentData;
},
getConsentMeta: function() {
if (gdprDataHandler.consentData && gdprDataHandler.consentData.vendorData && gdprDataHandler.generatedTime) {
return {
gdprApplies: gdprDataHandler.consentData.gdprApplies,
consentStringSize: (isStr(gdprDataHandler.consentData.vendorData.tcString)) ? gdprDataHandler.consentData.vendorData.tcString.length : 0,
generatedAt: gdprDataHandler.generatedTime,
apiVersion: gdprDataHandler.consentData.apiVersion
};
}
}
};

export let uspDataHandler = {
consentData: null,
setConsentData: function(consentInfo) {
generatedTime: null,
setConsentData: function(consentInfo, time = timestamp()) {
uspDataHandler.consentData = consentInfo;
uspDataHandler.generatedTime = time;
},
getConsentData: function() {
return uspDataHandler.consentData;
},
getConsentMeta: function() {
if (uspDataHandler.consentData && uspDataHandler.generatedTime) {
return {
usp: uspDataHandler.consentData,
generatedAt: uspDataHandler.generatedTime
}
}
}
};

Expand Down
19 changes: 19 additions & 0 deletions src/prebid.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { executeRenderer, isRendererRequired } from './Renderer.js';
import { createBid } from './bidfactory.js';
import { storageCallbacks } from './storageManager.js';
import { emitAdRenderSucceeded, emitAdRenderFail } from './adRendering.js';
import { gdprDataHandler, uspDataHandler } from './adapterManager.js'

const $$PREBID_GLOBAL$$ = getGlobal();
const CONSTANTS = require('./constants.json');
Expand Down Expand Up @@ -268,6 +269,24 @@ $$PREBID_GLOBAL$$.getAdserverTargeting = function (adUnitCode) {
return targeting.getAllTargeting(adUnitCode);
};

/**
* returns all consent data
* @return {Object} Map of consent types and data
* @alias module:pbjs.getConsentData
*/
function getConsentMetadata() {
return {
gdpr: gdprDataHandler.getConsentMeta(),
usp: uspDataHandler.getConsentMeta(),
coppa: !!(config.getConfig('coppa'))
}
}

$$PREBID_GLOBAL$$.getConsentMetadata = function () {
logInfo('Invoking $$PREBID_GLOBAL$$.getConsentMetadata');
return getConsentMetadata();
};

function getBids(type) {
const responses = auctionManager[type]()
.filter(bind.call(adUnitsFilter, this, auctionManager.getAdUnitCodes()));
Expand Down
27 changes: 27 additions & 0 deletions test/spec/modules/consentManagementUsp_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ describe('consentManagement', function () {
sinon.assert.notCalled(utils.logInfo);
});

it('should not produce any USP metadata', function() {
setConsentConfig({});
let consentMeta = uspDataHandler.getConsentMeta();
expect(consentMeta).to.be.undefined;
});

it('should exit the consent manager if only config.gdpr is an object', function() {
setConsentConfig({ gdpr: { cmpApi: 'iab' } });
expect(consentAPI).to.be.undefined;
Expand Down Expand Up @@ -366,6 +372,27 @@ describe('consentManagement', function () {
expect(didHookReturn).to.be.true;
expect(consent).to.equal(testConsentData.uspString);
});

it('returns USP consent metadata', function () {
let testConsentData = {
uspString: '1NY'
};

uspapiStub = sinon.stub(window, '__uspapi').callsFake((...args) => {
args[2](testConsentData, true);
});

setConsentConfig(goodConfig);
requestBidsHook(() => { didHookReturn = true; }, {});

let consentMeta = uspDataHandler.getConsentMeta();

sinon.assert.notCalled(utils.logWarn);
sinon.assert.notCalled(utils.logError);

expect(consentMeta.usp).to.equal(testConsentData.uspString);
expect(consentMeta.generatedAt).to.be.above(1644367751709);
});
});
});
});
34 changes: 34 additions & 0 deletions test/spec/modules/consentManagement_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ describe('consentManagement', function () {
expect(userCMP).to.be.undefined;
sinon.assert.calledOnce(utils.logWarn);
});

it('should not produce any consent metadata', function() {
setConsentConfig(undefined)
let consentMetadata = gdprDataHandler.getConsentMeta();
expect(consentMetadata).to.be.undefined;
sinon.assert.calledOnce(utils.logWarn);
})
});

describe('valid setConsentConfig value', function () {
Expand Down Expand Up @@ -667,6 +674,33 @@ describe('consentManagement', function () {
expect(consent.apiVersion).to.equal(2);
});

it('produces gdpr metadata', function () {
let testConsentData = {
tcString: 'abc12345234',
gdprApplies: true,
purposeOneTreatment: false,
eventStatus: 'tcloaded',
vendorData: {
tcString: 'abc12345234'
}
};
cmpStub = sinon.stub(window, '__tcfapi').callsFake((...args) => {
args[2](testConsentData, true);
});

setConsentConfig(goodConfigWithAllowAuction);

requestBidsHook(() => {
didHookReturn = true;
}, {});
let consentMeta = gdprDataHandler.getConsentMeta();
sinon.assert.notCalled(utils.logError);
expect(consentMeta.consentStringSize).to.be.above(0)
expect(consentMeta.gdprApplies).to.be.true;
expect(consentMeta.apiVersion).to.equal(2);
expect(consentMeta.generatedAt).to.be.above(1644367751709);
});

it('performs lookup check and stores consentData for a valid existing user with additional consent', function () {
let testConsentData = {
tcString: 'abc12345234',
Expand Down

0 comments on commit 334e32f

Please sign in to comment.