diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 426362e0d9c..1b9766553c2 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -12,6 +12,7 @@ const OpenxAdapter = function OpenxAdapter() { const BIDDER_VERSION = '1.0.1'; let startTime; let timeout = config.getConfig('bidderTimeout'); + let shouldSendBoPixel = true; let pdNode = null; @@ -64,7 +65,9 @@ const OpenxAdapter = function OpenxAdapter() { beaconParams.bp = adUnit.pub_rev; beaconParams.ts = adUnit.ts; addBidResponse(adUnit, bid); - buildBoPixel(adUnit.creative[0], beaconParams); + if (shouldSendBoPixel === true) { + buildBoPixel(adUnit.creative[0], beaconParams); + } } }; @@ -182,6 +185,16 @@ const OpenxAdapter = function OpenxAdapter() { return found; } + function formatCustomParms(customKey, customParams) { + let value = customParams[customKey]; + if (Array.isArray(value)) { + // if value is an array, join them with commas first + value = value.join(','); + } + // return customKey=customValue format, escaping + to . and / to _ + return (customKey + '=' + value).replace('+', '.').replace('/', '_') + } + function buildRequest(bids, params, delDomain) { if (!utils.isArray(bids)) { return; @@ -193,13 +206,35 @@ const OpenxAdapter = function OpenxAdapter() { return utils.parseSizesInput(bid.sizes).join(','); }).join('|'); + let customParamsForAllBids = []; + let hasCustomParam = false; bids.forEach(function (bid) { - for (let customParam in bid.params.customParams) { - if (bid.params.customParams.hasOwnProperty(customParam)) { - params['c.' + customParam] = bid.params.customParams[customParam]; - } + if (bid.params.customParams) { + let customParamsForBid = utils._map(Object.keys(bid.params.customParams), customKey => formatCustomParms(customKey, bid.params.customParams)); + let formattedCustomParams = window.btoa(customParamsForBid.join('&')); + hasCustomParam = true; + customParamsForAllBids.push(formattedCustomParams); + } else { + customParamsForAllBids.push(''); + } + }); + if (hasCustomParam) { + params.tps = customParamsForAllBids.join('%2C'); + } + + let customFloorsForAllBids = []; + let hasCustomFloor = false; + bids.forEach(function (bid) { + if (bid.params.customFloor) { + customFloorsForAllBids.push(bid.params.customFloor * 1000); + hasCustomFloor = true; + } else { + customFloorsForAllBids.push(0); } }); + if (hasCustomFloor) { + params.aumfs = customFloorsForAllBids.join('%2C'); + } try { let queryString = buildQueryStringFromParams(params); @@ -227,11 +262,15 @@ const OpenxAdapter = function OpenxAdapter() { } let delDomain = bids[0].params.delDomain; + let bcOverride = bids[0].params.bc; startTime = new Date(params.start); if (params.timeout) { timeout = params.timeout; } + if (bids[0].params.hasOwnProperty('sendBoPixel') && typeof (bids[0].params.sendBoPixel) === 'boolean') { + shouldSendBoPixel = bids[0].params.sendBoPixel; + } buildRequest(bids, { ju: currentURL, @@ -243,7 +282,7 @@ const OpenxAdapter = function OpenxAdapter() { tws: getViewportDimensions(isIfr), ef: 'bt%2Cdb', be: 1, - bc: `${BIDDER_CONFIG}_${BIDDER_VERSION}`, + bc: bcOverride || `${BIDDER_CONFIG}_${BIDDER_VERSION}`, nocache: new Date().getTime() }, delDomain); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 21ceb5a6dec..c08e8c256e6 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -136,12 +136,15 @@ describe('openx adapter tests', function () { }); describe('test openx ad requests', () => { let spyAjax; + let spyBtoa; beforeEach(() => { spyAjax = sinon.spy(ajax, 'ajax'); + spyBtoa = sinon.spy(window, 'btoa'); sinon.stub(document.body, 'appendChild'); }); afterEach(() => { spyAjax.restore(); + spyBtoa.restore(); document.body.appendChild.restore(); }); @@ -179,19 +182,96 @@ describe('openx adapter tests', function () { params: { delDomain: 'testdelDomain', unit: 1234, - customParams: {'test1': 'testval1'} + customParams: {'test1': 'testval1+', 'test2': ['testval2/', 'testval3']} } } ] }; adapter.callBids(params); - sinon.assert.calledOnce(spyAjax); + sinon.assert.calledOnce(spyAjax); + sinon.assert.calledWith(spyBtoa, 'test1=testval1.&test2=testval2_,testval3'); let bidUrl = spyAjax.getCall(0).args[0]; expect(bidUrl).to.include('testdelDomain'); expect(bidUrl).to.include('1234'); expect(bidUrl).to.include('300x250,300x600'); - expect(bidUrl).to.include('c.test1=testval1'); + }); + + it('should send out custom floors on bids that have customFloors specified', () => { + let params = { + bids: [ + { + sizes: [[300, 250], [300, 600]], + params: { + delDomain: 'testdelDomain', + unit: 1234, + customFloor: 1 + } + }, + { + sizes: [[320, 50]], + params: { + delDomain: 'testdelDomain', + unit: 1234 + } + }, + { + sizes: [[728, 90]], + params: { + delDomain: 'testdelDomain', + unit: 1234, + customFloor: 1.5 + } + } + ] + }; + adapter.callBids(params); + + sinon.assert.calledOnce(spyAjax); + let bidUrl = spyAjax.getCall(0).args[0]; + expect(bidUrl).to.include('testdelDomain'); + expect(bidUrl).to.include('1234'); + expect(bidUrl).to.include('300x250,300x600|320x50|728x90'); + expect(bidUrl).to.include('aumfs=1000%2C0%2C1500'); + }); + + it('should change bc param if configureable bc is specified', () => { + let params = { + bids: [ + { + sizes: [[300, 250], [300, 600]], + params: { + delDomain: 'testdelDomain', + unit: 1234, + bc: 'hb_pb_test' + } + }, + { + sizes: [[320, 50]], + params: { + delDomain: 'testdelDomain', + unit: 1234, + bc: 'hb_pb_test' + } + }, + { + sizes: [[728, 90]], + params: { + delDomain: 'testdelDomain', + unit: 1234, + bc: 'hb_pb_test' + } + } + ] + }; + adapter.callBids(params); + + sinon.assert.calledOnce(spyAjax); + let bidUrl = spyAjax.getCall(0).args[0]; + expect(bidUrl).to.include('testdelDomain'); + expect(bidUrl).to.include('1234'); + expect(bidUrl).to.include('300x250,300x600|320x50|728x90'); + expect(bidUrl).to.include('bc=hb_pb_test'); }); }); });