Skip to content

Commit

Permalink
prebid#4674 Addition of DigiTrust vendor check for gdpr when cmp is p…
Browse files Browse the repository at this point in the history
…resent.
  • Loading branch information
goosemanjack committed Jan 7, 2020
1 parent 927d36e commit 69a33f8
Show file tree
Hide file tree
Showing 5 changed files with 337 additions and 3 deletions.
25 changes: 25 additions & 0 deletions integrationExamples/gpt/cmp_files/purposes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"version": 1,
"purposes": [
{
"id": 25,
"name": "Custom Purpose 1",
"description": "Here's a description of the first purpose"
},
{
"id": 26,
"name": "Custom Purpose 2",
"description": "Here's a description of the second purpose"
},
{
"id": 27,
"name": "Custom Purpose 3",
"description": "Here's a description of the third purpose"
},
{
"id": 28,
"name": "Custom Purpose 4",
"description": "Here's a description of the fourth purpose"
}
]
}
1 change: 1 addition & 0 deletions integrationExamples/gpt/digitrust_Simple.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
{
code: 'test-div',
sizes: [[300, 250], [300, 600], [728, 90]],
mediaTypes: { banner: { sizes: [400, 600], name: 'testAdUnit'}},
bids: [
{
bidder: 'rubicon',
Expand Down
192 changes: 192 additions & 0 deletions integrationExamples/gpt/digitrust_cmp_test.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
<html>
<head>
<title>CMP Simple DigiTrust Prebid - No Framework</title>
<script>
(function (window) {
window.__cmp = (function () {
window.addEventListener('message', function (event) {
window.__cmp.receiveMessage(event);
});

var commandQueue = [];
var cmp = function (command, parameter, callback) {
commandQueue.push({
command: command,
parameter: parameter,
callback: callback
});
};
cmp.commandQueue = commandQueue;
cmp.receiveMessage = function (event) {
var data = event && event.data && event.data.__cmpCall;
if (data) {
commandQueue.push({
callId: data.callId,
command: data.command,
parameter: data.parameter,
event: event
});
}
};
cmp.config = {
customPurposeListLocation: './cmp_files/purposes.json',
globalVendorListLocation: 'https://vendorlist.consensu.org/vendorlist.json',
globalConsentLocation: 'http://cmp-origin-release.digitru.st/1/docs/portal.html',
storeConsentGlobally: false,
storePublisherConsentGlobally: false,
storePublisherData: true,
layout: 'footer',
logging: "debug",
blockBrowsing: false,
forceLocale: 'en',
testingMode: 'always show',
showFooterAfterSubmit: true,
};
return cmp;
}());
})(window);

window.__cmp('renderCmpIfNeeded');
</script>

<script>
var FAILSAFE_TIMEOUT = 2000;

var adUnits = [
{
code: 'test-div',
sizes: [[300, 250], [300, 600], [728, 90]],
mediaTypes: { banner: { sizes: [400, 600], name: 'testAdUnit' } },
bids: [
{
bidder: 'rubicon',
params: {
accountId: '1001',
siteId: '113932',
zoneId: '535510'
}
}
]
}
];

var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];
</script>
<script src="../../build/dev/prebid.js" async></script>

<script>
var googletag = googletag || {};
googletag.cmd = googletag.cmd || [];
googletag.cmd.push(function () {
googletag.pubads().disableInitialLoad();
});

pbjs.que.push(function () {
pbjs.setConfig({
debug: true,
consentManagement: {
cmpApi: 'iab',
timeout: 1000,
allowAuctionWithoutConsent: true
},
usersync: {
userIds: [{
name: "digitrust",
params: {
init: {
member: 'example_member_id',
site: 'example_site_id'
},
callback: function (digiTrustResult) {
// This callback can be used by publisher page to react to error conditions
// Or pass the DigiTrust ID on.
// If the Prebid userId system already has a managed copy of the DigiTrust ID
// this callback will not be invoked.
var elem = document.getElementById('idDiv');
var msg;
if (digiTrustResult.success) {
console.log('Success in Digitrust init');
if (digiTrustResult.identity && digiTrustResult.identity.id != null) {
msg = 'DigiTrust Id (encrypted): ' + digiTrustResult.identity.id;
elem.innerHTML = msg;
console.log(msg);
}
else {
console.error('Digitrust gave success, but no identity returned');
}
}
else {
console.error('Digitrust init failed');
}
}
},
storage: {
type: "html5",
name: "pbjsdigitrust",
expires: 60
}
}]
}
});
pbjs.addAdUnits(adUnits);
pbjs.requestBids({
bidsBackHandler: sendAdserverRequest
});
});

function sendAdserverRequest() {
if (pbjs.adserverRequestSent) return;
pbjs.adserverRequestSent = true;
googletag.cmd.push(function () {
pbjs.que.push(function () {
pbjs.setTargetingForGPTAsync();
googletag.pubads().refresh();
});
});
}

setTimeout(function () {
sendAdserverRequest();
}, FAILSAFE_TIMEOUT);
</script>

<script>
(function () {
var gads = document.createElement('script');
gads.async = true;
gads.type = 'text/javascript';
var useSSL = 'https:' == document.location.protocol;
gads.src = (useSSL ? 'https:' : 'http:') +
'//www.googletagservices.com/tag/js/gpt.js';
var node = document.getElementsByTagName('script')[0];
node.parentNode.insertBefore(gads, node);
})();
</script>

<script>
googletag.cmd.push(function () {
googletag.defineSlot('/112115922/FL_PB_MedRect', [[300, 250], [300, 600]], 'test-div').addService(googletag.pubads());
googletag.pubads().enableSingleRequest();
googletag.enableServices();
});
</script>
</head>

<body>
<h2>DigiTrust Prebid Sample - No Framework</h2>

<p>
This sample tests cmp behavior with simple integration path for using DigiTrust ID with Prebid.
You can use DigiTrust ID without integrating the entire DigiTrust suite.
</p>
<div id="idDiv"></div>

<div id='test-div'>
<script>
googletag.cmd.push(function () { googletag.display('test-div'); });
</script>
</div>
<script src="http://cmp-origin-release.digitru.st/1/cmp.bundle.js"></script>
</body>
</html>
48 changes: 46 additions & 2 deletions modules/digiTrustIdSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ var noop = function () {

const MAX_RETRIES = 2;
const DT_ID_SVC = 'https://prebid.digitru.st/id/v1';
const DT_VENDOR_ID = 65; // cmp gvlVendorId

var isFunc = function (fn) {
return typeof (fn) === 'function';
Expand Down Expand Up @@ -120,7 +121,7 @@ function initDigitrustFacade(config) {
}
}

if (!isMemberIdValid) {
if (!isMemberIdValid(obj.member)) {
if (!isAsync) {
return errResp
} else {
Expand Down Expand Up @@ -159,7 +160,12 @@ function initDigitrustFacade(config) {
}
}

callApi(opts);
// check gdpr vendor here. Full DigiTrust library has vendor check built in
gdprConsent.hasConsent(null, function (hasConsent) {
if (hasConsent) {
callApi(opts);
}
})

if (!isAsync) {
return errResp; // even if it will be successful later, without a callback we report a "failure in this moment"
Expand Down Expand Up @@ -189,6 +195,43 @@ var isMemberIdValid = function (memberId) {
}
};

/**
* DigiTrust consent handler for GDPR and __cmp.
* */
var gdprConsent = {
hasConsent: function (options, consentCb) {
options = options || { consentTimeout: 1500 };
var stopTimer;
var processed = false;
var consentAnswer = false;
if (typeof (window.__cmp) !== 'undefined') {
stopTimer = setTimeout(function () {
consentAnswer = true;
consentCb(consentAnswer);
processed = true;
}, options.consentTimeout);

window.__cmp('ping', null, function(pingAnswer) {
if (pingAnswer.gdprAppliesGlobally) {
window.__cmp('getVendorConsents', [DT_VENDOR_ID], function (result) {
if (processed) { return; } // timeout before cmp answer, cancel
clearTimeout(stopTimer);
var myconsent = result.vendorConsents[DT_VENDOR_ID];
consentCb(myconsent);
});
} else {
if (processed) { return; } // timeout before cmp answer, cancel
clearTimeout(stopTimer);
consentAnswer = true;
consentCb(consentAnswer);
}
});
}
consentAnswer = true;
consentCb(consentAnswer);
}
}

/**
* Encapsulation of needed info for the callback return.
*
Expand Down Expand Up @@ -321,6 +364,7 @@ export function surfaceTestHook() {
}

testHook.initDigitrustFacade = initDigitrustFacade; // expose for unit tests
testHook.gdpr = gdprConsent;

/** @type {Submodule} */
export const digiTrustIdSubmodule = {
Expand Down
74 changes: 73 additions & 1 deletion test/spec/modules/digitrustIdSystem_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,39 @@ import {

let assert = require('chai').assert;
let expect = require('chai').expect;

const DIGI_VENDOR_ID = 65;
var testHook = null;

/**
* A mock implementation of IAB Consent Provider
*/
function mockCmp(command, version, callback, parameter) {
var resultVal;
if (command == 'ping') {
resultVal = {
gdprAppliesGlobally: mockCmp.stubSettings.isGlobal
};
callback(resultVal);
} else if (command == 'getVendorConsents') {
let cbResult = {
vendorConsents: []
}
cbResult.vendorConsents[version] = mockCmp.stubSettings.consents;
callback(cbResult);
}
}

mockCmp.stubSettings = {
isGlobal: false,
consents: true
};

function setupCmpMock(isGlobal, consents) {
window.__cmp = mockCmp;
mockCmp.stubSettings.isGlobal = isGlobal;
mockCmp.stubSettings.consents = consents;
}

describe('DigiTrust Id System', function () {
it('Should create the test hook', function (done) {
testHook = surfaceTestHook();
Expand Down Expand Up @@ -47,4 +77,46 @@ describe('DigiTrust Id System', function () {
expect(window.DigiTrust.isClient).to.be.true;
done();
});

it('Should allow consent when given', function (done) {
testHook = surfaceTestHook();
setupCmpMock(true, true);
var handler = function(result) {
expect(result).to.be.true;
done();
}

testHook.gdpr.hasConsent(null, handler);
});

it('Should consent if does not apply', function (done) {
testHook = surfaceTestHook();
setupCmpMock(false, true);
var handler = function (result) {
expect(result).to.be.true;
done();
}

testHook.gdpr.hasConsent(null, handler);
});

it('Should not allow consent when not given', function (done) {
testHook = surfaceTestHook();
setupCmpMock(true, false);
var handler = function (result) {
expect(result).to.be.false;
done();
}

testHook.gdpr.hasConsent(null, handler);
});
it('Should allow consent if timeout', function (done) {
window.__cmp = function () { };
var handler = function (result) {
expect(result).to.be.true;
done();
}

testHook.gdpr.hasConsent({ consentTimeout: 1 }, handler);
});
});

0 comments on commit 69a33f8

Please sign in to comment.