diff --git a/modules/openxBidAdapter.js b/modules/openxBidAdapter.js index 6a8783a662a5..ba3bc98b7665 100644 --- a/modules/openxBidAdapter.js +++ b/modules/openxBidAdapter.js @@ -8,9 +8,10 @@ import {parse} from 'src/url'; const SUPPORTED_AD_TYPES = [BANNER, VIDEO]; const BIDDER_CODE = 'openx'; const BIDDER_CONFIG = 'hb_pb'; -const BIDDER_VERSION = '2.1.1'; +const BIDDER_VERSION = '2.1.2'; let shouldSendBoPixel = true; + export function resetBoPixel() { shouldSendBoPixel = true; } @@ -19,6 +20,10 @@ export const spec = { code: BIDDER_CODE, supportedMediaTypes: SUPPORTED_AD_TYPES, isBidRequestValid: function (bidRequest) { + if (bidRequest.mediaTypes && bidRequest.mediaTypes.banner) { + return !!((bidRequest.params.unit || bidRequest.params.placementId) && bidRequest.params.delDomain); + } + return !!(bidRequest.params.unit && bidRequest.params.delDomain); }, buildRequests: function (bidRequests, bidderRequest) { @@ -48,14 +53,14 @@ export const spec = { return mediaType === VIDEO ? createVideoBidResponses(oxResponseObj, serverRequest.payload) : createBannerBidResponses(oxResponseObj, serverRequest.payload); }, - getUserSyncs: function(syncOptions, responses) { + getUserSyncs: function (syncOptions, responses) { if (syncOptions.iframeEnabled) { let url = utils.deepAccess(responses, '0.body.ads.pixels') || - utils.deepAccess(responses, '0.body.pixels') || - '//u.openx.net/w/1.0/pd'; + utils.deepAccess(responses, '0.body.pixels') || + '//u.openx.net/w/1.0/pd'; return [{ type: 'iframe', - url: url, + url: url }]; } } @@ -214,14 +219,22 @@ function buildCommonQueryParamsFromBids(bids, bidderRequest) { } function buildOXBannerRequest(bids, bidderRequest) { + let customParamsForAllBids = []; + let hasCustomParam = false; let queryParams = buildCommonQueryParamsFromBids(bids, bidderRequest); - - queryParams.auid = utils._map(bids, bid => bid.params.unit).join(','); + let auids = utils._map(bids, bid => bid.params.unit); + let pids = utils._map(bids, bid => bid.params.placementId); queryParams.aus = utils._map(bids, bid => utils.parseSizesInput(bid.sizes).join(',')).join('|'); queryParams.bc = bids[0].params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`; + queryParams.divs = utils._map(bids, bid => bid.adUnitCode).join(','); + + if (auids.some(auid => auid)) { + queryParams.auid = auids.join(','); + } + if (pids.some(pid => pid)) { + queryParams.pids = pids.join(','); + } - let customParamsForAllBids = []; - let hasCustomParam = false; bids.forEach(function (bid) { if (bid.params.customParams) { let customParamsForBid = utils._map(Object.keys(bid.params.customParams), customKey => formatCustomParms(customKey, bid.params.customParams)); diff --git a/modules/openxBidAdapter.md b/modules/openxBidAdapter.md index 9e9d3ebfa7af..a7a39a8412ed 100644 --- a/modules/openxBidAdapter.md +++ b/modules/openxBidAdapter.md @@ -21,6 +21,7 @@ Module that connects to OpenX's demand sources { bidder: 'openx', params: { + placementId: '/123/abcdefg' unit: '539439964', delDomain: 'se-demo-d.openx.net' } @@ -46,3 +47,10 @@ Module that connects to OpenX's demand sources } ]; ``` + + +# Links +[Banner Ads](https://docs.openx.com/Content/developers/containers/prebid-adapter.html) + +[Video Ads](https://docs.openx.com/Content/developers/containers/prebid-video-adapter.html) + diff --git a/test/spec/modules/openxBidAdapter_spec.js b/test/spec/modules/openxBidAdapter_spec.js index 3585987e045b..7f9cac405c32 100644 --- a/test/spec/modules/openxBidAdapter_spec.js +++ b/test/spec/modules/openxBidAdapter_spec.js @@ -129,34 +129,43 @@ describe('OpenxAdapter', () => { describe('isBidRequestValid', () => { describe('when request is for a banner ad', () => { - const bannerBid = { - bidder: 'openx', - params: { - unit: '12345678', - delDomain: 'test-del-domain' - }, - adUnitCode: 'adunit-code', - mediaTypes: {banner: {}}, - sizes: [[300, 250], [300, 600]], - bidId: '30b31c1838de1e', - bidderRequestId: '22edbae2733bf6', - auctionId: '1d1a030790a475' - }; - - it('should return true when required params found', () => { - expect(spec.isBidRequestValid(bannerBid)).to.equal(true); + let bannerBid; + beforeEach(() => { + bannerBid = { + bidder: 'openx', + params: {}, + adUnitCode: 'adunit-code', + mediaTypes: {banner: {}}, + sizes: [[300, 250], [300, 600]], + bidId: '30b31c1838de1e', + bidderRequestId: '22edbae2733bf6', + auctionId: '1d1a030790a475' + }; }); it('should return false when there is no delivery domain', () => { - let bid = Object.assign({}, bannerBid); - bid.params = {'unit': '12345678'}; - expect(spec.isBidRequestValid(bid)).to.equal(false); + bannerBid.params = {'unit': '12345678'}; + expect(spec.isBidRequestValid(bannerBid)).to.equal(false); }); - it('should return false when there is no ad unit id ', () => { - let bid = Object.assign({}, bannerBid); - bid.params = {delDomain: 'test-del-domain'}; - expect(spec.isBidRequestValid(bid)).to.equal(false); + describe('when there is a delivery domain', () => { + beforeEach(function () { + bannerBid.params = {delDomain: 'test-delivery-domain'} + }); + + it('should return false when there is no ad unit id and no placement id', () => { + expect(spec.isBidRequestValid(bannerBid)).to.equal(false); + }); + + it('should return true if there is an adunit id ', () => { + bannerBid.params.unit = '12345678'; + expect(spec.isBidRequestValid(bannerBid)).to.equal(true); + }); + + it('should return true if there is an placement id ', () => { + bannerBid.params.placementId = '/12345678/aaaa/bbbb'; + expect(spec.isBidRequestValid(bannerBid)).to.equal(true); + }); }); }); @@ -186,7 +195,7 @@ describe('OpenxAdapter', () => { 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', - 'mediaTypes': 'video', + 'mediaType': 'video', 'sizes': [640, 480], 'bidId': '30b31c1838de1e', 'bidderRequestId': '22edbae2733bf6', @@ -233,7 +242,7 @@ describe('OpenxAdapter', () => { const bidRequestsWithMediaTypes = [{ 'bidder': 'openx', 'params': { - 'unit': '12345678', + 'unit': '11', 'delDomain': 'test-del-domain' }, 'adUnitCode': 'adunit-code', @@ -242,9 +251,24 @@ describe('OpenxAdapter', () => { sizes: [[300, 250], [300, 600]] } }, - 'bidId': '30b31c1838de1e', - 'bidderRequestId': '22edbae2733bf6', - 'auctionId': '1d1a030790a475' + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'unit': '22', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' }]; it('should send bid request to openx url via GET, with mediaType specified as banner', () => { @@ -259,6 +283,153 @@ describe('OpenxAdapter', () => { expect(request[0].method).to.equal('GET'); }); + it('should send the adunit codes', () => { + const request = spec.buildRequests(bidRequestsWithMediaTypes); + expect(request[0].data.divs).to.equal(`${bidRequestsWithMediaTypes[0].adUnitCode},${bidRequestsWithMediaTypes[1].adUnitCode}`); + }); + + it('should send ad unit ids when any are defined', () => { + const bidRequestsWithPlacementIds = [{ + 'bidder': 'openx', + 'params': { + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'unit': '22', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithPlacementIds); + expect(request[0].data.auid).to.equal(`,${bidRequestsWithPlacementIds[1].params.unit}`); + }); + + it('should not send any ad unit ids when none are defined', () => { + const bidRequestsWithoutPlacementIds = [{ + 'bidder': 'openx', + 'params': { + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithoutPlacementIds); + expect(request[0].data).to.not.have.any.keys('auid'); + }); + + it('should send placement ids when any are defined', () => { + const bidRequestsWithPlacementIds = [{ + 'bidder': 'openx', + 'params': { + 'unit': '11', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'unit': '22', + 'delDomain': 'test-del-domain', + placementId: 'test-placement-id-2' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithPlacementIds); + expect(request[0].data.pids).to.equal(`,${bidRequestsWithPlacementIds[1].params.placementId}`); + }); + + it('should not send any placement ids when none are defined', () => { + const bidRequestsWithoutPlacementIds = [{ + 'bidder': 'openx', + 'params': { + 'unit': '11', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + }, + 'bidId': 'test-bid-id-1', + 'bidderRequestId': 'test-bid-request-1', + 'auctionId': 'test-auction-1' + }, { + 'bidder': 'openx', + 'params': { + 'unit': '22', + 'delDomain': 'test-del-domain' + }, + 'adUnitCode': 'adunit-code', + mediaTypes: { + banner: { + sizes: [[728, 90]] + } + }, + 'bidId': 'test-bid-id-2', + 'bidderRequestId': 'test-bid-request-2', + 'auctionId': 'test-auction-2' + }]; + const request = spec.buildRequests(bidRequestsWithoutPlacementIds); + expect(request[0].data).to.not.have.any.keys('pids'); + }); + describe('when there is a legacy request with no media type', function () { const deprecatedBidRequestsFormatWithNoMediaType = [{ 'bidder': 'openx', @@ -1077,10 +1248,10 @@ describe('OpenxAdapter', () => { it('should register the pixel iframe from banner ad response', () => { let syncs = spec.getUserSyncs( - { iframeEnabled: true }, - [{ body: { ads: { pixels: syncUrl } } }] + {iframeEnabled: true}, + [{body: {ads: {pixels: syncUrl}}}] ); - expect(syncs).to.deep.equal([{ type: 'iframe', url: syncUrl }]); + expect(syncs).to.deep.equal([{type: 'iframe', url: syncUrl}]); }); it('should register the pixel iframe from video ad response', () => {