From 2f325747ebe1b5f8447a60930b5680395c0b338a Mon Sep 17 00:00:00 2001 From: PubMatic-OpenWrap Date: Mon, 30 Apr 2018 19:41:56 +0530 Subject: [PATCH] Add gdpr support for PubMaticBidAdapter (#2469) --- modules/pubmaticBidAdapter.js | 42 +++++++++++-- test/spec/modules/pubmaticBidAdapter_spec.js | 63 +++++++++++++++++++- 2 files changed, 97 insertions(+), 8 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index dfcde047580..1f056bf0eff 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -19,6 +19,11 @@ const CUSTOM_PARAMS = { 'verId': '' // OpenWrap Legacy: version ID }; const NET_REVENUE = false; +const dealChannelValues = { + 1: 'PMP', + 5: 'PREF', + 6: 'PMPG' +}; let publisherId = 0; @@ -195,7 +200,7 @@ export const spec = { * @param {validBidRequests[]} - an array of bids * @return ServerRequest Info describing the request to the server. */ - buildRequests: validBidRequests => { + buildRequests: (validBidRequests, bidderRequest) => { var conf = _initConf(); var payload = _createOrtbTemplate(conf); validBidRequests.forEach(bid => { @@ -217,14 +222,28 @@ export const spec = { payload.site.publisher.id = conf.pubId.trim(); publisherId = conf.pubId.trim(); payload.ext.wrapper = {}; - payload.ext.wrapper.profile = conf.profId || UNDEFINED; - payload.ext.wrapper.version = conf.verId || UNDEFINED; + payload.ext.wrapper.profile = parseInt(conf.profId) || UNDEFINED; + payload.ext.wrapper.version = parseInt(conf.verId) || UNDEFINED; payload.ext.wrapper.wiid = conf.wiid || UNDEFINED; payload.ext.wrapper.wv = constants.REPO_AND_VERSION; payload.ext.wrapper.transactionId = conf.transactionId; payload.ext.wrapper.wp = 'pbjs'; payload.user.gender = (conf.gender ? conf.gender.trim() : UNDEFINED); payload.user.geo = {}; + + // Attaching GDPR Consent Params + if (bidderRequest && bidderRequest.gdprConsent) { + payload.user.ext = { + consent: bidderRequest.gdprConsent.consentString + }; + + payload.regs = { + ext: { + gdpr: (bidderRequest.gdprConsent.gdprApplies ? 1 : 0) + } + }; + } + payload.user.geo.lat = _parseSlotParam('lat', conf.lat); payload.user.geo.lon = _parseSlotParam('lon', conf.lon); payload.user.yob = _parseSlotParam('yob', conf.yob); @@ -264,6 +283,11 @@ export const spec = { referrer: utils.getTopWindowUrl(), ad: bid.adm }; + + if (bid.ext && bid.ext.deal_channel) { + newBid['dealChannel'] = dealChannelValues[bid.ext.deal_channel] || null; + } + bidResponses.push(newBid); }); } @@ -276,11 +300,19 @@ export const spec = { /** * Register User Sync. */ - getUserSyncs: syncOptions => { + getUserSyncs: (syncOptions, responses, gdprConsent) => { + let syncurl = USYNCURL + publisherId; + + // Attaching GDPR Consent Params in UserSync url + if (gdprConsent) { + syncurl += '&gdpr=' + (gdprConsent.gdprApplies ? 1 : 0); + syncurl += '&consent=' + encodeURIComponent(gdprConsent.consentString || ''); + } + if (syncOptions.iframeEnabled) { return [{ type: 'iframe', - url: USYNCURL + publisherId + url: syncurl }]; } else { utils.logWarn('PubMatic: Please enable iframe based user sync.'); diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index cbf17f9478a..7ea10315a4e 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -44,7 +44,10 @@ describe('PubMatic adapter', () => { 'price': 1.3, 'adm': 'image3.pubmatic.com Layer based creative', 'h': 250, - 'w': 300 + 'w': 300, + 'ext': { + 'deal_channel': 6 + } }] }] } @@ -136,8 +139,44 @@ describe('PubMatic adapter', () => { expect(data.ext.wrapper.wv).to.equal(constants.REPO_AND_VERSION); // Wrapper Version expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].transactionId); // Prebid TransactionId expect(data.ext.wrapper.wiid).to.equal(bidRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID - expect(data.ext.wrapper.profile).to.equal(bidRequests[0].params.profId); // OpenWrap: Wrapper Profile ID - expect(data.ext.wrapper.version).to.equal(bidRequests[0].params.verId); // OpenWrap: Wrapper Profile Version ID + expect(data.ext.wrapper.profile).to.equal(parseInt(bidRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID + expect(data.ext.wrapper.version).to.equal(parseInt(bidRequests[0].params.verId)); // OpenWrap: Wrapper Profile Version ID + + expect(data.imp[0].id).to.equal(bidRequests[0].bidId); // Prebid bid id is passed as id + expect(data.imp[0].bidfloor).to.equal(parseFloat(bidRequests[0].params.kadfloor)); // kadfloor + expect(data.imp[0].tagid).to.equal('/15671365/DMDemo'); // tagid + expect(data.imp[0].banner.w).to.equal(300); // width + expect(data.imp[0].banner.h).to.equal(250); // height + expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid + }); + + it('Request params check with GDPR Consent', () => { + let bidRequest = { + gdprConsent: { + consentString: 'kjfdniwjnifwenrif3', + gdprApplies: true + } + }; + let request = spec.buildRequests(bidRequests, bidRequest); + let data = JSON.parse(request.data); + expect(data.user.ext.consent).to.equal('kjfdniwjnifwenrif3'); + expect(data.regs.ext.gdpr).to.equal(1); + expect(data.at).to.equal(1); // auction type + expect(data.cur[0]).to.equal('USD'); // currency + expect(data.site.domain).to.be.a('string'); // domain should be set + expect(data.site.page).to.equal(bidRequests[0].params.kadpageurl); // forced pageURL + expect(data.site.publisher.id).to.equal(bidRequests[0].params.publisherId); // publisher Id + expect(data.user.yob).to.equal(parseInt(bidRequests[0].params.yob)); // YOB + expect(data.user.gender).to.equal(bidRequests[0].params.gender); // Gender + expect(data.device.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.device.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.user.geo.lat).to.equal(parseFloat(bidRequests[0].params.lat)); // Latitude + expect(data.user.geo.lon).to.equal(parseFloat(bidRequests[0].params.lon)); // Lognitude + expect(data.ext.wrapper.wv).to.equal(constants.REPO_AND_VERSION); // Wrapper Version + expect(data.ext.wrapper.transactionId).to.equal(bidRequests[0].transactionId); // Prebid TransactionId + expect(data.ext.wrapper.wiid).to.equal(bidRequests[0].params.wiid); // OpenWrap: Wrapper Impression ID + expect(data.ext.wrapper.profile).to.equal(parseInt(bidRequests[0].params.profId)); // OpenWrap: Wrapper Profile ID + expect(data.ext.wrapper.version).to.equal(parseInt(bidRequests[0].params.verId)); // OpenWrap: Wrapper Profile Version ID expect(data.imp[0].id).to.equal(bidRequests[0].bidId); // Prebid bid id is passed as id expect(data.imp[0].bidfloor).to.equal(parseFloat(bidRequests[0].params.kadfloor)); // kadfloor @@ -175,6 +214,24 @@ describe('PubMatic adapter', () => { expect(response[0].referrer).to.include(utils.getTopWindowUrl()); expect(response[0].ad).to.equal(bidResponses.body.seatbid[0].bid[0].adm); }); + + it('should check for dealChannel value selection', () => { + let request = spec.buildRequests(bidRequests); + let response = spec.interpretResponse(bidResponses, request); + expect(response).to.be.an('array').with.length.above(0); + expect(response[0].dealChannel).to.equal('PMPG'); + }); + + it('should check for unexpected dealChannel value selection', () => { + let request = spec.buildRequests(bidRequests); + let updateBiResponse = bidResponses; + updateBiResponse.body.seatbid[0].bid[0].ext.deal_channel = 11; + + let response = spec.interpretResponse(updateBiResponse, request); + + expect(response).to.be.an('array').with.length.above(0); + expect(response[0].dealChannel).to.equal(null); + }); }); }); });