diff --git a/integrationExamples/gpt/cmp_files/purposes.json b/integrationExamples/gpt/cmp_files/purposes.json new file mode 100644 index 00000000000..04219e92ce4 --- /dev/null +++ b/integrationExamples/gpt/cmp_files/purposes.json @@ -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" + } + ] +} diff --git a/integrationExamples/gpt/digitrust_Simple.html b/integrationExamples/gpt/digitrust_Simple.html index c9a8c1d2ad6..91eca591898 100644 --- a/integrationExamples/gpt/digitrust_Simple.html +++ b/integrationExamples/gpt/digitrust_Simple.html @@ -86,6 +86,7 @@ { code: 'test-div', sizes: [[300, 250], [300, 600], [728, 90]], + mediaTypes: { banner: { sizes: [400, 600], name: 'testAdUnit'}}, bids: [ { bidder: 'rubicon', diff --git a/integrationExamples/gpt/digitrust_cmp_test.html b/integrationExamples/gpt/digitrust_cmp_test.html new file mode 100644 index 00000000000..f5fc0aace63 --- /dev/null +++ b/integrationExamples/gpt/digitrust_cmp_test.html @@ -0,0 +1,192 @@ + + + CMP Simple DigiTrust Prebid - No Framework + + + + + + + + + + + + + +

DigiTrust Prebid Sample - No Framework

+ +

+ 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. +

+
+ +
+ +
+ + + diff --git a/modules/digiTrustIdSystem.js b/modules/digiTrustIdSystem.js index 89557e0917e..d63a7ac8380 100644 --- a/modules/digiTrustIdSystem.js +++ b/modules/digiTrustIdSystem.js @@ -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 = 64; // cmp gvlVendorId var isFunc = function (fn) { return typeof (fn) === 'function'; @@ -120,7 +121,7 @@ function initDigitrustFacade(config) { } } - if (!isMemberIdValid) { + if (!isMemberIdValid(obj.member)) { if (!isAsync) { return errResp } else { @@ -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" @@ -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. * @@ -321,6 +364,7 @@ export function surfaceTestHook() { } testHook.initDigitrustFacade = initDigitrustFacade; // expose for unit tests +testHook.gdpr = gdprConsent; /** @type {Submodule} */ export const digiTrustIdSubmodule = { diff --git a/test/spec/modules/digitrustIdSystem_spec.js b/test/spec/modules/digitrustIdSystem_spec.js index 55035bc4b4e..4b138e0d49d 100644 --- a/test/spec/modules/digitrustIdSystem_spec.js +++ b/test/spec/modules/digitrustIdSystem_spec.js @@ -5,9 +5,38 @@ import { let assert = require('chai').assert; let expect = require('chai').expect; - 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(); @@ -47,4 +76,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); + }); });