Skip to content

Commit

Permalink
Prebid Auctions
Browse files Browse the repository at this point in the history
The Prebid Auction is introduced, making it possible to manage a series of auction events. Previously Prebid handled only one auction at a time. With this PR the `pbjs.adUnits` and `pbjs.bidderSettings` are moved to an `auction` instance. Auctions can be run concurrently, so for example if different groupings of ad placements have different configurations, auctions for each placement group can both be requested at page load and run asynchronously. Be aware that if multiple auctions are run concurrently for the same placement the last auction winner creative will replace any previous winner.
  • Loading branch information
protonate committed Jun 21, 2016
1 parent eae3400 commit 64dcd6d
Show file tree
Hide file tree
Showing 22 changed files with 422 additions and 294 deletions.
62 changes: 35 additions & 27 deletions src/adaptermanager.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,60 @@
/** @module adaptermanger */
var utils = require('./utils.js');

import { flatten, getBidderCodes } from './utils';
import { flatten, uniques } from './utils';

var utils = require('./utils.js');
var bidfactory = require('./bidfactory.js');
var CONSTANTS = require('./constants.json');
var events = require('./events');
import { BaseAdapter } from './adapters/baseAdapter';

var _bidderRegistry = {};
exports.bidderRegistry = _bidderRegistry;

