Skip to content

Commit

Permalink
Touchup add bid response (prebid#1822)
Browse files Browse the repository at this point in the history
* bidmanager: pass closure variables explicitly to helper functions in addBidResponse

* bidmanager: move addBidResponse helper functions out of closures
  • Loading branch information
kitwestneat authored and dluxemburg committed Jul 17, 2018
1 parent f6be137 commit c6e517c
Showing 1 changed file with 141 additions and 142 deletions.
283 changes: 141 additions & 142 deletions src/bidmanager.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,176 +80,175 @@ exports.bidsBackAll = function () {
return bidsBackAll();
};

/*
* This function should be called to by the bidder adapter to register a bid response
*/
exports.addBidResponse = createHook('asyncSeries', function (adUnitCode, bid) {
if (isValid()) {
prepareBidForAuction();

if (bid.mediaType === 'video') {
tryAddVideoBid(bid);
} else {
addBidToAuction(bid);
doCallbacksIfNeeded();
}
// Validate the arguments sent to us by the adapter. If this returns false, the bid should be totally ignored.
function isValidBid(bid, adUnitCode) {
function errorMessage(msg) {
return `Invalid bid from ${bid.bidderCode}. Ignoring bid: ${msg}`;
}

// Actual method logic is above. Everything below is helper functions.

// Validate the arguments sent to us by the adapter. If this returns false, the bid should be totally ignored.
function isValid() {
function errorMessage(msg) {
return `Invalid bid from ${bid.bidderCode}. Ignoring bid: ${msg}`;
}
if (!bid) {
utils.logError(`Some adapter tried to add an undefined bid for ${adUnitCode}.`);
return false;
}
if (!adUnitCode) {
utils.logError(errorMessage('No adUnitCode was supplied to addBidResponse.'));
return false;
}

if (!bid) {
utils.logError(`Some adapter tried to add an undefined bid for ${adUnitCode}.`);
return false;
}
if (!adUnitCode) {
utils.logError(errorMessage('No adUnitCode was supplied to addBidResponse.'));
return false;
}
const bidRequest = getBidderRequest(bid.bidderCode, adUnitCode);
if (!bidRequest.start) {
utils.logError(errorMessage('Cannot find valid matching bid request.'));
return false;
}

const bidRequest = getBidderRequest(bid.bidderCode, adUnitCode);
if (!bidRequest.start) {
utils.logError(errorMessage('Cannot find valid matching bid request.'));
return false;
}
if (bid.mediaType === 'native' && !nativeBidIsValid(bid)) {
utils.logError(errorMessage('Native bid missing some required properties.'));
return false;
}
if (bid.mediaType === 'video' && !isValidVideoBid(bid)) {
utils.logError(errorMessage(`Video bid does not have required vastUrl or renderer property`));
return false;
}
if (bid.mediaType === 'banner' && !validBidSize(bid, adUnitCode)) {
utils.logError(errorMessage(`Banner bids require a width and height`));
return false;
}

if (bid.mediaType === 'native' && !nativeBidIsValid(bid)) {
utils.logError(errorMessage('Native bid missing some required properties.'));
return false;
}
if (bid.mediaType === 'video' && !isValidVideoBid(bid)) {
utils.logError(errorMessage(`Video bid does not have required vastUrl or renderer property`));
return false;
}
if (bid.mediaType === 'banner' && !validBidSize(bid)) {
utils.logError(errorMessage(`Banner bids require a width and height`));
return false;
}
return true;
}

// check that the bid has a width and height set
function validBidSize(bid, adUnitCode) {
if ((bid.width || bid.width === 0) && (bid.height || bid.height === 0)) {
return true;
}

// check that the bid has a width and height set
function validBidSize(bid) {
if ((bid.width || bid.width === 0) && (bid.height || bid.height === 0)) {
return true;
}

const adUnit = getBidderRequest(bid.bidderCode, adUnitCode);
const sizes = adUnit && adUnit.bids && adUnit.bids[0] && adUnit.bids[0].sizes;
const parsedSizes = utils.parseSizesInput(sizes);

// 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;
}
const adUnit = getBidderRequest(bid.bidderCode, adUnitCode);
const sizes = adUnit && adUnit.bids && adUnit.bids[0] && adUnit.bids[0].sizes;
const parsedSizes = utils.parseSizesInput(sizes);

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;
}

// Postprocess the bids so that all the universal properties exist, no matter which bidder they came from.
// This should be called before addBidToAuction().
function prepareBidForAuction() {
const bidRequest = getBidderRequest(bid.bidderCode, adUnitCode);

Object.assign(bid, {
requestId: bidRequest.requestId,
responseTimestamp: timestamp(),
requestTimestamp: bidRequest.start,
cpm: parseFloat(bid.cpm) || 0,
bidder: bid.bidderCode,
adUnitCode
});
return false;
}

bid.timeToRespond = bid.responseTimestamp - bid.requestTimestamp;
// Postprocess the bids so that all the universal properties exist, no matter which bidder they came from.
// This should be called before addBidToAuction().
function prepareBidForAuction(bid, adUnitCode) {
const bidRequest = getBidderRequest(bid.bidderCode, adUnitCode);

Object.assign(bid, {
requestId: bidRequest.requestId,
responseTimestamp: timestamp(),
requestTimestamp: bidRequest.start,
cpm: parseFloat(bid.cpm) || 0,
bidder: bid.bidderCode,
adUnitCode
});

// 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, bid);
bid.timeToRespond = bid.responseTimestamp - bid.requestTimestamp;

// a publisher-defined renderer can be used to render bids
const adUnitRenderer =
bidRequest.bids && bidRequest.bids[0] && bidRequest.bids[0].renderer;
// 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, bid);

if (adUnitRenderer) {
bid.renderer = Renderer.install({ url: adUnitRenderer.url });
bid.renderer.setRender(adUnitRenderer.render);
}
// a publisher-defined renderer can be used to render bids
const adUnitRenderer =
bidRequest.bids && bidRequest.bids[0] && bidRequest.bids[0].renderer;

const priceStringsObj = getPriceBucketString(
bid.cpm,
config.getConfig('customPriceBucket'),
config.getConfig('currency.granularityMultiplier')
);
bid.pbLg = priceStringsObj.low;
bid.pbMg = priceStringsObj.med;
bid.pbHg = priceStringsObj.high;
bid.pbAg = priceStringsObj.auto;
bid.pbDg = priceStringsObj.dense;
bid.pbCg = priceStringsObj.custom;

// if there is any key value pairs to map do here
var keyValues;
if (bid.bidderCode && (bid.cpm > 0 || bid.dealId)) {
keyValues = getKeyValueTargetingPairs(bid.bidderCode, bid);
}
if (adUnitRenderer) {
bid.renderer = Renderer.install({ url: adUnitRenderer.url });
bid.renderer.setRender(adUnitRenderer.render);
}

// use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs
bid.adserverTargeting = Object.assign(bid.adserverTargeting || {}, keyValues);
const priceStringsObj = getPriceBucketString(
bid.cpm,
config.getConfig('customPriceBucket'),
config.getConfig('currency.granularityMultiplier')
);
bid.pbLg = priceStringsObj.low;
bid.pbMg = priceStringsObj.med;
bid.pbHg = priceStringsObj.high;
bid.pbAg = priceStringsObj.auto;
bid.pbDg = priceStringsObj.dense;
bid.pbCg = priceStringsObj.custom;

// if there is any key value pairs to map do here
var keyValues;
if (bid.bidderCode && (bid.cpm > 0 || bid.dealId)) {
keyValues = getKeyValueTargetingPairs(bid.bidderCode, bid);
}

function doCallbacksIfNeeded() {
if (bid.timeToRespond > $$PREBID_GLOBAL$$.cbTimeout + $$PREBID_GLOBAL$$.timeoutBuffer) {
const timedOut = true;
exports.executeCallback(timedOut);
}
// use any targeting provided as defaults, otherwise just set from getKeyValueTargetingPairs
bid.adserverTargeting = Object.assign(bid.adserverTargeting || {}, keyValues);
}

function doCallbacksIfNeeded(bid) {
if (bid.timeToRespond > $$PREBID_GLOBAL$$.cbTimeout + $$PREBID_GLOBAL$$.timeoutBuffer) {
const timedOut = true;
exports.executeCallback(timedOut);
}
}

// Add a bid to the auction.
function addBidToAuction() {
events.emit(CONSTANTS.EVENTS.BID_RESPONSE, bid);
// Add a bid to the auction.
function addBidToAuction(bid) {
events.emit(CONSTANTS.EVENTS.BID_RESPONSE, bid);

$$PREBID_GLOBAL$$._bidsReceived.push(bid);
$$PREBID_GLOBAL$$._bidsReceived.push(bid);

if (bid.adUnitCode && bidsBackAdUnit(bid.adUnitCode)) {
triggerAdUnitCallbacks(bid.adUnitCode);
}
if (bid.adUnitCode && bidsBackAdUnit(bid.adUnitCode)) {
triggerAdUnitCallbacks(bid.adUnitCode);
}

if (bidsBackAll()) {
exports.executeCallback();
}
if (bidsBackAll()) {
exports.executeCallback();
}
}

// Video bids may fail if the cache is down, or there's trouble on the network.
function tryAddVideoBid(bid) {
if (config.getConfig('usePrebidCache')) {
store([bid], function(error, cacheIds) {
if (error) {
utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`);
} else {
bid.videoCacheKey = cacheIds[0].uuid;
if (!bid.vastUrl) {
bid.vastUrl = getCacheUrl(bid.videoCacheKey);
}
addBidToAuction(bid);
// Video bids may fail if the cache is down, or there's trouble on the network.
function tryAddVideoBid(bid) {
if (config.getConfig('usePrebidCache')) {
store([bid], function(error, cacheIds) {
if (error) {
utils.logWarn(`Failed to save to the video cache: ${error}. Video bid must be discarded.`);
} else {
bid.videoCacheKey = cacheIds[0].uuid;
if (!bid.vastUrl) {
bid.vastUrl = getCacheUrl(bid.videoCacheKey);
}
doCallbacksIfNeeded();
});
} else {
addBidToAuction(bid);
doCallbacksIfNeeded();
}
addBidToAuction(bid);
}
doCallbacksIfNeeded(bid);
});
} else {
addBidToAuction(bid);
doCallbacksIfNeeded(bid);
}
}

/*
* This function should be called to by the bidder adapter to register a bid response
*/
exports.addBidResponse = createHook('asyncSeries', function (adUnitCode, bid) {
if (!isValidBid(bid, adUnitCode)) {
return;
}
prepareBidForAuction(bid, adUnitCode);

if (bid.mediaType === 'video') {
tryAddVideoBid(bid);
} else {
addBidToAuction(bid);
doCallbacksIfNeeded(bid);
}
});

Expand Down

0 comments on commit c6e517c

Please sign in to comment.