// Postprocess the bids so that all the universal properties exist, no matter which bidder they came from. // This should be called before addBidToAuction(). function getPreparedBidForAuction({adUnitCode, bid, bidderRequest, auctionId}) { const start = bidderRequest.start; let bidObject = Object.assign({}, bid, { auctionId, responseTimestamp: timestamp(), requestTimestamp: start, cpm: parseFloat(bid.cpm) || 0, bidder: bid.bidderCode, adUnitCode }); bidObject.timeToRespond = bidObject.responseTimestamp - bidObject.requestTimestamp; // Let listeners know that now is the time to adjust the bid, if they want to. // // CAREFUL: Publishers rely on certain bid properties to be available (like cpm), // but others to not be set yet (like priceStrings). See #1372 and #1389. events.emit(CONSTANTS.EVENTS.BID_ADJUSTMENT, bidObject); // a publisher-defined renderer can be used to render bids const bidReq = bidderRequest.bids && find(bidderRequest.bids, bid => bid.adUnitCode == adUnitCode); const adUnitRenderer = bidReq && bidReq.renderer; if (adUnitRenderer && adUnitRenderer.url) { bidObject.renderer = Renderer.install({ url: adUnitRenderer.url }); bidObject.renderer.setRender(adUnitRenderer.render); } // Use the config value 'mediaTypeGranularity' if it has been defined for mediaType, else use 'customPriceBucket' const mediaTypeGranularity = config.getConfig(`mediaTypePriceGranularity.${bid.mediaType}`); const priceStringsObj = getPriceBucketString( bidObject.cpm, (typeof mediaTypeGranularity === 'object') ? mediaTypeGranularity : config.getConfig('customPriceBucket'), config.getConfig('currency.granularityMultiplier') ); bidObject.pbLg = priceStringsObj.low; bidObject.pbMg = priceStringsObj.med; bidObject.pbHg = priceStringsObj.high; bidObject.pbAg = priceStringsObj.auto; bidObject.pbDg = priceStringsObj.dense; bidObject.pbCg = priceStringsObj.custom; // if there is any key value pairs to map do here var keyValues; if (bidObject.bidderCode && (bidObject.cpm > 0 || bidObject.dealId)) { keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject); } // use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs bidObject.adserverTargeting = Object.assign(bidObject.adserverTargeting || {}, keyValues); return bidObject; }
// Video bids may fail if the cache is down, or there's trouble on the network. function tryAddVideoBid(auctionInstance, bidResponse, bidRequests, afterBidAdded) { let addBid = true; const bidRequest = getBidRequest(bidResponse.adId, [bidRequests]); const videoMediaType = bidRequest && deepAccess(bidRequest, 'mediaTypes.video'); const context = videoMediaType && deepAccess(videoMediaType, 'context'); if (config.getConfig('cache.url') && context !== OUTSTREAM) { if (!bidResponse.videoCacheKey) { addBid = false; store([bidResponse], function (error, cacheIds) { if (error) { utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`); doCallbacksIfTimedout(auctionInstance, bidResponse); } else { bidResponse.videoCacheKey = cacheIds[0].uuid; if (!bidResponse.vastUrl) { bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); } addBidToAuction(auctionInstance, bidResponse); afterBidAdded(); } }); } else if (!bidResponse.vastUrl) { utils.logError('videoCacheKey specified but not required vastUrl for video bid'); addBid = false; } } if (addBid) { addBidToAuction(auctionInstance, bidResponse); afterBidAdded(); } }
function runIfOriginHasCapacity(call) { let hasCapacity = true; let maxRequests = config.getConfig('maxRequestsPerOrigin') || MAX_REQUESTS_PER_ORIGIN; call.bidRequests.some(bidRequest => { let requests = 1; let source = (typeof bidRequest.src !== 'undefined' && bidRequest.src === CONSTANTS.S2S.SRC) ? 's2s' : bidRequest.bidderCode; // if we have no previous info on this source just let them through if (sourceInfo[source]) { if (sourceInfo[source].SRA === false) { // some bidders might use more than the MAX_REQUESTS_PER_ORIGIN in a single auction. In those cases // set their request count to MAX_REQUESTS_PER_ORIGIN so the auction isn't permanently queued waiting // for capacity for that bidder requests = Math.min(bidRequest.bids.length, maxRequests); } if (outstandingRequests[sourceInfo[source].origin] + requests > maxRequests) { hasCapacity = false; } } // return only used for terminating this .some() iteration early if it is determined we don't have capacity return !hasCapacity; }); if (hasCapacity) { call.run(); } return hasCapacity; }
it('Verify build request', () => { config.setConfig({ 'currency': { 'adServerCurrency': 'EUR' } }); const request = spec.buildRequests(DEFAULT_PARAMS); expect(request).to.have.property('url').and.to.equal('http://prg.smartadserver.com/prebid/v1'); expect(request).to.have.property('method').and.to.equal('POST'); const requestContent = JSON.parse(request.data); expect(requestContent).to.have.property('siteid').and.to.equal('1234'); expect(requestContent).to.have.property('pageid').and.to.equal('5678'); expect(requestContent).to.have.property('formatid').and.to.equal('90'); expect(requestContent).to.have.property('currencyCode').and.to.equal('EUR'); expect(requestContent).to.have.property('bidfloor').and.to.equal(0.42); expect(requestContent).to.have.property('targeting').and.to.equal('test=prebid'); expect(requestContent).to.have.property('tagId').and.to.equal('sas_42'); expect(requestContent).to.have.property('sizes'); expect(requestContent.sizes[0]).to.have.property('w').and.to.equal(300); expect(requestContent.sizes[0]).to.have.property('h').and.to.equal(250); expect(requestContent.sizes[1]).to.have.property('w').and.to.equal(300); expect(requestContent.sizes[1]).to.have.property('h').and.to.equal(200); expect(requestContent).to.have.property('pageDomain').and.to.equal(utils.getTopWindowUrl()); expect(requestContent).to.have.property('transactionId').and.to.not.equal(null).and.to.not.be.undefined; });
it('returns false when a required property from an adpod bid is missing', function() { function testInvalidAdpodBid(badTestBid, shouldErrorBeLogged) { checkVideoBidSetupHook(callbackFn, badTestBid, bidderRequestNoExact, {}, ADPOD); expect(callbackResult).to.be.null; expect(bailResult).to.equal(false); expect(logErrorStub.called).to.equal(shouldErrorBeLogged); } let noCatBid = utils.deepClone(adpodTestBid); noCatBid.meta.iabSubCatId = undefined; testInvalidAdpodBid(noCatBid, false); let noContextBid = utils.deepClone(adpodTestBid); delete noContextBid.video.context; testInvalidAdpodBid(noContextBid, false); let wrongContextBid = utils.deepClone(adpodTestBid); wrongContextBid.video.context = 'instream'; testInvalidAdpodBid(wrongContextBid, false); let noDurationBid = utils.deepClone(adpodTestBid); delete noDurationBid.video.durationSeconds; testInvalidAdpodBid(noDurationBid, false); config.resetConfig(); let noCacheUrlBid = utils.deepClone(adpodTestBid); testInvalidAdpodBid(noCacheUrlBid, true); });
interpretResponse: function(serverResponse, bidRequest) { const bidResponses = []; const response = serverResponse.body; const crid = response.crid || 0; const width = response.width || 0; const height = response.height || 0; const cpm = response.cpm * 1000 || 0; if (width !== 0 && height !== 0 && cpm !== 0 && crid !== 0) { const dealId = response.dealid || ''; const currency = response.currency || 'JPY'; const netRevenue = (response.netRevenue === undefined) ? true : response.netRevenue; const referrer = utils.getTopWindowUrl(); const bidResponse = { requestId: bidRequest.data.uid, cpm: cpm, width: response.width, height: response.height, creativeId: crid, dealId: dealId, currency: currency, netRevenue: netRevenue, ttl: config.getConfig('_bidderTimeout'), referrer: referrer, ad: response.adTag }; bidResponses.push(bidResponse); } return bidResponses; }
function registerSyncs(responses) { if (spec.getUserSyncs) { let syncs = spec.getUserSyncs({ iframeEnabled: config.getConfig('userSync.iframeEnabled'), pixelEnabled: config.getConfig('userSync.pixelEnabled'), }, responses); if (syncs) { if (!Array.isArray(syncs)) { syncs = [syncs]; } syncs.forEach((sync) => { userSync.registerSync(sync.type, spec.code, sync.url) }); } } }
function _appendSiteAppDevice(request) { if (!request) return; // ORTB specifies app OR site if (typeof config.getConfig('app') === 'object') { request.app = config.getConfig('app'); request.app.publisher = {id: _s2sConfig.accountId} } else { request.site = { publisher: { id: _s2sConfig.accountId }, page: utils.getTopWindowUrl() } } if (typeof config.getConfig('device') === 'object') { request.device = config.getConfig('device'); } }
function makeSite(req) { let domain = getDomain(config.getConfig('publisherDomain')); return { 'id': req.params.source || domain, 'domain': domain, 'page': utils.getTopWindowUrl(), 'ref': utils.getTopWindowReferrer() }; }
function buildCommonQueryParamsFromBids(bids, bidderRequest) { const isInIframe = utils.inIframe(); let defaultParams; defaultParams = { ju: config.getConfig('pageUrl') || utils.getTopWindowUrl(), jr: utils.getTopWindowReferrer(), ch: document.charSet || document.characterSet, res: `${screen.width}x${screen.height}x${screen.colorDepth}`, ifr: isInIframe, tz: new Date().getTimezoneOffset(), tws: getViewportDimensions(isInIframe), be: 1, bc: bids[0].params.bc || `${BIDDER_CONFIG}_${BIDDER_VERSION}`, dddid: utils._map(bids, bid => bid.transactionId).join(','), nocache: new Date().getTime() }; if (bids[0].params.platform) { defaultParams.ph = bids[0].params.platform; } if (utils.deepAccess(bidderRequest, 'gdprConsent')) { let gdprConsentConfig = bidderRequest.gdprConsent; if (gdprConsentConfig.consentString !== undefined) { defaultParams.gdpr_consent = gdprConsentConfig.consentString; } if (gdprConsentConfig.gdprApplies !== undefined) { defaultParams.gdpr = gdprConsentConfig.gdprApplies ? 1 : 0; } if (config.getConfig('consentManagement.cmpApi') === 'iab') { defaultParams.x_gdpr_f = 1; } } if (bids[0].crumbs && bids[0].crumbs.pubcid) { defaultParams.pubcid = bids[0].crumbs.pubcid; } return defaultParams; }
afterEach(function() { storeStub.restore(); logWarnStub.restore(); logInfoStub.restore(); addBidToAuctionStub.restore(); doCallbacksIfTimedoutStub.restore(); clock.restore(); config.resetConfig(); auctionBids = []; })
it('should use publisher defined defined mapping file', function () { config.setConfig({ 'brandCategoryTranslation': { 'translationFile': 'http://sample.com' } }); getLocalStorageStub.returns(null); initTranslation('http://sample.com', 'somekey'); expect(fakeTranslationServer.requests.length).to.equal(2); expect(fakeTranslationServer.requests[0].url).to.equal('http://sample.com'); });
beforeEach(() => { $$PREBID_GLOBAL$$.consumableGlobals.pixelsDropped = false; config.setConfig({ consumable: { userSyncOn: 'bidResponse' }, }); bidResponse = getDefaultBidResponse(); bidResponse.ext = { pixels: getPixels() }; });
it('should send prebid cache call after set period of time (even if queue is not full)', function () { storeStub.callsFake(fakeStoreFn); config.setConfig({ adpod: { bidQueueSizeLimit: 2, bidQueueTimeDelay: 30, deferCaching: false, brandCategoryExclusion: true } }); let bidResponse = { adId: 'adId234', auctionId: 'timer_abc234', mediaType: 'video', cpm: 15, meta: { adServerCatId: 'airline' }, video: { context: ADPOD, durationSeconds: 30, durationBucket: 30 } }; let bidderRequest = { adUnitCode: 'adpod_2', auctionId: 'timer_abc234', mediaTypes: { video: { context: ADPOD, playerSize: [300, 300], adPodDurationSec: 120, durationRangeSec: [15, 30], requireExactDuration: true } } }; callPrebidCacheHook(callbackFn, auctionInstance, bidResponse, afterBidAddedSpy, bidderRequest); clock.tick(31); expect(callbackResult).to.be.null; expect(afterBidAddedSpy.calledOnce).to.equal(true); expect(auctionBids.length).to.equal(1); expect(auctionBids[0].adId).to.equal('adId234'); expect(auctionBids[0].customCacheKey).to.exist.and.to.match(/^15\.00_airline_30s_.*/); expect(auctionBids[0].adserverTargeting.hb_pb_cat_dur).to.equal('15.00_airline_30s'); expect(auctionBids[0].adserverTargeting.hb_cache_id).to.exist; expect(auctionBids[0].videoCacheKey).to.exist.and.to.equal(auctionBids[0].adserverTargeting.hb_cache_id) });
beforeEach(function() { callbackResult = null; bailResult = null; config.setConfig({ cache: { url: 'http://test.cache.url/endpoint' }, adpod: { brandCategoryExclusion: true } }); logWarnStub = sinon.stub(utils, 'logWarn'); logErrorStub = sinon.stub(utils, 'logError'); });
function getNormalizedBidRequest(bid) { let adUnitId = utils.getBidIdParameter('adUnitCode', bid) || null; let placementId = utils.getBidIdParameter('placementId', bid.params) || null; let publisherId = null; let placementKey = null; if (placementId === null) { publisherId = utils.getBidIdParameter('publisherId', bid.params) || null; placementKey = utils.getBidIdParameter('placementKey', bid.params) || null; } let keyValues = utils.getBidIdParameter('keyValues', bid.params) || null; let localSize = utils.getBidIdParameter('size', bid.params) || null; let bidId = utils.getBidIdParameter('bidId', bid); let transactionId = utils.getBidIdParameter('transactionId', bid); const currency = config.getConfig('currency.adServerCurrency'); let normalizedBidRequest = {}; if (placementId) { normalizedBidRequest.placementId = placementId; } else { if (publisherId) { normalizedBidRequest.publisherId = publisherId; } if (placementKey) { normalizedBidRequest.placementKey = placementKey; } } if (keyValues) { normalizedBidRequest.keyValues = keyValues; } if (localSize && localSize.w && localSize.h) { normalizedBidRequest.size = {}; normalizedBidRequest.size.h = localSize.h; normalizedBidRequest.size.w = localSize.w; } if (bidId) { normalizedBidRequest.id = bidId; } if (adUnitId) { normalizedBidRequest.adUnitId = adUnitId; } if (transactionId) { normalizedBidRequest.transactionId = transactionId; } if (currency) { normalizedBidRequest.currency = currency; } return normalizedBidRequest; }
it('should not add bid to auction when config adpod.brandCategoryExclusion is true but bid is missing adServerCatId', function() { storeStub.callsFake(fakeStoreFn); config.setConfig({ adpod: { bidQueueSizeLimit: 2, bidQueueTimeDelay: 30, deferCaching: false, brandCategoryExclusion: true } }); let bidResponse1 = { adId: 'missingCat_ad1', auctionId: 'missing_category_abc345', mediaType: 'video', cpm: 10, meta: { adServerCatId: undefined }, video: { context: ADPOD, durationSeconds: 15, durationBucket: 15 } }; let bidderRequest = { adUnitCode: 'adpod_5', auctionId: 'missing_category_abc345', mediaTypes: { video: { context: ADPOD, playerSize: [300, 300], adPodDurationSec: 45, durationRangeSec: [15, 30], requireExactDuration: false } } }; callPrebidCacheHook(callbackFn, auctionInstance, bidResponse1, afterBidAddedSpy, bidderRequest); expect(callbackResult).to.be.null; expect(afterBidAddedSpy.calledOnce).to.equal(true); expect(storeStub.called).to.equal(false); expect(logWarnStub.calledOnce).to.equal(true); expect(auctionBids.length).to.equal(0); });
const interpretResponse = ({ body }, { adformats, requestIds, sizes }) => { const ttl = Number(config.getConfig().bidderTimeout); const { bids = {} } = body; return Object.keys(bids) // extract Array of bid responses .map(placementId => bids[placementId]) // flatten .reduce((a, b) => a.concat(b), []) // transform to bidResponse .map((bid, i) => { const { bid_id: fb_bidid, placement_id: creativeId, bid_price_cents: cpm } = bid; const format = adformats[i]; const [width, height] = expandSize(flattenSize(sizes[i])); const ad = createAdHtml(creativeId, format, fb_bidid); const requestId = requestIds[i]; const bidResponse = { // Prebid attributes requestId, cpm: cpm / 100, width, height, ad, ttl, creativeId, netRevenue, currency, // Audience Network attributes hb_bidder, fb_bidid, fb_format: format, fb_placementid: creativeId }; // Video attributes if (isVideo(format)) { const pageurl = getTopWindowUrlEncoded(); bidResponse.mediaType = 'video'; bidResponse.vastUrl = `https://an.facebook.com/v1/instream/vast.xml?placementid=${creativeId}&pageurl=${pageurl}&playerwidth=${width}&playerheight=${height}&bidid=${fb_bidid}`; } return bidResponse; }); };
return function() { const usePrebidCache = config.getConfig('usePrebidCache'); const bidToUse = usePayloadResponse ? payloadBidResponse : urlBidResponse; const mockResponse = Object.assign({}, bidToUse); const callback = sinon.spy(); bidManager.addOneTimeCallback(callback); mockResponse.getSize = function() { return `${this.height}x${this.width}`; }; bidManager.addBidResponse(adUnit.code, mockResponse); const expectedBidsReceived = expectBidAdded ? 1 : 0; expect($$PREBID_GLOBAL$$._bidsReceived.length).to.equal(expectedBidsReceived); const storeStub = videoCacheStubProvider().store; if (usePrebidCache) { expect(storeStub.calledOnce).to.equal(true); expect(storeStub.getCall(0).args[0][0]).to.equal(mockResponse); } else { expect(storeStub.called).to.equal(false); } if (expectedBidsReceived === 1) { const bid = $$PREBID_GLOBAL$$._bidsReceived[0]; // Ensures that the BidAdjustment listeners execute before the bid goes into the auction. expect(bid.cpm).to.equal(adjustCpm(0.1)); if (usePayloadResponse) { expect(bid.vastXml).to.equal('<VAST version="3.0"></VAST>'); if (usePrebidCache) { expect(bid.vastUrl).to.equal(`https://prebid.adnxs.com/pbc/v1/cache?uuid=FAKE_UUID`); } } else { expect(bid.vastUrl).to.equal('www.myVastUrl.com'); } if (usePrebidCache) { expect(bid.videoCacheKey).to.equal('FAKE_UUID'); } } if (expectCallbackCalled) { expect(callback.calledOnce).to.equal(true); } else { expect(callback.called).to.equal(false); } };
it('adds device and app objects to request', () => { const _config = { s2sConfig: CONFIG, device: { ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC' }, app: { bundle: 'com.test.app' }, }; config.setConfig(_config); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); const requestBid = JSON.parse(requests[0].requestBody); expect(requestBid.device).to.deep.equal({ ifa: '6D92078A-8246-4BA4-AE5B-76104861E7DC', }); expect(requestBid.app).to.deep.equal({ bundle: 'com.test.app', publisher: {'id': '1'} }); });
it('registers video bids', () => { server.respondWith(JSON.stringify(VIDEO_RESPONSE)); config.setConfig({s2sConfig: CONFIG}); adapter.callBids(VIDEO_REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(addBidResponse); const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('cpm', 0.5); expect(response).to.have.property('adId', '123'); expect(response).to.have.property('videoCacheKey', 'video_cache_id'); expect(response).to.have.property('cache_id', 'video_cache_id'); expect(response).to.have.property('cache_url', 'video_cache_url'); expect(response).to.have.property('vastUrl', 'video_cache_url'); });
it('registers successful bids and calls done when there are less bids than requests', () => { server.respondWith(JSON.stringify(RESPONSE)); config.setConfig({s2sConfig: CONFIG}); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(addBidResponse); sinon.assert.calledOnce(done); expect(addBidResponse.firstCall.args[0]).to.equal('div-gpt-ad-1460505748561-0'); expect(addBidResponse.firstCall.args[1]).to.have.property('adId', '123'); expect(addBidResponse.firstCall.args[1]) .to.have.property('statusMessage', 'Bid available'); });
serverResponse.body.mids.forEach(mid => { if (mid.useCount > 0) { return; } if (!mid.useCount) { mid.useCount = 0; } var sizeNotFound = true; utils.parseSizesInput(bidParam.sizes).forEach(size => { if (size === mid.width + 'x' + mid.height) { sizeNotFound = false; } }); if (sizeNotFound) { return; } const bidResponse = { requestId: bidParam.bidId, bidderCode: spec.code, cpm: parseFloat(mid.cpm), width: mid.width, height: mid.height, ad: mid.ad_code_html, creativeId: mid.mid, currency: 'USD', netRevenue: false, ttl: config.getConfig('_bidderTimeout'), }; if (bidResponse.cpm <= 0) { return; } if (bidResponse.ad.length <= 0) { return; } mid.useCount++; bidResponse.ad += makeNotification(bidResponse, mid, bidParam); bidResponses.push(bidResponse); });
it('registers no-bid response when ad unit not set', function () { server.respondWith(JSON.stringify(RESPONSE_NO_BID_NO_UNIT)); config.setConfig(CONFIG_ARG); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(addBidResponse); const ad_unit_code = addBidResponse.firstCall.args[0]; expect(ad_unit_code).to.equal('div-gpt-ad-1460505748561-0'); const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('statusMessage', 'Bid returned empty or error response'); const bid_request_passed = addBidResponse.firstCall.args[1]; expect(bid_request_passed).to.have.property('adId', '123'); });
it('returns true when adpod bid is properly setup', function() { config.setConfig({ cache: { url: 'http://test.cache.url/endpoint' }, adpod: { brandCategoryExclusion: false } }); let goodBid = utils.deepClone(adpodTestBid); goodBid.meta.iabSubCatId = undefined; checkVideoBidSetupHook(callbackFn, goodBid, bidderRequestNoExact, {}, ADPOD); expect(callbackResult).to.be.null; expect(bailResult).to.equal(true); expect(logErrorStub.called).to.equal(false); });
beforeEach(function() { callbackResult = null; afterBidAddedSpy = sinon.spy(); storeStub = sinon.stub(videoCache, 'store'); logWarnStub = sinon.stub(utils, 'logWarn'); logInfoStub = sinon.stub(utils, 'logInfo'); addBidToAuctionStub = sinon.stub(auction, 'addBidToAuction').callsFake(function (auctionInstance, bid) { auctionBids.push(bid); }); doCallbacksIfTimedoutStub = sinon.stub(auction, 'doCallbacksIfTimedout'); clock = sinon.useFakeTimers(); config.setConfig({ cache: { url: 'https://prebid.adnxs.com/pbc/v1/cache' } }); });
return ads.reduce((bids, ad) => { if (ad.status !== 'ok') { return []; } let bid = { requestId: bidRequest.bidId, currency: 'USD', creativeId: ad.creative_id, cpm: ad.cpm || 0, dealId: ad.deal, ttl: 300, // 5 minutes netRevenue: config.getConfig('rubicon.netRevenue') || false, rubicon: { advertiserId: ad.advertiser, networkId: ad.network } }; if (ad.creative_type) { bid.mediaType = ad.creative_type; } if (ad.creative_type === VIDEO) { bid.width = bidRequest.params.video.playerWidth; bid.height = bidRequest.params.video.playerHeight; bid.vastUrl = ad.creative_depot_url; bid.impression_id = ad.impression_id; bid.videoCacheKey = ad.impression_id; } else { bid.ad = _renderCreative(ad.script, ad.impression_id); [bid.width, bid.height] = sizeMap[ad.size_id].split('x').map(num => Number(num)); } // add server-side targeting bid.rubiconTargeting = (Array.isArray(ad.targeting) ? ad.targeting : []) .reduce((memo, item) => { memo[item.key] = item.values[0]; return memo; }, {'rpfl_elemid': bidRequest.adUnitCode}); bids.push(bid); return bids; }, []);
it('should add first party data to page url in bid request if it exists in config', function () { config.setConfig({ ix: { firstPartyData: { ab: 123, cd: '123#ab', 'e/f': 456, 'h?g': '456#cd' } } }); const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID, DEFAULT_BANNER_OPTION); const pageUrl = JSON.parse(requestWithFirstPartyData.data.r).site.page; const expectedPageUrl = DEFAULT_BANNER_OPTION.refererInfo.referer + '?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd'; expect(pageUrl).to.equal(expectedPageUrl); });
it('registers bid responses when server requests cookie sync', () => { server.respondWith(JSON.stringify(RESPONSE_NO_PBS_COOKIE)); config.setConfig({s2sConfig: CONFIG}); adapter.callBids(REQUEST, BID_REQUESTS, addBidResponse, done, ajax); server.respond(); sinon.assert.calledOnce(addBidResponse); const ad_unit_code = addBidResponse.firstCall.args[0]; expect(ad_unit_code).to.equal('div-gpt-ad-1460505748561-0'); const response = addBidResponse.firstCall.args[1]; expect(response).to.have.property('statusMessage', 'Bid available'); expect(response).to.have.property('source', 's2s'); const bid_request_passed = addBidResponse.firstCall.args[1]; expect(bid_request_passed).to.have.property('adId', '123'); });
it('should add first party data to page url in bid request if it exists in config', () => { config.setConfig({ ix: { firstPartyData: { ab: 123, cd: '123#ab', 'e/f': 456, 'h?g': '456#cd' } } }); const requestWithFirstPartyData = spec.buildRequests(DEFAULT_BANNER_VALID_BID); const pageUrl = JSON.parse(requestWithFirstPartyData.data.r).site.page; const expectedPageUrl = `${utils.getTopWindowUrl()}?ab=123&cd=123%23ab&e%2Ff=456&h%3Fg=456%23cd`; expect(pageUrl).to.equal(expectedPageUrl); });