Skip to content

Commit b6c261c

Browse files
Openx bid adapter: support for MAP requests (prebid#14477)
* WIP deduplicate request * Cleanup of tests and buildRequest function * Improve tests * Revert changing platformID in test * Add additional tests * Search banner imp by id in test * Format tests * Fix lint errors --------- Co-authored-by: Rafal Sieczka <rafal.sieczka@openx.com> Co-authored-by: Rafał Sieczka <bukrain1@gmail.com>
1 parent 8a2b3c9 commit b6c261c

2 files changed

Lines changed: 109 additions & 59 deletions

File tree

modules/openxBidAdapter.js

Lines changed: 3 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -140,37 +140,11 @@ function isBidRequestValid(bidRequest) {
140140
}
141141

142142
function buildRequests(bidRequests, bidderRequest) {
143-
const videoRequests = bidRequests.filter(bidRequest => isVideoBidRequest(bidRequest));
144-
const bannerAndNativeRequests = bidRequests.filter(bidRequest => isBannerBidRequest(bidRequest) || isNativeBidRequest(bidRequest))
145-
// In case of multi-format bids remove `video` from mediaTypes as for video a separate bid request is built
146-
.map(bid => ({ ...bid, mediaTypes: { ...bid.mediaTypes, video: undefined } }));
147-
148-
const requests = bannerAndNativeRequests.length ? [createRequest(bannerAndNativeRequests, bidderRequest, null)] : [];
149-
videoRequests.forEach(bid => {
150-
requests.push(createRequest([bid], bidderRequest, VIDEO));
151-
});
152-
return requests;
153-
}
154-
155-
function createRequest(bidRequests, bidderRequest, mediaType) {
156-
return {
143+
return [{
157144
method: 'POST',
158145
url: config.getConfig('openxOrtbUrl') || REQUEST_URL,
159-
data: converter.toORTB({ bidRequests, bidderRequest, context: { mediaType } })
160-
}
161-
}
162-
163-
function isVideoBidRequest(bidRequest) {
164-
return utils.deepAccess(bidRequest, 'mediaTypes.video');
165-
}
166-
167-
function isNativeBidRequest(bidRequest) {
168-
return utils.deepAccess(bidRequest, 'mediaTypes.native');
169-
}
170-
171-
function isBannerBidRequest(bidRequest) {
172-
const isNotVideoOrNativeBid = !isVideoBidRequest(bidRequest) && !isNativeBidRequest(bidRequest)
173-
return utils.deepAccess(bidRequest, 'mediaTypes.banner') || isNotVideoOrNativeBid;
146+
data: converter.toORTB({ bidRequests, bidderRequest })
147+
}];
174148
}
175149

176150
function interpretResponse(resp, req) {

test/spec/modules/openxBidAdapter_spec.js

Lines changed: 106 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -414,16 +414,12 @@ describe('OpenxRtbAdapter', function () {
414414
playerSize: [640, 480]
415415
};
416416
const requests = spec.buildRequests([multiformat], mockBidderRequest);
417-
expect(requests).to.have.length(2);
417+
expect(requests).to.have.length(1);
418418
expect(requests[0].data.imp).to.have.length(1);
419419
expect(requests[0].data.imp[0].banner).to.exist;
420-
expect(requests[0].data.imp[0].video).to.not.exist;
421420
expect(requests[0].data.imp[0].native).to.not.exist;
422-
expect(requests[1].data.imp).to.have.length(1);
423-
expect(requests[1].data.imp[0].banner).to.not.exist;
424-
expect(requests[1].data.imp[0].native).to.not.exist;
425421
if (FEATURES.VIDEO) {
426-
expect(requests[1].data.imp[0].video).to.exist;
422+
expect(requests[0].data.imp[0].video).to.exist;
427423
}
428424
})
429425

@@ -452,21 +448,38 @@ describe('OpenxRtbAdapter', function () {
452448
sizes: [[300, 250]]
453449
}
454450
const requests = spec.buildRequests([multiformat], mockBidderRequest);
455-
expect(requests).to.have.length(2);
451+
expect(requests).to.have.length(1);
456452
expect(requests[0].data.imp).to.have.length(1);
457453
expect(requests[0].data.imp[0].banner).to.exist;
458-
expect(requests[0].data.imp[0].video).to.not.exist;
459454
if (FEATURES.NATIVE) {
460455
expect(requests[0].data.imp[0].native).to.exist;
461456
}
462-
expect(requests[1].data.imp).to.have.length(1);
463-
expect(requests[1].data.imp[0].banner).to.not.exist;
464-
expect(requests[1].data.imp[0].native).to.not.exist;
465457
if (FEATURES.VIDEO) {
466-
expect(requests[1].data.imp[0].video).to.exist;
458+
expect(requests[0].data.imp[0].video).to.exist;
467459
}
468460
})
469461

