Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Sonobi adapter for: config settings, floor, deals, unit tests #591

Merged
merged 1 commit into from
Sep 2, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 85 additions & 63 deletions src/adapters/sonobi.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,89 +4,111 @@ var adloader = require('../adloader.js');
var utils = require('../utils');

var SonobiAdapter = function SonobiAdapter(){
var test = false; // tag tester = true || false
var cb_map = {};
var keymakerAssoc = {}; // Remember placement codes for callback mapping
var bidIdAssoc = {}; // Remember bids for bid complete reporting

function _phone_in(params){
function _phone_in(request){
var trinity = 'https://apex.go.sonobi.com/trinity.js?key_maker=';
var bids = params.bids || [];
adloader.loadScript(trinity + JSON.stringify(_keymaker(bids)) + '&cv=' + _operator());
var adSlots = request.bids || [];
var bidderRequestId = request.bidderRequestId;
adloader.loadScript(trinity + JSON.stringify(_keymaker(adSlots)) + '&cv=' + _operator(bidderRequestId));
}

function _keymaker(bids){ // Make keys
function _keymaker(adSlots){ // Keymaker makes keys
var keyring = {};
utils._each(bids, function(o){
var sizes = utils.parseSizesInput(o.sizes).toString();
if (utils.isEmpty(sizes)){
utils.logWarn('Sonobi adapter expects sizes for ' + o.placementCode);
}
switch(true){
case (!o.params.ad_unit && !o.params.placement_id):
utils.logError('Sonobi unable to bid: Missing parameters for ' + o.placementCode);
break;
case (!!o.params.ad_unit && !!o.params.placement_id):
utils.logError('Sonobi unable to bid: Extra parameters for ' + o.placementCode);
break;
case (!!o.params.ad_unit && o.params.ad_unit.length === 0):
utils.logError('Sonobi unable to bid: Empty ad_unit for ' + o.placementCode);
break;
case (!!o.params.placement_id && o.params.placement_id.length === 0):
utils.logError('Sonobi unable to bid: Empty placement_id for ' + o.placementCode);
break;
case (!!o.params.placement_id): // Morpeus style
keyring[o.params.dom_id] = o.params.placement_id + (test ? '-test' : '') + '|' + sizes;
cb_map[o.params.dom_id] = o.placementCode;
break;
case (!!o.params.ad_unit && o.params.ad_unit.charAt(0) !== '/'):
// DFP docs do not necessarily require leading slash? - add it in if it's not there.
o.params.ad_unit = '/' + o.params.ad_unit;
/* falls through */
case (!!o.params.ad_unit): // Cypher style
keyring[o.params.ad_unit + '|' + o.params.dom_id] = sizes;
cb_map[o.params.ad_unit + '|' + o.params.dom_id] = o.placementCode;
break;
default: // I don't know how it's broken, but it is.
utils.logError('Sonobi unable to bid: Improper parameters for ' + o.placementCode);
utils._each(adSlots, function(bidSlot){
if(bidSlot.params){
// Optional (please don't set these as the word 'OPTIONAL' come on now why would you think that was OK?)
var dom_id = (bidSlot.params.dom_id && !utils.isEmpty(bidSlot.params.dom_id)) ? bidSlot.params.dom_id : !utils.isEmpty(bidSlot.placementCode) ? bidSlot.placementCode : "dom_" + utils.getUniqueIdentifierStr();
var floor = (bidSlot.params.floor) ? bidSlot.params.floor : null;
// Mandatory
var slotIdentifier = (bidSlot.params.ad_unit) ? bidSlot.params.ad_unit : (bidSlot.params.placement_id) ? bidSlot.params.placement_id : null;
var sizes = utils.parseSizesInput(bidSlot.sizes).toString() || null;
if (utils.isEmpty(sizes)){
utils.logError('Sonobi adapter expects sizes for ' + bidSlot.placementCode);
}
var args = (sizes) ? ((floor) ? (sizes + '|f=' + floor) : (sizes)) : (floor) ? ('f=' + floor) : '';
if (/[0-9a-fA-F]+/.test(slotIdentifier) && slotIdentifier.length === 20){
// Placements are 20 character hex
keyring[dom_id] = slotIdentifier + '|' + args;
keymakerAssoc[dom_id] = bidSlot.placementCode;
bidIdAssoc[bidSlot.placementCode] = bidSlot;
} else if (/\/?[0-9]*\/(.*\/?)*/.test(slotIdentifier)){
// AdUnitCode rules from DFP allow a lot of things you wouldn't expect
slotIdentifier = slotIdentifier.charAt(0) === '/' ? slotIdentifier : '/' + slotIdentifier;
// Consistency isn't really their thing they can't even decide if leading slash matters
keyring[slotIdentifier + '|' + dom_id] = args;
keymakerAssoc[slotIdentifier + '|' + dom_id] = bidSlot.placementCode;
bidIdAssoc[bidSlot.placementCode] = bidSlot;
} else {
keymakerAssoc[dom_id] = bidSlot.placementCode;
bidIdAssoc[bidSlot.placementCode] = bidSlot;
_failure(bidSlot.placementCode);
utils.logError('The ad unit code or Sonobi Placement id for slot ' + bidSlot.placementCode + ' is invalid');
}
}
});
return keyring;
}

function _operator(){ // Uniqify callbacks
var uniq = "cb" + utils.getUniqueIdentifierStr();
window[uniq] = _trinity;
return uniq;
function _operator(bidderRequestId){ // Name jsonp callbacks by request
var cb_name = "sbi_" + bidderRequestId;
window[cb_name] = _trinity;
return cb_name;
}

function _trinity(response){ // Callback
function _trinity(response){ // Call back
var slots = response.slots || {};
var sbi_dc = response.sbi_dc || '';
var bidObject = {};
for (var slot in slots) {
if (slots[slot].sbi_aid){
bidObject = bidfactory.createBid(1);
bidObject.bidderCode = 'sonobi';
bidObject.cpm = Number(slots[slot].sbi_mouse);
bidObject.ad = _get_creative(sbi_dc, slots[slot].sbi_aid);
bidObject.width = Number(slots[slot].sbi_size.split('x')[0]);
bidObject.height = Number(slots[slot].sbi_size.split('x')[1]);
bidmanager.addBidResponse(cb_map[slot], bidObject);
} else { // No aid? No ad.
bidObject = bidfactory.createBid(2);
bidObject.bidderCode = 'sonobi';
bidmanager.addBidResponse(cb_map[slot], bidObject);
utils._each(slots, function(bid, slot_id){
var placementCode = keymakerAssoc[slot_id];
if (bid.sbi_aid && bid.sbi_mouse && bid.sbi_size){ // I got the money you got the stuff?
_success(placementCode, sbi_dc, bid);
} else {
_failure(placementCode);
}
delete keymakerAssoc[slot_id]; // You're done get outta here
});
}

function _seraph(placementCode){ // Search for the one
var theOne = bidIdAssoc[placementCode];
delete bidIdAssoc[placementCode]; // Eliminate him
return theOne;
}

function _success(placementCode, sbi_dc, bid){
var goodBid = bidfactory.createBid(1, _seraph(placementCode));
if(bid.sbi_dozer){
goodBid.dealId = bid.sbi_dozer;
}
goodBid.bidderCode = 'sonobi';
goodBid.ad = _creative(sbi_dc, bid.sbi_aid);
goodBid.cpm = Number(bid.sbi_mouse);
// Video creatives will return sbi_size="outstream", default to 1x1
goodBid.width = Number(bid.sbi_size.split('x')[0]) || 1;
goodBid.height = Number(bid.sbi_size.split('x')[1]) || 1;
bidmanager.addBidResponse(placementCode, goodBid);
}

function _failure(placementCode){
var failBid = bidfactory.createBid(2, _seraph(placementCode));
failBid.bidderCode = 'sonobi';
bidmanager.addBidResponse(placementCode, failBid);
}

function _get_creative(sbi_dc, sbi_aid){
var creative = '<scr' + 'ipt type="text/javascript"src="https://' + sbi_dc;
creative += 'apex.go.sonobi.com/sbi.js?as=dfps&aid=' + sbi_aid;
creative += '"></scr' + 'ipt>';
return creative;
function _creative(sbi_dc, sbi_aid){
var src = 'https://' + sbi_dc + 'apex.go.sonobi.com/sbi.js?aid=' + sbi_aid + '&as=null';
return '<script type="text/javascript" src="' + src + '"></script>';
}

return { callBids: _phone_in };
return {
callBids: _phone_in,
formRequest: _keymaker,
parseResponse: _trinity,
success: _success,
failure: _failure
};
};

module.exports = SonobiAdapter;
84 changes: 0 additions & 84 deletions test/fixtures/fixtures.js
Original file line number Diff line number Diff line change
Expand Up @@ -973,90 +973,6 @@ export function getAdUnits() {
"requestId": "1ff753bd4ae5cb"
}
]
},
{
"code": "/7780971/apex_sparks_300",
"sizes": [
[
300,
250
]
],
"bids": [
{
"bidder": "sonobi",
"params": {
"dom_id": "div-gpt-ad-1455548812677-0",
"ad_unit": "/7780971/apex_sparks_300"
},
"placementCode": "/7780971/apex_sparks_300",
"sizes": [
[
300,
250
]
],
"bidId": "43a45a2cd8c6ef9",
"bidderRequestId": "42e2fe519b7c653",
"requestId": "1ff753bd4ae5cb"
}
]
},
{
"code": "/7780971/apex_sparks_skyscraper_x600",
"sizes": [
[
300,
600
]
],
"bids": [
{
"bidder": "sonobi",
"params": {
"dom_id": "div-gpt-ad-1455548812677-1",
"placement_id": "21d2da738fe0ba795cfb-test"
},
"placementCode": "/7780971/apex_sparks_skyscraper_x600",
"sizes": [
[
300,
600
]
],
"bidId": "44f16af92ca7607",
"bidderRequestId": "42e2fe519b7c653",
"requestId": "1ff753bd4ae5cb"
}
]
},
{
"code": "/7780971/apex_sparks_banner_x90",
"sizes": [
[
728,
90
]
],
"bids": [
{
"bidder": "sonobi",
"params": {
"dom_id": "div-gpt-ad-1455548812677-2",
"ad_unit": "/7780971/apex_sparks_banner_x90"
},
"placementCode": "/7780971/apex_sparks_banner_x90",
"sizes": [
[
728,
90
]
],
"bidId": "45e5c0084508efb",
"bidderRequestId": "42e2fe519b7c653",
"requestId": "1ff753bd4ae5cb"
}
]
}
];
};
Expand Down
Loading