From c957a56fb9c0789d887b9ce6aced35a854e94af3 Mon Sep 17 00:00:00 2001 From: Nisar Thadathil Date: Tue, 10 Jun 2025 15:24:01 +0530 Subject: [PATCH 1/3] vidoomy adapter: support for multiple bids response --- modules/vidoomyBidAdapter.js | 129 ++++++++++---------- test/spec/modules/vidoomyBidAdapter_spec.js | 90 ++++++++++++-- 2 files changed, 148 insertions(+), 71 deletions(-) diff --git a/modules/vidoomyBidAdapter.js b/modules/vidoomyBidAdapter.js index 894d3191311..80e0429f2c0 100644 --- a/modules/vidoomyBidAdapter.js +++ b/modules/vidoomyBidAdapter.js @@ -167,6 +167,7 @@ const buildRequests = (validBidRequests, bidderRequest) => { usp: bidderRequest.uspConsent || '', coppa: !!config.getConfig('coppa'), videoContext: videoContext || '', + multiBidsSupport: 1, bcat: ortb2.bcat || bid.params.bcat || [], badv: ortb2.badv || bid.params.badv || [], bapp: ortb2.bapp || bid.params.bapp || [], @@ -203,71 +204,75 @@ const render = (bid) => { const interpretResponse = (serverResponse, bidRequest) => { try { - let responseBody = serverResponse.body; - if (!responseBody) return; - if (responseBody.mediaType === 'video') { - responseBody.ad = responseBody.vastUrl || responseBody.vastXml; - const videoContext = bidRequest.data.videoContext; - - if (videoContext === OUTSTREAM) { - try { - const renderer = Renderer.install({ - id: bidRequest.bidId, - adunitcode: bidRequest.tagId, - loaded: false, - config: responseBody.mediaType, - url: responseBody.meta.rendererUrl - }); - renderer.setRender(render); - - responseBody.renderer = renderer; - } catch (e) { - responseBody.ad = responseBody.vastUrl || responseBody.vastXml; - logError(BIDDER_CODE + ': error while installing renderer to show outstream ad'); + let responseBodies = serverResponse.body; + if (!Array.isArray(responseBodies) || responseBodies.length === 0) return; + + const bids = []; + + for (let responseBody of responseBodies) { + if (!responseBody) continue; + if (responseBody.mediaType === 'video') { + responseBody.ad = responseBody.vastUrl || responseBody.vastXml; + const videoContext = bidRequest.data.videoContext; + + if (videoContext === OUTSTREAM) { + try { + const renderer = Renderer.install({ + id: bidRequest.bidId, + adunitcode: bidRequest.tagId, + loaded: false, + config: responseBody.mediaType, + url: responseBody.meta.rendererUrl + }); + renderer.setRender(render); + + responseBody.renderer = renderer; + } catch (e) { + responseBody.ad = responseBody.vastUrl || responseBody.vastXml; + logError(BIDDER_CODE + ': error while installing renderer to show outstream ad'); + } } } - } - const bid = { - ad: responseBody.ad, - renderer: responseBody.renderer, - mediaType: responseBody.mediaType, - requestId: responseBody.requestId, - cpm: responseBody.cpm, - currency: responseBody.currency, - width: responseBody.width, - height: responseBody.height, - creativeId: responseBody.creativeId, - netRevenue: responseBody.netRevenue, - ttl: responseBody.ttl, - meta: { - mediaType: responseBody.meta.mediaType, - rendererUrl: responseBody.meta.rendererUrl, - advertiserDomains: responseBody.meta.advertiserDomains, - advertiserId: responseBody.meta.advertiserId, - advertiserName: responseBody.meta.advertiserName, - agencyId: responseBody.meta.agencyId, - agencyName: responseBody.meta.agencyName, - brandId: responseBody.meta.brandId, - brandName: responseBody.meta.brandName, - dchain: responseBody.meta.dchain, - networkId: responseBody.meta.networkId, - networkName: responseBody.meta.networkName, - primaryCatId: responseBody.meta.primaryCatId, - secondaryCatIds: responseBody.meta.secondaryCatIds + const bid = { + ad: responseBody.ad, + renderer: responseBody.renderer, + mediaType: responseBody.mediaType, + requestId: responseBody.requestId, + cpm: responseBody.cpm, + currency: responseBody.currency, + width: responseBody.width, + height: responseBody.height, + creativeId: responseBody.creativeId, + netRevenue: responseBody.netRevenue, + ttl: responseBody.ttl, + meta: { + mediaType: responseBody.meta.mediaType, + rendererUrl: responseBody.meta.rendererUrl, + advertiserDomains: responseBody.meta.advertiserDomains, + advertiserId: responseBody.meta.advertiserId, + advertiserName: responseBody.meta.advertiserName, + agencyId: responseBody.meta.agencyId, + agencyName: responseBody.meta.agencyName, + brandId: responseBody.meta.brandId, + brandName: responseBody.meta.brandName, + dchain: responseBody.meta.dchain, + networkId: responseBody.meta.networkId, + networkName: responseBody.meta.networkName, + primaryCatId: responseBody.meta.primaryCatId, + secondaryCatIds: responseBody.meta.secondaryCatIds + } + }; + if (responseBody.vastUrl) { + bid.vastUrl = responseBody.vastUrl; + } else if (responseBody.vastXml) { + bid.vastXml = responseBody.vastXml; } - }; - if (responseBody.vastUrl) { - bid.vastUrl = responseBody.vastUrl; - } else if (responseBody.vastXml) { - bid.vastXml = responseBody.vastXml; - } - const bids = []; - - if (isBidResponseValid(bid)) { - bids.push(bid); - } else { - logError(BIDDER_CODE + ': server returns invalid response'); + if (isBidResponseValid(bid)) { + bids.push(bid); + } else { + logError(BIDDER_CODE + ': server returns invalid response'); + } } return bids; @@ -280,7 +285,7 @@ const interpretResponse = (serverResponse, bidRequest) => { function getUserSyncs(syncOptions, responses, gdprConsent, uspConsent) { if (syncOptions.iframeEnabled || syncOptions.pixelEnabled) { const pixelType = syncOptions.pixelEnabled ? 'image' : 'iframe'; - const urls = deepAccess(responses, '0.body.pixels') || COOKIE_SYNC_FALLBACK_URLS; + const urls = deepAccess(responses, '0.body.0.pixels') || COOKIE_SYNC_FALLBACK_URLS; return [].concat(urls).map(url => ({ type: pixelType, diff --git a/test/spec/modules/vidoomyBidAdapter_spec.js b/test/spec/modules/vidoomyBidAdapter_spec.js index 6f7c0beb29f..75fb2dc86c2 100644 --- a/test/spec/modules/vidoomyBidAdapter_spec.js +++ b/test/spec/modules/vidoomyBidAdapter_spec.js @@ -154,6 +154,11 @@ describe('vidoomyBidAdapter', function() { expect('' + request[1].data.pid).to.equal('456456'); }); + it('should send multiBidsSupport parameters', function () { + expect(''+ request[0].data.multiBidsSupport).to.equal('1'); + expect('' +request[1].data.multiBidsSupport).to.equal('1'); + }); + it('should send schain parameter in serialized form', function () { const serializedForm = '1.0,1!exchange1.com,1234%21abcd,1,bid-request-1,publisher%2C%20Inc.,publisher.com!exchange2.com,abcd,1,,,!exchange2.com,abcd,1,bid-request-2,intermediary,intermediary.com' expect(request[0].data).to.include.any.keys('schain'); @@ -270,7 +275,7 @@ describe('vidoomyBidAdapter', function() { describe('interpretResponse', function () { const serverResponseVideo = { - body: { + body: [{ 'vastUrl': 'https:\/\/vpaid.vidoomy.com\/demo-ad\/tag.xml', 'mediaType': 'video', 'requestId': '123123', @@ -298,11 +303,40 @@ describe('vidoomyBidAdapter', function() { 'primaryCatId': 'IAB3-1', 'secondaryCatIds': null } - } + }, + { + 'vastUrl': 'https:\/\/vpaid.vidoomy.com\/demo-ad-two\/tag.xml', + 'mediaType': 'video', + 'requestId': '102030', + 'cpm': 5.265, + 'currency': 'USD', + 'width': 10, + 'height': 400, + 'creativeId': '112233', + 'dealId': '23cb20aa264b72c', + 'netRevenue': true, + 'ttl': 80, + 'meta': { + 'mediaType': 'video', + 'rendererUrl': 'https:\/\/vpaid.vidoomy.com\/outstreamplayer\/bundle.js', + 'advertiserDomains': ['vidoomy.com'], + 'advertiserId': 123, + 'advertiserName': 'Vidoomy', + 'agencyId': null, + 'agencyName': null, + 'brandId': null, + 'brandName': null, + 'dchain': null, + 'networkId': null, + 'networkName': null, + 'primaryCatId': 'IAB3-1', + 'secondaryCatIds': null + } + }] } const serverResponseBanner = { - body: { + body: [{ 'ad': '