From 16b961727c28decc5b7a1d7a50320a64498b6859 Mon Sep 17 00:00:00 2001 From: Yuriy Date: Mon, 30 Jan 2017 14:16:52 +0200 Subject: [PATCH 01/31] Vertamedia prebid.js adapter initial --- adapters.json | 8 +- src/adapters/vertamedia.js | 101 ++++++++++++++++++ test/spec/adapters/vertamedia_spec.js | 147 ++++++++++++++++++++++++++ 3 files changed, 253 insertions(+), 3 deletions(-) create mode 100644 src/adapters/vertamedia.js create mode 100644 test/spec/adapters/vertamedia_spec.js diff --git a/adapters.json b/adapters.json index dd928df7c95..671df7a04b2 100644 --- a/adapters.json +++ b/adapters.json @@ -6,6 +6,7 @@ "adform", "adkernel", "admedia", + "vertamedia", "aol", "appnexus", "appnexusAst", @@ -38,14 +39,11 @@ "jcm", "underdogmedia", "memeglobal", - "criteo", "centro", - "xhb", "sharethrough", "roxot", "vertoz", "widespace", - "admixer", { "appnexus": { "alias": "brealtime" @@ -65,6 +63,10 @@ "appnexusAst": { "supportedMediaTypes": ["video"] } + }, { + "vertamedia": { + "supportedMediaTypes": ["video"] + } }, { "rubicon": { diff --git a/src/adapters/vertamedia.js b/src/adapters/vertamedia.js new file mode 100644 index 00000000000..248b6f2361c --- /dev/null +++ b/src/adapters/vertamedia.js @@ -0,0 +1,101 @@ +import Adapter from 'src/adapters/adapter'; +import bidfactory from 'src/bidfactory'; +import bidmanager from 'src/bidmanager'; +import * as utils from 'src/utils'; +import { ajax } from 'src/ajax'; +import { STATUS } from 'src/constants'; + +const ENDPOINT = 'http://rtb.vertamedia.com/hb/'; + +function VertamediaAdapter() { + let baseAdapter = Adapter.createNew('Vertamedia'), + bidRequest; + + baseAdapter.callBids = function (bidRequests) { + if (!bidRequests || !bidRequests.bids || bidRequests.bids.length == 0) { + return; + } + + var RTBDataParams = prepareAndSaveRTBRequestParams(bidRequests.bids[0]); + + if (!RTBDataParams) { + return; + } + + ajax(ENDPOINT, handleResponse, RTBDataParams, { + contentType: 'text/plain', + withCredentials: true, + method: 'GET' + }); + }; + + function prepareAndSaveRTBRequestParams(bid) { + if (!bid || !bid.params || !bid.params.aid || !bid.placementCode) { + return; + } + + bidRequest = bid; + bidRequest.width = parseInt(bid.sizes[0], 10) || undefined; + bidRequest.height = parseInt(bid.sizes[1], 10) || undefined; + + return { + aid: bid.params.aid, + w: parseInt(bid.sizes[0], 10) || undefined, + h: parseInt(bid.sizes[1], 10) || undefined, + domain: document.location.hostname + }; + } + + /* Notify Prebid of bid responses so bids can get in the auction */ + function handleResponse(response) { + let parsed; + + try { + parsed = JSON.parse(response); + } catch (error) { + utils.logError(error); + } + + if (!parsed || parsed.error || !parsed.bids || !parsed.bids.length) { + utils.logError(`in response for ${baseAdapter.getBidderCode()} adapter`); + bidmanager.addBidResponse(bidRequest.placementCode, createBid(STATUS.NO_BID)); + + return; + } + + bidmanager.addBidResponse(bidRequest.placementCode, createBid(STATUS.GOOD, parsed.bids[0])); + } + + function createBid(status, tag) { + let bid = bidfactory.createBid(status, tag); + + bid.code = baseAdapter.getBidderCode(); + bid.bidderCode = bidRequest.bidder; + + if (!tag || status !== STATUS.GOOD) { + return bid; + } + + bid.mediaType = 'video'; + bid.cpm = tag.cpm; + bid.creative_id = tag.cmpId; + bid.width = bidRequest.width; + bid.height = bidRequest.height; + bid.vastUrl = tag.url; + + return bid; + } + + return { + createNew: VertamediaAdapter.createNew, + callBids: baseAdapter.callBids, + setBidderCode: baseAdapter.setBidderCode + }; + +} + +VertamediaAdapter.createNew = function () { + return new VertamediaAdapter(); +}; + +module.exports = VertamediaAdapter; diff --git a/test/spec/adapters/vertamedia_spec.js b/test/spec/adapters/vertamedia_spec.js new file mode 100644 index 00000000000..2b6e9e466e4 --- /dev/null +++ b/test/spec/adapters/vertamedia_spec.js @@ -0,0 +1,147 @@ +import { expect } from 'chai'; +import Adapter from 'src/adapters/vertamedia'; +import bidmanager from 'src/bidmanager'; + +const ENDPOINT = 'http://rtb.vertamedia.com/hb/?aid=22489&w=640&h=480&domain=localhost'; + +const REQUEST = { + "bidderCode": "vertamedia", + "requestId": "d3e07445-ab06-44c8-a9dd-5ef9af06d2a6", + "bidderRequestId": "7101db09af0db2", + "bids": [ + { + "bidder": "vertamedia", + "params": { + aid: 22489, + placementId: '123456' + }, + "placementCode": "/19968336/header-bid-tag1", + "sizes": [640, 480], + "bidId": "84ab500420319d", + "bidderRequestId": "7101db09af0db2", + "requestId": "d3e07445-ab06-44c8-a9dd-5ef9af06d2a6" + } + ], + "start": 1469479810130 +}; +var RESPONSE = { + "source": { + "aid": 22489, + "pubId": 18016, + "sid": "0" + }, + "bids": [ + { + "cmpId": 9541, + "cpm": 4.5, + "url": "http://rtb.vertamedia.com/vast?adid=BFDB9CC0038AD918", + "cur": "USD" + } + ] +}; + + +describe('VertamediaAdater', () => { + + let adapter; + + beforeEach(() => adapter = Adapter.createNew()); + + describe('request function', () => { + + let xhr; + let requests; + + beforeEach(() => { + xhr = sinon.useFakeXMLHttpRequest(); + requests = []; + xhr.onCreate = request => requests.push(request); + }); + + afterEach(() => xhr.restore()); + + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + + it('requires paramters to make request', () => { + adapter.callBids({}); + expect(requests).to.be.empty; + }); + + it('requires member && invCode', () => { + let backup = REQUEST.bids[0].params; + REQUEST.bids[0].params = {member: 1234}; + adapter.callBids(REQUEST); + expect(requests).to.be.empty; + REQUEST.bids[0].params = backup; + }); + + + it('sends bid request to ENDPOINT via POST', () => { + adapter.callBids(REQUEST); + expect(requests[0].url).to.equal(ENDPOINT); + expect(requests[0].method).to.equal('GET'); + }); + + }); + + describe('response handler', () => { + + let server; + + beforeEach(() => { + server = sinon.fakeServer.create(); + sinon.stub(bidmanager, 'addBidResponse'); + }); + + afterEach(() => { + server.restore(); + bidmanager.addBidResponse.restore(); + }); + + it('registers bids', () => { + server.respondWith(JSON.stringify(RESPONSE)); + + adapter.callBids(REQUEST); + server.respond(); + sinon.assert.calledOnce(bidmanager.addBidResponse); + + const response = bidmanager.addBidResponse.firstCall.args[1]; + expect(response).to.have.property('statusMessage', 'Bid available'); + expect(response).to.have.property('cpm', 4.5); + }); + + it('handles nobid responses', () => { + server.respondWith(JSON.stringify({ + aid: 356465468, + w: 640, + h: 480, + domain: 'localhost' + })); + + adapter.callBids(REQUEST); + server.respond(); + sinon.assert.calledOnce(bidmanager.addBidResponse); + + const response = bidmanager.addBidResponse.firstCall.args[1]; + expect(response).to.have.property( + 'statusMessage', + 'Bid returned empty or error response' + ); + }); + + it('handles JSON.parse errors', () => { + server.respondWith(''); + + adapter.callBids(REQUEST); + server.respond(); + sinon.assert.calledOnce(bidmanager.addBidResponse); + + expect(bidmanager.addBidResponse.firstCall.args[1]).to.have.property( + 'statusMessage', + 'Bid returned empty or error response' + ); + }); + }); +}); From 267f04c4b2e081daef52900286f54d6d42ab6951 Mon Sep 17 00:00:00 2001 From: Yuriy Date: Mon, 30 Jan 2017 14:20:27 +0200 Subject: [PATCH 02/31] sync --- adapters.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/adapters.json b/adapters.json index 671df7a04b2..a2bebb8d5f0 100644 --- a/adapters.json +++ b/adapters.json @@ -39,11 +39,14 @@ "jcm", "underdogmedia", "memeglobal", + "criteo", "centro", + "xhb", "sharethrough", "roxot", "vertoz", "widespace", + "admixer", { "appnexus": { "alias": "brealtime" From 99a311f1f31b7180d0a333ef0e5226fdef07dcf9 Mon Sep 17 00:00:00 2001 From: Yuriy Date: Mon, 30 Jan 2017 14:23:18 +0200 Subject: [PATCH 03/31] remove https --- src/adapters/vertamedia.js | 2 +- test/spec/adapters/vertamedia_spec.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/adapters/vertamedia.js b/src/adapters/vertamedia.js index 248b6f2361c..c154d200e18 100644 --- a/src/adapters/vertamedia.js +++ b/src/adapters/vertamedia.js @@ -5,7 +5,7 @@ import * as utils from 'src/utils'; import { ajax } from 'src/ajax'; import { STATUS } from 'src/constants'; -const ENDPOINT = 'http://rtb.vertamedia.com/hb/'; +const ENDPOINT = '//rtb.vertamedia.com/hb/'; function VertamediaAdapter() { let baseAdapter = Adapter.createNew('Vertamedia'), diff --git a/test/spec/adapters/vertamedia_spec.js b/test/spec/adapters/vertamedia_spec.js index 2b6e9e466e4..64e2cae55ea 100644 --- a/test/spec/adapters/vertamedia_spec.js +++ b/test/spec/adapters/vertamedia_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import Adapter from 'src/adapters/vertamedia'; import bidmanager from 'src/bidmanager'; -const ENDPOINT = 'http://rtb.vertamedia.com/hb/?aid=22489&w=640&h=480&domain=localhost'; +const ENDPOINT = '//rtb.vertamedia.com/hb/?aid=22489&w=640&h=480&domain=localhost'; const REQUEST = { "bidderCode": "vertamedia", From f861ad256932ac1e9c85fa1997b5223e715e0e49 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Mon, 30 Jan 2017 14:54:04 +0200 Subject: [PATCH 04/31] add http --- test/spec/adapters/vertamedia_spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/spec/adapters/vertamedia_spec.js b/test/spec/adapters/vertamedia_spec.js index 64e2cae55ea..2b6e9e466e4 100644 --- a/test/spec/adapters/vertamedia_spec.js +++ b/test/spec/adapters/vertamedia_spec.js @@ -2,7 +2,7 @@ import { expect } from 'chai'; import Adapter from 'src/adapters/vertamedia'; import bidmanager from 'src/bidmanager'; -const ENDPOINT = '//rtb.vertamedia.com/hb/?aid=22489&w=640&h=480&domain=localhost'; +const ENDPOINT = 'http://rtb.vertamedia.com/hb/?aid=22489&w=640&h=480&domain=localhost'; const REQUEST = { "bidderCode": "vertamedia", From 8295748fa1779108af8310ea01f677155265358b Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Mon, 30 Jan 2017 15:27:59 +0200 Subject: [PATCH 05/31] remove let --- src/adapters/vertamedia.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/adapters/vertamedia.js b/src/adapters/vertamedia.js index c154d200e18..e59faab6c28 100644 --- a/src/adapters/vertamedia.js +++ b/src/adapters/vertamedia.js @@ -8,7 +8,7 @@ import { STATUS } from 'src/constants'; const ENDPOINT = '//rtb.vertamedia.com/hb/'; function VertamediaAdapter() { - let baseAdapter = Adapter.createNew('Vertamedia'), + var baseAdapter = Adapter.createNew('Vertamedia'), bidRequest; baseAdapter.callBids = function (bidRequests) { @@ -48,7 +48,7 @@ function VertamediaAdapter() { /* Notify Prebid of bid responses so bids can get in the auction */ function handleResponse(response) { - let parsed; + var parsed; try { parsed = JSON.parse(response); @@ -67,7 +67,7 @@ function VertamediaAdapter() { } function createBid(status, tag) { - let bid = bidfactory.createBid(status, tag); + var bid = bidfactory.createBid(status, tag); bid.code = baseAdapter.getBidderCode(); bid.bidderCode = bidRequest.bidder; From 9738c9a7eff0c162cdaa100691897ea09a150fd4 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Mon, 30 Jan 2017 15:34:19 +0200 Subject: [PATCH 06/31] fix typo --- src/adapters/vertamedia.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adapters/vertamedia.js b/src/adapters/vertamedia.js index e59faab6c28..d7f119e5c3d 100644 --- a/src/adapters/vertamedia.js +++ b/src/adapters/vertamedia.js @@ -8,7 +8,7 @@ import { STATUS } from 'src/constants'; const ENDPOINT = '//rtb.vertamedia.com/hb/'; function VertamediaAdapter() { - var baseAdapter = Adapter.createNew('Vertamedia'), + var baseAdapter = Adapter.createNew('vertamedia'), bidRequest; baseAdapter.callBids = function (bidRequests) { From ec830c3d6c32680fcab61dc0473e6d859f69b9cf Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Mon, 30 Jan 2017 15:56:06 +0200 Subject: [PATCH 07/31] fix spaces --- src/adapters/vertamedia.js | 132 ++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/src/adapters/vertamedia.js b/src/adapters/vertamedia.js index d7f119e5c3d..1b6c1978364 100644 --- a/src/adapters/vertamedia.js +++ b/src/adapters/vertamedia.js @@ -8,94 +8,94 @@ import { STATUS } from 'src/constants'; const ENDPOINT = '//rtb.vertamedia.com/hb/'; function VertamediaAdapter() { - var baseAdapter = Adapter.createNew('vertamedia'), - bidRequest; + var baseAdapter = Adapter.createNew('vertamedia'), + bidRequest; - baseAdapter.callBids = function (bidRequests) { - if (!bidRequests || !bidRequests.bids || bidRequests.bids.length == 0) { - return; - } + baseAdapter.callBids = function (bidRequests) { + if (!bidRequests || !bidRequests.bids || bidRequests.bids.length === 0) { + return; + } - var RTBDataParams = prepareAndSaveRTBRequestParams(bidRequests.bids[0]); + var RTBDataParams = prepareAndSaveRTBRequestParams(bidRequests.bids[0]); - if (!RTBDataParams) { - return; - } + if (!RTBDataParams) { + return; + } - ajax(ENDPOINT, handleResponse, RTBDataParams, { - contentType: 'text/plain', - withCredentials: true, - method: 'GET' - }); - }; + ajax(ENDPOINT, handleResponse, RTBDataParams, { + contentType: 'text/plain', + withCredentials: true, + method: 'GET' + }); + }; - function prepareAndSaveRTBRequestParams(bid) { - if (!bid || !bid.params || !bid.params.aid || !bid.placementCode) { - return; - } - - bidRequest = bid; - bidRequest.width = parseInt(bid.sizes[0], 10) || undefined; - bidRequest.height = parseInt(bid.sizes[1], 10) || undefined; - - return { - aid: bid.params.aid, - w: parseInt(bid.sizes[0], 10) || undefined, - h: parseInt(bid.sizes[1], 10) || undefined, - domain: document.location.hostname - }; + function prepareAndSaveRTBRequestParams(bid) { + if (!bid || !bid.params || !bid.params.aid || !bid.placementCode) { + return; } - /* Notify Prebid of bid responses so bids can get in the auction */ - function handleResponse(response) { - var parsed; + bidRequest = bid; + bidRequest.width = parseInt(bid.sizes[0], 10) || undefined; + bidRequest.height = parseInt(bid.sizes[1], 10) || undefined; - try { - parsed = JSON.parse(response); - } catch (error) { - utils.logError(error); - } - - if (!parsed || parsed.error || !parsed.bids || !parsed.bids.length) { - utils.logError(`in response for ${baseAdapter.getBidderCode()} adapter`); - bidmanager.addBidResponse(bidRequest.placementCode, createBid(STATUS.NO_BID)); + return { + aid: bid.params.aid, + w: parseInt(bid.sizes[0], 10) || undefined, + h: parseInt(bid.sizes[1], 10) || undefined, + domain: document.location.hostname + }; + } - return; - } + /* Notify Prebid of bid responses so bids can get in the auction */ + function handleResponse(response) { + var parsed; - bidmanager.addBidResponse(bidRequest.placementCode, createBid(STATUS.GOOD, parsed.bids[0])); + try { + parsed = JSON.parse(response); + } catch (error) { + utils.logError(error); } - function createBid(status, tag) { - var bid = bidfactory.createBid(status, tag); + if (!parsed || parsed.error || !parsed.bids || !parsed.bids.length) { + utils.logError(`in response for ${baseAdapter.getBidderCode()} adapter`); + bidmanager.addBidResponse(bidRequest.placementCode, createBid(STATUS.NO_BID)); - bid.code = baseAdapter.getBidderCode(); - bid.bidderCode = bidRequest.bidder; + return; + } + + bidmanager.addBidResponse(bidRequest.placementCode, createBid(STATUS.GOOD, parsed.bids[0])); + } - if (!tag || status !== STATUS.GOOD) { - return bid; - } + function createBid(status, tag) { + var bid = bidfactory.createBid(status, tag); - bid.mediaType = 'video'; - bid.cpm = tag.cpm; - bid.creative_id = tag.cmpId; - bid.width = bidRequest.width; - bid.height = bidRequest.height; - bid.vastUrl = tag.url; + bid.code = baseAdapter.getBidderCode(); + bid.bidderCode = bidRequest.bidder; - return bid; + if (!tag || status !== STATUS.GOOD) { + return bid; } - return { - createNew: VertamediaAdapter.createNew, - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode - }; + bid.mediaType = 'video'; + bid.cpm = tag.cpm; + bid.creative_id = tag.cmpId; + bid.width = bidRequest.width; + bid.height = bidRequest.height; + bid.vastUrl = tag.url; + + return bid; + } + + return { + createNew: VertamediaAdapter.createNew, + callBids: baseAdapter.callBids, + setBidderCode: baseAdapter.setBidderCode + }; } VertamediaAdapter.createNew = function () { - return new VertamediaAdapter(); + return new VertamediaAdapter(); }; module.exports = VertamediaAdapter; From ec77d6daf9b4e1e12efb08c65cfc815eee224f94 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Mon, 6 Feb 2017 10:41:51 +0200 Subject: [PATCH 08/31] add descriptionUrl; remove log --- src/adapters/vertamedia.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adapters/vertamedia.js b/src/adapters/vertamedia.js index 1b6c1978364..ea9e5402b09 100644 --- a/src/adapters/vertamedia.js +++ b/src/adapters/vertamedia.js @@ -57,7 +57,6 @@ function VertamediaAdapter() { } if (!parsed || parsed.error || !parsed.bids || !parsed.bids.length) { - utils.logError(`in response for ${baseAdapter.getBidderCode()} adapter`); bidmanager.addBidResponse(bidRequest.placementCode, createBid(STATUS.NO_BID)); return; @@ -81,6 +80,7 @@ function VertamediaAdapter() { bid.creative_id = tag.cmpId; bid.width = bidRequest.width; bid.height = bidRequest.height; + bid.descriptionUrl = tag.url; bid.vastUrl = tag.url; return bid; From d346ac87c3f5ca75231fa88a4100fdc57e0b3ecd Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Wed, 22 Mar 2017 15:07:10 +0200 Subject: [PATCH 09/31] fix getSize --- src/adapters/vertamedia.js | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/adapters/vertamedia.js b/src/adapters/vertamedia.js index ea9e5402b09..6fa3fe60f2a 100644 --- a/src/adapters/vertamedia.js +++ b/src/adapters/vertamedia.js @@ -35,17 +35,42 @@ function VertamediaAdapter() { } bidRequest = bid; - bidRequest.width = parseInt(bid.sizes[0], 10) || undefined; - bidRequest.height = parseInt(bid.sizes[1], 10) || undefined; + + let size = getSizes(bid.sizes)[0]; + + bidRequest.width = size.width; + bidRequest.height = size.height; return { aid: bid.params.aid, - w: parseInt(bid.sizes[0], 10) || undefined, - h: parseInt(bid.sizes[1], 10) || undefined, + w: size.width, + h: size.height, domain: document.location.hostname }; } + function getSizes(requestSizes) { + let sizes = []; + let sizeObj = {}; + + if (utils.isArray(requestSizes) && requestSizes.length === 2 && + !utils.isArray(requestSizes[0])) { + sizeObj.width = parseInt(requestSizes[0], 10); + sizeObj.height = parseInt(requestSizes[1], 10); + sizes.push(sizeObj); + } else if (typeof requestSizes === 'object') { + for (let i = 0; i < requestSizes.length; i++) { + let size = requestSizes[i]; + sizeObj = {}; + sizeObj.width = parseInt(size[0], 10); + sizeObj.height = parseInt(size[1], 10); + sizes.push(sizeObj); + } + } + + return sizes; + } + /* Notify Prebid of bid responses so bids can get in the auction */ function handleResponse(response) { var parsed; From edc9745f5204b0f037593812899540727584cf54 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Thu, 23 Mar 2017 15:36:22 +0200 Subject: [PATCH 10/31] add usege parseSizesInput --- src/adapters/vertamedia.js | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/adapters/vertamedia.js b/src/adapters/vertamedia.js index 6fa3fe60f2a..13f036764d7 100644 --- a/src/adapters/vertamedia.js +++ b/src/adapters/vertamedia.js @@ -36,7 +36,7 @@ function VertamediaAdapter() { bidRequest = bid; - let size = getSizes(bid.sizes)[0]; + let size = getSize(bid.sizes); bidRequest.width = size.width; bidRequest.height = size.height; @@ -49,26 +49,20 @@ function VertamediaAdapter() { }; } - function getSizes(requestSizes) { - let sizes = []; - let sizeObj = {}; - - if (utils.isArray(requestSizes) && requestSizes.length === 2 && - !utils.isArray(requestSizes[0])) { - sizeObj.width = parseInt(requestSizes[0], 10); - sizeObj.height = parseInt(requestSizes[1], 10); - sizes.push(sizeObj); - } else if (typeof requestSizes === 'object') { - for (let i = 0; i < requestSizes.length; i++) { - let size = requestSizes[i]; - sizeObj = {}; - sizeObj.width = parseInt(size[0], 10); - sizeObj.height = parseInt(size[1], 10); - sizes.push(sizeObj); - } + function getSize(requestSizes) { + var parsed = {}, + size = utils.parseSizesInput(requestSizes)[0]; + + if (typeof size !== 'string') { + return parsed; } - return sizes; + let parsedSize = size.toUpperCase().split('X'); + + return { + width: parseInt(parsedSize[0], 10) || undefined, + height: parseInt(parsedSize[1], 10) || undefined + }; } /* Notify Prebid of bid responses so bids can get in the auction */ From 82b2830d332d242ade1a3c6135e357fb2cf1c268 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Tue, 24 Oct 2017 19:38:38 +0300 Subject: [PATCH 11/31] Add support for vastTag --- src/adapters/vertamedia.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/adapters/vertamedia.js b/src/adapters/vertamedia.js index 13f036764d7..0609c492079 100644 --- a/src/adapters/vertamedia.js +++ b/src/adapters/vertamedia.js @@ -100,7 +100,7 @@ function VertamediaAdapter() { bid.width = bidRequest.width; bid.height = bidRequest.height; bid.descriptionUrl = tag.url; - bid.vastUrl = tag.url; + bid.vastUrl = tag.vastUrl; return bid; } From afcc529340060d8094b9b84c7ddfa115c239e20f Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Wed, 25 Oct 2017 13:46:04 +0300 Subject: [PATCH 12/31] Add moulty bid request; set vastUrl for bider; --- modules/vertamediaBidAdapter.js | 51 +++++++++++++++++---------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index 37e846e85be..78ce4ebb302 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -1,33 +1,36 @@ -import Adapter from 'src/adapter'; -import bidfactory from 'src/bidfactory'; -import bidmanager from 'src/bidmanager'; -import * as utils from 'src/utils'; -import { ajax } from 'src/ajax'; -import { STATUS } from 'src/constants'; -import adaptermanager from 'src/adaptermanager'; +import Adapter from "src/adapter"; +import bidfactory from "src/bidfactory"; +import bidmanager from "src/bidmanager"; +import * as utils from "src/utils"; +import {ajax} from "src/ajax"; +import {STATUS} from "src/constants"; +import adaptermanager from "src/adaptermanager"; const ENDPOINT = '//rtb.vertamedia.com/hb/'; function VertamediaAdapter() { const baseAdapter = new Adapter('vertamedia'); - let bidRequest; baseAdapter.callBids = function (bidRequests) { if (!bidRequests || !bidRequests.bids || bidRequests.bids.length === 0) { return; } - var RTBDataParams = prepareAndSaveRTBRequestParams(bidRequests.bids[0]); + for (var i = 0; i < bidRequests.bids.length; i++) { + var prepData = prepareAndSaveRTBRequestParams(bidRequests.bids[i]) + var bidRequest = prepData[0]; + var RTBDataParams = prepData[1]; - if (!RTBDataParams) { - return; - } + if (!RTBDataParams) { + return; + } - ajax(ENDPOINT, handleResponse, RTBDataParams, { - contentType: 'text/plain', - withCredentials: true, - method: 'GET' - }); + ajax(ENDPOINT, handleResponse.bind(null, bidRequest), RTBDataParams, { + contentType: 'text/plain', + withCredentials: true, + method: 'GET' + }); + } }; function prepareAndSaveRTBRequestParams(bid) { @@ -35,19 +38,19 @@ function VertamediaAdapter() { return; } - bidRequest = bid; + let bidRequest = bid; let size = getSize(bid.sizes); bidRequest.width = size.width; bidRequest.height = size.height; - return { + return [bidRequest, { aid: bid.params.aid, w: size.width, h: size.height, domain: document.location.hostname - }; + }]; } function getSize(requestSizes) { @@ -67,7 +70,7 @@ function VertamediaAdapter() { } /* Notify Prebid of bid responses so bids can get in the auction */ - function handleResponse(response) { + function handleResponse(bidRequest, response) { var parsed; try { @@ -77,15 +80,15 @@ function VertamediaAdapter() { } if (!parsed || parsed.error || !parsed.bids || !parsed.bids.length) { - bidmanager.addBidResponse(bidRequest.placementCode, createBid(STATUS.NO_BID)); + bidmanager.addBidResponse(bidRequest.placementCode, createBid(bidRequest, STATUS.NO_BID)); return; } - bidmanager.addBidResponse(bidRequest.placementCode, createBid(STATUS.GOOD, parsed.bids[0])); + bidmanager.addBidResponse(bidRequest.placementCode, createBid(bidRequest, STATUS.GOOD, parsed.bids[0])); } - function createBid(status, tag) { + function createBid(bidRequest, status, tag) { var bid = bidfactory.createBid(status, tag); bid.code = baseAdapter.getBidderCode(); From f3e6eaac366e4a17a66be9636a185fdffb2ec4f6 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Wed, 1 Nov 2017 12:20:41 +0200 Subject: [PATCH 13/31] update for vertamedia adapter to Prebid 1.0 --- modules/vertamediaBidAdapter.js | 223 +++++++++--------- .../spec/modules/vertamediaBidAdapter_spec.js | 209 ++++++++-------- 2 files changed, 214 insertions(+), 218 deletions(-) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index 78ce4ebb302..15ea5b3fa07 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -1,122 +1,123 @@ -import Adapter from "src/adapter"; -import bidfactory from "src/bidfactory"; -import bidmanager from "src/bidmanager"; -import * as utils from "src/utils"; -import {ajax} from "src/ajax"; -import {STATUS} from "src/constants"; -import adaptermanager from "src/adaptermanager"; - -const ENDPOINT = '//rtb.vertamedia.com/hb/'; - -function VertamediaAdapter() { - const baseAdapter = new Adapter('vertamedia'); - - baseAdapter.callBids = function (bidRequests) { - if (!bidRequests || !bidRequests.bids || bidRequests.bids.length === 0) { - return; - } - - for (var i = 0; i < bidRequests.bids.length; i++) { - var prepData = prepareAndSaveRTBRequestParams(bidRequests.bids[i]) - var bidRequest = prepData[0]; - var RTBDataParams = prepData[1]; - - if (!RTBDataParams) { - return; - } - - ajax(ENDPOINT, handleResponse.bind(null, bidRequest), RTBDataParams, { +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; +import {VIDEO} from 'src/mediaTypes'; + +const URL = '//rtb.vertamedia.com/hb/'; +const BIDDER_CODE = 'vertamedia'; + +export const spec = { + code: BIDDER_CODE, + supportedMediaTypes: [VIDEO], + isBidRequestValid: function (bid) { + return Boolean(bid && bid.params && bid.params.aid); + }, + + /** + * Make a server request from the list of BidRequests + * @param bidRequests + * @param bidderRequest + */ + buildRequests: function (bidRequests, bidderRequest) { + return bidRequests.map((bid) => { + return { contentType: 'text/plain', withCredentials: true, - method: 'GET' - }); - } - }; - - function prepareAndSaveRTBRequestParams(bid) { - if (!bid || !bid.params || !bid.params.aid || !bid.placementCode) { - return; - } - - let bidRequest = bid; - - let size = getSize(bid.sizes); - - bidRequest.width = size.width; - bidRequest.height = size.height; - - return [bidRequest, { - aid: bid.params.aid, - w: size.width, - h: size.height, - domain: document.location.hostname - }]; - } - - function getSize(requestSizes) { - const parsed = {}; - const size = utils.parseSizesInput(requestSizes)[0]; - - if (typeof size !== 'string') { - return parsed; - } - - let parsedSize = size.toUpperCase().split('X'); - - return { - width: parseInt(parsedSize[0], 10) || undefined, - height: parseInt(parsedSize[1], 10) || undefined - }; - } - - /* Notify Prebid of bid responses so bids can get in the auction */ - function handleResponse(bidRequest, response) { - var parsed; - - try { - parsed = JSON.parse(response); - } catch (error) { - utils.logError(error); + method: 'GET', + url: URL, + data: prepareRTBRequestParams(bid), + bidderRequest + } + }); + }, + + /** + * Unpack the response from the server into a list of bids + * @param serverResponse + * @param bidderRequest + * @return {Bid[]} An array of bids which were nested inside the server + */ + interpretResponse: function (serverResponse, {bidderRequest}) { + serverResponse = serverResponse.body; + const isInvalidValidResp = !serverResponse || !serverResponse.bids || !serverResponse.bids.length; + let bids = []; + + if (isInvalidValidResp) { + let extMessage = serverResponse && serverResponse.ext && serverResponse.ext.message ? `: ${serverResponse.ext.message}` : ''; + let errorMessage = `in response for ${bidderRequest.bidderCode} adapter ${extMessage}`; + + utils.logError(errorMessage); + + return bids; } - if (!parsed || parsed.error || !parsed.bids || !parsed.bids.length) { - bidmanager.addBidResponse(bidRequest.placementCode, createBid(bidRequest, STATUS.NO_BID)); - - return; - } + serverResponse.bids.forEach(serverBid => { + if (serverBid.cpm !== 0) { + const bid = createBid(serverBid, bidderRequest); + bids.push(bid); + } + }); + + return bids; + }, +}; + +/** + * Prepare all parameters for request + * @param bid {object} + * @returns {object} + */ +function prepareRTBRequestParams(bid) { + let size = getSize(bid.sizes); + + return { + aid: bid.params.aid, + w: size.width, + h: size.height, + callbackId: bid.bidId, + domain: utils.getTopWindowLocation().hostname + }; +} - bidmanager.addBidResponse(bidRequest.placementCode, createBid(bidRequest, STATUS.GOOD, parsed.bids[0])); +/** + * Prepare size for request + * @param requestSizes {array} + * @returns {object} bid The bid to validate + */ +function getSize(requestSizes) { + const parsed = {}; + const size = utils.parseSizesInput(requestSizes)[0]; + + if (typeof size !== 'string') { + return parsed; } - function createBid(bidRequest, status, tag) { - var bid = bidfactory.createBid(status, tag); + let parsedSize = size.toUpperCase().split('X'); - bid.code = baseAdapter.getBidderCode(); - bid.bidderCode = bidRequest.bidder; - - if (!tag || status !== STATUS.GOOD) { - return bid; - } - - bid.mediaType = 'video'; - bid.cpm = tag.cpm; - bid.creative_id = tag.cmpId; - bid.width = bidRequest.width; - bid.height = bidRequest.height; - bid.descriptionUrl = tag.url; - bid.vastUrl = tag.vastUrl; - - return bid; - } - - return Object.assign(this, { - callBids: baseAdapter.callBids, - setBidderCode: baseAdapter.setBidderCode - }); + return { + width: parseInt(parsedSize[0], 10) || undefined, + height: parseInt(parsedSize[1], 10) || undefined + }; } -adaptermanager.registerBidAdapter(new VertamediaAdapter(), 'vertamedia', { - supportedMediaTypes: ['video'] -}); +/** + * Configure new bid by response + * @param bidRequest {object} + * @param bidResponse {object} + * @returns {object} + */ +function createBid(bidResponse, bidRequest) { + return { + bidderCode: bidRequest.bidderCode, + mediaType: 'video', + cpm: bidResponse.cpm, + requestId: bidResponse.requestId, + creative_id: bidResponse.cmpId, + width: bidResponse.width, + height: bidResponse.height, + descriptionUrl: bidResponse.url, + vastUrl: bidResponse.vastUrl, + currency: bidResponse.cur + }; +} -module.exports = VertamediaAdapter; +registerBidder(spec); diff --git a/test/spec/modules/vertamediaBidAdapter_spec.js b/test/spec/modules/vertamediaBidAdapter_spec.js index 11c29dafad0..3c5c987b096 100644 --- a/test/spec/modules/vertamediaBidAdapter_spec.js +++ b/test/spec/modules/vertamediaBidAdapter_spec.js @@ -1,141 +1,136 @@ -import { expect } from 'chai'; -import Adapter from 'modules/vertamediaBidAdapter'; -import bidmanager from 'src/bidmanager'; - -const ENDPOINT = 'http://rtb.vertamedia.com/hb/?aid=22489&w=640&h=480&domain=localhost'; +import {expect} from 'chai'; +import {spec} from 'modules/vertamediaBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; +const ENDPOINT = '//rtb.vertamedia.com/hb/'; const REQUEST = { - 'bidderCode': 'vertamedia', - 'requestId': 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6', + 'bidder': 'vertamedia', + 'params': { + 'aid': 12345 + }, + 'adUnitCode': 'adunit-code', + 'sizes': [640, 480], + 'bidId': '84ab500420319d', 'bidderRequestId': '7101db09af0db2', - 'bids': [ - { - 'bidder': 'vertamedia', - 'params': { - aid: 22489, - placementId: '123456' - }, - 'placementCode': '/19968336/header-bid-tag1', - 'sizes': [640, 480], - 'bidId': '84ab500420319d', - 'bidderRequestId': '7101db09af0db2', - 'requestId': 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6' - } - ], - 'start': 1469479810130 + 'auctionId': '2e41f65424c87c' }; -var RESPONSE = { - 'source': { - 'aid': 22489, - 'pubId': 18016, - 'sid': '0' - }, - 'bids': [ - { - 'cmpId': 9541, - 'cpm': 4.5, - 'url': 'http://rtb.vertamedia.com/vast?adid=BFDB9CC0038AD918', - 'cur': 'USD' - } + +const serverResponse = { + 'source': {'aid': 12345, 'pubId': 54321}, + 'bids': [{ + 'cmpId': 342516, + 'requestId': '2e41f65424c87c', + 'creative_id': 342516, + 'width': 640, + 'height': 480, + 'descriptionUrl': '44F2AEB9BFC881B3', + 'cpm': 0.9, + 'url': '44F2AEB9BFC881B3', + 'vastUrl': 'http://rtb.vertamedia.com/vast/?adid=44F2AEB9BFC881B3', + 'cur': 'USD' + } ] }; -describe('VertamediaAdater', () => { - let adapter; - - beforeEach(() => adapter = new Adapter()); - - describe('request function', () => { - let xhr; - let requests; - - beforeEach(() => { - xhr = sinon.useFakeXMLHttpRequest(); - requests = []; - xhr.onCreate = request => requests.push(request); - }); - - afterEach(() => xhr.restore()); +describe('vertamediaBidAdapter', () => { + const adapter = newBidder(spec); + describe('inherited functions', () => { it('exists and is a function', () => { expect(adapter.callBids).to.exist.and.to.be.a('function'); }); + }); - it('requires paramters to make request', () => { - adapter.callBids({}); - expect(requests).to.be.empty; - }); - - it('requires member && invCode', () => { - let backup = REQUEST.bids[0].params; - REQUEST.bids[0].params = {member: 1234}; - adapter.callBids(REQUEST); - expect(requests).to.be.empty; - REQUEST.bids[0].params = backup; + describe('isBidRequestValid', () => { + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(REQUEST)).to.equal(true); }); - it('sends bid request to ENDPOINT via POST', () => { - adapter.callBids(REQUEST); - expect(requests[0].url).to.equal(ENDPOINT); - expect(requests[0].method).to.equal('GET'); + it('should return false when required params are not passed', () => { + let bid = Object.assign({}, REQUEST); + delete bid.params; + expect(spec.isBidRequestValid(bid)).to.equal(false); }); }); - describe('response handler', () => { - let server; + describe('buildRequests', () => { + let bidRequests = [REQUEST]; - beforeEach(() => { - server = sinon.fakeServer.create(); - sinon.stub(bidmanager, 'addBidResponse'); - }); + const request = spec.buildRequests(bidRequests, {}); - afterEach(() => { - server.restore(); - bidmanager.addBidResponse.restore(); + it('sends bid request to ENDPOINT via GET', () => { + expect(request[0].method).to.equal('GET'); + }); + it('sends bid request to correct ENDPOINT', () => { + expect(request[0].url).to.equal(ENDPOINT); }); - it('registers bids', () => { - server.respondWith(JSON.stringify(RESPONSE)); + it('sends correct bid parameters', () => { + const bid = Object.assign({}, request[0].data); + delete bid.domain; - adapter.callBids(REQUEST); - server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); + const eq = { + aid: 12345, + w: 640, + h: 480, + callbackId: '84ab500420319d' + }; - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property('statusMessage', 'Bid available'); - expect(response).to.have.property('cpm', 4.5); + expect(bid).to.deep.equal(eq); }); + }); + describe('buildRequests', () => { + let bidRequests = [REQUEST]; - it('handles nobid responses', () => { - server.respondWith(JSON.stringify({ - aid: 356465468, + const request = spec.buildRequests(bidRequests, {}); + + it('sends bid request to ENDPOINT via GET', () => { + expect(request[0].method).to.equal('GET'); + }); + it('sends bid request to correct ENDPOINT', () => { + expect(request[0].url).to.equal(ENDPOINT); + }); + + it('sends correct bid parameters', () => { + const bid = Object.assign({}, request[0].data); + delete bid.domain; + + const eq = { + aid: 12345, w: 640, h: 480, - domain: 'localhost' - })); - - adapter.callBids(REQUEST); - server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); - - const response = bidmanager.addBidResponse.firstCall.args[1]; - expect(response).to.have.property( - 'statusMessage', - 'Bid returned empty or error response' - ); + callbackId: '84ab500420319d' + }; + + expect(bid).to.deep.equal(eq); }); + }); - it('handles JSON.parse errors', () => { - server.respondWith(''); + describe('interpretResponse', () => { + let bidderRequest = {bidderCode: 'bidderCode'}; + it('should get correct bid response', () => { + const result = spec.interpretResponse({body: serverResponse}, {bidderRequest}); + const eq = [{ + bidderCode: 'bidderCode', + mediaType: 'video', + cpm: 0.9, + requestId: '2e41f65424c87c', + creative_id: 342516, + width: 640, + height: 480, + descriptionUrl: '44F2AEB9BFC881B3', + vastUrl: 'http://rtb.vertamedia.com/vast/?adid=44F2AEB9BFC881B3', + currency: 'USD' + }]; + + expect(result).to.deep.equal(eq); + }); - adapter.callBids(REQUEST); - server.respond(); - sinon.assert.calledOnce(bidmanager.addBidResponse); + it('handles nobid responses', () => { + const nobidServerResponse = {bids: []}; + const nobidResult = spec.interpretResponse({body: nobidServerResponse}, {bidderRequest}); - expect(bidmanager.addBidResponse.firstCall.args[1]).to.have.property( - 'statusMessage', - 'Bid returned empty or error response' - ); + expect(nobidResult.length).to.equal(0); }); }); }); From e4c30e89eba2fc14441b7ca0449282f625d65dff Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Wed, 1 Nov 2017 12:43:00 +0200 Subject: [PATCH 14/31] Add vertamedia md file --- modules/vertamediaBidAdapter.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 modules/vertamediaBidAdapter.md diff --git a/modules/vertamediaBidAdapter.md b/modules/vertamediaBidAdapter.md new file mode 100644 index 00000000000..0b96ed23c16 --- /dev/null +++ b/modules/vertamediaBidAdapter.md @@ -0,0 +1,26 @@ +# Overview + +**Module Name**: VertaMedia Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: support@verta.media + +# Description + +Get access to multiple demand partners across VertaMedia AdExchange and maximize your yield with VertaMedia header bidding adapter. + +VertaMedia header bidding adapter connects with VertaMedia demand sources in order to fetch bids. +This adapter provides a solution for accessing Video demand + + +# Test Parameters +``` + var adUnits = [{ + code: 'div-test-div', + sizes: [[640, 480]], // ad size + bids: [{ + bidder: 'vertamedia', // adapter name + params: { + aid: 332842 + } + }] +``` From 78b4827ab41b7ca4e7a933648c4cd6b078262e80 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Wed, 1 Nov 2017 14:46:56 +0200 Subject: [PATCH 15/31] Add required fields --- modules/vertamediaBidAdapter.js | 32 ++++----- .../spec/modules/vertamediaBidAdapter_spec.js | 66 ++++++------------- 2 files changed, 38 insertions(+), 60 deletions(-) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index 15ea5b3fa07..124d4b678d9 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -20,12 +20,12 @@ export const spec = { buildRequests: function (bidRequests, bidderRequest) { return bidRequests.map((bid) => { return { + data: prepareRTBRequestParams(bid), contentType: 'text/plain', withCredentials: true, + bidderRequest, method: 'GET', - url: URL, - data: prepareRTBRequestParams(bid), - bidderRequest + url: URL } }); }, @@ -70,11 +70,11 @@ function prepareRTBRequestParams(bid) { let size = getSize(bid.sizes); return { + domain: utils.getTopWindowLocation().hostname, + callbackId: bid.bidId, aid: bid.params.aid, - w: size.width, h: size.height, - callbackId: bid.bidId, - domain: utils.getTopWindowLocation().hostname + w: size.width }; } @@ -84,8 +84,8 @@ function prepareRTBRequestParams(bid) { * @returns {object} bid The bid to validate */ function getSize(requestSizes) { - const parsed = {}; const size = utils.parseSizesInput(requestSizes)[0]; + const parsed = {}; if (typeof size !== 'string') { return parsed; @@ -94,8 +94,8 @@ function getSize(requestSizes) { let parsedSize = size.toUpperCase().split('X'); return { - width: parseInt(parsedSize[0], 10) || undefined, - height: parseInt(parsedSize[1], 10) || undefined + height: parseInt(parsedSize[1], 10) || undefined, + width: parseInt(parsedSize[0], 10) || undefined }; } @@ -108,15 +108,17 @@ function getSize(requestSizes) { function createBid(bidResponse, bidRequest) { return { bidderCode: bidRequest.bidderCode, - mediaType: 'video', - cpm: bidResponse.cpm, requestId: bidResponse.requestId, - creative_id: bidResponse.cmpId, - width: bidResponse.width, - height: bidResponse.height, descriptionUrl: bidResponse.url, + creativeId: bidResponse.cmpId, vastUrl: bidResponse.vastUrl, - currency: bidResponse.cur + height: bidResponse.height, + currency: bidResponse.cur, + width: bidResponse.width, + cpm: bidResponse.cpm, + mediaType: 'video', + netRevenue: true, + ttl: 3600 }; } diff --git a/test/spec/modules/vertamediaBidAdapter_spec.js b/test/spec/modules/vertamediaBidAdapter_spec.js index 3c5c987b096..4f04ea8a615 100644 --- a/test/spec/modules/vertamediaBidAdapter_spec.js +++ b/test/spec/modules/vertamediaBidAdapter_spec.js @@ -8,26 +8,26 @@ const REQUEST = { 'params': { 'aid': 12345 }, + 'bidderRequestId': '7101db09af0db2', + 'auctionId': '2e41f65424c87c', 'adUnitCode': 'adunit-code', - 'sizes': [640, 480], 'bidId': '84ab500420319d', - 'bidderRequestId': '7101db09af0db2', - 'auctionId': '2e41f65424c87c' + 'sizes': [640, 480] }; const serverResponse = { 'source': {'aid': 12345, 'pubId': 54321}, 'bids': [{ - 'cmpId': 342516, + 'vastUrl': 'http://rtb.vertamedia.com/vast/?adid=44F2AEB9BFC881B3', + 'descriptionUrl': '44F2AEB9BFC881B3', 'requestId': '2e41f65424c87c', + 'url': '44F2AEB9BFC881B3', 'creative_id': 342516, - 'width': 640, + 'cmpId': 342516, 'height': 480, - 'descriptionUrl': '44F2AEB9BFC881B3', - 'cpm': 0.9, - 'url': '44F2AEB9BFC881B3', - 'vastUrl': 'http://rtb.vertamedia.com/vast/?adid=44F2AEB9BFC881B3', - 'cur': 'USD' + 'cur': 'USD', + 'width': 640, + 'cpm': 0.9 } ] }; @@ -70,36 +70,10 @@ describe('vertamediaBidAdapter', () => { delete bid.domain; const eq = { + callbackId: '84ab500420319d', aid: 12345, w: 640, - h: 480, - callbackId: '84ab500420319d' - }; - - expect(bid).to.deep.equal(eq); - }); - }); - describe('buildRequests', () => { - let bidRequests = [REQUEST]; - - const request = spec.buildRequests(bidRequests, {}); - - it('sends bid request to ENDPOINT via GET', () => { - expect(request[0].method).to.equal('GET'); - }); - it('sends bid request to correct ENDPOINT', () => { - expect(request[0].url).to.equal(ENDPOINT); - }); - - it('sends correct bid parameters', () => { - const bid = Object.assign({}, request[0].data); - delete bid.domain; - - const eq = { - aid: 12345, - w: 640, - h: 480, - callbackId: '84ab500420319d' + h: 480 }; expect(bid).to.deep.equal(eq); @@ -111,16 +85,18 @@ describe('vertamediaBidAdapter', () => { it('should get correct bid response', () => { const result = spec.interpretResponse({body: serverResponse}, {bidderRequest}); const eq = [{ + vastUrl: 'http://rtb.vertamedia.com/vast/?adid=44F2AEB9BFC881B3', + descriptionUrl: '44F2AEB9BFC881B3', + requestId: '2e41f65424c87c', bidderCode: 'bidderCode', + creativeId: 342516, mediaType: 'video', - cpm: 0.9, - requestId: '2e41f65424c87c', - creative_id: 342516, - width: 640, + netRevenue: true, + currency: 'USD', height: 480, - descriptionUrl: '44F2AEB9BFC881B3', - vastUrl: 'http://rtb.vertamedia.com/vast/?adid=44F2AEB9BFC881B3', - currency: 'USD' + width: 640, + ttl: 3600, + cpm: 0.9 }]; expect(result).to.deep.equal(eq); From 0945af1768ca632d3f67456ddfc4f792ef46dd89 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Fri, 3 Nov 2017 19:21:03 +0200 Subject: [PATCH 16/31] Remove defaults; fix md file; --- modules/vertamediaBidAdapter.js | 8 ++------ modules/vertamediaBidAdapter.md | 1 + 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index 124d4b678d9..81e2872d371 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -21,8 +21,6 @@ export const spec = { return bidRequests.map((bid) => { return { data: prepareRTBRequestParams(bid), - contentType: 'text/plain', - withCredentials: true, bidderRequest, method: 'GET', url: URL @@ -52,7 +50,7 @@ export const spec = { serverResponse.bids.forEach(serverBid => { if (serverBid.cpm !== 0) { - const bid = createBid(serverBid, bidderRequest); + const bid = createBid(serverBid); bids.push(bid); } }); @@ -101,13 +99,11 @@ function getSize(requestSizes) { /** * Configure new bid by response - * @param bidRequest {object} * @param bidResponse {object} * @returns {object} */ -function createBid(bidResponse, bidRequest) { +function createBid(bidResponse) { return { - bidderCode: bidRequest.bidderCode, requestId: bidResponse.requestId, descriptionUrl: bidResponse.url, creativeId: bidResponse.cmpId, diff --git a/modules/vertamediaBidAdapter.md b/modules/vertamediaBidAdapter.md index 0b96ed23c16..b64e6b24214 100644 --- a/modules/vertamediaBidAdapter.md +++ b/modules/vertamediaBidAdapter.md @@ -23,4 +23,5 @@ This adapter provides a solution for accessing Video demand aid: 332842 } }] + }]; ``` From 59735e44f574215b55d54b5ef126870193cf00c9 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Tue, 21 Nov 2017 21:23:00 +0200 Subject: [PATCH 17/31] add outstream mediaType support --- modules/vertamediaBidAdapter.js | 42 ++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index 81e2872d371..03ab4eed587 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -1,10 +1,13 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; import {VIDEO} from 'src/mediaTypes'; +import {Renderer} from 'src/Renderer'; const URL = '//rtb.vertamedia.com/hb/'; const BIDDER_CODE = 'vertamedia'; +let isMediaTypeOutstream = true; + export const spec = { code: BIDDER_CODE, supportedMediaTypes: [VIDEO], @@ -18,6 +21,11 @@ export const spec = { * @param bidderRequest */ buildRequests: function (bidRequests, bidderRequest) { + const videoMediaType = utils.deepAccess(bidRequests[0], 'mediaTypes.video'); + const context = utils.deepAccess(bidRequests[0], 'mediaTypes.video.context'); + + isMediaTypeOutstream = videoMediaType && context === 'outstream'; + return bidRequests.map((bid) => { return { data: prepareRTBRequestParams(bid), @@ -103,7 +111,7 @@ function getSize(requestSizes) { * @returns {object} */ function createBid(bidResponse) { - return { + let bid = { requestId: bidResponse.requestId, descriptionUrl: bidResponse.url, creativeId: bidResponse.cmpId, @@ -116,6 +124,38 @@ function createBid(bidResponse) { netRevenue: true, ttl: 3600 }; + + if (isMediaTypeOutstream) { + Object.assign(bid, { + adResponse: bidResponse, + renderer: newRenderer(bidResponse.requestId) + }); + } + + return bid; +} + +function newRenderer(requestId) { + const renderer = Renderer.install({ + id: requestId, + url: '//player.vertamedia.com/outstream-unit/2.01/outstream.min.js', + loaded: false, + }); + + renderer.setRender(outstreamRender); + + return renderer; +} + +function outstreamRender(bid) { + bid.renderer.push(() => { + window.VOutstreamAPI.initOutstreams([{ + width: bid.width, + height: bid.height, + vastUrl: bid.vastUrl, + elId: bid.adUnitCode + }]); + }); } registerBidder(spec); From aece210201b1b625f84bc1b9f956adce123747e8 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Tue, 21 Nov 2017 22:57:12 +0200 Subject: [PATCH 18/31] add outstream mediaType support --- modules/vertamediaBidAdapter.js | 16 +++++++--------- modules/vertamediaBidAdapter.md | 16 +++++++++++++++- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index 03ab4eed587..f836c35f9ee 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -6,8 +6,6 @@ import {Renderer} from 'src/Renderer'; const URL = '//rtb.vertamedia.com/hb/'; const BIDDER_CODE = 'vertamedia'; -let isMediaTypeOutstream = true; - export const spec = { code: BIDDER_CODE, supportedMediaTypes: [VIDEO], @@ -21,11 +19,6 @@ export const spec = { * @param bidderRequest */ buildRequests: function (bidRequests, bidderRequest) { - const videoMediaType = utils.deepAccess(bidRequests[0], 'mediaTypes.video'); - const context = utils.deepAccess(bidRequests[0], 'mediaTypes.video.context'); - - isMediaTypeOutstream = videoMediaType && context === 'outstream'; - return bidRequests.map((bid) => { return { data: prepareRTBRequestParams(bid), @@ -45,6 +38,10 @@ export const spec = { interpretResponse: function (serverResponse, {bidderRequest}) { serverResponse = serverResponse.body; const isInvalidValidResp = !serverResponse || !serverResponse.bids || !serverResponse.bids.length; + const videoMediaType = utils.deepAccess(bidderRequest.bids[0], 'mediaTypes.video'); + const context = utils.deepAccess(bidderRequest.bids[0], 'mediaTypes.video.context'); + const isMediaTypeOutstream = (videoMediaType && context === 'outstream'); + let bids = []; if (isInvalidValidResp) { @@ -58,7 +55,7 @@ export const spec = { serverResponse.bids.forEach(serverBid => { if (serverBid.cpm !== 0) { - const bid = createBid(serverBid); + const bid = createBid(isMediaTypeOutstream, serverBid); bids.push(bid); } }); @@ -107,10 +104,11 @@ function getSize(requestSizes) { /** * Configure new bid by response + * @param isMediaTypeOutstream {boolean} * @param bidResponse {object} * @returns {object} */ -function createBid(bidResponse) { +function createBid(isMediaTypeOutstream, bidResponse) { let bid = { requestId: bidResponse.requestId, descriptionUrl: bidResponse.url, diff --git a/modules/vertamediaBidAdapter.md b/modules/vertamediaBidAdapter.md index b64e6b24214..d802e056364 100644 --- a/modules/vertamediaBidAdapter.md +++ b/modules/vertamediaBidAdapter.md @@ -9,7 +9,7 @@ Get access to multiple demand partners across VertaMedia AdExchange and maximize your yield with VertaMedia header bidding adapter. VertaMedia header bidding adapter connects with VertaMedia demand sources in order to fetch bids. -This adapter provides a solution for accessing Video demand +This adapter provides a solution for accessing Video demand and outstream unit # Test Parameters @@ -23,5 +23,19 @@ This adapter provides a solution for accessing Video demand aid: 332842 } }] + }{ + code: 'outstream-test-div', + sizes: [[640, 480]], // ad size + mediaTypes: { + video: { + context: 'outstream' + } + }, + bids: [{ + bidder: 'vertamedia', // adapter name + params: { + aid: 332842 + } + }] }]; ``` From 42127de16910addd75e764304664641ec033cf28 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Tue, 21 Nov 2017 23:37:34 +0200 Subject: [PATCH 19/31] Resolve conflicts --- modules/vertamediaBidAdapter.js | 3 --- modules/vertamediaBidAdapter.md | 4 ---- 2 files changed, 7 deletions(-) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index b4f3c665601..f836c35f9ee 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -1,10 +1,7 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; import {VIDEO} from 'src/mediaTypes'; -<<<<<<< HEAD import {Renderer} from 'src/Renderer'; -======= ->>>>>>> unstream/master const URL = '//rtb.vertamedia.com/hb/'; const BIDDER_CODE = 'vertamedia'; diff --git a/modules/vertamediaBidAdapter.md b/modules/vertamediaBidAdapter.md index 86638dd4c54..0ce4f2cbd58 100644 --- a/modules/vertamediaBidAdapter.md +++ b/modules/vertamediaBidAdapter.md @@ -9,11 +9,7 @@ Get access to multiple demand partners across VertaMedia AdExchange and maximize your yield with VertaMedia header bidding adapter. VertaMedia header bidding adapter connects with VertaMedia demand sources in order to fetch bids. -<<<<<<< HEAD -This adapter provides a solution for accessing Video demand and outstream unit -======= This adapter provides a solution for accessing Video demand ->>>>>>> unstream/master # Test Parameters From f878902a896471de42f3f8492a0c86a4be20e4fa Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Tue, 21 Nov 2017 23:52:11 +0200 Subject: [PATCH 20/31] fix test --- test/spec/modules/vertamediaBidAdapter_spec.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/spec/modules/vertamediaBidAdapter_spec.js b/test/spec/modules/vertamediaBidAdapter_spec.js index d505472dea1..1147cb45ad8 100644 --- a/test/spec/modules/vertamediaBidAdapter_spec.js +++ b/test/spec/modules/vertamediaBidAdapter_spec.js @@ -81,7 +81,11 @@ describe('vertamediaBidAdapter', () => { }); describe('interpretResponse', () => { - let bidderRequest = {bidderCode: 'bidderCode'}; + let bidderRequest = { + bidderCode: 'bidderCode', + bids: [{mediaTypes: {video: {}}}] + }; + it('should get correct bid response', () => { const result = spec.interpretResponse({body: serverResponse}, {bidderRequest}); const eq = [{ From cee63907316c40e48824be6c2fc366b853cf8639 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Fri, 8 Dec 2017 18:08:13 +0200 Subject: [PATCH 21/31] Add Vertamedia display adapter --- modules/ertamediaDisBidAdapter.md | 27 ++++ modules/vertamediaDisBidAdapter.js | 120 ++++++++++++++++++ .../modules/vertamediaDisBidAdapter_spec.js | 111 ++++++++++++++++ 3 files changed, 258 insertions(+) create mode 100644 modules/ertamediaDisBidAdapter.md create mode 100644 modules/vertamediaDisBidAdapter.js create mode 100644 test/spec/modules/vertamediaDisBidAdapter_spec.js diff --git a/modules/ertamediaDisBidAdapter.md b/modules/ertamediaDisBidAdapter.md new file mode 100644 index 00000000000..3ac177eef33 --- /dev/null +++ b/modules/ertamediaDisBidAdapter.md @@ -0,0 +1,27 @@ +# Overview + +**Module Name**: VertaMedia Bidder Adapter +**Module Type**: Bidder Adapter +**Maintainer**: support@verta.media + +# Description + +Get access to multiple demand partners across VertaMedia AdExchange and maximize your yield with VertaMedia header bidding adapter. + +VertaMedia header bidding adapter connects with VertaMedia demand sources in order to fetch bids. +This adapter provides a solution for accessing display demand + + +# Test Parameters +``` + var adUnits = [{ + code: 'div-test-div', + sizes: [[300, 250]], // ad size + bids: [{ + bidder: 'vertamediadis', // adapter name + params: { + aid: 332842 + } + }] + }]; +``` diff --git a/modules/vertamediaDisBidAdapter.js b/modules/vertamediaDisBidAdapter.js new file mode 100644 index 00000000000..2ebbd76666f --- /dev/null +++ b/modules/vertamediaDisBidAdapter.js @@ -0,0 +1,120 @@ +import * as utils from 'src/utils'; +import {registerBidder} from 'src/adapters/bidderFactory'; + +const URL = '//hb2.vertamedia.com/auction/'; +const BIDDER_CODE = 'vertamediadis'; + +export const spec = { + code: BIDDER_CODE, + isBidRequestValid: function (bid) { + return Boolean(bid && bid.params && bid.params.aid); + }, + + /** + * Make a server request from the list of BidRequests + * @param bidRequests + * @param bidderRequest + */ + buildRequests: function (bidRequests, bidderRequest) { + return bidRequests.map((bid) => { + return { + data: prepareRTBRequestParams(bid), + bidderRequest, + method: 'GET', + url: URL + } + }); + }, + + /** + * Unpack the response from the server into a list of bids + * @param serverResponse + * @param bidderRequest + * @return {Bid[]} An array of bids which were nested inside the server + */ + interpretResponse: function (serverResponse, {bidderRequest}) { + serverResponse = serverResponse.body; + const isInvalidValidResp = !serverResponse || !serverResponse.bids || !serverResponse.bids.length; + + let bids = []; + + if (isInvalidValidResp) { + let extMessage = serverResponse && serverResponse.ext && serverResponse.ext.message ? `: ${serverResponse.ext.message}` : ''; + let errorMessage = `in response for ${bidderRequest.bidderCode} adapter ${extMessage}`; + + utils.logError(errorMessage); + + return bids; + } + + serverResponse.bids.forEach(serverBid => { + if (serverBid.cpm !== 0) { + const bid = createBid(serverBid); + bids.push(bid); + } + }); + + return bids; + }, +}; + +/** + * Prepare all parameters for request + * @param bid {object} + * @returns {object} + */ +function prepareRTBRequestParams(bid) { + let size = getSize(bid.sizes); + + return { + domain: utils.getTopWindowLocation().hostname, + callbackId: bid.bidId, + aid: bid.params.aid, + ad_type: 'display', + h: size.height, + w: size.width + }; +} + +/** + * Prepare size for request + * @param requestSizes {array} + * @returns {object} bid The bid to validate + */ +function getSize(requestSizes) { + const size = utils.parseSizesInput(requestSizes)[0]; + const parsed = {}; + + if (typeof size !== 'string') { + return parsed; + } + + let parsedSize = size.toUpperCase().split('X'); + + return { + height: parseInt(parsedSize[1], 10) || undefined, + width: parseInt(parsedSize[0], 10) || undefined + }; +} + +/** + * Configure new bid by response + * @param bidResponse {object} + * @returns {object} + */ +function createBid(bidResponse) { + return { + requestId: bidResponse.requestId, + creativeId: bidResponse.cmpId, + height: bidResponse.height, + currency: bidResponse.cur, + width: bidResponse.width, + cpm: bidResponse.cpm, + mediaType: 'display', + ad: bidResponse.ad, + netRevenue: true, + ttl: 3600 + }; +} + +registerBidder(spec); diff --git a/test/spec/modules/vertamediaDisBidAdapter_spec.js b/test/spec/modules/vertamediaDisBidAdapter_spec.js new file mode 100644 index 00000000000..34ebaec5ba7 --- /dev/null +++ b/test/spec/modules/vertamediaDisBidAdapter_spec.js @@ -0,0 +1,111 @@ +import {expect} from 'chai'; +import {spec} from 'modules/vertamediaDisBidAdapter'; +import {newBidder} from 'src/adapters/bidderFactory'; + +const ENDPOINT = '//hb2.vertamedia.com/auction/'; +const REQUEST = { + 'bidder': 'vertamediadis', + 'params': { + 'aid': 12345 + }, + 'bidderRequestId': '7101db09af0db2', + 'auctionId': '2e41f65424c87c', + 'adUnitCode': 'adunit-code', + 'bidId': '84ab500420319d', + 'sizes': [300, 250] +}; + +const serverResponse = { + 'source': {'aid': 12345, 'pubId': 54321}, + 'bids': [{ + 'ad': '', + 'requestId': '2e41f65424c87c', + 'creative_id': 342516, + 'cmpId': 342516, + 'height': 250, + 'cur': 'USD', + 'width': 300, + 'cpm': 0.9 + }] +}; + +describe('vertamediaDisBidAdapter', () => { + const adapter = newBidder(spec); + + describe('inherited functions', () => { + it('exists and is a function', () => { + expect(adapter.callBids).to.exist.and.to.be.a('function'); + }); + }); + + describe('isBidRequestValid', () => { + it('should return true when required params found', () => { + expect(spec.isBidRequestValid(REQUEST)).to.equal(true); + }); + + it('should return false when required params are not passed', () => { + let bid = Object.assign({}, REQUEST); + delete bid.params; + expect(spec.isBidRequestValid(bid)).to.equal(false); + }); + }); + + describe('buildRequests', () => { + let bidRequests = [REQUEST]; + + const request = spec.buildRequests(bidRequests, {}); + + it('sends bid request to ENDPOINT via GET', () => { + expect(request[0].method).to.equal('GET'); + }); + it('sends bid request to correct ENDPOINT', () => { + expect(request[0].url).to.equal(ENDPOINT); + }); + + it('sends correct bid parameters', () => { + const bid = Object.assign({}, request[0].data); + delete bid.domain; + + const eq = { + callbackId: '84ab500420319d', + ad_type: 'display', + aid: 12345, + w: 300, + h: 250 + }; + + expect(bid).to.deep.equal(eq); + }); + }); + + describe('interpretResponse', () => { + let bidderRequest = { + bidderCode: 'bidderCode', + }; + + it('should get correct bid response', () => { + const result = spec.interpretResponse({body: serverResponse}, {bidderRequest}); + const eq = [{ + requestId: '2e41f65424c87c', + creativeId: 342516, + mediaType: 'display', + netRevenue: true, + currency: 'USD', + ad: '', + height: 250, + width: 300, + ttl: 3600, + cpm: 0.9 + }]; + + expect(result).to.deep.equal(eq); + }); + + it('handles nobid responses', () => { + const nobidServerResponse = {bids: []}; + const nobidResult = spec.interpretResponse({body: nobidServerResponse}, {bidderRequest}); + + expect(nobidResult.length).to.equal(0); + }); + }); +}); From cedbf3c8a8b4a660dc2e1278a7881ab4f726a582 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Wed, 13 Dec 2017 11:43:26 +0200 Subject: [PATCH 22/31] remove Boolean convert for isBidRequestValid --- modules/vertamediaBidAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index b314f6fd872..5598ecab8c0 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -10,7 +10,7 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: [VIDEO], isBidRequestValid: function (bid) { - return Boolean(bid && bid.params && bid.params.aid); + return bid && bid.params && bid.params.aid; }, /** From 77316eadbe61eee67000313cff53af0894b3c688 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Wed, 13 Dec 2017 11:59:23 +0200 Subject: [PATCH 23/31] Remove boolean convert for isBidRequestValid method; fix tests; fix typo --- modules/vertamediaDisBidAdapter.js | 2 +- .../{ertamediaDisBidAdapter.md => vertamediaDisBidAdapter.md} | 2 +- test/spec/modules/vertamediaBidAdapter_spec.js | 4 ++-- test/spec/modules/vertamediaDisBidAdapter_spec.js | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) rename modules/{ertamediaDisBidAdapter.md => vertamediaDisBidAdapter.md} (96%) diff --git a/modules/vertamediaDisBidAdapter.js b/modules/vertamediaDisBidAdapter.js index 2ebbd76666f..8a30840a60e 100644 --- a/modules/vertamediaDisBidAdapter.js +++ b/modules/vertamediaDisBidAdapter.js @@ -7,7 +7,7 @@ const BIDDER_CODE = 'vertamediadis'; export const spec = { code: BIDDER_CODE, isBidRequestValid: function (bid) { - return Boolean(bid && bid.params && bid.params.aid); + return bid && bid.params && bid.params.aid; }, /** diff --git a/modules/ertamediaDisBidAdapter.md b/modules/vertamediaDisBidAdapter.md similarity index 96% rename from modules/ertamediaDisBidAdapter.md rename to modules/vertamediaDisBidAdapter.md index 3ac177eef33..b0b36f2e326 100644 --- a/modules/ertamediaDisBidAdapter.md +++ b/modules/vertamediaDisBidAdapter.md @@ -20,7 +20,7 @@ This adapter provides a solution for accessing display demand bids: [{ bidder: 'vertamediadis', // adapter name params: { - aid: 332842 + aid: 324758 } }] }]; diff --git a/test/spec/modules/vertamediaBidAdapter_spec.js b/test/spec/modules/vertamediaBidAdapter_spec.js index 15466a94aca..b8e8d62042c 100644 --- a/test/spec/modules/vertamediaBidAdapter_spec.js +++ b/test/spec/modules/vertamediaBidAdapter_spec.js @@ -42,13 +42,13 @@ describe('vertamediaBidAdapter', () => { describe('isBidRequestValid', () => { it('should return true when required params found', () => { - expect(spec.isBidRequestValid(REQUEST)).to.equal(true); + expect(spec.isBidRequestValid(REQUEST)).to.equal(12345); }); it('should return false when required params are not passed', () => { let bid = Object.assign({}, REQUEST); delete bid.params; - expect(spec.isBidRequestValid(bid)).to.equal(false); + expect(spec.isBidRequestValid(bid)).to.equal(undefined); }); }); diff --git a/test/spec/modules/vertamediaDisBidAdapter_spec.js b/test/spec/modules/vertamediaDisBidAdapter_spec.js index 34ebaec5ba7..f5aa283e7b6 100644 --- a/test/spec/modules/vertamediaDisBidAdapter_spec.js +++ b/test/spec/modules/vertamediaDisBidAdapter_spec.js @@ -40,13 +40,13 @@ describe('vertamediaDisBidAdapter', () => { describe('isBidRequestValid', () => { it('should return true when required params found', () => { - expect(spec.isBidRequestValid(REQUEST)).to.equal(true); + expect(spec.isBidRequestValid(REQUEST)).to.equal(12345); }); it('should return false when required params are not passed', () => { let bid = Object.assign({}, REQUEST); delete bid.params; - expect(spec.isBidRequestValid(bid)).to.equal(false); + expect(spec.isBidRequestValid(bid)).to.equal(undefined); }); }); From ce5954d716e52f3d497d9f17b99880f9a851fc1a Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Wed, 3 Jan 2018 18:46:55 +0200 Subject: [PATCH 24/31] add display support for Vertamedia adapter; documentation update --- modules/vertamediaBidAdapter.js | 32 +++-- modules/vertamediaBidAdapter.md | 58 ++++++--- modules/vertamediaDisBidAdapter.js | 120 ------------------ modules/vertamediaDisBidAdapter.md | 27 ---- .../modules/vertamediaDisBidAdapter_spec.js | 111 ---------------- 5 files changed, 64 insertions(+), 284 deletions(-) delete mode 100644 modules/vertamediaDisBidAdapter.js delete mode 100644 modules/vertamediaDisBidAdapter.md delete mode 100644 test/spec/modules/vertamediaDisBidAdapter_spec.js diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index 5598ecab8c0..281f794e15f 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -3,8 +3,10 @@ import {registerBidder} from 'src/adapters/bidderFactory'; import {VIDEO} from 'src/mediaTypes'; import {Renderer} from 'src/Renderer'; -const URL = '//rtb.vertamedia.com/hb/'; +const URL = '//hb2.vertamedia.com/auction/'; const BIDDER_CODE = 'vertamedia'; +const OUTSTREAM = 'outstream'; +const DISPLAY = 'display'; export const spec = { code: BIDDER_CODE, @@ -40,7 +42,7 @@ export const spec = { const isInvalidValidResp = !serverResponse || !serverResponse.bids || !serverResponse.bids.length; const videoMediaType = utils.deepAccess(bidderRequest.bids[0], 'mediaTypes.video'); const context = utils.deepAccess(bidderRequest.bids[0], 'mediaTypes.video.context'); - const isMediaTypeOutstream = (videoMediaType && context === 'outstream'); + const mediaType = !videoMediaType ? DISPLAY : context === OUTSTREAM ? OUTSTREAM : VIDEO; let bids = []; @@ -55,7 +57,7 @@ export const spec = { serverResponse.bids.forEach(serverBid => { if (serverBid.cpm !== 0) { - const bid = createBid(isMediaTypeOutstream, serverBid); + const bid = createBid(mediaType, serverBid); bids.push(bid); } }); @@ -70,12 +72,14 @@ export const spec = { * @returns {object} */ function prepareRTBRequestParams(bid) { - let size = getSize(bid.sizes); + const size = getSize(bid.sizes); + const mediaType = utils.deepAccess(bid, 'mediaTypes.video') ? VIDEO : DISPLAY; return { domain: utils.getTopWindowLocation().hostname, callbackId: bid.bidId, aid: bid.params.aid, + ad_type: mediaType, h: size.height, w: size.width }; @@ -104,26 +108,36 @@ function getSize(requestSizes) { /** * Configure new bid by response - * @param isMediaTypeOutstream {boolean} + * @param mediaType {string} * @param bidResponse {object} * @returns {object} */ -function createBid(isMediaTypeOutstream, bidResponse) { +function createBid(mediaType, bidResponse) { let bid = { requestId: bidResponse.requestId, creativeId: bidResponse.cmpId, - vastUrl: bidResponse.vastUrl, height: bidResponse.height, currency: bidResponse.cur, width: bidResponse.width, cpm: bidResponse.cpm, - mediaType: 'video', netRevenue: true, + mediaType, ttl: 3600 }; - if (isMediaTypeOutstream) { + if (mediaType === DISPLAY) { + return Object.assign(bid, { + ad: bidResponse.ad + }); + } + + Object.assign(bid, { + vastUrl: bidResponse.vastUrl + }); + + if (mediaType === OUTSTREAM) { Object.assign(bid, { + mediaType: 'video', adResponse: bidResponse, renderer: newRenderer(bidResponse.requestId) }); diff --git a/modules/vertamediaBidAdapter.md b/modules/vertamediaBidAdapter.md index 0ce4f2cbd58..2f6faf5c840 100644 --- a/modules/vertamediaBidAdapter.md +++ b/modules/vertamediaBidAdapter.md @@ -9,33 +9,57 @@ Get access to multiple demand partners across VertaMedia AdExchange and maximize your yield with VertaMedia header bidding adapter. VertaMedia header bidding adapter connects with VertaMedia demand sources in order to fetch bids. -This adapter provides a solution for accessing Video demand +This adapter provides a solution for accessing Video demand and display demand # Test Parameters ``` - var adUnits = [{ + var adUnits = [ + + // Video instream adUnit + { code: 'div-test-div', - sizes: [[640, 480]], // ad size + sizes: [[640, 480]], + mediaTypes: { + video: { + context: 'instream' + } + }, bids: [{ - bidder: 'vertamedia', // adapter name - params: { - aid: 332842 - } + bidder: 'vertamedia', + params: { + aid: 332842 + } }] - }{ + }, + + // Video outstream adUnit + { code: 'outstream-test-div', - sizes: [[640, 480]], // ad size + sizes: [[640, 480]], mediaTypes: { - video: { - context: 'outstream' - } + video: { + context: 'outstream' + } }, bids: [{ - bidder: 'vertamedia', // adapter name - params: { - aid: 332842 - } + bidder: 'vertamedia', + params: { + aid: 332842 + } + }] + }, + + // Banner adUnit + { + code: 'div-test-div', + sizes: [[300, 250]], + bids: [{ + bidder: 'vertamedia', + params: { + aid: 324758 + } }] - }]; + } + ]; ``` diff --git a/modules/vertamediaDisBidAdapter.js b/modules/vertamediaDisBidAdapter.js deleted file mode 100644 index 8a30840a60e..00000000000 --- a/modules/vertamediaDisBidAdapter.js +++ /dev/null @@ -1,120 +0,0 @@ -import * as utils from 'src/utils'; -import {registerBidder} from 'src/adapters/bidderFactory'; - -const URL = '//hb2.vertamedia.com/auction/'; -const BIDDER_CODE = 'vertamediadis'; - -export const spec = { - code: BIDDER_CODE, - isBidRequestValid: function (bid) { - return bid && bid.params && bid.params.aid; - }, - - /** - * Make a server request from the list of BidRequests - * @param bidRequests - * @param bidderRequest - */ - buildRequests: function (bidRequests, bidderRequest) { - return bidRequests.map((bid) => { - return { - data: prepareRTBRequestParams(bid), - bidderRequest, - method: 'GET', - url: URL - } - }); - }, - - /** - * Unpack the response from the server into a list of bids - * @param serverResponse - * @param bidderRequest - * @return {Bid[]} An array of bids which were nested inside the server - */ - interpretResponse: function (serverResponse, {bidderRequest}) { - serverResponse = serverResponse.body; - const isInvalidValidResp = !serverResponse || !serverResponse.bids || !serverResponse.bids.length; - - let bids = []; - - if (isInvalidValidResp) { - let extMessage = serverResponse && serverResponse.ext && serverResponse.ext.message ? `: ${serverResponse.ext.message}` : ''; - let errorMessage = `in response for ${bidderRequest.bidderCode} adapter ${extMessage}`; - - utils.logError(errorMessage); - - return bids; - } - - serverResponse.bids.forEach(serverBid => { - if (serverBid.cpm !== 0) { - const bid = createBid(serverBid); - bids.push(bid); - } - }); - - return bids; - }, -}; - -/** - * Prepare all parameters for request - * @param bid {object} - * @returns {object} - */ -function prepareRTBRequestParams(bid) { - let size = getSize(bid.sizes); - - return { - domain: utils.getTopWindowLocation().hostname, - callbackId: bid.bidId, - aid: bid.params.aid, - ad_type: 'display', - h: size.height, - w: size.width - }; -} - -/** - * Prepare size for request - * @param requestSizes {array} - * @returns {object} bid The bid to validate - */ -function getSize(requestSizes) { - const size = utils.parseSizesInput(requestSizes)[0]; - const parsed = {}; - - if (typeof size !== 'string') { - return parsed; - } - - let parsedSize = size.toUpperCase().split('X'); - - return { - height: parseInt(parsedSize[1], 10) || undefined, - width: parseInt(parsedSize[0], 10) || undefined - }; -} - -/** - * Configure new bid by response - * @param bidResponse {object} - * @returns {object} - */ -function createBid(bidResponse) { - return { - requestId: bidResponse.requestId, - creativeId: bidResponse.cmpId, - height: bidResponse.height, - currency: bidResponse.cur, - width: bidResponse.width, - cpm: bidResponse.cpm, - mediaType: 'display', - ad: bidResponse.ad, - netRevenue: true, - ttl: 3600 - }; -} - -registerBidder(spec); diff --git a/modules/vertamediaDisBidAdapter.md b/modules/vertamediaDisBidAdapter.md deleted file mode 100644 index b0b36f2e326..00000000000 --- a/modules/vertamediaDisBidAdapter.md +++ /dev/null @@ -1,27 +0,0 @@ -# Overview - -**Module Name**: VertaMedia Bidder Adapter -**Module Type**: Bidder Adapter -**Maintainer**: support@verta.media - -# Description - -Get access to multiple demand partners across VertaMedia AdExchange and maximize your yield with VertaMedia header bidding adapter. - -VertaMedia header bidding adapter connects with VertaMedia demand sources in order to fetch bids. -This adapter provides a solution for accessing display demand - - -# Test Parameters -``` - var adUnits = [{ - code: 'div-test-div', - sizes: [[300, 250]], // ad size - bids: [{ - bidder: 'vertamediadis', // adapter name - params: { - aid: 324758 - } - }] - }]; -``` diff --git a/test/spec/modules/vertamediaDisBidAdapter_spec.js b/test/spec/modules/vertamediaDisBidAdapter_spec.js deleted file mode 100644 index f5aa283e7b6..00000000000 --- a/test/spec/modules/vertamediaDisBidAdapter_spec.js +++ /dev/null @@ -1,111 +0,0 @@ -import {expect} from 'chai'; -import {spec} from 'modules/vertamediaDisBidAdapter'; -import {newBidder} from 'src/adapters/bidderFactory'; - -const ENDPOINT = '//hb2.vertamedia.com/auction/'; -const REQUEST = { - 'bidder': 'vertamediadis', - 'params': { - 'aid': 12345 - }, - 'bidderRequestId': '7101db09af0db2', - 'auctionId': '2e41f65424c87c', - 'adUnitCode': 'adunit-code', - 'bidId': '84ab500420319d', - 'sizes': [300, 250] -}; - -const serverResponse = { - 'source': {'aid': 12345, 'pubId': 54321}, - 'bids': [{ - 'ad': '', - 'requestId': '2e41f65424c87c', - 'creative_id': 342516, - 'cmpId': 342516, - 'height': 250, - 'cur': 'USD', - 'width': 300, - 'cpm': 0.9 - }] -}; - -describe('vertamediaDisBidAdapter', () => { - const adapter = newBidder(spec); - - describe('inherited functions', () => { - it('exists and is a function', () => { - expect(adapter.callBids).to.exist.and.to.be.a('function'); - }); - }); - - describe('isBidRequestValid', () => { - it('should return true when required params found', () => { - expect(spec.isBidRequestValid(REQUEST)).to.equal(12345); - }); - - it('should return false when required params are not passed', () => { - let bid = Object.assign({}, REQUEST); - delete bid.params; - expect(spec.isBidRequestValid(bid)).to.equal(undefined); - }); - }); - - describe('buildRequests', () => { - let bidRequests = [REQUEST]; - - const request = spec.buildRequests(bidRequests, {}); - - it('sends bid request to ENDPOINT via GET', () => { - expect(request[0].method).to.equal('GET'); - }); - it('sends bid request to correct ENDPOINT', () => { - expect(request[0].url).to.equal(ENDPOINT); - }); - - it('sends correct bid parameters', () => { - const bid = Object.assign({}, request[0].data); - delete bid.domain; - - const eq = { - callbackId: '84ab500420319d', - ad_type: 'display', - aid: 12345, - w: 300, - h: 250 - }; - - expect(bid).to.deep.equal(eq); - }); - }); - - describe('interpretResponse', () => { - let bidderRequest = { - bidderCode: 'bidderCode', - }; - - it('should get correct bid response', () => { - const result = spec.interpretResponse({body: serverResponse}, {bidderRequest}); - const eq = [{ - requestId: '2e41f65424c87c', - creativeId: 342516, - mediaType: 'display', - netRevenue: true, - currency: 'USD', - ad: '', - height: 250, - width: 300, - ttl: 3600, - cpm: 0.9 - }]; - - expect(result).to.deep.equal(eq); - }); - - it('handles nobid responses', () => { - const nobidServerResponse = {bids: []}; - const nobidResult = spec.interpretResponse({body: nobidServerResponse}, {bidderRequest}); - - expect(nobidResult.length).to.equal(0); - }); - }); -}); From 95dca95df38a16eacb767606ab88f1c55586ed97 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Wed, 3 Jan 2018 18:47:44 +0200 Subject: [PATCH 25/31] update tests for VertamediaBidAdapter --- .../spec/modules/vertamediaBidAdapter_spec.js | 173 ++++++++++++++---- 1 file changed, 139 insertions(+), 34 deletions(-) diff --git a/test/spec/modules/vertamediaBidAdapter_spec.js b/test/spec/modules/vertamediaBidAdapter_spec.js index b8e8d62042c..02013c2d972 100644 --- a/test/spec/modules/vertamediaBidAdapter_spec.js +++ b/test/spec/modules/vertamediaBidAdapter_spec.js @@ -2,9 +2,25 @@ import {expect} from 'chai'; import {spec} from 'modules/vertamediaBidAdapter'; import {newBidder} from 'src/adapters/bidderFactory'; -const ENDPOINT = '//rtb.vertamedia.com/hb/'; -const REQUEST = { +const ENDPOINT = '//hb2.vertamedia.com/auction/'; + +const DISPLAY_REQUEST = { + 'bidder': 'vertamedia', + 'params': { + 'aid': 12345 + }, + 'bidderRequestId': '7101db09af0db2', + 'auctionId': '2e41f65424c87c', + 'adUnitCode': 'adunit-code', + 'bidId': '84ab500420319d', + 'sizes': [300, 250] +}; + +const VIDEO_REQUEST = { 'bidder': 'vertamedia', + 'mediaTypes': { + 'video': {} + }, 'params': { 'aid': 12345 }, @@ -15,7 +31,7 @@ const REQUEST = { 'sizes': [640, 480] }; -const serverResponse = { +const SERVER_VIDEO_RESPONSE = { 'source': {'aid': 12345, 'pubId': 54321}, 'bids': [{ 'vastUrl': 'http://rtb.vertamedia.com/vast/?adid=44F2AEB9BFC881B3', @@ -30,6 +46,55 @@ const serverResponse = { } ] }; +const SERVER_DISPLAY_RESPONSE = { + 'source': {'aid': 12345, 'pubId': 54321}, + 'bids': [{ + 'ad': '', + 'requestId': '2e41f65424c87c', + 'creative_id': 342516, + 'cmpId': 342516, + 'height': 250, + 'cur': 'USD', + 'width': 300, + 'cpm': 0.9 + }] +}; + +const videoBidderRequest = { + bidderCode: 'bidderCode', + bids: [{mediaTypes: {video: {}}}] +}; + +const displayBidderRequest = { + bidderCode: 'bidderCode', + bids: [{}] +}; + +const videoEqResponse = [{ + vastUrl: 'http://rtb.vertamedia.com/vast/?adid=44F2AEB9BFC881B3', + requestId: '2e41f65424c87c', + creativeId: 342516, + mediaType: 'video', + netRevenue: true, + currency: 'USD', + height: 480, + width: 640, + ttl: 3600, + cpm: 0.9 +}]; + +const displayEqResponse = [{ + requestId: '2e41f65424c87c', + creativeId: 342516, + mediaType: 'display', + netRevenue: true, + currency: 'USD', + ad: '', + height: 250, + width: 300, + ttl: 3600, + cpm: 0.9 +}]; describe('vertamediaBidAdapter', () => { const adapter = newBidder(spec); @@ -42,34 +107,39 @@ describe('vertamediaBidAdapter', () => { describe('isBidRequestValid', () => { it('should return true when required params found', () => { - expect(spec.isBidRequestValid(REQUEST)).to.equal(12345); + expect(spec.isBidRequestValid(VIDEO_REQUEST)).to.equal(12345); }); it('should return false when required params are not passed', () => { - let bid = Object.assign({}, REQUEST); + let bid = Object.assign({}, VIDEO_REQUEST); delete bid.params; expect(spec.isBidRequestValid(bid)).to.equal(undefined); }); }); describe('buildRequests', () => { - let bidRequests = [REQUEST]; + let videoBidRequests = [VIDEO_REQUEST]; + let dispalyBidRequests = [DISPLAY_REQUEST]; - const request = spec.buildRequests(bidRequests, {}); + const displayRequest = spec.buildRequests(dispalyBidRequests, {}); + const videoRequest = spec.buildRequests(videoBidRequests, {}); it('sends bid request to ENDPOINT via GET', () => { - expect(request[0].method).to.equal('GET'); + expect(videoRequest[0].method).to.equal('GET'); + expect(displayRequest[0].method).to.equal('GET'); }); it('sends bid request to correct ENDPOINT', () => { - expect(request[0].url).to.equal(ENDPOINT); + expect(videoRequest[0].url).to.equal(ENDPOINT); + expect(displayRequest[0].url).to.equal(ENDPOINT); }); - it('sends correct bid parameters', () => { - const bid = Object.assign({}, request[0].data); + it('sends correct video bid parameters', () => { + const bid = Object.assign({}, videoRequest[0].data); delete bid.domain; const eq = { callbackId: '84ab500420319d', + ad_type: 'video', aid: 12345, w: 640, h: 480 @@ -77,37 +147,72 @@ describe('vertamediaBidAdapter', () => { expect(bid).to.deep.equal(eq); }); + + it('sends correct display bid parameters', () => { + const bid = Object.assign({}, displayRequest[0].data); + delete bid.domain; + + const eq = { + callbackId: '84ab500420319d', + ad_type: 'display', + aid: 12345, + w: 300, + h: 250 + }; + + expect(bid).to.deep.equal(eq); + }); }); describe('interpretResponse', () => { - let bidderRequest = { - bidderCode: 'bidderCode', - bids: [{mediaTypes: {video: {}}}] - }; + let serverResponse; + let bidderRequest; + let eqResponse; + + afterEach(() => { + serverResponse = null; + bidderRequest = null; + eqResponse = null; + }); + + it('should get correct video bid response', () => { + serverResponse = SERVER_VIDEO_RESPONSE; + bidderRequest = videoBidderRequest; + eqResponse = videoEqResponse; + + bidServerResponseCheck(); + }); + + it('should get correct display bid response', () => { + serverResponse = SERVER_DISPLAY_RESPONSE; + bidderRequest = displayBidderRequest; + eqResponse = displayEqResponse; - it('should get correct bid response', () => { + bidServerResponseCheck(); + }); + + function bidServerResponseCheck() { const result = spec.interpretResponse({body: serverResponse}, {bidderRequest}); - const eq = [{ - vastUrl: 'http://rtb.vertamedia.com/vast/?adid=44F2AEB9BFC881B3', - requestId: '2e41f65424c87c', - creativeId: 342516, - mediaType: 'video', - netRevenue: true, - currency: 'USD', - height: 480, - width: 640, - ttl: 3600, - cpm: 0.9 - }]; - - expect(result).to.deep.equal(eq); + expect(result).to.deep.equal(eqResponse); + } + + function nobidServerResponseCheck() { + const noBidServerResponse = {bids: []}; + const noBidResult = spec.interpretResponse({body: noBidServerResponse}, {bidderRequest}); + + expect(noBidResult.length).to.equal(0); + } + + it('handles video nobid responses', () => { + bidderRequest = videoBidderRequest; + + nobidServerResponseCheck(); }); - it('handles nobid responses', () => { - const nobidServerResponse = {bids: []}; - const nobidResult = spec.interpretResponse({body: nobidServerResponse}, {bidderRequest}); + it('handles display nobid responses', () => { + bidderRequest = displayBidderRequest; - expect(nobidResult.length).to.equal(0); + nobidServerResponseCheck(); }); }); }); From 11f20fa231af059d6fcd634ba25f8425b1ae2565 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Wed, 3 Jan 2018 19:01:19 +0200 Subject: [PATCH 26/31] add supportedMediaTypes --- modules/vertamediaBidAdapter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index 281f794e15f..fcf89fec690 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -1,6 +1,6 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; -import {VIDEO} from 'src/mediaTypes'; +import {VIDEO, BANNER} from 'src/mediaTypes'; import {Renderer} from 'src/Renderer'; const URL = '//hb2.vertamedia.com/auction/'; @@ -10,7 +10,7 @@ const DISPLAY = 'display'; export const spec = { code: BIDDER_CODE, - supportedMediaTypes: [VIDEO], + supportedMediaTypes: [VIDEO, BANNER], isBidRequestValid: function (bid) { return bid && bid.params && bid.params.aid; }, From 5d427d41fa434e7ae179607c62c09f89ba3772f7 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Thu, 4 Jan 2018 11:34:10 +0200 Subject: [PATCH 27/31] Add comments --- modules/vertamediaBidAdapter.js | 9 +++++++++ test/spec/modules/vertamediaBidAdapter_spec.js | 2 ++ 2 files changed, 11 insertions(+) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index fcf89fec690..ad6d822537c 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -146,6 +146,11 @@ function createBid(mediaType, bidResponse) { return bid; } +/** + * Create Vertamedia renderer + * @param requestId + * @returns {*} + */ function newRenderer(requestId) { const renderer = Renderer.install({ id: requestId, @@ -158,6 +163,10 @@ function newRenderer(requestId) { return renderer; } +/** + * Initialise Vertamedia outstream + * @param bid + */ function outstreamRender(bid) { bid.renderer.push(() => { window.VOutstreamAPI.initOutstreams([{ diff --git a/test/spec/modules/vertamediaBidAdapter_spec.js b/test/spec/modules/vertamediaBidAdapter_spec.js index 02013c2d972..19e0f4f9333 100644 --- a/test/spec/modules/vertamediaBidAdapter_spec.js +++ b/test/spec/modules/vertamediaBidAdapter_spec.js @@ -128,6 +128,7 @@ describe('vertamediaBidAdapter', () => { expect(videoRequest[0].method).to.equal('GET'); expect(displayRequest[0].method).to.equal('GET'); }); + it('sends bid request to correct ENDPOINT', () => { expect(videoRequest[0].url).to.equal(ENDPOINT); expect(displayRequest[0].url).to.equal(ENDPOINT); @@ -193,6 +194,7 @@ describe('vertamediaBidAdapter', () => { function bidServerResponseCheck() { const result = spec.interpretResponse({body: serverResponse}, {bidderRequest}); + expect(result).to.deep.equal(eqResponse); } From 95fe42d1191c3bba9f013d22f8234c38e852506d Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Tue, 23 Jan 2018 15:40:44 +0200 Subject: [PATCH 28/31] Add moulty mediatypes support --- modules/vertamediaBidAdapter.js | 37 +++++++++++++------ .../spec/modules/vertamediaBidAdapter_spec.js | 7 ++-- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index ad6d822537c..d2a9ff80f35 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -2,6 +2,7 @@ import * as utils from 'src/utils'; import {registerBidder} from 'src/adapters/bidderFactory'; import {VIDEO, BANNER} from 'src/mediaTypes'; import {Renderer} from 'src/Renderer'; +import findIndex from 'core-js/library/fn/array/find-index'; const URL = '//hb2.vertamedia.com/auction/'; const BIDDER_CODE = 'vertamedia'; @@ -27,7 +28,7 @@ export const spec = { bidderRequest, method: 'GET', url: URL - } + }; }); }, @@ -40,9 +41,6 @@ export const spec = { interpretResponse: function (serverResponse, {bidderRequest}) { serverResponse = serverResponse.body; const isInvalidValidResp = !serverResponse || !serverResponse.bids || !serverResponse.bids.length; - const videoMediaType = utils.deepAccess(bidderRequest.bids[0], 'mediaTypes.video'); - const context = utils.deepAccess(bidderRequest.bids[0], 'mediaTypes.video.context'); - const mediaType = !videoMediaType ? DISPLAY : context === OUTSTREAM ? OUTSTREAM : VIDEO; let bids = []; @@ -56,18 +54,23 @@ export const spec = { } serverResponse.bids.forEach(serverBid => { - if (serverBid.cpm !== 0) { - const bid = createBid(mediaType, serverBid); + const requestId = findIndex(bidderRequest.bids, (bidRequest) => { + return bidRequest.bidId === serverBid.requestId; + }); + + if (serverBid.cpm !== 0 && requestId !== -1) { + const bid = createBid(serverBid, getMediaType(bidderRequest.bids[requestId])); + bids.push(bid); } }); return bids; - }, + } }; /** - * Prepare all parameters for request + * Parse mediaType * @param bid {object} * @returns {object} */ @@ -85,6 +88,18 @@ function prepareRTBRequestParams(bid) { }; } +/** + * Prepare all parameters for request + * @param bidderRequest {object} + * @returns {object} + */ +function getMediaType(bidderRequest) { + const videoMediaType = utils.deepAccess(bidderRequest, 'mediaTypes.video'); + const context = utils.deepAccess(bidderRequest, 'mediaTypes.video.context'); + + return !videoMediaType ? DISPLAY : context === OUTSTREAM ? OUTSTREAM : VIDEO; +} + /** * Prepare size for request * @param requestSizes {array} @@ -108,11 +123,11 @@ function getSize(requestSizes) { /** * Configure new bid by response - * @param mediaType {string} * @param bidResponse {object} + * @param mediaType {Object} * @returns {object} */ -function createBid(mediaType, bidResponse) { +function createBid(bidResponse, mediaType) { let bid = { requestId: bidResponse.requestId, creativeId: bidResponse.cmpId, @@ -155,7 +170,7 @@ function newRenderer(requestId) { const renderer = Renderer.install({ id: requestId, url: '//player.vertamedia.com/outstream-unit/2.01/outstream.min.js', - loaded: false, + loaded: false }); renderer.setRender(outstreamRender); diff --git a/test/spec/modules/vertamediaBidAdapter_spec.js b/test/spec/modules/vertamediaBidAdapter_spec.js index 19e0f4f9333..dc5531c1c06 100644 --- a/test/spec/modules/vertamediaBidAdapter_spec.js +++ b/test/spec/modules/vertamediaBidAdapter_spec.js @@ -62,12 +62,12 @@ const SERVER_DISPLAY_RESPONSE = { const videoBidderRequest = { bidderCode: 'bidderCode', - bids: [{mediaTypes: {video: {}}}] + bids: [{mediaTypes: {video: {}}, bidId: '2e41f65424c87c'}] }; const displayBidderRequest = { bidderCode: 'bidderCode', - bids: [{}] + bids: [{bidId: '2e41f65424c87c'}] }; const videoEqResponse = [{ @@ -194,7 +194,8 @@ describe('vertamediaBidAdapter', () => { function bidServerResponseCheck() { const result = spec.interpretResponse({body: serverResponse}, {bidderRequest}); - + console.log(result); + console.log(eqResponse); expect(result).to.deep.equal(eqResponse); } From 2ae551325d9eb04afad0c0d61b08cca73cdab2a1 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Wed, 24 Jan 2018 12:07:46 +0200 Subject: [PATCH 29/31] cleanup logs --- test/spec/modules/vertamediaBidAdapter_spec.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/spec/modules/vertamediaBidAdapter_spec.js b/test/spec/modules/vertamediaBidAdapter_spec.js index dc5531c1c06..a91be68a25d 100644 --- a/test/spec/modules/vertamediaBidAdapter_spec.js +++ b/test/spec/modules/vertamediaBidAdapter_spec.js @@ -194,8 +194,7 @@ describe('vertamediaBidAdapter', () => { function bidServerResponseCheck() { const result = spec.interpretResponse({body: serverResponse}, {bidderRequest}); - console.log(result); - console.log(eqResponse); + expect(result).to.deep.equal(eqResponse); } From 580f67021be25cd857876b1b292ef4cc1e3e8313 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Wed, 24 Jan 2018 18:54:26 +0200 Subject: [PATCH 30/31] Add sending multiple sizes --- modules/vertamediaBidAdapter.js | 25 +------------------ .../spec/modules/vertamediaBidAdapter_spec.js | 8 +++--- 2 files changed, 4 insertions(+), 29 deletions(-) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index d2a9ff80f35..238495f3966 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -75,7 +75,6 @@ export const spec = { * @returns {object} */ function prepareRTBRequestParams(bid) { - const size = getSize(bid.sizes); const mediaType = utils.deepAccess(bid, 'mediaTypes.video') ? VIDEO : DISPLAY; return { @@ -83,8 +82,7 @@ function prepareRTBRequestParams(bid) { callbackId: bid.bidId, aid: bid.params.aid, ad_type: mediaType, - h: size.height, - w: size.width + sizes: utils.parseSizesInput(bid.sizes).join() }; } @@ -100,27 +98,6 @@ function getMediaType(bidderRequest) { return !videoMediaType ? DISPLAY : context === OUTSTREAM ? OUTSTREAM : VIDEO; } -/** - * Prepare size for request - * @param requestSizes {array} - * @returns {object} bid The bid to validate - */ -function getSize(requestSizes) { - const size = utils.parseSizesInput(requestSizes)[0]; - const parsed = {}; - - if (typeof size !== 'string') { - return parsed; - } - - let parsedSize = size.toUpperCase().split('X'); - - return { - height: parseInt(parsedSize[1], 10) || undefined, - width: parseInt(parsedSize[0], 10) || undefined - }; -} - /** * Configure new bid by response * @param bidResponse {object} diff --git a/test/spec/modules/vertamediaBidAdapter_spec.js b/test/spec/modules/vertamediaBidAdapter_spec.js index a91be68a25d..32353b0097e 100644 --- a/test/spec/modules/vertamediaBidAdapter_spec.js +++ b/test/spec/modules/vertamediaBidAdapter_spec.js @@ -28,7 +28,7 @@ const VIDEO_REQUEST = { 'auctionId': '2e41f65424c87c', 'adUnitCode': 'adunit-code', 'bidId': '84ab500420319d', - 'sizes': [640, 480] + 'sizes': [[480, 360], [640, 480]] }; const SERVER_VIDEO_RESPONSE = { @@ -142,8 +142,7 @@ describe('vertamediaBidAdapter', () => { callbackId: '84ab500420319d', ad_type: 'video', aid: 12345, - w: 640, - h: 480 + sizes: '480x360,640x480' }; expect(bid).to.deep.equal(eq); @@ -157,8 +156,7 @@ describe('vertamediaBidAdapter', () => { callbackId: '84ab500420319d', ad_type: 'display', aid: 12345, - w: 300, - h: 250 + sizes: '300x250' }; expect(bid).to.deep.equal(eq); From 7013a40aac1182a4079563246c095403110319f5 Mon Sep 17 00:00:00 2001 From: "m.sorochuk" Date: Mon, 12 Feb 2018 13:45:30 +0200 Subject: [PATCH 31/31] add multiple bids reguest --- modules/vertamediaBidAdapter.js | 92 ++++++++++++------- .../spec/modules/vertamediaBidAdapter_spec.js | 12 +-- 2 files changed, 65 insertions(+), 39 deletions(-) diff --git a/modules/vertamediaBidAdapter.js b/modules/vertamediaBidAdapter.js index 238495f3966..5876f0b2e7e 100644 --- a/modules/vertamediaBidAdapter.js +++ b/modules/vertamediaBidAdapter.js @@ -5,6 +5,7 @@ import {Renderer} from 'src/Renderer'; import findIndex from 'core-js/library/fn/array/find-index'; const URL = '//hb2.vertamedia.com/auction/'; +const OUTSTREAM_SRC = '//player.vertamedia.com/outstream-unit/2.01/outstream.min.js'; const BIDDER_CODE = 'vertamedia'; const OUTSTREAM = 'outstream'; const DISPLAY = 'display'; @@ -22,14 +23,12 @@ export const spec = { * @param bidderRequest */ buildRequests: function (bidRequests, bidderRequest) { - return bidRequests.map((bid) => { - return { - data: prepareRTBRequestParams(bid), - bidderRequest, - method: 'GET', - url: URL - }; - }); + return { + data: bidToTag(bidRequests), + bidderRequest, + method: 'GET', + url: URL + }; }, /** @@ -40,49 +39,76 @@ export const spec = { */ interpretResponse: function (serverResponse, {bidderRequest}) { serverResponse = serverResponse.body; - const isInvalidValidResp = !serverResponse || !serverResponse.bids || !serverResponse.bids.length; - let bids = []; - if (isInvalidValidResp) { - let extMessage = serverResponse && serverResponse.ext && serverResponse.ext.message ? `: ${serverResponse.ext.message}` : ''; - let errorMessage = `in response for ${bidderRequest.bidderCode} adapter ${extMessage}`; + if (!utils.isArray(serverResponse)) { + return parseRTBResponse(serverResponse, bidderRequest); + } - utils.logError(errorMessage); + serverResponse.forEach(serverBidResponse => { + bids = utils.flatten(bids, parseRTBResponse(serverBidResponse, bidderRequest)); + }); - return bids; - } + return bids; + } +}; - serverResponse.bids.forEach(serverBid => { - const requestId = findIndex(bidderRequest.bids, (bidRequest) => { - return bidRequest.bidId === serverBid.requestId; - }); +function parseRTBResponse(serverResponse, bidderRequest) { + const isInvalidValidResp = !serverResponse || !serverResponse.bids || !serverResponse.bids.length; - if (serverBid.cpm !== 0 && requestId !== -1) { - const bid = createBid(serverBid, getMediaType(bidderRequest.bids[requestId])); + let bids = []; - bids.push(bid); - } - }); + if (isInvalidValidResp) { + let extMessage = serverResponse && serverResponse.ext && serverResponse.ext.message ? `: ${serverResponse.ext.message}` : ''; + let errorMessage = `in response for ${bidderRequest.bidderCode} adapter ${extMessage}`; + + utils.logError(errorMessage); return bids; } -}; + + serverResponse.bids.forEach(serverBid => { + const requestId = findIndex(bidderRequest.bids, (bidRequest) => { + return bidRequest.bidId === serverBid.requestId; + }); + + if (serverBid.cpm !== 0 && requestId !== -1) { + const bid = createBid(serverBid, getMediaType(bidderRequest.bids[requestId])); + + bids.push(bid); + } + }); + + return bids; +} + +function bidToTag(bidRequests) { + let tag = { + domain: utils.getTopWindowLocation().hostname + }; + + for (let i = 0, length = bidRequests.length; i < length; i++) { + Object.assign(tag, prepareRTBRequestParams(i, bidRequests[i])); + } + + return tag; +} /** * Parse mediaType + * @param _index {number} * @param bid {object} * @returns {object} */ -function prepareRTBRequestParams(bid) { +function prepareRTBRequestParams(_index, bid) { const mediaType = utils.deepAccess(bid, 'mediaTypes.video') ? VIDEO : DISPLAY; + const index = !_index ? '' : `${_index + 1}`; return { - domain: utils.getTopWindowLocation().hostname, - callbackId: bid.bidId, - aid: bid.params.aid, - ad_type: mediaType, - sizes: utils.parseSizesInput(bid.sizes).join() + ['callbackId' + index]: bid.bidId, + ['aid' + index]: bid.params.aid, + ['ad_type' + index]: mediaType, + ['sizes' + index]: utils.parseSizesInput(bid.sizes).join() }; } @@ -146,7 +172,7 @@ function createBid(bidResponse, mediaType) { function newRenderer(requestId) { const renderer = Renderer.install({ id: requestId, - url: '//player.vertamedia.com/outstream-unit/2.01/outstream.min.js', + url: OUTSTREAM_SRC, loaded: false }); diff --git a/test/spec/modules/vertamediaBidAdapter_spec.js b/test/spec/modules/vertamediaBidAdapter_spec.js index 32353b0097e..271f1f2d04a 100644 --- a/test/spec/modules/vertamediaBidAdapter_spec.js +++ b/test/spec/modules/vertamediaBidAdapter_spec.js @@ -125,17 +125,17 @@ describe('vertamediaBidAdapter', () => { const videoRequest = spec.buildRequests(videoBidRequests, {}); it('sends bid request to ENDPOINT via GET', () => { - expect(videoRequest[0].method).to.equal('GET'); - expect(displayRequest[0].method).to.equal('GET'); + expect(videoRequest.method).to.equal('GET'); + expect(displayRequest.method).to.equal('GET'); }); it('sends bid request to correct ENDPOINT', () => { - expect(videoRequest[0].url).to.equal(ENDPOINT); - expect(displayRequest[0].url).to.equal(ENDPOINT); + expect(videoRequest.url).to.equal(ENDPOINT); + expect(displayRequest.url).to.equal(ENDPOINT); }); it('sends correct video bid parameters', () => { - const bid = Object.assign({}, videoRequest[0].data); + const bid = Object.assign({}, videoRequest.data); delete bid.domain; const eq = { @@ -149,7 +149,7 @@ describe('vertamediaBidAdapter', () => { }); it('sends correct display bid parameters', () => { - const bid = Object.assign({}, displayRequest[0].data); + const bid = Object.assign({}, displayRequest.data); delete bid.domain; const eq = {