From 5162ad82f757d97ee87f3bab0d7ee7fde08fd625 Mon Sep 17 00:00:00 2001 From: Kenan Gillet <1706856+kenan-gillet@users.noreply.github.com> Date: Thu, 25 Mar 2021 13:12:43 -0700 Subject: [PATCH] Openx Bid Adapter: add floor support for Video (#6460) * fix confusing comment * refactor(openxBidAdapter): extract enrichQueryWithFloors * PBID-1194: add floor for Video --- modules/openxBidAdapter.js | 39 ++++++----- test/spec/modules/openxBidAdapter_spec.js | 84 +++++++++++++++++++++++ 2 files changed, 107 insertions(+), 16 deletions(-) diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index bbf3d6fdea1..7b4722e3371 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -341,21 +341,7 @@ function buildOXBannerRequest(bids, bidderRequest) { queryParams.tps = customParamsForAllBids.join(','); } - let customFloorsForAllBids = []; - let hasCustomFloor = false; - bids.forEach(function (bid) { - let floor = getBidFloor(bid, BANNER); - - if (floor) { - customFloorsForAllBids.push(floor); - hasCustomFloor = true; - } else { - customFloorsForAllBids.push(0); - } - }); - if (hasCustomFloor) { - queryParams.aumfs = customFloorsForAllBids.join(','); - } + enrichQueryWithFloors(queryParams, BANNER, bids); let url = queryParams.ph ? `https://u.openx.net/w/1.0/arj` @@ -430,6 +416,9 @@ function generateVideoParameters(bid, bidderRequest) { queryParams.vtest = 1; } + // each video bid makes a separate request + enrichQueryWithFloors(queryParams, VIDEO, [bid]); + return queryParams; } @@ -463,6 +452,24 @@ function createVideoBidResponses(response, {bid, startTime}) { return bidResponses; } +function enrichQueryWithFloors(queryParams, mediaType, bids) { + let customFloorsForAllBids = []; + let hasCustomFloor = false; + bids.forEach(function (bid) { + let floor = getBidFloor(bid, mediaType); + + if (floor) { + customFloorsForAllBids.push(floor); + hasCustomFloor = true; + } else { + customFloorsForAllBids.push(0); + } + }); + if (hasCustomFloor) { + queryParams.aumfs = customFloorsForAllBids.join(','); + } +} + function getBidFloor(bidRequest, mediaType) { let floorInfo = {}; const currency = config.getConfig('currency.adServerCurrency') || DEFAULT_CURRENCY; @@ -476,7 +483,7 @@ function getBidFloor(bidRequest, mediaType) { } let floor = floorInfo.floor || bidRequest.params.customFloor || 0; - return Math.round(floor * 1000); // normalize to microCpm + return Math.round(floor * 1000); // normalize to micro currency } registerBidder(spec); diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 121f8e76a07..28984bc4a44 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -1,6 +1,7 @@ import {expect} from 'chai'; import {spec, USER_ID_CODE_TO_QUERY_ARG} from 'modules/openxBidAdapter.js'; import {newBidder} from 'src/adapters/bidderFactory.js'; +import {BANNER, VIDEO} from 'src/mediaTypes.js'; import {userSync} from 'src/userSync.js'; import {config} from 'src/config.js'; import * as utils from 'src/utils.js'; @@ -1187,6 +1188,7 @@ describe('OpenxAdapter', function () { let getFloorSpy = sinon.spy(bidRequest1, 'getFloor'); spec.buildRequests([bidRequest1], mockBidderRequest); + expect(getFloorSpy.args[0][0].mediaType).to.equal(BANNER); expect(getFloorSpy.args[0][0].currency).to.equal('USD'); }); @@ -1205,6 +1207,7 @@ describe('OpenxAdapter', function () { let getFloorSpy = sinon.spy(bidRequest1, 'getFloor'); spec.buildRequests([bidRequest1], mockBidderRequest); + expect(getFloorSpy.args[0][0].mediaType).to.equal(BANNER); expect(getFloorSpy.args[0][0].currency).to.equal('bitcoin'); }); }) @@ -1345,6 +1348,87 @@ describe('OpenxAdapter', function () { }); }); }); + + describe('floors', function () { + it('should send out custom floors on bids that have customFloors specified', function () { + const bidRequest = Object.assign({}, + bidRequestsWithMediaTypes[0], + { + params: { + 'unit': '12345678', + 'delDomain': 'test-del-domain', + 'customFloor': 1.500001 + } + } + ); + + const request = spec.buildRequests([bidRequest], mockBidderRequest); + const dataParams = request[0].data; + + expect(dataParams.aumfs).to.exist; + expect(dataParams.aumfs).to.equal('1500'); + }); + + context('with floors module', function () { + let adServerCurrencyStub; + function makeBidWithFloorInfo(floorInfo) { + return Object.assign(utils.deepClone(bidRequestsWithMediaTypes[0]), + { + getFloor: () => { + return floorInfo; + } + }); + } + + beforeEach(function () { + adServerCurrencyStub = sinon + .stub(config, 'getConfig') + .withArgs('currency.adServerCurrency') + }); + + afterEach(function () { + config.getConfig.restore(); + }); + + it('should send out floors on bids', function () { + const floors = [9.99, 18.881]; + const bidRequests = floors.map(floor => { + return makeBidWithFloorInfo({ + currency: 'AUS', + floor: floor + }); + }); + const request = spec.buildRequests(bidRequests, mockBidderRequest); + + expect(request[0].data.aumfs).to.exist; + expect(request[0].data.aumfs).to.equal('9990'); + expect(request[1].data.aumfs).to.exist; + expect(request[1].data.aumfs).to.equal('18881'); + }); + + it('should send out floors on bids in the default currency', function () { + const bidRequest1 = makeBidWithFloorInfo({}); + + let getFloorSpy = sinon.spy(bidRequest1, 'getFloor'); + + spec.buildRequests([bidRequest1], mockBidderRequest); + expect(getFloorSpy.args[0][0].mediaType).to.equal(VIDEO); + expect(getFloorSpy.args[0][0].currency).to.equal('USD'); + }); + + it('should send out floors on bids in the ad server currency if defined', function () { + adServerCurrencyStub.returns('bitcoin'); + + const bidRequest1 = makeBidWithFloorInfo({}); + + let getFloorSpy = sinon.spy(bidRequest1, 'getFloor'); + + spec.buildRequests([bidRequest1], mockBidderRequest); + expect(getFloorSpy.args[0][0].mediaType).to.equal(VIDEO); + expect(getFloorSpy.args[0][0].currency).to.equal('bitcoin'); + }); + }) + }) }); describe('buildRequest for multi-format ad', function () {