diff --git a/modules/gridBidAdapter.js b/modules/gridBidAdapter.js index 60ae9dbc3a0..9c63e871356 100644 --- a/modules/gridBidAdapter.js +++ b/modules/gridBidAdapter.js @@ -6,8 +6,6 @@ import { generateUUID, mergeDeep, logWarn, - parseUrl, - isArray, isNumber, isStr } from '../src/utils.js'; @@ -16,25 +14,16 @@ import { Renderer } from '../src/Renderer.js'; import { VIDEO, BANNER } from '../src/mediaTypes.js'; import { config } from '../src/config.js'; import { getStorageManager } from '../src/storageManager.js'; -import { find } from '../src/polyfill.js'; const BIDDER_CODE = 'grid'; const ENDPOINT_URL = 'https://grid.bidswitch.net/hbjson'; -const ADAPTER_VERSION_FOR_CRITEO_MODE = 34; -const CDB_ENDPOINT = 'https://bidder.criteo.com/cdb'; -const PROFILE_ID_INLINE = 207; -const SID_COOKIE_NAME = 'cto_sid'; -const IDCPY_COOKIE_NAME = 'cto_idcpy'; -const OPTOUT_COOKIE_NAME = 'cto_optout'; -const BUNDLE_COOKIE_NAME = 'cto_bundle'; - const SYNC_URL = 'https://x.bidswitch.net/sync?ssp=themediagrid'; const TIME_TO_LIVE = 360; const USER_ID_KEY = 'tmguid'; const GVLID = 686; const RENDERER_URL = 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js'; -export const storage = getStorageManager({bidderCode: BIDDER_CODE}); +export const storage = getStorageManager({ bidderCode: BIDDER_CODE }); const LOG_ERROR_MESS = { noAuid: 'Bid from response has no auid parameter - ', @@ -105,17 +94,11 @@ export const spec = { const imp = []; const bidsMap = {}; const requests = []; - const criteoBidsMap = {}; - const criteoBidRequests = []; const sources = []; const bidsArray = []; validBidRequests.forEach((bid) => { const bidObject = { bid, savedPrebidBid: null }; - if (bid.params.withCriteo && criteoSpec.isBidRequestValid(bid)) { - criteoBidsMap[bid.bidId] = bidObject; - criteoBidRequests.push(bid); - } if (!bid.params.uid && !bid.params.secid) { return; } @@ -402,11 +385,6 @@ export const spec = { } }); - const criteoRequest = criteoBidRequests.length && criteoSpec.buildRequests(criteoBidRequests, bidderRequest); - if (criteoRequest) { - criteoRequest.criteoBidsMap = criteoBidsMap; - } - return [...requests.map((req, i) => { let sp; const url = (endpoint || ENDPOINT_URL).replace(/[?&]sp=([^?&=]+)/, (i, found) => { @@ -428,7 +406,7 @@ export const spec = { url: endpoint || ENDPOINT_URL, data: JSON.stringify(mainRequest), bidsMap - }] : []), ...(criteoRequest ? [criteoRequest] : [])]; + }] : [])]; }, /** * Unpack the response from the server into a list of bids. @@ -438,34 +416,26 @@ export const spec = { * @param {*} RendererConst * @return {Bid[]} An array of bids which were nested inside the server. */ - interpretResponse: function(serverResponse, bidRequest, RendererConst = Renderer) { - if (bidRequest.criteoBidsMap && bidRequest.bidRequests) { - const criteoBids = criteoSpec.interpretResponse(serverResponse, bidRequest); - return criteoBids.filter((bid) => { - const { savedPrebidBid } = bidRequest.criteoBidsMap[bid.requestId] || {}; - return canPublishResponse(bid.cpm, savedPrebidBid && savedPrebidBid.cpm); - }); - } else { - serverResponse = serverResponse && serverResponse.body; - const bidResponses = []; + interpretResponse: function (serverResponse, bidRequest, RendererConst = Renderer) { + serverResponse = serverResponse && serverResponse.body; + const bidResponses = []; - let errorMessage; + let errorMessage; - if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse; - else if (serverResponse.seatbid && !serverResponse.seatbid.length) { - errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray; - } + if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse; + else if (serverResponse.seatbid && !serverResponse.seatbid.length) { + errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray; + } - const bidderCode = this.forceBidderName || this.code; + const bidderCode = this.forceBidderName || this.code; - if (!errorMessage && serverResponse.seatbid) { - serverResponse.seatbid.forEach(respItem => { - _addBidResponse(_getBidFromResponse(respItem), bidRequest, bidResponses, RendererConst, bidderCode); - }); - } - if (errorMessage) logError(errorMessage); - return bidResponses; + if (!errorMessage && serverResponse.seatbid) { + serverResponse.seatbid.forEach(respItem => { + _addBidResponse(_getBidFromResponse(respItem), bidRequest, bidResponses, RendererConst, bidderCode); + }); } + if (errorMessage) logError(errorMessage); + return bidResponses; }, getUserSyncs: function (...args) { const [syncOptions,, gdprConsent, uspConsent] = args; @@ -743,373 +713,4 @@ export function getSyncUrl() { return SYNC_URL; } -// ================ Criteo methods ================== - -const criteoSpec = { - /** f - * @param {object} bid - * @return {boolean} - */ - isBidRequestValid: (bid) => { - // either one of zoneId or networkId should be set - if (!(bid && bid.params && (bid.params.zoneId || bid.params.networkId))) { - return false; - } - - // video media types requires some mandatory params - if (hasVideoMediaType(bid)) { - if (!hasValidVideoMediaType(bid)) { - return false; - } - } - - return true; - }, - - /** - * @param {BidRequest[]} bidRequests - * @param {*} bidderRequest - * @return {ServerRequest} - */ - buildRequests: (bidRequests, bidderRequest) => { - let url; - let data; - let fpd = bidderRequest.ortb2 || {}; - - Object.assign(bidderRequest, { - publisherExt: fpd.site?.ext, - userExt: fpd.user?.ext, - ceh: config.getConfig('criteo.ceh'), - coppa: config.getConfig('coppa') - }); - - const context = buildContext(bidRequests, bidderRequest); - url = buildCdbUrl(context); - data = buildCdbRequest(context, bidRequests, bidderRequest); - - if (data) { - return { method: 'POST', url, data, bidRequests }; - } - }, - - /** - * @param {*} response - * @param {ServerRequest} request - * @return {Bid[]} - */ - interpretResponse: (response, request) => { - const body = response.body || response; - const bids = []; - - if (body && body.slots && isArray(body.slots)) { - body.slots.forEach(slot => { - const bidRequest = find(request.bidRequests, b => b.adUnitCode === slot.impid && (!b.params.zoneId || parseInt(b.params.zoneId) === slot.zoneid)); - const bidId = bidRequest.bidId; - const bid = { - requestId: bidId, - cpm: slot.cpm, - currency: slot.currency, - netRevenue: true, - ttl: slot.ttl || 60, - creativeId: slot.creativecode, - width: slot.width, - height: slot.height, - dealId: slot.dealCode, - }; - if (body.ext?.paf?.transmission && slot.ext?.paf?.content_id) { - const pafResponseMeta = { - content_id: slot.ext.paf.content_id, - transmission: response.ext.paf.transmission - }; - bid.meta = Object.assign({}, bid.meta, { paf: pafResponseMeta }); - } - if (slot.adomain) { - bid.meta = Object.assign({}, bid.meta, { advertiserDomains: slot.adomain }); - } - if (slot.video) { - bid.vastUrl = slot.displayurl; - bid.mediaType = VIDEO; - } else { - bid.ad = slot.creative; - } - bids.push(bid); - }); - } - - return bids; - } -}; - -function readFromAllStorages(name) { - const fromCookie = storage.getCookie(name); - const fromLocalStorage = storage.getDataFromLocalStorage(name); - - return fromCookie || fromLocalStorage || undefined; -} - -/** - * @param {BidRequest[]} bidRequests - * @param bidderRequest - */ -function buildContext(bidRequests, bidderRequest) { - let referrer = ''; - if (bidderRequest && bidderRequest.refererInfo) { - referrer = bidderRequest.refererInfo.page; - } - const queryString = parseUrl(bidderRequest?.refererInfo?.topmostLocation).search; - - const context = { - url: referrer, - debug: queryString['pbt_debug'] === '1', - noLog: queryString['pbt_nolog'] === '1', - amp: false, - }; - - bidRequests.forEach(bidRequest => { - if (bidRequest.params.integrationMode === 'amp') { - context.amp = true; - } - }); - - return context; -} - -/** - * @param {CriteoContext} context - * @return {string} - */ -function buildCdbUrl(context) { - let url = CDB_ENDPOINT; - url += '?profileId=' + PROFILE_ID_INLINE; - url += '&av=' + String(ADAPTER_VERSION_FOR_CRITEO_MODE); - url += '&wv=' + encodeURIComponent('$prebid.version$'); - url += '&cb=' + String(Math.floor(Math.random() * 99999999999)); - - if (storage.localStorageIsEnabled()) { - url += '&lsavail=1'; - } else { - url += '&lsavail=0'; - } - - if (context.amp) { - url += '&im=1'; - } - if (context.debug) { - url += '&debug=1'; - } - if (context.noLog) { - url += '&nolog=1'; - } - - const bundle = readFromAllStorages(BUNDLE_COOKIE_NAME); - if (bundle) { - url += `&bundle=${bundle}`; - } - - const optout = readFromAllStorages(OPTOUT_COOKIE_NAME); - if (optout) { - url += `&optout=1`; - } - - const sid = readFromAllStorages(SID_COOKIE_NAME); - if (sid) { - url += `&sid=${sid}`; - } - - const idcpy = readFromAllStorages(IDCPY_COOKIE_NAME); - if (idcpy) { - url += `&idcpy=${idcpy}`; - } - - return url; -} - -/** - * @param {CriteoContext} context - * @param {BidRequest[]} bidRequests - * @param bidderRequest - * @return {*} - */ -function buildCdbRequest(context, bidRequests, bidderRequest) { - let networkId; - let schain; - const request = { - publisher: { - url: context.url, - ext: bidderRequest.publisherExt, - }, - regs: { - coppa: bidderRequest.coppa === true ? 1 : (bidderRequest.coppa === false ? 0 : undefined) - }, - slots: bidRequests.map(bidRequest => { - networkId = bidRequest.params.networkId || networkId; - schain = bidRequest.schain || schain; - const slot = { - impid: bidRequest.adUnitCode, - transactionid: bidRequest.ortb2Imp?.ext?.tid, - // TODO: fix auctionId leak: https://github.com/prebid/Prebid.js/issues/9781 - auctionId: bidRequest.auctionId, - }; - if (bidRequest.params.zoneId) { - slot.zoneid = bidRequest.params.zoneId; - } - if (deepAccess(bidRequest, 'ortb2Imp.ext')) { - slot.ext = bidRequest.ortb2Imp.ext; - } - if (bidRequest.params.ext) { - slot.ext = Object.assign({}, slot.ext, bidRequest.params.ext); - } - if (bidRequest.params.publisherSubId) { - slot.publishersubid = bidRequest.params.publisherSubId; - } - - if (hasBannerMediaType(bidRequest)) { - slot.sizes = parseSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes'), parseSize); - } else { - slot.sizes = []; - } - - if (hasVideoMediaType(bidRequest)) { - const video = { - playersizes: parseSizes(deepAccess(bidRequest, 'mediaTypes.video.playerSize'), parseSize), - mimes: bidRequest.mediaTypes.video.mimes, - protocols: bidRequest.mediaTypes.video.protocols, - maxduration: bidRequest.mediaTypes.video.maxduration, - api: bidRequest.mediaTypes.video.api, - skip: bidRequest.mediaTypes.video.skip, - placement: bidRequest.mediaTypes.video.placement, - minduration: bidRequest.mediaTypes.video.minduration, - playbackmethod: bidRequest.mediaTypes.video.playbackmethod, - startdelay: bidRequest.mediaTypes.video.startdelay - }; - if ('plcmt' in bidRequest.mediaTypes.video) { - video.plcmt = bidRequest.mediaTypes.video.plcmt; - } - const paramsVideo = bidRequest.params.video; - if (paramsVideo !== undefined) { - video.skip = video.skip || paramsVideo.skip || 0; - video.placement = video.placement || paramsVideo.placement; - video.minduration = video.minduration || paramsVideo.minduration; - video.playbackmethod = video.playbackmethod || paramsVideo.playbackmethod; - video.startdelay = video.startdelay || paramsVideo.startdelay || 0; - } - - slot.video = video; - } - - enrichSlotWithFloors(slot, bidRequest); - - return slot; - }), - }; - if (networkId) { - request.publisher.networkid = networkId; - } - if (schain) { - request.source = { - ext: { - schain: schain - } - }; - } - request.user = { - ext: bidderRequest.userExt - }; - if (bidderRequest && bidderRequest.ceh) { - request.user.ceh = bidderRequest.ceh; - } - if (bidderRequest && bidderRequest.gdprConsent) { - request.gdprConsent = {}; - if (typeof bidderRequest.gdprConsent.gdprApplies !== 'undefined') { - request.gdprConsent.gdprApplies = !!(bidderRequest.gdprConsent.gdprApplies); - } - request.gdprConsent.version = bidderRequest.gdprConsent.apiVersion; - if (typeof bidderRequest.gdprConsent.consentString !== 'undefined') { - request.gdprConsent.consentData = bidderRequest.gdprConsent.consentString; - } - } - if (bidderRequest && bidderRequest.uspConsent) { - request.user.uspIab = bidderRequest.uspConsent; - } - return request; -} - -function parseSizes(sizes, parser = s => s) { - if (sizes === undefined) { - return []; - } - if (Array.isArray(sizes[0])) { // is there several sizes ? (ie. [[728,90],[200,300]]) - return sizes.map(size => parser(size)); - } - return [parser(sizes)]; // or a single one ? (ie. [728,90]) -} - -function parseSize(size) { - return size[0] + 'x' + size[1]; -} - -function hasVideoMediaType(bidRequest) { - return deepAccess(bidRequest, 'mediaTypes.video') !== undefined; -} - -function hasBannerMediaType(bidRequest) { - return deepAccess(bidRequest, 'mediaTypes.banner') !== undefined; -} - -function hasValidVideoMediaType(bidRequest) { - let isValid = true; - - var requiredMediaTypesParams = ['mimes', 'playerSize', 'maxduration', 'protocols', 'api', 'skip', 'placement', 'playbackmethod']; - - requiredMediaTypesParams.forEach(function (param) { - if (deepAccess(bidRequest, 'mediaTypes.video.' + param) === undefined && deepAccess(bidRequest, 'params.video.' + param) === undefined) { - isValid = false; - logError('TheMediaGrid Bid Adapter (withCriteo mode): mediaTypes.video.' + param + ' is required'); - } - }); - - if (isValid) { - const videoPlacement = bidRequest.mediaTypes.video.placement || bidRequest.params.video.placement; - // We do not support long form for now, also we have to check that context & placement are consistent - if (bidRequest.mediaTypes.video.context === 'instream' && videoPlacement === 1) { - return true; - } else if (bidRequest.mediaTypes.video.context === 'outstream' && videoPlacement !== 1) { - return true; - } - } - - return false; -} - -function enrichSlotWithFloors(slot, bidRequest) { - try { - const slotFloors = {}; - - if (bidRequest.getFloor) { - if (bidRequest.mediaTypes?.banner) { - slotFloors.banner = {}; - const bannerSizes = parseSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes')) - bannerSizes.forEach(bannerSize => slotFloors.banner[parseSize(bannerSize).toString()] = bidRequest.getFloor({ size: bannerSize, mediaType: BANNER })); - } - - if (bidRequest.mediaTypes?.video) { - slotFloors.video = {}; - const videoSizes = parseSizes(deepAccess(bidRequest, 'mediaTypes.video.playerSize')) - videoSizes.forEach(videoSize => slotFloors.video[parseSize(videoSize).toString()] = bidRequest.getFloor({ size: videoSize, mediaType: VIDEO })); - } - - if (Object.keys(slotFloors).length > 0) { - if (!slot.ext) { - slot.ext = {} - } - Object.assign(slot.ext, { - floors: slotFloors - }); - } - } - } catch (e) { - logError('Could not parse floors from Prebid: ' + e); - } -} - registerBidder(spec); diff --git a/test/spec/modules/gridBidAdapter_spec.js b/test/spec/modules/gridBidAdapter_spec.js index 039741a641c..4a1148bf377 100644 --- a/test/spec/modules/gridBidAdapter_spec.js +++ b/test/spec/modules/gridBidAdapter_spec.js @@ -424,171 +424,6 @@ describe('TheMediaGrid Adapter', function () { getDataFromLocalStorageStub.restore(); }); - it('should send additional request with adUnits with withCriteo parameter', function () { - const fpdUserIdVal = '0b0f84a1-1596-4165-9742-2e1a7dfac57f'; - const getDataFromLocalStorageStub = sinon.stub(storage, 'getDataFromLocalStorage').callsFake( - arg => arg === 'tmguid' ? fpdUserIdVal : null); - - const bidRequestsWithCriteo = bidRequests.map((bid, i) => - i % 2 ? bid : { - ...bid, - params: { - ...bid.params, - withCriteo: true, - networkId: 123 + i - }, - mediaTypes: { - ...bid.mediaTypes, - ...(bid.mediaTypes.video && { video: { - ...bid.mediaTypes.video, - context: 'instream', - protocols: [1, 2, 3], - maxduration: 30, - api: [1, 2], - skip: 1, - placement: 1, - plcmt: 2, - minduration: 0, - playbackmethod: 1, - startdelay: 0 - } - }) - } - }); - - const [request, criteoRequest] = spec.buildRequests(bidRequestsWithCriteo, bidderRequest); - expect(request.data).to.be.an('string'); - expect(criteoRequest.data).to.be.an('object'); - const payload = parseRequest(request.data); - const criteoPayload = criteoRequest.data; - expect(request.url).to.equal('https://grid.bidswitch.net/hbjson'); - expect(criteoRequest.url.replace(/\?.*$/, '')) - .to.equal('https://bidder.criteo.com/cdb'); - expect(payload).to.deep.equal({ - 'id': bidderRequest.bidderRequestId, - 'site': { - 'page': referrer - }, - 'tmax': bidderRequest.timeout, - 'source': { - 'tid': bidderRequest.auctionId, - 'ext': {'wrapper': 'Prebid_js', 'wrapper_version': '$prebid.version$'} - }, - 'user': { - 'id': fpdUserIdVal - }, - 'imp': [{ - 'id': bidRequests[0].bidId, - 'tagid': bidRequests[0].params.uid, - 'ext': {'divid': bidRequests[0].adUnitCode}, - 'bidfloor': bidRequests[0].params.bidFloor, - 'banner': { - 'w': 300, - 'h': 250, - 'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}] - } - }, { - 'id': bidRequests[1].bidId, - 'tagid': bidRequests[1].params.uid, - 'ext': {'divid': bidRequests[1].adUnitCode}, - 'banner': { - 'w': 300, - 'h': 250, - 'format': [{'w': 300, 'h': 250}, {'w': 300, 'h': 600}] - } - }, { - 'id': bidRequests[2].bidId, - 'tagid': bidRequests[2].params.uid, - 'ext': {'divid': bidRequests[2].adUnitCode}, - 'video': { - 'w': 400, - 'h': 600, - 'protocols': [1, 2, 3], - 'mimes': ['video/mp4', 'video/webm', 'application/javascript', 'video/ogg'], - 'context': 'instream', - 'maxduration': 30, - 'minduration': 0, - 'api': [1, 2], - 'skip': 1, - 'placement': 1, - 'plcmt': 2, - 'playbackmethod': 1, - 'startdelay': 0 - } - }, { - 'id': bidRequests[3].bidId, - 'tagid': bidRequests[3].params.uid, - 'ext': {'divid': bidRequests[3].adUnitCode}, - 'banner': { - 'w': 728, - 'h': 90, - 'format': [{'w': 728, 'h': 90}] - }, - 'video': { - 'w': 400, - 'h': 600, - 'protocols': [1, 2, 3] - } - }] - }); - - expect(criteoPayload).to.deep.equal({ - 'publisher': { - 'ext': undefined, - 'url': bidderRequest.refererInfo.page, - 'networkid': 125 - }, - 'regs': { - 'coppa': undefined - }, - 'slots': [{ - 'impid': bidRequests[0].adUnitCode, - 'transactionid': bidderRequest.transactionId, - ext: bidRequests[0].ortb2Imp.ext, - 'auctionId': bidderRequest.auctionId, - 'sizes': ['300x250', '300x600'] - }, { - 'impid': bidRequests[2].adUnitCode, - ext: bidRequests[2].ortb2Imp.ext, - 'transactionid': bidderRequest.transactionId, - 'auctionId': bidderRequest.auctionId, - 'sizes': [], - 'video': { - 'api': [ - 1, - 2 - ], - 'maxduration': 30, - 'mimes': [ - 'video/mp4', - 'video/webm', - 'application/javascript', - 'video/ogg', - ], - 'minduration': 0, - 'placement': 1, - 'plcmt': 2, - 'playbackmethod': 1, - 'playersizes': [ - '400x600' - ], - 'protocols': [ - 1, - 2, - 3 - ], - 'skip': 1, - 'startdelay': 0 - } - }], - 'user': { - 'ext': undefined - } - }); - - getDataFromLocalStorageStub.restore(); - }); - it('if gdprConsent is present payload must have gdpr params', function () { const gdprBidderRequest = Object.assign({gdprConsent: {consentString: 'AAA', gdprApplies: true}}, bidderRequest); const [request] = spec.buildRequests(bidRequests, gdprBidderRequest); @@ -1565,137 +1400,6 @@ describe('TheMediaGrid Adapter', function () { expect(result).to.deep.equal(expectedResponse); }); - it('should add response with biggest price', function () { - const mainResponse = [ - {'bid': [{'impid': '2164be6358b9', 'price': 1.15, 'adm': '
test content 1
', 'auid': 1, 'h': 250, 'w': 300, dealid: 11}], 'seat': '1'}, - {'bid': [{'impid': '4e111f1b66e4', 'price': 0.5, 'adm': '
test content 2
', 'auid': 2, 'h': 600, 'w': 300, dealid: 12}], 'seat': '1'}, - ]; - const criteoResponse = [ - { - impid: 'adunit-code-1', - cpm: 0.15, - creative: '
test content 3
', - creativecode: 1, - bidId: '2164be6358b9', - currency: 'USD', - width: 300, - height: 250, - dealCode: 11, - zoneid: 123, - ttl: 360, - adomain: ['criteo.com'], - }, - { - impid: 'adunit-code-1', - cpm: 1, - creative: '
test content 4
', - creativecode: 2, - bidId: '4e111f1b66e4', - currency: 'USD', - width: 300, - height: 600, - dealCode: 12, - zoneid: 456, - ttl: 360, - adomain: ['criteo.com'], - } - ]; - const bidRequests = [ - { - 'bidder': 'grid', - 'params': { - 'uid': '1', - 'zoneId': 123, - 'withCriteo': true - }, - 'adUnitCode': 'adunit-code-1', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '2164be6358b9', - 'bidderRequestId': '106efe3247', - 'auctionId': '32a1f276cb87cb8', - 'transactionId': '43534f55b213ac', - }, - { - 'bidder': 'grid', - 'params': { - 'uid': '2', - 'zoneId': 456, - 'withCriteo': true - }, - 'adUnitCode': 'adunit-code-1', - 'sizes': [[300, 250], [300, 600]], - 'bidId': '4e111f1b66e4', - 'bidderRequestId': '106efe3247', - 'auctionId': '32a1f276cb87cb8', - 'transactionId': '43534f55b213ac', - } - ]; - const bidderRequest = { - refererInfo: { page: 'https://example.com' }, - bidderRequestId: '106efe3247', - transactionId: '43534f55b213ac', - auctionId: '32a1f276cb87cb8', - timeout: 3000 - }; - const [mainRequest, criteoRequest] = spec.buildRequests(bidRequests, bidderRequest); - const expectedMainResponse = [ - { - 'requestId': '2164be6358b9', - 'cpm': 1.15, - 'creativeId': 1, - 'dealId': 11, - 'width': 300, - 'height': 250, - 'ad': '
test content 1
', - 'currency': 'USD', - 'mediaType': 'banner', - 'netRevenue': true, - 'ttl': 360, - 'meta': { - advertiserDomains: [] - }, - }, - { - 'requestId': '4e111f1b66e4', - 'cpm': 0.5, - 'creativeId': 2, - 'dealId': 12, - 'width': 300, - 'height': 600, - 'ad': '
test content 2
', - 'currency': 'USD', - 'mediaType': 'banner', - 'netRevenue': true, - 'ttl': 360, - 'meta': { - advertiserDomains: [] - }, - } - ]; - const expectedCriteoResponse = [ - { - 'requestId': '4e111f1b66e4', - 'cpm': 1, - 'creativeId': 2, - 'dealId': 12, - 'width': 300, - 'height': 600, - 'ad': '
test content 4
', - 'currency': 'USD', - 'netRevenue': true, - 'ttl': 360, - 'meta': { - advertiserDomains: ['criteo.com'] - }, - } - ]; - - const mainResult = spec.interpretResponse({'body': {'seatbid': mainResponse}}, mainRequest); - const criteoResult = spec.interpretResponse({'body': {'slots': criteoResponse}}, criteoRequest); - expect(mainResult).to.deep.equal(expectedMainResponse); - expect(criteoResult).to.deep.equal(expectedCriteoResponse); - }); - it('response with ext.bidder.grid.demandSource', function () { const bidRequests = [ {