From cb4018a37bc47cf5a0517df752f35146217df899 Mon Sep 17 00:00:00 2001 From: Jaimin Panchal Date: Mon, 4 Dec 2017 14:12:43 -0500 Subject: [PATCH] video bug fix (#1906) * video bug fix added required params to prebidServerAdapter * Emitted auction_end and updated ttl for prebidServer * fix logging of server adapters --- modules/prebidServerBidAdapter.js | 15 ++++- src/adaptermanager.js | 2 +- src/adapters/bidderFactory.js | 102 +++++++++++++++--------------- src/auction.js | 41 ++++++++---- 4 files changed, 94 insertions(+), 66 deletions(-) diff --git a/modules/prebidServerBidAdapter.js b/modules/prebidServerBidAdapter.js index 4a42a0c3398..d83037d4bc1 100644 --- a/modules/prebidServerBidAdapter.js +++ b/modules/prebidServerBidAdapter.js @@ -7,11 +7,15 @@ import { cookieSet } from 'src/cookie.js'; import adaptermanager from 'src/adaptermanager'; import { config } from 'src/config'; import { VIDEO } from 'src/mediaTypes'; +import { isValid } from 'src/adapters/bidderFactory'; const getConfig = config.getConfig; const TYPE = S2S.SRC; let _synced = false; +const DEFAULT_S2S_TTL = 60; +const DEFAULT_S2S_CURRENCY = 'USD'; +const DEFAULT_S2S_NETREVENUE = true; let _s2sConfig; config.setDefaults({ @@ -293,8 +297,17 @@ export function PrebidServer() { if (bidObj.deal_id) { bidObject.dealId = bidObj.deal_id; } + bidObject.requestId = bidObj.bid_id; + bidObject.creativeId = bidObj.creative_id; - addBidResponse(bidObj.code, bidObject); + // TODO: Remove when prebid-server returns ttl, currency and netRevenue + bidObject.ttl = (bidObj.ttl) ? bidObj.ttl : DEFAULT_S2S_TTL; + bidObject.currency = (bidObj.currency) ? bidObj.currency : DEFAULT_S2S_CURRENCY; + bidObject.netRevenue = (bidObj.netRevenue) ? bidObj.netRevenue : DEFAULT_S2S_NETREVENUE; + + if (isValid(bidObj.code, bidObject, bidRequests)) { + addBidResponse(bidObj.code, bidObject); + } }); } } diff --git a/src/adaptermanager.js b/src/adaptermanager.js index a009e91cd24..cb64651ef18 100644 --- a/src/adaptermanager.js +++ b/src/adaptermanager.js @@ -237,7 +237,7 @@ exports.callBids = (adUnits, bidRequests, addBidResponse, doneCb) => { // only log adapters that actually have adUnit bids let allBidders = s2sBidRequest.ad_units.reduce((adapters, adUnit) => { - return adapters.concat((adUnit.bids || []).reduce((adapters, bid) => { return adapters.concat(bid.bidderCode) }, [])); + return adapters.concat((adUnit.bids || []).reduce((adapters, bid) => { return adapters.concat(bid.bidder) }, [])); }, []); utils.logMessage(`CALLING S2S HEADER BIDDERS ==== ${adaptersServerSide.filter(adapter => { return allBidders.includes(adapter); diff --git a/src/adapters/bidderFactory.js b/src/adapters/bidderFactory.js index 6b80267c47f..885b9e96d43 100644 --- a/src/adapters/bidderFactory.js +++ b/src/adapters/bidderFactory.js @@ -333,69 +333,69 @@ export function newBidder(spec) { } return true; } +} - // Validate the arguments sent to us by the adapter. If this returns false, the bid should be totally ignored. - function isValid(adUnitCode, bid, bidRequests) { - function hasValidKeys() { - let bidKeys = Object.keys(bid); - return COMMON_BID_RESPONSE_KEYS.every(key => bidKeys.includes(key)); - } - - function errorMessage(msg) { - return `Invalid bid from ${bid.bidderCode}. Ignoring bid: ${msg}`; - } +// check that the bid has a width and height set +function validBidSize(adUnitCode, bid, bidRequests) { + if ((bid.width || bid.width === 0) && (bid.height || bid.height === 0)) { + return true; + } - if (!adUnitCode) { - logWarn('No adUnitCode was supplied to addBidResponse.'); - return false; - } + const adUnit = getBidderRequest(bidRequests, bid.bidderCode, adUnitCode); - if (!bid) { - logWarn(`Some adapter tried to add an undefined bid for ${adUnitCode}.`); - return false; - } + const sizes = adUnit && adUnit.bids && adUnit.bids[0] && adUnit.bids[0].sizes; + const parsedSizes = parseSizesInput(sizes); - if (!hasValidKeys()) { - logError(errorMessage(`Bidder ${bid.bidderCode} is missing required params. Check http://prebid.org/dev-docs/bidder-adapter-1.html for list of params.`)); - return false; - } + // if a banner impression has one valid size, we assign that size to any bid + // response that does not explicitly set width or height + if (parsedSizes.length === 1) { + const [ width, height ] = parsedSizes[0].split('x'); + bid.width = width; + bid.height = height; + return true; + } - if (bid.mediaType === 'native' && !nativeBidIsValid(bid, bidRequests)) { - logError(errorMessage('Native bid missing some required properties.')); - return false; - } - if (bid.mediaType === 'video' && !isValidVideoBid(bid, bidRequests)) { - logError(errorMessage(`Video bid does not have required vastUrl or renderer property`)); - return false; - } - if (bid.mediaType === 'banner' && !validBidSize(adUnitCode, bid, bidRequests)) { - logError(errorMessage(`Banner bids require a width and height`)); - return false; - } + return false; +} - return true; +// Validate the arguments sent to us by the adapter. If this returns false, the bid should be totally ignored. +export function isValid(adUnitCode, bid, bidRequests) { + function hasValidKeys() { + let bidKeys = Object.keys(bid); + return COMMON_BID_RESPONSE_KEYS.every(key => bidKeys.includes(key)); } - // check that the bid has a width and height set - function validBidSize(adUnitCode, bid, bidRequests) { - if ((bid.width || bid.width === 0) && (bid.height || bid.height === 0)) { - return true; - } + function errorMessage(msg) { + return `Invalid bid from ${bid.bidderCode}. Ignoring bid: ${msg}`; + } - const adUnit = getBidderRequest(bidRequests, bid.bidderCode, adUnitCode); + if (!adUnitCode) { + logWarn('No adUnitCode was supplied to addBidResponse.'); + return false; + } - const sizes = adUnit && adUnit.bids && adUnit.bids[0] && adUnit.bids[0].sizes; - const parsedSizes = parseSizesInput(sizes); + if (!bid) { + logWarn(`Some adapter tried to add an undefined bid for ${adUnitCode}.`); + return false; + } - // if a banner impression has one valid size, we assign that size to any bid - // response that does not explicitly set width or height - if (parsedSizes.length === 1) { - const [ width, height ] = parsedSizes[0].split('x'); - bid.width = width; - bid.height = height; - return true; - } + if (!hasValidKeys()) { + logError(errorMessage(`Bidder ${bid.bidderCode} is missing required params. Check http://prebid.org/dev-docs/bidder-adapter-1.html for list of params.`)); + return false; + } + if (bid.mediaType === 'native' && !nativeBidIsValid(bid, bidRequests)) { + logError(errorMessage('Native bid missing some required properties.')); return false; } + if (bid.mediaType === 'video' && !isValidVideoBid(bid, bidRequests)) { + logError(errorMessage(`Video bid does not have required vastUrl or renderer property`)); + return false; + } + if (bid.mediaType === 'banner' && !validBidSize(adUnitCode, bid, bidRequests)) { + logError(errorMessage(`Banner bids require a width and height`)); + return false; + } + + return true; } diff --git a/src/auction.js b/src/auction.js index 01d0f4cdc36..ce3985bff5e 100644 --- a/src/auction.js +++ b/src/auction.js @@ -56,6 +56,7 @@ import { Renderer } from 'src/Renderer'; import { config } from 'src/config'; import { userSync } from 'src/userSync'; import { createHook } from 'src/hook'; +import { videoAdUnit } from 'src/video'; const { syncUsers } = userSync; const utils = require('./utils'); @@ -112,6 +113,16 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } if (_callback != null) { + if (timedOut) { + utils.logMessage(`Auction ${_auctionId} timedOut`); + const timedOutBidders = getTimedOutBids(_bidderRequests, _bidsReceived); + if (timedOutBidders.length) { + events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, timedOutBidders); + } + } + + events.emit(CONSTANTS.EVENTS.AUCTION_END, {auctionId: _auctionId}); + try { _auctionStatus = AUCTION_COMPLETED; const adUnitCodes = _adUnitCodes; @@ -130,14 +141,6 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) } } _callback = null; - - if (timedOut) { - utils.logMessage(`Auction ${_auctionId} timedOut`); - const timedOutBidders = getTimedOutBids(_bidderRequests, _bidsReceived); - if (timedOutBidders.length) { - events.emit(CONSTANTS.EVENTS.BID_TIMEOUT, timedOutBidders); - } - } } } @@ -148,15 +151,25 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) return innerBidRequestId === bidRequest.bidderRequestId; }); request.doneCbCallCount += 1; - if (_bidderRequests.every((bidRequest) => bidRequest.doneCbCallCount >= 1)) { - // when all bidders have called done callback atleast once it means auction is complete - utils.logInfo(`Bids Received for Auction with id: ${_auctionId}`, _bidsReceived); - _auctionStatus = AUCTION_COMPLETED; - executeCallback(false, true); + // In case of mediaType video and prebidCache enabled, call bidsBackHandler after cache is stored. + if ((request.bids.filter(videoAdUnit).length == 0) || (request.bids.filter(videoAdUnit).length > 0 && !config.getConfig('usePrebidCache'))) { + bidsBackAll() } }, 1); } + /** + * Execute bidBackHandler if all bidders have called done. + */ + function bidsBackAll() { + if (_bidderRequests.every((bidRequest) => bidRequest.doneCbCallCount >= 1)) { + // when all bidders have called done callback atleast once it means auction is complete + utils.logInfo(`Bids Received for Auction with id: ${_auctionId}`, _bidsReceived); + _auctionStatus = AUCTION_COMPLETED; + executeCallback(false, true); + } + } + function callBids() { startAuctionTimer(); _auctionStatus = AUCTION_STARTED; @@ -183,6 +196,7 @@ export function newAuction({adUnits, adUnitCodes, callback, cbTimeout, labels}) addBidReceived, executeCallback, callBids, + bidsBackAll, setWinningBid: (winningBid) => { _winningBid = winningBid }, getWinningBid: () => _winningBid, getTimeout: () => _timeout, @@ -232,6 +246,7 @@ export const addBidResponse = createHook('asyncSeries', function(adUnitCode, bid bidResponse.vastUrl = getCacheUrl(bidResponse.videoCacheKey); } addBidToAuction(bidResponse); + auctionInstance.bidsBackAll(); } doCallbacksIfNeeded(); });