462+
it('should send banner, video and native bids in a single HTTP request', function () {
463+
const allBids = [...bidRequestsWithMediaTypes, nativeBidRequest];
464+
const request = spec.buildRequests(allBids, mockBidderRequest);
465+
466+
expect(request).to.have.length(1);
467+
expect(request[0].data.imp).to.have.length(3);
468+
469+
const bannerImp = request[0].data.imp.find(imp => imp.id === bidRequestsWithMediaTypes[0].bidId);
470+
expect(bannerImp.banner).to.exist;
471+
472+
if (FEATURES.VIDEO) {
473+
const videoImp = request[0].data.imp.find(imp => imp.id === bidRequestsWithMediaTypes[1].bidId);
474+
expect(videoImp.video).to.exist;
475+
}
476+
477+
if (FEATURES.NATIVE) {
478+
const nativeImp = request[0].data.imp.find(imp => imp.id === nativeBidRequest.bidId);
479+
expect(nativeImp.native).to.exist;
480+
}
481+
});
482+
470483
it('should send bid request to openx url via POST', function () {
471484
const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest);
472485
expect(request[0].url).to.equal(REQUEST_URL);
@@ -480,19 +493,26 @@ describe('OpenxRtbAdapter', function () {
480493
expect(request[0].data.ext.platformId).to.be.undefined;
481494
});
482495

483-
it('should send platform id, if available', function () {
496+
it('should send platform id from first bid, if available', function () {
484497
bidRequestsWithMediaTypes[0].params.platform = '1cabba9e-cafe-3665-beef-f00f00f00f00';
485498
bidRequestsWithMediaTypes[1].params.platform = '51ca3159-abc2-4035-8e00-fe26eaa09397';
486499

487500
const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest);
501+
expect(request.length).to.equal(1);
488502
expect(request[0].data.ext.platform).to.equal(bidRequestsWithMediaTypes[0].params.platform);
489-
expect(request[1].data.ext.platform).to.equal(bidRequestsWithMediaTypes[1].params.platform);
503+
});
504+
505+
it('should send delDomain from first bid when bids have different delDomains', function () {
506+
bidRequestsWithMediaTypes[0].params.delDomain = 'domain-a.test';
507+
bidRequestsWithMediaTypes[1].params.delDomain = 'domain-b.test';
508+
const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest);
509+
expect(request[0].data.ext.delDomain).to.equal('domain-a.test');
490510
});
491511

492512
it('should send openx adunit codes', function () {
493513
const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest);
494514
expect(request[0].data.imp[0].tagid).to.equal(bidRequestsWithMediaTypes[0].params.unit);
495-
expect(request[1].data.imp[0].tagid).to.equal(bidRequestsWithMediaTypes[1].params.unit);
515+
expect(request[0].data.imp[1].tagid).to.equal(bidRequestsWithMediaTypes[1].params.unit);
496516
});
497517

