forked from prebid/Prebid.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ServerBid Server BidAdapter (prebid#1819)
* ServerBid Server BidAdapter Allow S2S configuration with ServerBid. * Updates to meet 1.0 callBids/config changes. * Fix linting issues.
- Loading branch information
Showing
2 changed files
with
535 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
import Adapter from 'src/adapter'; | ||
import bidfactory from 'src/bidfactory'; | ||
import * as utils from 'src/utils'; | ||
import adaptermanager from 'src/adaptermanager'; | ||
import { STATUS, S2S } from 'src/constants'; | ||
import { config } from 'src/config'; | ||
|
||
const TYPE = S2S.SRC; | ||
const getConfig = config.getConfig; | ||
const REQUIRED_S2S_CONFIG_KEYS = ['siteId', 'networkId', 'bidders', 'endpoint']; | ||
|
||
let _s2sConfig; | ||
config.setDefaults({ | ||
's2sConfig': { | ||
enabled: false, | ||
timeout: 1000, | ||
adapter: 'serverbidServer' | ||
} | ||
}); | ||
|
||
var ServerBidServerAdapter; | ||
ServerBidServerAdapter = function ServerBidServerAdapter() { | ||
const baseAdapter = new Adapter('serverbidServer'); | ||
|
||
const BASE_URI = 'https://e.serverbid.com/api/v2'; | ||
|
||
const sizeMap = [ | ||
null, | ||
'120x90', | ||
'120x90', | ||
'468x60', | ||
'728x90', | ||
'300x250', | ||
'160x600', | ||
'120x600', | ||
'300x100', | ||
'180x150', | ||
'336x280', | ||
'240x400', | ||
'234x60', | ||
'88x31', | ||
'120x60', | ||
'120x240', | ||
'125x125', | ||
'220x250', | ||
'250x250', | ||
'250x90', | ||
'0x0', | ||
'200x90', | ||
'300x50', | ||
'320x50', | ||
'320x480', | ||
'185x185', | ||
'620x45', | ||
'300x125', | ||
'800x250' | ||
]; | ||
|
||
sizeMap[77] = '970x90'; | ||
sizeMap[123] = '970x250'; | ||
sizeMap[43] = '300x600'; | ||
|
||
function setS2sConfig(options) { | ||
let contains = (xs, x) => xs.indexOf(x) > -1; | ||
let userConfig = Object.keys(options); | ||
|
||
REQUIRED_S2S_CONFIG_KEYS.forEach(key => { | ||
if (!contains(userConfig, key)) { | ||
utils.logError(key + ' missing in server to server config'); | ||
return void 0; // void 0 to beat the linter | ||
} | ||
}) | ||
|
||
_s2sConfig = options; | ||
} | ||
getConfig('s2sConfig', ({s2sConfig}) => setS2sConfig(s2sConfig)); | ||
|
||
function getLocalConfig() { | ||
return (_s2sConfig || {}); | ||
} | ||
|
||
function _convertFields(bid) { | ||
let safeBid = bid || {}; | ||
let converted = {}; | ||
let name = safeBid.bidder; | ||
converted[name] = safeBid.params; | ||
return converted; | ||
} | ||
|
||
baseAdapter.callBids = function(s2sBidRequest, bidRequests, addBidResponse, done, ajax) { | ||
let params = s2sBidRequest; | ||
let shouldDoWorkFn = function(bidRequest) { | ||
return bidRequest && | ||
bidRequest.ad_units && | ||
utils.isArray(bidRequest.ad_units) && | ||
bidRequest.ad_units.length; | ||
} | ||
if (shouldDoWorkFn(params)) { | ||
_callBids(s2sBidRequest, bidRequests, addBidResponse, done, ajax); | ||
} | ||
}; | ||
|
||
function _callBids(s2sBidRequest, bidRequests, addBidResponse, done, ajax) { | ||
let bidRequest = s2sBidRequest; | ||
|
||
// one request per ad unit | ||
for (let i = 0; i < bidRequest.ad_units.length; i++) { | ||
let adunit = bidRequest.ad_units[i]; | ||
let siteId = _s2sConfig.siteId; | ||
let networkId = getLocalConfig().networkId; | ||
let sizes = adunit.sizes; | ||
|
||
const data = { | ||
placements: [], | ||
time: Date.now(), | ||
user: {}, | ||
url: utils.getTopWindowUrl(), | ||
referrer: document.referrer, | ||
enableBotFiltering: true, | ||
includePricingData: true, | ||
parallel: true | ||
}; | ||
|
||
const bids = adunit.bids || []; | ||
|
||
// one placement for each of the bids | ||
for (let i = 0; i < bids.length; i++) { | ||
const bid = bids[i]; | ||
bid.code = adunit.code; | ||
|
||
const placement = Object.assign({}, { | ||
divName: bid.bid_id, | ||
networkId: networkId, | ||
siteId: siteId, | ||
adTypes: bid.adTypes || getSize(sizes), | ||
bidders: _convertFields(bid), | ||
skipSelection: true | ||
}); | ||
|
||
if (placement.networkId && placement.siteId) { | ||
data.placements.push(placement); | ||
} | ||
} | ||
if (data.placements.length) { | ||
ajax(BASE_URI, _responseCallback(addBidResponse, bids), JSON.stringify(data), { method: 'POST', withCredentials: true, contentType: 'application/json' }); | ||
} | ||
} | ||
} | ||
|
||
function _responseCallback(addBidResponse, bids) { | ||
return function (resp) { | ||
let bid; | ||
let bidId; | ||
let result; | ||
let bidObj; | ||
let bidCode; | ||
let placementCode; | ||
let skipSelectionRequestsReturnArray = function (decision) { | ||
return (decision || []).length ? decision[0] : {}; | ||
}; | ||
|
||
try { | ||
result = JSON.parse(resp); | ||
} catch (error) { | ||
utils.logError(error); | ||
} | ||
|
||
for (let i = 0; i < bids.length; i++) { | ||
bidObj = bids[i]; | ||
bidId = bidObj.bid_id; | ||
bidObj.bidId = bidObj.bid_id; | ||
bidCode = bidObj.bidder; | ||
placementCode = bidObj.code; | ||
let noBid = function(bidObj) { | ||
bid = bidfactory.createBid(STATUS.NO_BID, bidObj); | ||
bid.bidderCode = bidCode; | ||
return bid; | ||
}; | ||
|
||
if (result) { | ||
const decision = result.decisions && skipSelectionRequestsReturnArray(result.decisions[bidId]); | ||
const price = decision && decision.pricing && decision.pricing.clearPrice; | ||
|
||
if (decision && price) { | ||
bid = bidfactory.createBid(STATUS.GOOD, bidObj); | ||
bid = Object.assign(bid, {bidderCode: bidCode, | ||
cpm: price, | ||
width: decision.width, | ||
height: decision.height, | ||
ad: retrieveAd(decision)}) | ||
} else { | ||
bid = noBid(bidObj); | ||
} | ||
} else { | ||
bid = noBid(bidObj); | ||
} | ||
addBidResponse(placementCode, bid); | ||
} | ||
done() | ||
} | ||
}; | ||
|
||
function retrieveAd(decision) { | ||
return decision.contents && decision.contents[0] && decision.contents[0].body + utils.createTrackPixelHtml(decision.impressionUrl); | ||
} | ||
|
||
function getSize(sizes) { | ||
let width = 'w'; | ||
let height = 'h'; | ||
const result = []; | ||
sizes.forEach(function(size) { | ||
const index = sizeMap.indexOf(size[width] + 'x' + size[height]); | ||
if (index >= 0) { | ||
result.push(index); | ||
} | ||
}); | ||
return result; | ||
} | ||
|
||
// Export the `callBids` function, so that Prebid.js can execute | ||
// this function when the page asks to send out bid requests. | ||
return Object.assign(this, { | ||
queueSync: baseAdapter.queueSync, | ||
callBids: baseAdapter.callBids, | ||
setBidderCode: baseAdapter.setBidderCode, | ||
type: TYPE | ||
}); | ||
}; | ||
|
||
ServerBidServerAdapter.createNew = function() { | ||
return new ServerBidServerAdapter(); | ||
}; | ||
|
||
adaptermanager.registerBidAdapter(new ServerBidServerAdapter(), 'serverbidServer'); | ||
|
||
module.exports = ServerBidServerAdapter; |
Oops, something went wrong.