function getBids({ bidderCode, requestId, bidderRequestId, adUnits }) {
return adUnits.map(adUnit => {
return adUnit.bids.filter(bid => bid.bidder === bidderCode)
.map(bid => Object.assign(bid, {
placementCode: adUnit.code,
sizes: adUnit.sizes,
bidId: utils.getUniqueIdentifierStr(),
bidderRequestId,
requestId
}));
}).reduce(flatten, []);
function makeBids({ bidderCode, bidderRequestId, adUnit }) {
return adUnit.bids.filter(bidRequest => bidRequest.bidder === bidderCode)
.map(bidRequest => Object.assign(bidfactory.createBid(1), bidRequest, {
placementCode: adUnit.code,
sizes: adUnit.sizes,
bidderRequestId
}));
}

exports.callBids = ({ adUnits }) => {
const requestId = utils.getUniqueIdentifierStr();
function getAuctionBidderCodes(auction) {
return auction.getAdUnits()
.map(unit => unit.bids
.map(bidder => bidder.bidder))
.reduce(flatten)
.filter(uniques);
}

getBidderCodes(adUnits).forEach(bidderCode => {
const adapter = _bidderRegistry[bidderCode];
if (adapter) {
function bidderHasAdapter(bidderCode) {
return _bidderRegistry[bidderCode];
}

exports.callBids = auction => {
auction.setBidderRequests(getAuctionBidderCodes(auction)
.filter(bidderHasAdapter)
.map(bidderCode => {
const adapter = _bidderRegistry[bidderCode];
const prebidAuctionId = auction.getId();
const bidderRequestId = utils.getUniqueIdentifierStr();
const adUnit = auction.getAdUnits().find(adUnit => adUnit.bids.find(bid => bid.bidder === bidderCode));
const bidderRequest = {
bidderCode,
requestId,
prebidAuctionId,
bidderRequestId,
bids: getBids({ bidderCode, requestId, bidderRequestId, adUnits }),
bids: makeBids({ bidderCode, bidderRequestId, adUnit }),
start: new Date().getTime()
};
utils.logMessage(`CALLING BIDDER ======= ${bidderCode}`);
pbjs._bidsRequested.push(bidderRequest);
utils.logMessage(`CALLING BIDDER ======= ${bidderCode}:`, bidderRequest);
events.emit(CONSTANTS.EVENTS.BID_REQUESTED, bidderRequest);
if (bidderRequest.bids && bidderRequest.bids.length) {
adapter.callBids(bidderRequest);
adapter.callBids(bidderRequest, auction);
}
} else {
utils.logError(`Adapter trying to be called which does not exist: ${bidderCode} adaptermanager.callBids`);
}
});

return bidderRequest;
}));
};

exports.registerBidAdapter = function (bidAdaptor, bidderCode) {
Expand Down
19 changes: 10 additions & 9 deletions src/adapters/adequant.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ var adloader = require('../adloader.js');

module.exports = function() {
var req_url_base = 'https://rex.adequant.com/rex/c2s_prebid?';

function _callBids(params) {
var req_url = [];
var publisher_id = null;
var sizes = [];
var cats = null;
var replies = [];
var placements = {};

var bids = params.bids || [];
for (var i = 0; i < bids.length; i++) {
var bid_request = bids[i];
var br_params = bid_request.params || {};
placements[bid_request.placementCode] = true;

publisher_id = br_params.publisher_id.toString() || publisher_id;
var bidfloor = br_params.bidfloor || 0.01;
cats = br_params.cats || cats;
Expand All @@ -33,18 +33,18 @@ module.exports = function() {
if (cats) { req_url.push('c='+cats.join('+')); }
if (sizes) { req_url.push('s='+sizes.join('+')); }

adloader.loadScript(req_url_base+req_url.join('&'), function() { process_bids(replies, placements); });
adloader.loadScript(req_url_base+req_url.join('&'), function() { process_bids(replies, placements, bids); });
}
function process_bids(replies, placements) {

function process_bids(replies, placements, bids) {
var placement_code, bid, adequant_creatives = window.adequant_creatives;
if (adequant_creatives && adequant_creatives.seatbid) {
for (var i=0; i<adequant_creatives.seatbid.length; i++) {
var bid_response = adequant_creatives.seatbid[i].bid[0];
placement_code = replies[parseInt(bid_response.impid,10)-1];
if (!placement_code || !placements[placement_code]) { continue; }

bid = bidfactory.createBid(1);
const bidRequestId = bids.find(bid => bid.placementCode === placement_code).bidId;
bid = bidfactory.createBid(1, bidRequestId);
bid.bidderCode = 'adequant';
bid.cpm = bid_response.price;
bid.ad = bid_response.adm;
Expand All @@ -55,8 +55,9 @@ module.exports = function() {
}
}
for (placement_code in placements) {
const bidRequestId = bids.find(bid => bid.placementCode === placement_code).bidId;
if (placements[placement_code]) {
bid = bidfactory.createBid(2);
bid = bidfactory.createBid(2, bidRequestId);
bid.bidderCode = 'adequant';
bidmanager.addBidResponse(placement_code, bid);
}
Expand Down
4 changes: 2 additions & 2 deletions src/adapters/adform.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ function AdformAdapter() {
if (adItem && adItem.response === 'banner' &&
verifySize(adItem, bid.sizes)) {

bidObject = bidfactory.createBid(1);
bidObject = bidfactory.createBid(1, bid.bidId);
bidObject.bidderCode = bidder;
bidObject.cpm = adItem.win_bid;
bidObject.cur = adItem.win_cur;
Expand All @@ -76,7 +76,7 @@ function AdformAdapter() {
bidObject.height = adItem.height;
bidmanager.addBidResponse(bid.placementCode, bidObject);
} else {
bidObject = bidfactory.createBid(2);
bidObject = bidfactory.createBid(2, bid.bidId);
bidObject.bidderCode = bidder;
bidmanager.addBidResponse(bid.placementCode, bidObject);
}
Expand Down
4 changes: 2 additions & 2 deletions src/adapters/aol.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ var AolAdapter = function AolAdapter() {
// clean up--we no longer need to store the bid
delete bidsMap[context.alias];

var bidResponse = bidfactory.createBid(1);
var bidResponse = bidfactory.createBid(1, bid.bidId);
var ad = response.getCreative();
if (typeof response.getPixels() !== 'undefined') {
ad += response.getPixels();
Expand Down Expand Up @@ -105,7 +105,7 @@ var AolAdapter = function AolAdapter() {
// clean up--we no longer need to store the bid
delete bidsMap[context.alias];

var bidResponse = bidfactory.createBid(2);
var bidResponse = bidfactory.createBid(2, bid.bidId);
bidResponse.bidderCode = ADTECH_BIDDER_NAME;
bidResponse.reason = response.getNbr();
bidResponse.raw = response.getResponse();
Expand Down
30 changes: 9 additions & 21 deletions src/adapters/appnexus.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getBidRequest } from '../utils.js';
import { findBidRequest } from '../utils.js';

var CONSTANTS = require('../constants.json');
var utils = require('../utils.js');
Expand All @@ -12,23 +12,10 @@ AppNexusAdapter = function AppNexusAdapter() {
var baseAdapter = Adapter.createNew('appnexus');

baseAdapter.callBids = function (params) {
//var bidCode = baseAdapter.getBidderCode();

var anArr = params.bids;

//var bidsCount = anArr.length;

//set expected bids count for callback execution
//bidmanager.setExpectedBidsCount(bidCode, bidsCount);

for (var i = 0; i < anArr.length; i++) {
var bidRequest = anArr[i];
var callbackId = bidRequest.bidId;
adloader.loadScript(buildJPTCall(bidRequest, callbackId));

//store a reference to the bidRequest from the callback id
//bidmanager.pbCallbackMap[callbackId] = bidRequest;
}
params.bids.map(bid => {
const callbackId = bid.bidId;
adloader.loadScript(buildJPTCall(bid, callbackId));
});
};

function buildJPTCall(bid, callbackId) {
Expand Down Expand Up @@ -151,7 +138,8 @@ AppNexusAdapter = function AppNexusAdapter() {
var responseCPM;
var id = jptResponseObj.callback_uid;
var placementCode = '';
var bidObj = getBidRequest(id);
var bidObj = findBidRequest({ bidId: id });

if (bidObj) {

bidCode = bidObj.bidder;
Expand All @@ -178,7 +166,7 @@ AppNexusAdapter = function AppNexusAdapter() {
//store bid response
//bid status is good (indicating 1)
var adId = jptResponseObj.result.creative_id;
bid = bidfactory.createBid(1);
bid = bidfactory.createBid(1, id);
bid.creative_id = adId;
bid.bidderCode = bidCode;
bid.cpm = responseCPM;
Expand All @@ -196,7 +184,7 @@ AppNexusAdapter = function AppNexusAdapter() {

// @endif
//indicate that there is no bid for this placement
bid = bidfactory.createBid(2);
bid = bidfactory.createBid(2, id);
bid.bidderCode = bidCode;
bidmanager.addBidResponse(placementCode, bid);
}
Expand Down
23 changes: 14 additions & 9 deletions src/adapters/brightcom.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { findAuctionByBidderCode } from '../utils';

var CONSTANTS = require('../constants.json');
var utils = require('../utils.js');
var bidfactory = require('../bidfactory.js');
Expand All @@ -8,7 +10,7 @@ var adloader = require('../adloader');
* Adapter for requesting bids from Brightcom
*/
var BrightcomAdapter = function BrightcomAdapter() {

// Set Brightcom Bidder URL
var brightcomUrl = 'hb.iselephant.com/auc/ortb';

Expand Down Expand Up @@ -117,14 +119,14 @@ var BrightcomAdapter = function BrightcomAdapter() {

// Add the call to get the bid
adloader.loadScript(bidRequestCallUrl, null);

}

//expose the callback to the global object:
pbjs.brightcomResponse = function(brightcomResponseObj) {

var bid = {};

// Make sure response is valid
if (
(brightcomResponseObj) && (brightcomResponseObj.id) &&
Expand All @@ -133,20 +135,23 @@ var BrightcomAdapter = function BrightcomAdapter() {
) {

// Go through the received bids
brightcomResponseObj.seatbid[0].bid.forEach( function(curBid) {
brightcomResponseObj.seatbid[0].bid.forEach(function(curBid) {

// Get the bid request data
var bidRequest = pbjs._bidsRequested.find(bidSet => bidSet.bidderCode === 'brightcom').bids[0]; // this assumes a single request only
const auction = auction || pbjs.auctionManager.getSingleAuction();

// this assumes a single auction only
var bidRequest = auction.getBidderRequests().find(bidderRequest => bidderRequest.bidderCode === 'brightcom').bids[0];

// Make sure the bid exists
if (bidRequest) {

var placementCode = bidRequest.placementCode;
bidRequest.status = CONSTANTS.STATUS.GOOD;

curBid.placementCode = placementCode;
curBid.size = bidRequest.sizes;

// Get the creative
var responseCreative = curBid.adm;
// Build the NURL element
Expand Down Expand Up @@ -189,7 +194,7 @@ var BrightcomAdapter = function BrightcomAdapter() {

}
});

}

// Define all unreceived ad unit codes as invalid (if Brightcom don't want to bid on an impression, it won't include it in the response)
Expand Down
5 changes: 3 additions & 2 deletions src/adapters/nginad.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { findBidderRequestByBidId } from '../utils';

var CONSTANTS = require('../constants.json');
var utils = require('../utils.js');
var bidfactory = require('../bidfactory.js');
Expand Down Expand Up @@ -142,8 +144,7 @@ var NginAdAdapter = function NginAdAdapter() {
var id = nginadBid.impid;

// try to fetch the bid request we sent NginAd
var bidObj = pbjs._bidsRequested.find(bidSet => bidSet.bidderCode === 'nginad').bids
.find(bid => bid.bidId === id);
var bidObj = findBidderRequestByBidId({ adId: id });
if (!bidObj) {
return handleErrorResponse(nginadBid, defaultPlacementForBadBid);
}
Expand Down
Loading

0 comments on commit 64dcd6d

Please sign in to comment.