498518
it('should send out custom params on bids that have customParams specified', function () {
@@ -561,7 +581,7 @@ describe('OpenxRtbAdapter', function () {
561581
expect(request[0].data.imp[0].bidfloorcur).to.equal('USD');
562582
});
563583

564-
it('should send not send floors', function () {
584+
it('should not send floors', function () {
565585
adServerCurrencyStub.returns('EUR');
566586
const bidRequest = Object.assign({},
567587
bidRequestsWithMediaTypes[0],
@@ -904,7 +924,6 @@ describe('OpenxRtbAdapter', function () {
904924
it('should send a signal to specify that US Privacy applies to this request', async function () {
905925
const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest));
906926
expect(request[0].data.regs.ext.us_privacy).to.equal('1YYN');
907-
expect(request[1].data.regs.ext.us_privacy).to.equal('1YYN');
908927
});
909928

910929
it('should not send the regs object, when consent string is undefined', async function () {
@@ -946,29 +965,25 @@ describe('OpenxRtbAdapter', function () {
946965
bidderRequest.bids = bidRequests;
947966
const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest));
948967
expect(request[0].data.regs.ext.gdpr).to.equal(1);
949-
expect(request[1].data.regs.ext.gdpr).to.equal(1);
950968
});
951969

952970
it('should send the consent string', async function () {
953971
bidderRequest.bids = bidRequests;
954972
const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest));
955973
expect(request[0].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString);
956-
expect(request[1].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString);
957974
});
958975

959976
it('should send the addtlConsent string', async function () {
960977
bidderRequest.bids = bidRequests;
961978
const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest));
962979
expect(request[0].data.user.ext.ConsentedProvidersSettings.consented_providers).to.equal(bidderRequest.gdprConsent.addtlConsent);
963-
expect(request[1].data.user.ext.ConsentedProvidersSettings.consented_providers).to.equal(bidderRequest.gdprConsent.addtlConsent);
964980
});
965981

966982
it('should send a signal to specify that GDPR does not apply to this request', async function () {
967983
bidderRequest.gdprConsent.gdprApplies = false;
968984
bidderRequest.bids = bidRequests;
969985
const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest));
970986
expect(request[0].data.regs.ext.gdpr).to.equal(0);
971-
expect(request[1].data.regs.ext.gdpr).to.equal(0);
972987
});
973988

974989
it('when GDPR application is undefined, should not send a signal to specify whether GDPR applies to this request, ' +
@@ -978,15 +993,14 @@ describe('OpenxRtbAdapter', function () {
978993
const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest));
979994
expect(request[0].data.regs?.ext?.gdpr).to.not.be.ok;
980995
expect(request[0].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString);
981-
expect(request[1].data.user.ext.consent).to.equal(bidderRequest.gdprConsent.consentString);
982996
});
983997

984998
it('when consent string is undefined, should not send the consent string, ', async function () {
985999
delete bidderRequest.gdprConsent.consentString;
9861000
bidderRequest.bids = bidRequests;
9871001
const request = spec.buildRequests(bidRequests, await addFPDToBidderRequest(bidderRequest));
9881002
expect(request[0].data.imp[0].ext.consent).to.equal(undefined);
989-
expect(request[1].data.imp[0].ext.consent).to.equal(undefined);
1003+
expect(request[0].data.imp[1].ext.consent).to.equal(undefined);
9901004
});
9911005
});
9921006

@@ -1002,8 +1016,6 @@ describe('OpenxRtbAdapter', function () {
10021016
const request = spec.buildRequests(bidRequests, bidderRequest);
10031017
expect(request[0].data.regs.gpp).to.equal('test-gpp-string');
10041018
expect(request[0].data.regs.gpp_sid).to.deep.equal([6]);
1005-
expect(request[1].data.regs.gpp).to.equal('test-gpp-string');
1006-
expect(request[1].data.regs.gpp_sid).to.deep.equal([6]);
10071019
});
10081020

