From 6237a0afea79e3f0fc98bda1fa1729fd1013db76 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Sun, 10 Dec 2017 20:10:58 -0800 Subject: [PATCH 01/30] first commit --- modules/pubmaticBidAdapter.js | 288 +++++++++++++++++++ test/spec/modules/pubmaticBidAdapter_spec.js | 119 ++++++++ 2 files changed, 407 insertions(+) create mode 100644 modules/pubmaticBidAdapter.js create mode 100644 test/spec/modules/pubmaticBidAdapter_spec.js diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js new file mode 100644 index 00000000000..eb5b8d0fe46 --- /dev/null +++ b/modules/pubmaticBidAdapter.js @@ -0,0 +1,288 @@ +import * as utils from 'src/utils'; +import { registerBidder } from 'src/adapters/bidderFactory'; +const constants = require('src/constants.json'); + +const BIDDER_CODE = 'pubmatic'; +const ENDPOINT = '//openbid.pubmatic.com/translator?source=prebid-server'; +const USYNCURL = '//ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p='; +const CURRENCY = 'USD'; +const AUCTION_TYPE = 2; //todo ?? is auction type correct ? second price auction +//todo: now what is significance of value ? +const CUSTOM_PARAMS = { + 'kadpageurl': 'kadpageurl', + 'gender': 'gender', + 'yob': 'yob', + 'dctr': 'dctr', // Custom Targeting + 'lat': 'lat', // Location - Latitude + 'lon': 'lon', // Location - Longitude + 'wiid': 'wiid', // Wrapper Impression ID + 'profId': 'profId', // Legacy: Profile ID + 'verId': 'verId' // Legacy: version ID +}; + +let publisherId = 0; + +function _processPmZoneId(zoneId) { + if (utils.isStr(zoneId)) { + return zoneId.split(',').slice(0, 50).join(); + } else { + return undefined; + } +} + +function _cleanSlot(slotName) { + if (utils.isStr(slotName)) { + return slotName.replace(/^\s+/g, '').replace(/\s+$/g, ''); + } + return ''; +} + +function _parseAdSlot(bid){ + + bid.params.adUnit = ''; + bid.params.adUnitIndex = '0'; + bid.params.width = 0; + bid.params.height = 0; + + bid.params.adSlot = _cleanSlot(bid.params.adSlot); + + var slot = bid.params.adSlot; + var splits = slot.split(':'); + + slot = splits[0]; + if(splits.length == 2){ + bid.params.adUnitIndex = splits[1]; + } + splits = slot.split('@'); + if(splits.length != 2){ + return; + } + bid.params.adUnit = splits[0]; + splits = splits[1].split('x'); + if(splits.length != 2){ + return; + } + bid.params.width = parseInt(splits[0]); + bid.params.height = parseInt(splits[1]); +} + +//todo: remove commented code +function _initConf() { + var conf = {}; + var currTime = new Date(); + conf.sec = 0; + //todo remove + let _protocol = (window.location.protocol === 'https:' ? (conf.sec = 1, 'https') : 'http') + '://'; + conf.wp = 'PreBid';//todo : do we need to send this ? + conf.wv = constants.REPO_AND_VERSION; + // istanbul ignore else + //if (window.navigator.cookieEnabled === false) { + // conf.fpcd = '1'; + //} + try { + conf.pageURL = window.top.location.href; + conf.hostname = window.top.location.hostname; + conf.refurl = window.top.document.referrer; + } catch (e) { + conf.pageURL = window.location.href; + conf.hostname = window.location.hostname; + conf.refurl = window.document.referrer; + } + /*conf.kltstamp = currTime.getFullYear() + + '-' + (currTime.getMonth() + 1) + + '-' + currTime.getDate() + + ' ' + currTime.getHours() + + ':' + currTime.getMinutes() + + ':' + currTime.getSeconds(); + */ + //conf.timezone = currTime.getTimezoneOffset() / 60 * -1; + return conf; +} + +function _handleCustomParams(params, conf) { + // istanbul ignore else + if (!conf.kadpageurl) { + conf.kadpageurl = conf.pageURL; + } + + var key, value, entry; + for (key in CUSTOM_PARAMS) { + // istanbul ignore else + if (CUSTOM_PARAMS.hasOwnProperty(key)) { + value = params[key]; + // istanbul ignore else + if (value) { + entry = CUSTOM_PARAMS[key]; + + if (typeof entry === 'object') { + value = entry.m(value, conf); + key = entry.n; + } else { + key = CUSTOM_PARAMS[key]; + } + + if (utils.isStr(value)) { + conf[key] = value; + } else { + utils.logWarn('PubMatic: Ignoring param key: ' + CUSTOM_PARAMS[key] + ', expects string-value, found ' + typeof value); + } + } + } + } + return conf; +} + +function _createOrtbTemplate(conf){ + return { + id : '' + new Date().getTime(), + at: AUCTION_TYPE, + cur: [CURRENCY], + imp: [], + site: { + domain: conf.hostname, + page: conf.pageURL, + publisher: {} + }, + device: { + ua: navigator.userAgent, + js: 1, + dnt: (navigator.doNotTrack == "yes" || navigator.doNotTrack == "1" || navigator.msDoNotTrack == "1") ? 1 : 0, + h: screen.height, + w: screen.width, + language: navigator.language, + ip: "123.4.12.34" //todo : REMOVE :: Mandatory w/o this we are not getting bids, isnt it retrieved from header ? + }, + user: {}, + ext: {} + }; +} + +function _createImpressionObject(bid, conf){ + return { + id: bid.bidId, + tagid: bid.params.adUnit, + bidfloor: bid.params.kadfloor || undefined, + secure: conf.sec, + banner: { + pos: 0, + w: bid.params.width, + h: bid.params.height, + topframe: 1, //todo: may need to change for postbid : check with open bid + }, + ext: { + pmZoneId: _processPmZoneId(bid.params.pmzoneid) + } + }; +} + +export const spec = { + code: BIDDER_CODE, + + /** + * Determines whether or not the given bid request is valid. Valid bid request must have placementId and hbid + * + * @param {BidRequest} bid The bid params to validate. + * @return boolean True if this is a valid bid, and false otherwise. + */ + isBidRequestValid: bid => { + //if(bid && bid.params && bid.params.publisherId){ + //_parseAdSlot(bid); + //return !!(bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex && bid.params.width && bid.params.height); + //}else{ + // return false; + //} + return !!(bid && bid.params && bid.params.publisherId && bid.params.adSlot); + }, + + /** + * Make a server request from the list of BidRequests. + * + * @param {validBidRequests[]} - an array of bids + * @return ServerRequest Info describing the request to the server. + */ + buildRequests: validBidRequests => { + var conf = _initConf(); + var payload = _createOrtbTemplate(conf); + validBidRequests.forEach(bid => { + _parseAdSlot(bid); + if(! (bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex && bid.params.width && bid.params.height)){ + utils.logWarn('PubMatic: Skipping the non-standard adslot:', bid.params.adSlot, bid); + return; + } + conf.pubId = conf.pubId || bid.params.publisherId; + conf = _handleCustomParams(bid.params, conf); + conf.transactionId = bid.transactionId; + payload.imp.push(_createImpressionObject(bid, conf)); + }); + + if(payload.imp.length == 0){ + return; + } + + payload.site.publisher.id = conf.pubId; + publisherId = conf.pubId; + payload.ext.wrapper = {}; + payload.ext.wrapper.profile = conf.profId || undefined; + payload.ext.wrapper.version = conf.verId || undefined; + payload.ext.wrapper.wiid = conf.wiid || undefined; + payload.ext.wrapper.wv = conf.wv || undefined; + payload.ext.wrapper.transactionId = conf.transactionId; + payload.user.gender = conf.gender || undefined; + payload.user.lat = conf.lat || undefined; + payload.user.lon = conf.lon || undefined; + payload.user.yob = conf.yob || undefined; + payload.site.page = conf.kadpageurl || payload.site.page; + return { + method: 'POST', + url: ENDPOINT, + data: JSON.stringify(payload) + }; + }, + + /** + * Unpack the response from the server into a list of bids. + * + * @param {*} response A successful response from the server. + * @return {Bid[]} An array of bids which were nested inside the server. + */ + interpretResponse: (response, request) => { + const bidResponses = []; + try { + if (response.body && response.body.seatbid && response.body.seatbid[0] && response.body.seatbid[0].bid) { + response.body.seatbid[0].bid.forEach(bid => { + let newBid = { + requestId: bid.impid, + cpm: bid.price, // Can we round to min precision ? + width: bid.w, + height: bid.h, + creativeId: bid.crid || bid.id, + dealId: bid.dealid, + currency: CURRENCY, + netRevenue: true, // todo: mandatory: Mike to confirm + ttl: 300, + referrer: utils.getTopWindowUrl(), + ad: bid.adm + }; + bidResponses.push(newBid); + }); + } + } catch (error) { + utils.logError(error); + } + return bidResponses; + }, + + /** + * Register User Sync. + */ + getUserSyncs: syncOptions => { + if (syncOptions.iframeEnabled) { + return [{ + type: 'iframe', + url: USYNCURL + publisherId + }]; + } + } +}; + +registerBidder(spec); \ No newline at end of file diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js new file mode 100644 index 00000000000..04d5cd843cf --- /dev/null +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -0,0 +1,119 @@ +import {expect} from 'chai'; +import {spec} from 'modules/pubmaticBidAdapter'; +const constants = require('src/constants.json'); + +describe('PubMatic adapter', () => { + let bidRequests; + + beforeEach(() => { + bidRequests = [ + { + bidder: 'pubmatic', + params: { + publisherId: '301', + adSlot: '/15671365/DMDemo@300x250:0', + kadfloor: '1.2', + pmzoneid: 'aabc, ddef', + kadpageurl: 'www.publisher.com', + yob: '1986', + gender: 'M', + lat: '12.3', + lon: '23.7', + wiid: '1234567890', + profId: '100', + verId: '200' + }, + placementCode: '/19968336/header-bid-tag-1', + sizes: [[300, 250], [300, 600]], + bidId: '23acc48ad47af5', + requestId: '0fb4905b-9456-4152-86be-c6f6d259ba99', + bidderRequestId: '1c56ad30b9b8ca8', + transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' + } + ]; + }); + + describe('implementation', () => { + + describe('Bid validations', () => { + + it('valid bid case', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: '301', + adSlot: '/15671365/DMDemo@300x250:0' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(true); + }); + + it('invalid bid case: publisherId not passed', () => { + let validBid = { + bidder: 'pubmatic', + params: { + adSlot: '/15671365/DMDemo@300x250:0' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('invalid bid case: adSlot not passed', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: '301' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + }); + + describe('Request formation', () => { + it('Endpoint checking', () => { + let request = spec.buildRequests(bidRequests); + expect(request.url).to.equal('//openbid.pubmatic.com/translator?source=prebid-server'); + expect(request.method).to.equal('POST'); + }); + + it('Request params check', () => { + let request = spec.buildRequests(bidRequests); + let data = JSON.parse(request.data); + expect(data.at).to.equal(2); //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(bidRequests[0].params.yob); // YOB + expect(data.user.gender).to.equal(bidRequests[0].params.gender); // Gender + expect(data.user.lat).to.equal(bidRequests[0].params.lat); // Latitude + expect(data.user.lon).to.equal(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(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.imp[0].id).to.equal(bidRequests[0].bidId); // Prebid bid id is passed as id + expect(data.imp[0].bidfloor).to.equal(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); // pmzoneid + }); + + it('invalid adslot', () => { + bidRequests[0].params.adSlot = '/15671365/DMDemo'; + let request = spec.buildRequests(bidRequests); + expect(request).to.equal(undefined); + }); + }); + + }); + + + +}); \ No newline at end of file From d713a4e168965e06bcbf1862a2b96d8cc8161533 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Mon, 11 Dec 2017 13:02:26 -0800 Subject: [PATCH 02/30] ip field removed, added comments to params, netRevenue set to true also changed surce of end-point to prebid-client from prebid-server --- modules/pubmaticBidAdapter.js | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index eb5b8d0fe46..8aa257a7d31 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -3,21 +3,21 @@ import { registerBidder } from 'src/adapters/bidderFactory'; const constants = require('src/constants.json'); const BIDDER_CODE = 'pubmatic'; -const ENDPOINT = '//openbid.pubmatic.com/translator?source=prebid-server'; +const ENDPOINT = '//openbid.pubmatic.com/translator?source=prebid-client'; const USYNCURL = '//ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p='; const CURRENCY = 'USD'; const AUCTION_TYPE = 2; //todo ?? is auction type correct ? second price auction //todo: now what is significance of value ? const CUSTOM_PARAMS = { 'kadpageurl': 'kadpageurl', - 'gender': 'gender', - 'yob': 'yob', - 'dctr': 'dctr', // Custom Targeting - 'lat': 'lat', // Location - Latitude - 'lon': 'lon', // Location - Longitude - 'wiid': 'wiid', // Wrapper Impression ID - 'profId': 'profId', // Legacy: Profile ID - 'verId': 'verId' // Legacy: version ID + 'gender': 'gender', // User gender + 'yob': 'yob', // User year of birth + 'dctr': 'dctr', // Custom Targeting //todo : remove ???? + 'lat': 'lat', // User location - Latitude + 'lon': 'lon', // User Location - Longitude + 'wiid': 'wiid', // OpenWrap Wrapper Impression ID + 'profId': 'profId', // OpenWrap Legacy: Profile ID + 'verId': 'verId' // OpenWrap Legacy: version ID }; let publisherId = 0; @@ -149,8 +149,7 @@ function _createOrtbTemplate(conf){ dnt: (navigator.doNotTrack == "yes" || navigator.doNotTrack == "1" || navigator.msDoNotTrack == "1") ? 1 : 0, h: screen.height, w: screen.width, - language: navigator.language, - ip: "123.4.12.34" //todo : REMOVE :: Mandatory w/o this we are not getting bids, isnt it retrieved from header ? + language: navigator.language }, user: {}, ext: {} @@ -258,7 +257,7 @@ export const spec = { creativeId: bid.crid || bid.id, dealId: bid.dealid, currency: CURRENCY, - netRevenue: true, // todo: mandatory: Mike to confirm + netRevenue: true, ttl: 300, referrer: utils.getTopWindowUrl(), ad: bid.adm From 10a8fa0862f93b0b1b7420e65eb1abf5ffd5ff0f Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Mon, 11 Dec 2017 15:01:41 -0800 Subject: [PATCH 03/30] added _processFloor --- modules/pubmaticBidAdapter.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 8aa257a7d31..f5e3556c640 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -26,6 +26,16 @@ function _processPmZoneId(zoneId) { if (utils.isStr(zoneId)) { return zoneId.split(',').slice(0, 50).join(); } else { + utils.logWarn('PubMatic: Ignoring param key: pmzoneid, expects string-value, found ' + typeof zoneId); + return undefined; + } +} + +function _processFloor(floor){ + if (utils.isStr(floor)) { + return parseFloat(floor) || undefined; + } else { + utils.logWarn('PubMatic: Ignoring param key: kadfloor, expects string-value, found ' + typeof floor); return undefined; } } @@ -160,7 +170,7 @@ function _createImpressionObject(bid, conf){ return { id: bid.bidId, tagid: bid.params.adUnit, - bidfloor: bid.params.kadfloor || undefined, + bidfloor: _processFloor(bid.params.kadfloor), secure: conf.sec, banner: { pos: 0, From 3a8cbe4a517ddb2b3b4c24112c0695ae43ceeabc Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Mon, 11 Dec 2017 15:30:09 -0800 Subject: [PATCH 04/30] removed comments --- modules/pubmaticBidAdapter.js | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index f5e3556c640..e81a30fe97d 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -76,19 +76,12 @@ function _parseAdSlot(bid){ bid.params.height = parseInt(splits[1]); } -//todo: remove commented code function _initConf() { var conf = {}; var currTime = new Date(); - conf.sec = 0; - //todo remove - let _protocol = (window.location.protocol === 'https:' ? (conf.sec = 1, 'https') : 'http') + '://'; + conf.sec = window.location.protocol === 'https:' ? 1 : 0; conf.wp = 'PreBid';//todo : do we need to send this ? conf.wv = constants.REPO_AND_VERSION; - // istanbul ignore else - //if (window.navigator.cookieEnabled === false) { - // conf.fpcd = '1'; - //} try { conf.pageURL = window.top.location.href; conf.hostname = window.top.location.hostname; @@ -98,14 +91,6 @@ function _initConf() { conf.hostname = window.location.hostname; conf.refurl = window.document.referrer; } - /*conf.kltstamp = currTime.getFullYear() + - '-' + (currTime.getMonth() + 1) + - '-' + currTime.getDate() + - ' ' + currTime.getHours() + - ':' + currTime.getMinutes() + - ':' + currTime.getSeconds(); - */ - //conf.timezone = currTime.getTimezoneOffset() / 60 * -1; return conf; } @@ -194,12 +179,6 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: bid => { - //if(bid && bid.params && bid.params.publisherId){ - //_parseAdSlot(bid); - //return !!(bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex && bid.params.width && bid.params.height); - //}else{ - // return false; - //} return !!(bid && bid.params && bid.params.publisherId && bid.params.adSlot); }, From b6e7805d4ab75dfbac14da64e08b7bf4849a624b Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Mon, 11 Dec 2017 15:47:05 -0800 Subject: [PATCH 05/30] fixed unit test cases --- test/spec/modules/pubmaticBidAdapter_spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 04d5cd843cf..fd440387a80 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -75,7 +75,7 @@ describe('PubMatic adapter', () => { describe('Request formation', () => { it('Endpoint checking', () => { let request = spec.buildRequests(bidRequests); - expect(request.url).to.equal('//openbid.pubmatic.com/translator?source=prebid-server'); + expect(request.url).to.equal('//openbid.pubmatic.com/translator?source=prebid-client'); expect(request.method).to.equal('POST'); }); @@ -98,7 +98,7 @@ describe('PubMatic adapter', () => { expect(data.ext.wrapper.version).to.equal(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(bidRequests[0].params.kadfloor); // kadfloor + 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 From 24b8772613aa028bedaae01780da71636e15efc3 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Tue, 12 Dec 2017 13:21:19 -0800 Subject: [PATCH 06/30] review comments --- modules/pubmaticBidAdapter.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index e81a30fe97d..a9c9202fa1b 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -6,13 +6,12 @@ const BIDDER_CODE = 'pubmatic'; const ENDPOINT = '//openbid.pubmatic.com/translator?source=prebid-client'; const USYNCURL = '//ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p='; const CURRENCY = 'USD'; -const AUCTION_TYPE = 2; //todo ?? is auction type correct ? second price auction -//todo: now what is significance of value ? +const AUCTION_TYPE = 2; +//todo: now what is significance of value ? const CUSTOM_PARAMS = { 'kadpageurl': 'kadpageurl', 'gender': 'gender', // User gender 'yob': 'yob', // User year of birth - 'dctr': 'dctr', // Custom Targeting //todo : remove ???? 'lat': 'lat', // User location - Latitude 'lon': 'lon', // User Location - Longitude 'wiid': 'wiid', // OpenWrap Wrapper Impression ID @@ -22,6 +21,7 @@ const CUSTOM_PARAMS = { let publisherId = 0; +// todo write a generic function, switch case function _processPmZoneId(zoneId) { if (utils.isStr(zoneId)) { return zoneId.split(',').slice(0, 50).join(); @@ -80,11 +80,12 @@ function _initConf() { var conf = {}; var currTime = new Date(); conf.sec = window.location.protocol === 'https:' ? 1 : 0; - conf.wp = 'PreBid';//todo : do we need to send this ? - conf.wv = constants.REPO_AND_VERSION; + conf.wp = 'pbjs'; + conf.wv = constants.REPO_AND_VERSION;// check later + //todo check available api, getOrigin try { conf.pageURL = window.top.location.href; - conf.hostname = window.top.location.hostname; + conf.hostname = window.top.location.hostname;// todo: domain w/o potocol conf.refurl = window.top.document.referrer; } catch (e) { conf.pageURL = window.location.href; @@ -161,7 +162,7 @@ function _createImpressionObject(bid, conf){ pos: 0, w: bid.params.width, h: bid.params.height, - topframe: 1, //todo: may need to change for postbid : check with open bid + topframe: 1, //todo: use api }, ext: { pmZoneId: _processPmZoneId(bid.params.pmzoneid) @@ -215,6 +216,7 @@ export const spec = { payload.ext.wrapper.wiid = conf.wiid || undefined; payload.ext.wrapper.wv = conf.wv || undefined; payload.ext.wrapper.transactionId = conf.transactionId; + payload.ext.wrapper.wp = conf.wp; payload.user.gender = conf.gender || undefined; payload.user.lat = conf.lat || undefined; payload.user.lon = conf.lon || undefined; @@ -241,6 +243,7 @@ export const spec = { let newBid = { requestId: bid.impid, cpm: bid.price, // Can we round to min precision ? + //todo: keep it 2 decimal only width: bid.w, height: bid.h, creativeId: bid.crid || bid.id, From 143461c8ba72b0fd0a06d24e5bce0038193917ef Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Tue, 12 Dec 2017 13:52:34 -0800 Subject: [PATCH 07/30] added method _parseSlotParam removed method _processFloor and _processPmZoneId added const for undefined --- modules/pubmaticBidAdapter.js | 46 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index a9c9202fa1b..7b2e8d116d9 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -7,6 +7,7 @@ const ENDPOINT = '//openbid.pubmatic.com/translator?source=prebid-client'; const USYNCURL = '//ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p='; const CURRENCY = 'USD'; const AUCTION_TYPE = 2; +const UNDEFINED = undefined; //todo: now what is significance of value ? const CUSTOM_PARAMS = { 'kadpageurl': 'kadpageurl', @@ -21,22 +22,19 @@ const CUSTOM_PARAMS = { let publisherId = 0; -// todo write a generic function, switch case -function _processPmZoneId(zoneId) { - if (utils.isStr(zoneId)) { - return zoneId.split(',').slice(0, 50).join(); - } else { - utils.logWarn('PubMatic: Ignoring param key: pmzoneid, expects string-value, found ' + typeof zoneId); - return undefined; +function _parseSlotParam(paramName, paramValue){ + if (!utils.isStr(paramValue)) { + utils.logWarn('PubMatic: Ignoring param key: '+paramName+', expects string-value, found ' + typeof paramValue); + return UNDEFINED; } -} -function _processFloor(floor){ - if (utils.isStr(floor)) { - return parseFloat(floor) || undefined; - } else { - utils.logWarn('PubMatic: Ignoring param key: kadfloor, expects string-value, found ' + typeof floor); - return undefined; + switch(paramName){ + case 'pmzoneid': + return paramValue.split(',').slice(0, 50).join(); + case 'kadfloor': + return parseFloat(paramValue) || UNDEFINED; + default: + return paramValue; } } @@ -156,7 +154,7 @@ function _createImpressionObject(bid, conf){ return { id: bid.bidId, tagid: bid.params.adUnit, - bidfloor: _processFloor(bid.params.kadfloor), + bidfloor: _parseSlotParam('kadfloor', bid.params.kadfloor), secure: conf.sec, banner: { pos: 0, @@ -165,7 +163,7 @@ function _createImpressionObject(bid, conf){ topframe: 1, //todo: use api }, ext: { - pmZoneId: _processPmZoneId(bid.params.pmzoneid) + pmZoneId: _parseSlotParam('pmzoneid', bid.params.pmzoneid) } }; } @@ -211,16 +209,16 @@ export const spec = { payload.site.publisher.id = conf.pubId; publisherId = conf.pubId; payload.ext.wrapper = {}; - payload.ext.wrapper.profile = conf.profId || undefined; - payload.ext.wrapper.version = conf.verId || undefined; - payload.ext.wrapper.wiid = conf.wiid || undefined; - payload.ext.wrapper.wv = conf.wv || undefined; + payload.ext.wrapper.profile = conf.profId || UNDEFINED; + payload.ext.wrapper.version = conf.verId || UNDEFINED; + payload.ext.wrapper.wiid = conf.wiid || UNDEFINED; + payload.ext.wrapper.wv = conf.wv || UNDEFINED; payload.ext.wrapper.transactionId = conf.transactionId; payload.ext.wrapper.wp = conf.wp; - payload.user.gender = conf.gender || undefined; - payload.user.lat = conf.lat || undefined; - payload.user.lon = conf.lon || undefined; - payload.user.yob = conf.yob || undefined; + payload.user.gender = conf.gender || UNDEFINED; + payload.user.lat = conf.lat || UNDEFINED; + payload.user.lon = conf.lon || UNDEFINED; + payload.user.yob = conf.yob || UNDEFINED; payload.site.page = conf.kadpageurl || payload.site.page; return { method: 'POST', From 97c3ea459619ec96dabeaccd306a7255164077cd Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Tue, 12 Dec 2017 13:59:01 -0800 Subject: [PATCH 08/30] minor changes --- modules/pubmaticBidAdapter.js | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 7b2e8d116d9..60af38cbf63 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -8,16 +8,15 @@ const USYNCURL = '//ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p='; const CURRENCY = 'USD'; const AUCTION_TYPE = 2; const UNDEFINED = undefined; -//todo: now what is significance of value ? const CUSTOM_PARAMS = { - 'kadpageurl': 'kadpageurl', - 'gender': 'gender', // User gender - 'yob': 'yob', // User year of birth - 'lat': 'lat', // User location - Latitude - 'lon': 'lon', // User Location - Longitude - 'wiid': 'wiid', // OpenWrap Wrapper Impression ID - 'profId': 'profId', // OpenWrap Legacy: Profile ID - 'verId': 'verId' // OpenWrap Legacy: version ID + 'kadpageurl': '', // Custom page url + 'gender': '', // User gender + 'yob': '', // User year of birth + 'lat': '', // User location - Latitude + 'lon': '', // User Location - Longitude + 'wiid': '', // OpenWrap Wrapper Impression ID + 'profId': '', // OpenWrap Legacy: Profile ID + 'verId': '' // OpenWrap Legacy: version ID }; let publisherId = 0; @@ -109,8 +108,9 @@ function _handleCustomParams(params, conf) { entry = CUSTOM_PARAMS[key]; if (typeof entry === 'object') { - value = entry.m(value, conf); - key = entry.n; + // will be used in future when we want to process a custom param before using + // 'keyname': {f: function(){}} + value = entry.f(value, conf); } else { key = CUSTOM_PARAMS[key]; } @@ -270,6 +270,8 @@ export const spec = { type: 'iframe', url: USYNCURL + publisherId }]; + }else{ + utils.logWarn('PubMatic: Please enable iframe based user sync.'); } } }; From f93c0fb5b0c2995c9c9410d92d3a4e0de22b82df Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Tue, 12 Dec 2017 14:03:13 -0800 Subject: [PATCH 09/30] minor change --- modules/pubmaticBidAdapter.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 60af38cbf63..05610068656 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -111,8 +111,6 @@ function _handleCustomParams(params, conf) { // will be used in future when we want to process a custom param before using // 'keyname': {f: function(){}} value = entry.f(value, conf); - } else { - key = CUSTOM_PARAMS[key]; } if (utils.isStr(value)) { From c8f7293d4adfb43c8466a8f864a4209ec5699c66 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Tue, 12 Dec 2017 14:12:16 -0800 Subject: [PATCH 10/30] publisherId isStr check added --- modules/pubmaticBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 05610068656..541cb468a6e 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -176,7 +176,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: bid => { - return !!(bid && bid.params && bid.params.publisherId && bid.params.adSlot); + return !!(bid && bid.params && utils.isStr(bid.params.publisherId) && bid.params.adSlot); }, /** From ec96c341501b068ba5263d56063604f42a5bdf2c Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Tue, 12 Dec 2017 14:27:42 -0800 Subject: [PATCH 11/30] test case for string publisherId and adSlot --- modules/pubmaticBidAdapter.js | 2 +- test/spec/modules/pubmaticBidAdapter_spec.js | 57 +++++++++++++------- 2 files changed, 40 insertions(+), 19 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 541cb468a6e..d29519e9954 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -176,7 +176,7 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: bid => { - return !!(bid && bid.params && utils.isStr(bid.params.publisherId) && bid.params.adSlot); + return !!(bid && bid.params && utils.isStr(bid.params.publisherId) && utils.isStr(bid.params.adSlot)); }, /** diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index fd440387a80..1e8d3508792 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -36,9 +36,8 @@ describe('PubMatic adapter', () => { describe('implementation', () => { describe('Bid validations', () => { - it('valid bid case', () => { - let validBid = { + let validBid = { bidder: 'pubmatic', params: { publisherId: '301', @@ -49,19 +48,31 @@ describe('PubMatic adapter', () => { expect(isValid).to.equal(true); }); - it('invalid bid case: publisherId not passed', () => { - let validBid = { - bidder: 'pubmatic', - params: { - adSlot: '/15671365/DMDemo@300x250:0' - } - }, - isValid = spec.isBidRequestValid(validBid); - expect(isValid).to.equal(false); + it('invalid bid case: publisherId not passed', () => { + let validBid = { + bidder: 'pubmatic', + params: { + adSlot: '/15671365/DMDemo@300x250:0' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); }); - it('invalid bid case: adSlot not passed', () => { - let validBid = { + it('invalid bid case: publisherId is not string', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: 301, + adSlot: '/15671365/DMDemo@300x250:0' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + + it('invalid bid case: adSlot not passed', () => { + let validBid = { bidder: 'pubmatic', params: { publisherId: '301' @@ -69,8 +80,20 @@ describe('PubMatic adapter', () => { }, isValid = spec.isBidRequestValid(validBid); expect(isValid).to.equal(false); - }); - }); + }); + + it('invalid bid case: adSlot is not string', () => { + let validBid = { + bidder: 'pubmatic', + params: { + publisherId: '301', + adSlot: 15671365 + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); + }); + }); describe('Request formation', () => { it('Endpoint checking', () => { @@ -114,6 +137,4 @@ describe('PubMatic adapter', () => { }); - - -}); \ No newline at end of file +}); \ No newline at end of file From 5c34e03de3bb43ab0179a0807d880aa540726c39 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Tue, 12 Dec 2017 15:17:32 -0800 Subject: [PATCH 12/30] using prebid apis for getting pageURL and refURL, added a small function to find domain from given url --- modules/pubmaticBidAdapter.js | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index d29519e9954..e3e9e86f41c 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -21,6 +21,12 @@ const CUSTOM_PARAMS = { let publisherId = 0; +function _getDomainFromURL(url){ + let anchor = document.createElement('a'); + anchor.href = url; + return anchor.hostname; +} + function _parseSlotParam(paramName, paramValue){ if (!utils.isStr(paramValue)) { utils.logWarn('PubMatic: Ignoring param key: '+paramName+', expects string-value, found ' + typeof paramValue); @@ -75,20 +81,8 @@ function _parseAdSlot(bid){ function _initConf() { var conf = {}; - var currTime = new Date(); - conf.sec = window.location.protocol === 'https:' ? 1 : 0; - conf.wp = 'pbjs'; - conf.wv = constants.REPO_AND_VERSION;// check later - //todo check available api, getOrigin - try { - conf.pageURL = window.top.location.href; - conf.hostname = window.top.location.hostname;// todo: domain w/o potocol - conf.refurl = window.top.document.referrer; - } catch (e) { - conf.pageURL = window.location.href; - conf.hostname = window.location.hostname; - conf.refurl = window.document.referrer; - } + conf.pageURL = utils.getTopWindowUrl(); + conf.refURL = utils.getTopWindowReferrer(); return conf; } @@ -131,8 +125,8 @@ function _createOrtbTemplate(conf){ cur: [CURRENCY], imp: [], site: { - domain: conf.hostname, page: conf.pageURL, + ref: conf.refURL, publisher: {} }, device: { @@ -153,12 +147,12 @@ function _createImpressionObject(bid, conf){ id: bid.bidId, tagid: bid.params.adUnit, bidfloor: _parseSlotParam('kadfloor', bid.params.kadfloor), - secure: conf.sec, + secure: window.location.protocol === 'https:' ? 1 : 0, banner: { pos: 0, w: bid.params.width, h: bid.params.height, - topframe: 1, //todo: use api + topframe: utils.inIframe() ? 0 : 1, }, ext: { pmZoneId: _parseSlotParam('pmzoneid', bid.params.pmzoneid) @@ -210,14 +204,15 @@ export const spec = { payload.ext.wrapper.profile = conf.profId || UNDEFINED; payload.ext.wrapper.version = conf.verId || UNDEFINED; payload.ext.wrapper.wiid = conf.wiid || UNDEFINED; - payload.ext.wrapper.wv = conf.wv || UNDEFINED; + payload.ext.wrapper.wv = constants.REPO_AND_VERSION; payload.ext.wrapper.transactionId = conf.transactionId; - payload.ext.wrapper.wp = conf.wp; + payload.ext.wrapper.wp = 'pbjs'; payload.user.gender = conf.gender || UNDEFINED; payload.user.lat = conf.lat || UNDEFINED; payload.user.lon = conf.lon || UNDEFINED; payload.user.yob = conf.yob || UNDEFINED; payload.site.page = conf.kadpageurl || payload.site.page; + payload.site.domain = _getDomainFromURL(payload.site.page); return { method: 'POST', url: ENDPOINT, From 9f9b3ce745c3c2535c4f276e252929544f9d5752 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Tue, 12 Dec 2017 15:34:44 -0800 Subject: [PATCH 13/30] bid precision set to 2 --- modules/pubmaticBidAdapter.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index e3e9e86f41c..a77f06291ad 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -233,8 +233,7 @@ export const spec = { response.body.seatbid[0].bid.forEach(bid => { let newBid = { requestId: bid.impid, - cpm: bid.price, // Can we round to min precision ? - //todo: keep it 2 decimal only + cpm: (parseFloat(bid.price)||0).toFixed(2), width: bid.w, height: bid.h, creativeId: bid.crid || bid.id, From 7c947869f303890725a892abf92bcc7615d2aa78 Mon Sep 17 00:00:00 2001 From: Manasi Moghe Date: Wed, 13 Dec 2017 15:34:15 +0530 Subject: [PATCH 14/30] Added test cases for interpretResponse function --- test/spec/modules/pubmaticBidAdapter_spec.js | 70 +++++++++++++++----- 1 file changed, 54 insertions(+), 16 deletions(-) diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 1e8d3508792..92307538d06 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -1,9 +1,11 @@ import {expect} from 'chai'; import {spec} from 'modules/pubmaticBidAdapter'; +import * as utils from 'src/utils'; const constants = require('src/constants.json'); describe('PubMatic adapter', () => { let bidRequests; + let bidResponses; beforeEach(() => { bidRequests = [ @@ -31,13 +33,28 @@ describe('PubMatic adapter', () => { transactionId: '92489f71-1bf2-49a0-adf9-000cea934729' } ]; + + bidResponses = { + 'body': { + 'id': '93D3BAD6-E2E2-49FB-9D89-920B1761C865', + 'seatbid': [{ + 'bid': [{ + 'id': '74858439-49D7-4169-BA5D-44A046315B2F', + 'impid': '22bddb28db77d', + 'price': 1.3, + 'adm': 'image3.pubmatic.com Layer based creative', + 'h': 250, + 'w': 300 + }] + }] + } + }; }); describe('implementation', () => { - describe('Bid validations', () => { it('valid bid case', () => { - let validBid = { + let validBid = { bidder: 'pubmatic', params: { publisherId: '301', @@ -48,15 +65,15 @@ describe('PubMatic adapter', () => { expect(isValid).to.equal(true); }); - it('invalid bid case: publisherId not passed', () => { - let validBid = { - bidder: 'pubmatic', - params: { - adSlot: '/15671365/DMDemo@300x250:0' - } - }, - isValid = spec.isBidRequestValid(validBid); - expect(isValid).to.equal(false); + it('invalid bid case: publisherId not passed', () => { + let validBid = { + bidder: 'pubmatic', + params: { + adSlot: '/15671365/DMDemo@300x250:0' + } + }, + isValid = spec.isBidRequestValid(validBid); + expect(isValid).to.equal(false); }); it('invalid bid case: publisherId is not string', () => { @@ -105,8 +122,8 @@ describe('PubMatic adapter', () => { it('Request params check', () => { let request = spec.buildRequests(bidRequests); let data = JSON.parse(request.data); - expect(data.at).to.equal(2); //auction type - expect(data.cur[0]).to.equal("USD"); //currency + expect(data.at).to.equal(2); // 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 @@ -120,7 +137,7 @@ describe('PubMatic adapter', () => { 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.imp[0].id).to.equal(bidRequests[0].bidId); // Prebid bid id is passed as 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 @@ -135,6 +152,27 @@ describe('PubMatic adapter', () => { }); }); + describe('Response checking', () => { + it('should check for valid response values', () => { + let request = spec.buildRequests(bidRequests); + let response = spec.interpretResponse(bidResponses, request); + expect(response).to.be.an('array').with.length.above(0); + expect(response[0].requestId).to.equal(bidResponses.body.seatbid[0].bid[0].impid); + expect(response[0].cpm).to.equal((bidResponses.body.seatbid[0].bid[0].price).toFixed(2)); + expect(response[0].width).to.equal(bidResponses.body.seatbid[0].bid[0].w); + expect(response[0].height).to.equal(bidResponses.body.seatbid[0].bid[0].h); + if (bidResponses.body.seatbid[0].bid[0].crid) { + expect(response[0].creativeId).to.equal(bidResponses.body.seatbid[0].bid[0].crid); + } else { + expect(response[0].creativeId).to.equal(bidResponses.body.seatbid[0].bid[0].id); + } + expect(response[0].dealId).to.equal(bidResponses.body.seatbid[0].bid[0].dealid); + expect(response[0].currency).to.equal('USD'); + expect(response[0].netRevenue).to.equal(true); + expect(response[0].ttl).to.equal(300); + expect(response[0].referrer).to.include(utils.getTopWindowUrl()); + expect(response[0].ad).to.equal(bidResponses.body.seatbid[0].bid[0].adm); + }); + }); }); - -}); \ No newline at end of file +}); From 90d4ba653b5867560f36dc77b28388e877ad66e4 Mon Sep 17 00:00:00 2001 From: Harshad Mane Date: Wed, 13 Dec 2017 09:00:15 -0800 Subject: [PATCH 15/30] do not put warning for undefined valued params --- modules/pubmaticBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index a77f06291ad..e54a1cda7ab 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -29,7 +29,7 @@ function _getDomainFromURL(url){ function _parseSlotParam(paramName, paramValue){ if (!utils.isStr(paramValue)) { - utils.logWarn('PubMatic: Ignoring param key: '+paramName+', expects string-value, found ' + typeof paramValue); + paramValue && utils.logWarn('PubMatic: Ignoring param key: '+paramName+', expects string-value, found ' + typeof paramValue); return UNDEFINED; } From bd009e86fa490785be9864ee3b4a9c58aba51a2f Mon Sep 17 00:00:00 2001 From: Manasi Moghe Date: Fri, 15 Dec 2017 13:27:20 +0530 Subject: [PATCH 16/30] changes for UOE-3239 and UOE-3236 --- modules/pubmaticBidAdapter.js | 81 ++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 34 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index e54a1cda7ab..f367a397dce 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -16,24 +16,24 @@ const CUSTOM_PARAMS = { 'lon': '', // User Location - Longitude 'wiid': '', // OpenWrap Wrapper Impression ID 'profId': '', // OpenWrap Legacy: Profile ID - 'verId': '' // OpenWrap Legacy: version ID + 'verId': '' // OpenWrap Legacy: version ID }; let publisherId = 0; -function _getDomainFromURL(url){ +function _getDomainFromURL(url) { let anchor = document.createElement('a'); anchor.href = url; return anchor.hostname; } -function _parseSlotParam(paramName, paramValue){ - if (!utils.isStr(paramValue)) { - paramValue && utils.logWarn('PubMatic: Ignoring param key: '+paramName+', expects string-value, found ' + typeof paramValue); +function _parseSlotParam(paramName, paramValue) { + if (!utils.isStr(paramValue)) { + paramValue && utils.logWarn('PubMatic: Ignoring param key: ' + paramName + ', expects string-value, found ' + typeof paramValue); return UNDEFINED; } - switch(paramName){ + switch (paramName) { case 'pmzoneid': return paramValue.split(',').slice(0, 50).join(); case 'kadfloor': @@ -50,8 +50,7 @@ function _cleanSlot(slotName) { return ''; } -function _parseAdSlot(bid){ - +function _parseAdSlot(bid) { bid.params.adUnit = ''; bid.params.adUnitIndex = '0'; bid.params.width = 0; @@ -63,16 +62,18 @@ function _parseAdSlot(bid){ var splits = slot.split(':'); slot = splits[0]; - if(splits.length == 2){ + if (splits.length == 2) { bid.params.adUnitIndex = splits[1]; } splits = slot.split('@'); - if(splits.length != 2){ + if (splits.length != 2) { + utils.logWarn('AdSlot Error: adSlot not in required format'); return; - } + } bid.params.adUnit = splits[0]; splits = splits[1].split('x'); - if(splits.length != 2){ + if (splits.length != 2) { + utils.logWarn('AdSlot Error: adSlot not in required format'); return; } bid.params.width = parseInt(splits[0]); @@ -81,7 +82,7 @@ function _parseAdSlot(bid){ function _initConf() { var conf = {}; - conf.pageURL = utils.getTopWindowUrl(); + conf.pageURL = utils.getTopWindowUrl(); conf.refURL = utils.getTopWindowReferrer(); return conf; } @@ -103,14 +104,14 @@ function _handleCustomParams(params, conf) { if (typeof entry === 'object') { // will be used in future when we want to process a custom param before using - // 'keyname': {f: function(){}} + // 'keyname': {f: function() {}} value = entry.f(value, conf); } if (utils.isStr(value)) { conf[key] = value; } else { - utils.logWarn('PubMatic: Ignoring param key: ' + CUSTOM_PARAMS[key] + ', expects string-value, found ' + typeof value); + utils.logWarn('PubMatic: Ignoring param : ' + key + ' with value : ' + CUSTOM_PARAMS[key] + ', expects string-value, found ' + typeof value); } } } @@ -118,9 +119,9 @@ function _handleCustomParams(params, conf) { return conf; } -function _createOrtbTemplate(conf){ +function _createOrtbTemplate(conf) { return { - id : '' + new Date().getTime(), + id: '' + new Date().getTime(), at: AUCTION_TYPE, cur: [CURRENCY], imp: [], @@ -132,7 +133,7 @@ function _createOrtbTemplate(conf){ device: { ua: navigator.userAgent, js: 1, - dnt: (navigator.doNotTrack == "yes" || navigator.doNotTrack == "1" || navigator.msDoNotTrack == "1") ? 1 : 0, + dnt: (navigator.doNotTrack == 'yes' || navigator.doNotTrack == '1' || navigator.msDoNotTrack == '1') ? 1 : 0, h: screen.height, w: screen.width, language: navigator.language @@ -142,7 +143,7 @@ function _createOrtbTemplate(conf){ }; } -function _createImpressionObject(bid, conf){ +function _createImpressionObject(bid, conf) { return { id: bid.bidId, tagid: bid.params.adUnit, @@ -150,7 +151,7 @@ function _createImpressionObject(bid, conf){ secure: window.location.protocol === 'https:' ? 1 : 0, banner: { pos: 0, - w: bid.params.width, + w: bid.params.width, h: bid.params.height, topframe: utils.inIframe() ? 0 : 1, }, @@ -170,7 +171,19 @@ export const spec = { * @return boolean True if this is a valid bid, and false otherwise. */ isBidRequestValid: bid => { - return !!(bid && bid.params && utils.isStr(bid.params.publisherId) && utils.isStr(bid.params.adSlot)); + if (bid && bid.params) { + if (!utils.isStr(bid.params.publisherId)) { + utils.logWarn('PubMatic Error: publisherId is mandatory and cannot be numeric. Call to OpenBid will not be sent.'); + return false; + } + if (!utils.isStr(bid.params.adSlot)) { + utils.logWarn('PubMatic: adSlotId is mandatory and cannot be numeric. Call to OpenBid will not be sent.'); + return false; + } + return true; + } + return false; + // return !!(bid && bid.params && utils.isStr(bid.params.publisherId) && utils.isStr(bid.params.adSlot)); }, /** @@ -184,7 +197,7 @@ export const spec = { var payload = _createOrtbTemplate(conf); validBidRequests.forEach(bid => { _parseAdSlot(bid); - if(! (bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex && bid.params.width && bid.params.height)){ + if (!(bid.params.adSlot && bid.params.adUnit && bid.params.adUnitIndex && bid.params.width && bid.params.height)) { utils.logWarn('PubMatic: Skipping the non-standard adslot:', bid.params.adSlot, bid); return; } @@ -193,13 +206,13 @@ export const spec = { conf.transactionId = bid.transactionId; payload.imp.push(_createImpressionObject(bid, conf)); }); - - if(payload.imp.length == 0){ + + if (payload.imp.length == 0) { return; } - payload.site.publisher.id = conf.pubId; - publisherId = conf.pubId; + 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; @@ -207,11 +220,11 @@ export const spec = { payload.ext.wrapper.wv = constants.REPO_AND_VERSION; payload.ext.wrapper.transactionId = conf.transactionId; payload.ext.wrapper.wp = 'pbjs'; - payload.user.gender = conf.gender || UNDEFINED; - payload.user.lat = conf.lat || UNDEFINED; - payload.user.lon = conf.lon || UNDEFINED; - payload.user.yob = conf.yob || UNDEFINED; - payload.site.page = conf.kadpageurl || payload.site.page; + payload.user.gender = (conf.gender ? conf.gender.trim() : UNDEFINED); + payload.user.lat = conf.lat || UNDEFINED; + payload.user.lon = conf.lon || UNDEFINED; + payload.user.yob = conf.yob || UNDEFINED; + payload.site.page = (conf.kadpageurl && conf.kadpageurl || (payload.site.page && payload.site.page); payload.site.domain = _getDomainFromURL(payload.site.page); return { method: 'POST', @@ -233,7 +246,7 @@ export const spec = { response.body.seatbid[0].bid.forEach(bid => { let newBid = { requestId: bid.impid, - cpm: (parseFloat(bid.price)||0).toFixed(2), + cpm: (parseFloat(bid.price) || 0).toFixed(2), width: bid.w, height: bid.h, creativeId: bid.crid || bid.id, @@ -262,10 +275,10 @@ export const spec = { type: 'iframe', url: USYNCURL + publisherId }]; - }else{ + } else { utils.logWarn('PubMatic: Please enable iframe based user sync.'); } } }; -registerBidder(spec); \ No newline at end of file +registerBidder(spec); From 5aa08390657e34382819541599e6b157ed444b20 Mon Sep 17 00:00:00 2001 From: Manasi Moghe Date: Fri, 15 Dec 2017 15:25:07 +0530 Subject: [PATCH 17/30] Linting errors fixed --- modules/pubmaticBidAdapter.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index f367a397dce..7c4f0957330 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -221,10 +221,10 @@ export const spec = { payload.ext.wrapper.transactionId = conf.transactionId; payload.ext.wrapper.wp = 'pbjs'; payload.user.gender = (conf.gender ? conf.gender.trim() : UNDEFINED); - payload.user.lat = conf.lat || UNDEFINED; - payload.user.lon = conf.lon || UNDEFINED; - payload.user.yob = conf.yob || UNDEFINED; - payload.site.page = (conf.kadpageurl && conf.kadpageurl || (payload.site.page && payload.site.page); + payload.user.lat = conf.lat || UNDEFINED; + payload.user.lon = conf.lon || UNDEFINED; + payload.user.yob = conf.yob || UNDEFINED; + payload.site.page = conf.kadpageurl || payload.site.page; payload.site.domain = _getDomainFromURL(payload.site.page); return { method: 'POST', From 3ed20332dc31190f19e6fe872f24b9953072864f Mon Sep 17 00:00:00 2001 From: Dattaprasad Mundada Date: Fri, 15 Dec 2017 20:49:47 +0530 Subject: [PATCH 18/30] Add geo object in device --- modules/pubmaticBidAdapter.js | 16 +++++- test/spec/modules/pubmaticBidAdapter_spec.js | 60 ++++++++++---------- 2 files changed, 44 insertions(+), 32 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 7c4f0957330..ecef554233d 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -38,6 +38,12 @@ function _parseSlotParam(paramName, paramValue) { return paramValue.split(',').slice(0, 50).join(); case 'kadfloor': return parseFloat(paramValue) || UNDEFINED; + case 'lat': + return parseFloat(paramValue) || UNDEFINED; + case 'lon': + return parseFloat(paramValue) || UNDEFINED; + case 'yob': + return parseInt(paramValue) || UNDEFINED; default: return paramValue; } @@ -221,9 +227,13 @@ export const spec = { payload.ext.wrapper.transactionId = conf.transactionId; payload.ext.wrapper.wp = 'pbjs'; payload.user.gender = (conf.gender ? conf.gender.trim() : UNDEFINED); - payload.user.lat = conf.lat || UNDEFINED; - payload.user.lon = conf.lon || UNDEFINED; - payload.user.yob = conf.yob || UNDEFINED; + payload.user.geo = {}; + payload.user.geo.lat = _parseSlotParam('lat', conf.lat); + payload.user.geo.lon = _parseSlotParam('lon', conf.lon); + payload.user.yob = _parseSlotParam('yob', conf.yob); + payload.device.geo = {}; + payload.device.geo.lat = _parseSlotParam('lat', conf.lat); + payload.device.geo.lon = _parseSlotParam('lon', conf.lon); payload.site.page = conf.kadpageurl || payload.site.page; payload.site.domain = _getDomainFromURL(payload.site.page); return { diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 92307538d06..78634b131b7 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -15,15 +15,15 @@ describe('PubMatic adapter', () => { publisherId: '301', adSlot: '/15671365/DMDemo@300x250:0', kadfloor: '1.2', - pmzoneid: 'aabc, ddef', - kadpageurl: 'www.publisher.com', - yob: '1986', - gender: 'M', - lat: '12.3', - lon: '23.7', - wiid: '1234567890', - profId: '100', - verId: '200' + pmzoneid: 'aabc, ddef', + kadpageurl: 'www.publisher.com', + yob: '1986', + gender: 'M', + lat: '12.3', + lon: '23.7', + wiid: '1234567890', + profId: '100', + verId: '200' }, placementCode: '/19968336/header-bid-tag-1', sizes: [[300, 250], [300, 600]], @@ -78,13 +78,13 @@ describe('PubMatic adapter', () => { it('invalid bid case: publisherId is not string', () => { let validBid = { - bidder: 'pubmatic', - params: { - publisherId: 301, - adSlot: '/15671365/DMDemo@300x250:0' - } - }, - isValid = spec.isBidRequestValid(validBid); + bidder: 'pubmatic', + params: { + publisherId: 301, + adSlot: '/15671365/DMDemo@300x250:0' + } + }, + isValid = spec.isBidRequestValid(validBid); expect(isValid).to.equal(false); }); @@ -97,17 +97,17 @@ describe('PubMatic adapter', () => { }, isValid = spec.isBidRequestValid(validBid); expect(isValid).to.equal(false); - }); + }); it('invalid bid case: adSlot is not string', () => { let validBid = { - bidder: 'pubmatic', - params: { - publisherId: '301', - adSlot: 15671365 - } - }, - isValid = spec.isBidRequestValid(validBid); + bidder: 'pubmatic', + params: { + publisherId: '301', + adSlot: 15671365 + } + }, + isValid = spec.isBidRequestValid(validBid); expect(isValid).to.equal(false); }); }); @@ -115,8 +115,8 @@ describe('PubMatic adapter', () => { describe('Request formation', () => { it('Endpoint checking', () => { let request = spec.buildRequests(bidRequests); - expect(request.url).to.equal('//openbid.pubmatic.com/translator?source=prebid-client'); - expect(request.method).to.equal('POST'); + expect(request.url).to.equal('//openbid.pubmatic.com/translator?source=prebid-client'); + expect(request.method).to.equal('POST'); }); it('Request params check', () => { @@ -127,10 +127,12 @@ describe('PubMatic adapter', () => { 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(bidRequests[0].params.yob); // YOB + 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.user.lat).to.equal(bidRequests[0].params.lat); // Latitude - expect(data.user.lon).to.equal(bidRequests[0].params.lon); // Lognitude + 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 From eda0b4b01dca73d2e1826e61a1c4e5a2afdad627 Mon Sep 17 00:00:00 2001 From: Manasi Moghe Date: Wed, 20 Dec 2017 13:23:40 +0530 Subject: [PATCH 19/30] Changes to trim kadpageurl and pmzoneid before sending it in request --- modules/pubmaticBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index ecef554233d..b5df1b69647 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -162,7 +162,7 @@ function _createImpressionObject(bid, conf) { topframe: utils.inIframe() ? 0 : 1, }, ext: { - pmZoneId: _parseSlotParam('pmzoneid', bid.params.pmzoneid) + pmZoneId: _parseSlotParam('pmzoneid', bid.params.pmzoneid).trim() } }; } @@ -234,7 +234,7 @@ export const spec = { payload.device.geo = {}; payload.device.geo.lat = _parseSlotParam('lat', conf.lat); payload.device.geo.lon = _parseSlotParam('lon', conf.lon); - payload.site.page = conf.kadpageurl || payload.site.page; + payload.site.page = conf.kadpageurl.trim() || payload.site.page.trim(); payload.site.domain = _getDomainFromURL(payload.site.page); return { method: 'POST', From f33459eba5e0b0732d373acd623d414ccf360b5e Mon Sep 17 00:00:00 2001 From: Dattaprasad Mundada Date: Wed, 20 Dec 2017 14:43:33 +0530 Subject: [PATCH 20/30] Remove spaces when multiple Id's added in pmzoneId --- modules/pubmaticBidAdapter.js | 2 +- test/spec/modules/pubmaticBidAdapter_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index b5df1b69647..19f4f932eb7 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -35,7 +35,7 @@ function _parseSlotParam(paramName, paramValue) { switch (paramName) { case 'pmzoneid': - return paramValue.split(',').slice(0, 50).join(); + return paramValue.split(',').slice(0, 50).map(id => id.trim()).join(); case 'kadfloor': return parseFloat(paramValue) || UNDEFINED; case 'lat': diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 78634b131b7..49d60d45947 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -144,7 +144,7 @@ describe('PubMatic adapter', () => { 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); // pmzoneid + expect(data.imp[0].ext.pmZoneId).to.equal(bidRequests[0].params.pmzoneid.split(',').slice(0, 50).map(id => id.trim()).join()); // pmzoneid }); it('invalid adslot', () => { From f16e42cf4a661ec60c2aeae6d5c3c3cf1f6ea629 Mon Sep 17 00:00:00 2001 From: Manasi Moghe Date: Thu, 21 Dec 2017 12:09:18 +0530 Subject: [PATCH 21/30] rolling back changes for pmzoneid --- modules/pubmaticBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 19f4f932eb7..bdb8f6d4aca 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -162,7 +162,7 @@ function _createImpressionObject(bid, conf) { topframe: utils.inIframe() ? 0 : 1, }, ext: { - pmZoneId: _parseSlotParam('pmzoneid', bid.params.pmzoneid).trim() + pmZoneId: _parseSlotParam('pmzoneid', bid.params.pmzoneid) } }; } From 7072d3c427b8eac34f8bf06bd8e05b138016e01d Mon Sep 17 00:00:00 2001 From: Dattaprasad Mundada Date: Fri, 22 Dec 2017 18:25:44 +0530 Subject: [PATCH 22/30] Add PubMaticBidAdapter param info --- modules/pubmaticBidAdapter.md | 39 +++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 modules/pubmaticBidAdapter.md diff --git a/modules/pubmaticBidAdapter.md b/modules/pubmaticBidAdapter.md new file mode 100644 index 00000000000..7859141528a --- /dev/null +++ b/modules/pubmaticBidAdapter.md @@ -0,0 +1,39 @@ +# Overview + +``` +Module Name: PubMatic Bid Adapter +Module Type: Bidder Adapter +Maintainer: UOEDev@pubmatic.com +``` + +# Description + +Connects to PubMatic exchange for bids. + +PubMatic bid adapter supports Banner currently. + +# Sample Ad Unit: For Publishers +``` +var adUnits = [ +{ + code: 'test-div', + sizes: [ + [300, 250], + [728, 90] + ], + bids: [{ + bidder: 'pubmatic', + params: { + publisherId: '301', // required + adSlot: '/15671365/DMDemo@728x90:0', // required + pmzoneid: 'zone1, zone11', // optional + lat: '40.712775', // optional + lon: '-74.005973', // optional + yob: '1982', // optional + kadpageurl: 'www.test.com', // optional + gender: 'M', // optional + kadfloor: '1.75' // optional + } + }] +} +``` From 23151be16f41299f263a4d79e649bc429c64d304 Mon Sep 17 00:00:00 2001 From: Dattaprasad Mundada Date: Fri, 22 Dec 2017 19:34:22 +0530 Subject: [PATCH 23/30] Update params in pubmaticBidAdapter.md --- modules/pubmaticBidAdapter.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/pubmaticBidAdapter.md b/modules/pubmaticBidAdapter.md index 7859141528a..408dbd9affb 100644 --- a/modules/pubmaticBidAdapter.md +++ b/modules/pubmaticBidAdapter.md @@ -25,14 +25,14 @@ var adUnits = [ bidder: 'pubmatic', params: { publisherId: '301', // required - adSlot: '/15671365/DMDemo@728x90:0', // required + adSlot: '/15671365/DMDemo@728x90', // required pmzoneid: 'zone1, zone11', // optional lat: '40.712775', // optional lon: '-74.005973', // optional yob: '1982', // optional kadpageurl: 'www.test.com', // optional gender: 'M', // optional - kadfloor: '1.75' // optional + kadfloor: '0.50' // optional } }] } From 6ed1a464ebbb1bd370b04e62282daa2235cb36f2 Mon Sep 17 00:00:00 2001 From: Dattaprasad Mundada Date: Wed, 3 Jan 2018 21:47:18 +0530 Subject: [PATCH 24/30] Update maintainer mail-id --- modules/pubmaticBidAdapter.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/pubmaticBidAdapter.md b/modules/pubmaticBidAdapter.md index 408dbd9affb..20fa178d8e7 100644 --- a/modules/pubmaticBidAdapter.md +++ b/modules/pubmaticBidAdapter.md @@ -3,7 +3,7 @@ ``` Module Name: PubMatic Bid Adapter Module Type: Bidder Adapter -Maintainer: UOEDev@pubmatic.com +Maintainer: header-bidding@pubmatic.com ``` # Description From d81bf1cf3f2b2726a6d4230a00f0a41f2cd70810 Mon Sep 17 00:00:00 2001 From: Manasi Moghe Date: Thu, 4 Jan 2018 14:39:52 +0530 Subject: [PATCH 25/30] endpoint changed to hbopenbid.pubmatic.com, netRevenue default value changed to false, test cases updated --- modules/pubmaticBidAdapter.js | 5 +++-- test/spec/modules/pubmaticBidAdapter_spec.js | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index bdb8f6d4aca..47623f3d69f 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -3,7 +3,7 @@ import { registerBidder } from 'src/adapters/bidderFactory'; const constants = require('src/constants.json'); const BIDDER_CODE = 'pubmatic'; -const ENDPOINT = '//openbid.pubmatic.com/translator?source=prebid-client'; +const ENDPOINT = '//hbopenbid.pubmatic.com/translator?source=prebid-client'; const USYNCURL = '//ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p='; const CURRENCY = 'USD'; const AUCTION_TYPE = 2; @@ -18,6 +18,7 @@ const CUSTOM_PARAMS = { 'profId': '', // OpenWrap Legacy: Profile ID 'verId': '' // OpenWrap Legacy: version ID }; +const NET_REVENUE = false; let publisherId = 0; @@ -262,7 +263,7 @@ export const spec = { creativeId: bid.crid || bid.id, dealId: bid.dealid, currency: CURRENCY, - netRevenue: true, + netRevenue: NET_REVENUE, ttl: 300, referrer: utils.getTopWindowUrl(), ad: bid.adm diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 49d60d45947..1259ef6d6d5 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -115,7 +115,7 @@ describe('PubMatic adapter', () => { describe('Request formation', () => { it('Endpoint checking', () => { let request = spec.buildRequests(bidRequests); - expect(request.url).to.equal('//openbid.pubmatic.com/translator?source=prebid-client'); + expect(request.url).to.equal('//hbopenbid.pubmatic.com/translator?source=prebid-client'); expect(request.method).to.equal('POST'); }); @@ -170,7 +170,7 @@ describe('PubMatic adapter', () => { } expect(response[0].dealId).to.equal(bidResponses.body.seatbid[0].bid[0].dealid); expect(response[0].currency).to.equal('USD'); - expect(response[0].netRevenue).to.equal(true); + expect(response[0].netRevenue).to.equal(false); expect(response[0].ttl).to.equal(300); expect(response[0].referrer).to.include(utils.getTopWindowUrl()); expect(response[0].ad).to.equal(bidResponses.body.seatbid[0].bid[0].adm); From 23d990d170d8ca1b07c46d3063ddf967eb386300 Mon Sep 17 00:00:00 2001 From: PubMatic-OpenWrap Date: Fri, 5 Jan 2018 10:43:18 -0800 Subject: [PATCH 26/30] changed auction type to 1 --- modules/pubmaticBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 47623f3d69f..39c7566d38d 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -6,7 +6,7 @@ const BIDDER_CODE = 'pubmatic'; const ENDPOINT = '//hbopenbid.pubmatic.com/translator?source=prebid-client'; const USYNCURL = '//ads.pubmatic.com/AdServer/js/showad.js#PIX&kdntuid=1&p='; const CURRENCY = 'USD'; -const AUCTION_TYPE = 2; +const AUCTION_TYPE = 1; const UNDEFINED = undefined; const CUSTOM_PARAMS = { 'kadpageurl': '', // Custom page url From 8f5652ae12a74def386836cd399de8d8cd4833e9 Mon Sep 17 00:00:00 2001 From: PubMatic-OpenWrap Date: Fri, 5 Jan 2018 10:45:39 -0800 Subject: [PATCH 27/30] changed at to 1 in test cases --- test/spec/modules/pubmaticBidAdapter_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/modules/pubmaticBidAdapter_spec.js b/test/spec/modules/pubmaticBidAdapter_spec.js index 1259ef6d6d5..cbf17f9478a 100644 --- a/test/spec/modules/pubmaticBidAdapter_spec.js +++ b/test/spec/modules/pubmaticBidAdapter_spec.js @@ -122,7 +122,7 @@ describe('PubMatic adapter', () => { it('Request params check', () => { let request = spec.buildRequests(bidRequests); let data = JSON.parse(request.data); - expect(data.at).to.equal(2); // auction type + 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 From 2ac7153c4d17dee0898ce80f437458afe4b805a8 Mon Sep 17 00:00:00 2001 From: PubMatic-OpenWrap Date: Wed, 10 Jan 2018 18:01:05 -0800 Subject: [PATCH 28/30] removed comments --- modules/pubmaticBidAdapter.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/pubmaticBidAdapter.js b/modules/pubmaticBidAdapter.js index 39c7566d38d..dfcde047580 100644 --- a/modules/pubmaticBidAdapter.js +++ b/modules/pubmaticBidAdapter.js @@ -95,17 +95,14 @@ function _initConf() { } function _handleCustomParams(params, conf) { - // istanbul ignore else if (!conf.kadpageurl) { conf.kadpageurl = conf.pageURL; } var key, value, entry; for (key in CUSTOM_PARAMS) { - // istanbul ignore else if (CUSTOM_PARAMS.hasOwnProperty(key)) { value = params[key]; - // istanbul ignore else if (value) { entry = CUSTOM_PARAMS[key]; @@ -190,7 +187,6 @@ export const spec = { return true; } return false; - // return !!(bid && bid.params && utils.isStr(bid.params.publisherId) && utils.isStr(bid.params.adSlot)); }, /** From b039912de4b1762253478c4f3e9240c1ebd401f3 Mon Sep 17 00:00:00 2001 From: PubMatic-OpenWrap Date: Wed, 10 Jan 2018 18:05:40 -0800 Subject: [PATCH 29/30] UserSync requirements are mentioned in .md file --- modules/pubmaticBidAdapter.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/modules/pubmaticBidAdapter.md b/modules/pubmaticBidAdapter.md index 20fa178d8e7..bcdad3d2357 100644 --- a/modules/pubmaticBidAdapter.md +++ b/modules/pubmaticBidAdapter.md @@ -37,3 +37,17 @@ var adUnits = [ }] } ``` + +### Configuration + +PubMatic recommends the UserSync configuration below. Without it, the PubMatic adapter will not able to perform user syncs, which lowers match rate and reduces monetization. + +```javascript +pbjs.setConfig({ + userSync: { + iframeEnabled: true, + enabledBidders: ['pubmatic'], + syncDelay: 6000 + }}); +``` +Note: Combine the above the configuration with any other UserSync configuration. Multiple setConfig() calls overwrite each other and only last call for a given attribute will take effect. From bd9ad84e318a52caed1be8178632d283e23491d2 Mon Sep 17 00:00:00 2001 From: PubMatic-OpenWrap Date: Wed, 10 Jan 2018 18:08:50 -0800 Subject: [PATCH 30/30] updated test ids --- modules/pubmaticBidAdapter.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/pubmaticBidAdapter.md b/modules/pubmaticBidAdapter.md index bcdad3d2357..768b3c541f6 100644 --- a/modules/pubmaticBidAdapter.md +++ b/modules/pubmaticBidAdapter.md @@ -24,8 +24,8 @@ var adUnits = [ bids: [{ bidder: 'pubmatic', params: { - publisherId: '301', // required - adSlot: '/15671365/DMDemo@728x90', // required + publisherId: '156209', // required + adSlot: 'pubmatic_test2@300x250', // required pmzoneid: 'zone1, zone11', // optional lat: '40.712775', // optional lon: '-74.005973', // optional