From 9e5a0b4dc4a01d249978cd2f8b0f90568e853e38 Mon Sep 17 00:00:00 2001 From: JonGoSonobi Date: Wed, 22 Jun 2022 11:59:34 -0400 Subject: [PATCH] Sonobi Bid Adapter: fix gpid bid request value and add media type value (#8541) * Fixed an issue where the key_maker value in the bid request was malformed when adding gpid. Added new media type value to the bid request. * changed a few if statements to avoid running some conditions when not needed --- modules/sonobiBidAdapter.js | 37 +++++++++---- test/spec/modules/sonobiBidAdapter_spec.js | 61 ++++++++++++++-------- 2 files changed, 66 insertions(+), 32 deletions(-) diff --git a/modules/sonobiBidAdapter.js b/modules/sonobiBidAdapter.js index b65fde79553..5309dbdad5a 100644 --- a/modules/sonobiBidAdapter.js +++ b/modules/sonobiBidAdapter.js @@ -56,15 +56,23 @@ export const spec = { */ buildRequests: (validBidRequests, bidderRequest) => { const bids = validBidRequests.map(bid => { + let mediaType; + + if (deepAccess(bid, 'mediaTypes.video')) { + mediaType = 'video'; + } else if (deepAccess(bid, 'mediaTypes.banner')) { + mediaType = 'display'; + } + let slotIdentifier = _validateSlot(bid); if (/^[\/]?[\d]+[[\/].+[\/]?]?$/.test(slotIdentifier)) { slotIdentifier = slotIdentifier.charAt(0) === '/' ? slotIdentifier : '/' + slotIdentifier; return { - [`${slotIdentifier}|${bid.bidId}`]: `${_validateSize(bid)}${_validateFloor(bid)}${_validateGPID(bid)}` + [`${slotIdentifier}|${bid.bidId}`]: `${_validateSize(bid)}|${_validateFloor(bid)}${_validateGPID(bid)}${_validateMediaType(mediaType)}` } } else if (/^[0-9a-fA-F]{20}$/.test(slotIdentifier) && slotIdentifier.length === 20) { return { - [bid.bidId]: `${slotIdentifier}|${_validateSize(bid)}${_validateFloor(bid)}${_validateGPID(bid)}` + [bid.bidId]: `${slotIdentifier}|${_validateSize(bid)}|${_validateFloor(bid)}${_validateGPID(bid)}${_validateMediaType(mediaType)}` } } else { logError(`The ad unit code or Sonobi Placement id for slot ${bid.bidId} is invalid`); @@ -273,7 +281,7 @@ export const spec = { }); }); } - } catch (e) {} + } catch (e) { } return syncs; } }; @@ -286,7 +294,7 @@ function _findBidderRequest(bidderRequests, bidId) { } } -function _validateSize (bid) { +function _validateSize(bid) { if (deepAccess(bid, 'mediaTypes.video')) { return ''; // Video bids arent allowed to override sizes via the trinity request } @@ -304,18 +312,18 @@ function _validateSize (bid) { } } -function _validateSlot (bid) { +function _validateSlot(bid) { if (bid.params.ad_unit) { return bid.params.ad_unit; } return bid.params.placement_id; } -function _validateFloor (bid) { +function _validateFloor(bid) { const floor = getBidFloor(bid); if (floor) { - return `|f=${floor}`; + return `f=${floor},`; } return ''; } @@ -324,11 +332,22 @@ function _validateGPID(bid) { const gpid = deepAccess(bid, 'ortb2Imp.ext.data.pbadslot') || deepAccess(getGptSlotInfoForAdUnitCode(bid.adUnitCode), 'gptSlot') || bid.params.ad_unit; if (gpid) { - return `|gpid=${gpid}` + return `gpid=${gpid},` } return '' } +function _validateMediaType(mediaType) { + let mediaTypeValidation = ''; + if (mediaType === 'video') { + mediaTypeValidation = 'c=v,'; + } else if (mediaType === 'display') { + mediaTypeValidation = 'c=d,'; + } + + return mediaTypeValidation; +} + const _creative = (mediaType, referer) => (sbiDc, sbiAid) => { if (mediaType === 'video' || mediaType === 'outstream') { return _videoCreative(sbiDc, sbiAid, referer) @@ -341,7 +360,7 @@ function _videoCreative(sbiDc, sbiAid, referer) { return `https://${sbiDc}apex.go.sonobi.com/vast.xml?vid=${sbiAid}&ref=${encodeURIComponent(referer)}` } -function _getBidIdFromTrinityKey (key) { +function _getBidIdFromTrinityKey(key) { return key.split('|').slice(-1)[0] } diff --git a/test/spec/modules/sonobiBidAdapter_spec.js b/test/spec/modules/sonobiBidAdapter_spec.js index a502cc3d17d..7803cfff394 100644 --- a/test/spec/modules/sonobiBidAdapter_spec.js +++ b/test/spec/modules/sonobiBidAdapter_spec.js @@ -1,7 +1,7 @@ import { expect } from 'chai' import { spec, _getPlatform } from 'modules/sonobiBidAdapter.js' import { newBidder } from 'src/adapters/bidderFactory.js' -import {userSync} from '../../../src/userSync.js'; +import { userSync } from '../../../src/userSync.js'; import { config } from 'src/config.js'; import * as utils from '../../../src/utils.js'; @@ -239,13 +239,13 @@ describe('SonobiBidAdapter', function () { describe('.buildRequests', function () { let sandbox; - beforeEach(function() { + beforeEach(function () { sinon.stub(userSync, 'canBidderRegisterSync'); sinon.stub(utils, 'getGptSlotInfoForAdUnitCode') - .onFirstCall().returns({gptSlot: '/123123/gpt_publisher/adunit-code-3', divId: 'adunit-code-3-div-id'}); + .onFirstCall().returns({ gptSlot: '/123123/gpt_publisher/adunit-code-3', divId: 'adunit-code-3-div-id' }); sandbox = sinon.createSandbox(); }); - afterEach(function() { + afterEach(function () { userSync.canBidderRegisterSync.restore(); utils.getGptSlotInfoForAdUnitCode.restore(); sandbox.restore(); @@ -284,6 +284,11 @@ describe('SonobiBidAdapter', function () { pbadslot: '/123123/gpt_publisher/adunit-code-1' } } + }, + mediaTypes: { + video: { + context: 'outstream' + } } }, { @@ -296,11 +301,16 @@ describe('SonobiBidAdapter', function () { 'adUnitCode': 'adunit-code-3', 'sizes': [[120, 600], [300, 600], [160, 600]], 'bidId': '30b31c1838de1d', - 'getFloor': ({currency, mediaType, size}) => { + 'getFloor': ({ currency, mediaType, size }) => { return { currency: 'USD', floor: 0.42 } + }, + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } } }, { @@ -313,12 +323,17 @@ describe('SonobiBidAdapter', function () { 'adUnitCode': 'adunit-code-2', 'sizes': [[120, 600], [300, 600], [160, 600]], 'bidId': '30b31c1838de1e', + mediaTypes: { + banner: { + sizes: [[300, 250], [300, 600]] + } + } }]; let keyMakerData = { - '30b31c1838de1f': '1a2b3c4d5e6f1a2b3c4d|300x250,300x600|f=1.25|gpid=/123123/gpt_publisher/adunit-code-1', - '30b31c1838de1d': '1a2b3c4d5e6f1a2b3c4e|300x250,300x600|f=0.42|gpid=/123123/gpt_publisher/adunit-code-3', - '/7780971/sparks_prebid_LB|30b31c1838de1e': '300x250,300x600|gpid=/7780971/sparks_prebid_LB', + '30b31c1838de1f': '1a2b3c4d5e6f1a2b3c4d||f=1.25,gpid=/123123/gpt_publisher/adunit-code-1,c=v,', + '30b31c1838de1d': '1a2b3c4d5e6f1a2b3c4e|300x250,300x600|f=0.42,gpid=/123123/gpt_publisher/adunit-code-3,c=d,', + '/7780971/sparks_prebid_LB|30b31c1838de1e': '300x250,300x600|gpid=/7780971/sparks_prebid_LB,c=d,', }; let bidderRequests = { @@ -336,7 +351,7 @@ describe('SonobiBidAdapter', function () { uspConsent: 'someCCPAString' }; - it('should set fpd if there is any data in ortb2', function() { + it('should set fpd if there is any data in ortb2', function () { const ortb2 = { site: { ext: { @@ -360,14 +375,14 @@ describe('SonobiBidAdapter', function () { }); it('should populate coppa as 1 if set in config', function () { - config.setConfig({coppa: true}); + config.setConfig({ coppa: true }); const bidRequests = spec.buildRequests(bidRequest, bidderRequests); expect(bidRequests.data.coppa).to.equal(1); }); it('should populate coppa as 0 if set in config', function () { - config.setConfig({coppa: false}); + config.setConfig({ coppa: false }); const bidRequests = spec.buildRequests(bidRequest, bidderRequests); expect(bidRequests.data.coppa).to.equal(0); @@ -462,7 +477,7 @@ describe('SonobiBidAdapter', function () { }) it('should return null if there is nothing to bid on', function () { - const bidRequests = spec.buildRequests([{params: {}}], bidderRequests) + const bidRequests = spec.buildRequests([{ params: {} }], bidderRequests) expect(bidRequests).to.equal(null); }); @@ -472,7 +487,7 @@ describe('SonobiBidAdapter', function () { expect(bidRequests.data.ius).to.equal(0); }); - it('should set ius as 1 if Sonobi can drop iframe pixels', function() { + it('should set ius as 1 if Sonobi can drop iframe pixels', function () { userSync.canBidderRegisterSync.returns(true); const bidRequests = spec.buildRequests(bidRequest, bidderRequests); expect(bidRequests.data.ius).to.equal(1); @@ -525,14 +540,14 @@ describe('SonobiBidAdapter', function () { }); it('should return a properly formatted request with userid as a JSON-encoded set of User ID results', function () { - bidRequest[0].userId = {'pubcid': 'abcd-efg-0101', 'tdid': 'td-abcd-efg-0101', 'id5id': {'uid': 'ID5-ZHMOrVeUVTUKgrZ-a2YGxeh5eS_pLzHCQGYOEAiTBQ', 'ext': {'linkType': 2}}}; - bidRequest[1].userId = {'pubcid': 'abcd-efg-0101', 'tdid': 'td-abcd-efg-0101', 'id5id': {'uid': 'ID5-ZHMOrVeUVTUKgrZ-a2YGxeh5eS_pLzHCQGYOEAiTBQ', 'ext': {'linkType': 2}}}; + bidRequest[0].userId = { 'pubcid': 'abcd-efg-0101', 'tdid': 'td-abcd-efg-0101', 'id5id': { 'uid': 'ID5-ZHMOrVeUVTUKgrZ-a2YGxeh5eS_pLzHCQGYOEAiTBQ', 'ext': { 'linkType': 2 } } }; + bidRequest[1].userId = { 'pubcid': 'abcd-efg-0101', 'tdid': 'td-abcd-efg-0101', 'id5id': { 'uid': 'ID5-ZHMOrVeUVTUKgrZ-a2YGxeh5eS_pLzHCQGYOEAiTBQ', 'ext': { 'linkType': 2 } } }; const bidRequests = spec.buildRequests(bidRequest, bidderRequests); expect(bidRequests.url).to.equal('https://apex.go.sonobi.com/trinity.json'); expect(bidRequests.method).to.equal('GET'); expect(bidRequests.data.ref).not.to.be.empty; expect(bidRequests.data.s).not.to.be.empty; - expect(JSON.parse(bidRequests.data.userid)).to.eql({'pubcid': 'abcd-efg-0101', 'tdid': 'td-abcd-efg-0101', 'id5id': 'ID5-ZHMOrVeUVTUKgrZ-a2YGxeh5eS_pLzHCQGYOEAiTBQ'}); + expect(JSON.parse(bidRequests.data.userid)).to.eql({ 'pubcid': 'abcd-efg-0101', 'tdid': 'td-abcd-efg-0101', 'id5id': 'ID5-ZHMOrVeUVTUKgrZ-a2YGxeh5eS_pLzHCQGYOEAiTBQ' }); }); it('should return a properly formatted request with userid omitted if there are no userIds', function () { @@ -557,17 +572,17 @@ describe('SonobiBidAdapter', function () { expect(bidRequests.data.userid).to.equal(undefined); }); - it('should return a properly formatted request with keywrods included as a csv of strings', function() { + it('should return a properly formatted request with keywrods included as a csv of strings', function () { const bidRequests = spec.buildRequests(bidRequest, bidderRequests); expect(bidRequests.data.kw).to.equal('sports,news,some_other_keyword'); }); - it('should return a properly formatted request with us_privacy included', function() { + it('should return a properly formatted request with us_privacy included', function () { const bidRequests = spec.buildRequests(bidRequest, bidderRequests); expect(bidRequests.data.us_privacy).to.equal('someCCPAString'); }); - it('should make a request to the url defined in the bidder param', function() { + it('should make a request to the url defined in the bidder param', function () { const bRequest = [ { ...bidRequest[0], @@ -755,7 +770,7 @@ describe('SonobiBidAdapter', function () { 'dealId': 'dozerkey', 'aid': 'force_1550072228_da1c5d030cb49150c5db8a2136175755', 'mediaType': 'video', - renderer: () => {}, + renderer: () => { }, meta: { advertiserDomains: ['sonobi.com'] } @@ -828,13 +843,13 @@ describe('SonobiBidAdapter', function () { }) describe('_getPlatform', function () { it('should return mobile', function () { - expect(_getPlatform({innerWidth: 767})).to.equal('mobile') + expect(_getPlatform({ innerWidth: 767 })).to.equal('mobile') }) it('should return tablet', function () { - expect(_getPlatform({innerWidth: 800})).to.equal('tablet') + expect(_getPlatform({ innerWidth: 800 })).to.equal('tablet') }) it('should return desktop', function () { - expect(_getPlatform({innerWidth: 1000})).to.equal('desktop') + expect(_getPlatform({ innerWidth: 1000 })).to.equal('desktop') }) }) })