10091021
it('should not send GPP string and GPP section IDs in bid request when not available', async function () {
@@ -1014,8 +1026,6 @@ describe('OpenxRtbAdapter', function () {
10141026
const request = spec.buildRequests(bidRequests, bidderRequest);
10151027
expect(request[0].data.regs.gpp).to.not.exist;
10161028
expect(request[0].data.regs.gpp_sid).to.not.exist;
1017-
expect(request[1].data.regs.gpp).to.not.exist;
1018-
expect(request[1].data.regs.gpp_sid).to.not.exist;
10191029
});
10201030
});
10211031
});
@@ -1216,7 +1226,7 @@ describe('OpenxRtbAdapter', function () {
12161226
context('video', function () {
12171227
it('should send bid request with a mediaTypes specified with video type', function () {
12181228
const request = spec.buildRequests(bidRequestsWithMediaTypes, mockBidderRequest);
1219-
expect(request[1].data.imp[0]).to.have.any.keys(VIDEO);
1229+
expect(request[0].data.imp[1]).to.have.any.keys(VIDEO);
12201230
});
12211231

12221232
it('Update imp.video with OpenRTB options from mimeTypes and params', function() {
@@ -1253,8 +1263,8 @@ describe('OpenxRtbAdapter', function () {
12531263
h: 250
12541264
};
12551265
const requests = spec.buildRequests([bid01], bidderRequest);
1256-
expect(requests).to.have.lengthOf(2);
1257-
expect(requests[1].data.imp[0].video).to.deep.equal(expected);
1266+
expect(requests).to.have.lengthOf(1);
1267+
expect(requests[0].data.imp[0].video).to.deep.equal(expected);
12581268
});
12591269
});
12601270
}
@@ -1538,6 +1548,7 @@ describe('OpenxRtbAdapter', function () {
15381548
crid: 'test-creative-id',
15391549
dealid: 'test-deal-id',
15401550
adm: '<VAST version="4.0"><Ad></Ad></VAST>',
1551+
mtype: 2,
15411552
}]
15421553
}],
15431554
cur: 'AUS'
@@ -1658,6 +1669,71 @@ describe('OpenxRtbAdapter', function () {
16581669
});
16591670
}
16601671

1672+
context('when multiple bid requests (banner + video) are in one request and both bids are returned', function() {
1673+
it('should correctly return both banner and video bids', function () {
1674+
const bidRequestConfigs = [
1675+
{
1676+
bidder: 'openx',
1677+
params: {
1678+
unit: '1',
1679+
delDomain: 'test-del-domain'
1680+
},
1681+
adUnitCode: 'au-1',
1682+
mediaTypes: {
1683+
banner: {
1684+
sizes: [[300, 250]]
1685+
}
1686+
},
1687+
bidId: 'bid-id-banner',
1688+
bidderRequestId: 'br-1',
1689+
auctionId: 'a-1'
1690+
},
1691+
{
1692+
bidder: 'openx',
1693+
params: {
1694+
unit: '2',
1695+
delDomain: 'test-del-domain'
1696+
},
1697+
adUnitCode: 'au-2',
1698+
mediaTypes: {
1699+
video: {
1700+
playerSize: [640, 480]
1701+
}
1702+
},
1703+
bidId: 'bid-id-video',
1704+
bidderRequestId: 'br-1',
1705+
auctionId: 'a-1'
1706+
}
1707+
];
1708+
const bidRequest = spec.buildRequests(bidRequestConfigs, { refererInfo: {} })[0];
1709+
const bidResponse = {
1710+
seatbid: [{
1711+
bid: [
1712+
{
1713+
impid: 'bid-id-banner',
1714+
price: 1,
1715+
adm: '<div>ad</div>',
1716+
mtype: 1
1717+
},
1718+
{
1719+
impid: 'bid-id-video',
1720+
price: 2,
1721+
adm: '<VAST/>',
1722+
mtype: 2
1723+
}
1724+
]
1725+
}],
1726+
cur: 'USD'
1727+
};
1728+
const result = spec.interpretResponse({ body: bidResponse }, bidRequest);
1729+
expect(result.bids).to.have.length(2);
1730+
expect(result.bids[0].mediaType).to.equal(BANNER);
1731+
expect(result.bids[1].mediaType).to.equal(VIDEO);
1732+
expect(result.bids[0].requestId).to.equal('bid-id-banner');
1733+
expect(result.bids[1].requestId).to.equal('bid-id-video');
1734+
});
1735+
});
1736+
16611737
if (FEATURES.NATIVE) {
16621738
context('when native request and the response is a native', function() {
16631739
beforeEach(function () {

0 commit comments

Comments
 (0)