diff --git a/modules/33acrossBidAdapter.js b/modules/33acrossBidAdapter.js index 07773ebe999..5df2af7f32e 100644 --- a/modules/33acrossBidAdapter.js +++ b/modules/33acrossBidAdapter.js @@ -5,6 +5,8 @@ import * as utils from '../src/utils.js'; const BIDDER_CODE = '33across'; const END_POINT = 'https://ssc.33across.com/api/v1/hb'; const SYNC_ENDPOINT = 'https://ssc-cms.33across.com/ps/?m=xch&rt=html&ru=deb'; +const MEDIA_TYPE = 'banner'; +const CURRENCY = 'USD'; const adapterState = { uniqueSiteIds: [] @@ -67,11 +69,27 @@ function _getAdSlotHTMLElement(adUnitCode) { // Infer the necessary data from valid bid for a minimal ttxRequest and create HTTP request // NOTE: At this point, TTX only accepts request for a single impression -function _createServerRequest(bidRequest, gdprConsent = {}, uspConsent, pageUrl) { +function _createServerRequest({bidRequest, gdprConsent = {}, uspConsent, pageUrl}) { const ttxRequest = {}; const params = bidRequest.params; const element = _getAdSlotHTMLElement(bidRequest.adUnitCode); const sizes = _transformSizes(bidRequest.sizes); + + let format; + + // We support size based bidfloors so obtain one if there's a rule associated + if (typeof bidRequest.getFloor === 'function') { + let getFloor = bidRequest.getFloor.bind(bidRequest); + + format = sizes.map((size) => { + const formatExt = _getBidFloors(getFloor, size); + + return Object.assign({}, size, formatExt); + }); + } else { + format = sizes; + } + const minSize = _getMinSize(sizes); const viewabilityAmount = _isViewabilityMeasurable(element) @@ -86,7 +104,7 @@ function _createServerRequest(bidRequest, gdprConsent = {}, uspConsent, pageUrl) ttxRequest.imp = []; ttxRequest.imp[0] = { banner: { - format: sizes + format }, ext: { ttx: { @@ -179,6 +197,24 @@ function _createSync({ siteId = 'zzz000000000003zzz', gdprConsent = {}, uspConse return sync; } +function _getBidFloors(getFloor, size) { + const bidFloors = getFloor({ + currency: CURRENCY, + mediaType: MEDIA_TYPE, + size: [ size.w, size.h ] + }); + + if (!isNaN(bidFloors.floor) && (bidFloors.currency === CURRENCY)) { + return { + ext: { + ttx: { + bidfloors: [ bidFloors.floor ] + } + } + } + } +} + function _getSize(size) { return { w: parseInt(size[0], 10), @@ -320,7 +356,14 @@ function buildRequests(bidRequests, bidderRequest) { adapterState.uniqueSiteIds = bidRequests.map(req => req.params.siteId).filter(utils.uniques); - return bidRequests.map(req => _createServerRequest(req, gdprConsent, uspConsent, pageUrl)); + return bidRequests.map(bidRequest => _createServerRequest( + { + bidRequest, + gdprConsent, + uspConsent, + pageUrl + }) + ); } // NOTE: At this point, the response from 33exchange will only ever contain one bid i.e. the highest bid diff --git a/test/spec/modules/33acrossBidAdapter_spec.js b/test/spec/modules/33acrossBidAdapter_spec.js index 0e67b7efb63..3721cef18d9 100644 --- a/test/spec/modules/33acrossBidAdapter_spec.js +++ b/test/spec/modules/33acrossBidAdapter_spec.js @@ -140,6 +140,22 @@ describe('33acrossBidAdapter:', function () { return this; }; + this.withFormatFloors = floors => { + const format = ttxRequest.imp[0].banner.format.map((fm, i) => { + return Object.assign(fm, { + ext: { + ttx: { + bidfloors: [ floors[i] ] + } + } + }) + }); + + ttxRequest.imp[0].banner.format = format; + + return this; + }; + this.build = () => ttxRequest; } @@ -667,6 +683,57 @@ describe('33acrossBidAdapter:', function () { expect(builtServerRequests).to.deep.equal([serverRequest]); }); }); + + context('when price floor module is not enabled in bidRequest', function() { + it('does not set any bidfloors in ttxRequest', function() { + const ttxRequest = new TtxRequestBuilder() + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + const builtServerRequests = spec.buildRequests(bidRequests, {}); + + expect(builtServerRequests).to.deep.equal([serverRequest]); + }); + }); + + context('when price floor module is enabled in bidRequest', function() { + it('does not set any bidfloors in ttxRequest if there is no floor', function() { + bidRequests[0].getFloor = () => ({}); + + const ttxRequest = new TtxRequestBuilder() + .build(); + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + const builtServerRequests = spec.buildRequests(bidRequests, {}); + + expect(builtServerRequests).to.deep.equal([serverRequest]); + }); + + it('sets bidfloors in ttxRequest if there is a floor', function() { + bidRequests[0].getFloor = ({size, currency, mediaType}) => { + const floor = (size[0] === 300 && size[1] === 250) ? 1.0 : 0.10 + return ( + { + floor, + currency: 'USD' + } + ); + }; + + const ttxRequest = new TtxRequestBuilder() + .withFormatFloors([ 1.0, 0.10 ]) + .build(); + + const serverRequest = new ServerRequestBuilder() + .withData(ttxRequest) + .build(); + const builtServerRequests = spec.buildRequests(bidRequests, {}); + + expect(builtServerRequests).to.deep.equal([serverRequest]); + }); + }); }); describe('interpretResponse', function() {