Skip to content

Commit

Permalink
Update AdButler adapter for Prebid v1.0 (prebid#1664)
Browse files Browse the repository at this point in the history
* Adding AdButler Adapter

* Prevent AdButler TypeError

Only attempt to build a bid response if we have the information of which
bid to respond to.

* Refactor AdButler Testing

Now stubbing adLoader instead of spying. Additional changes to ensure
all tests still passed.

* Prevent AdButler TypeErrors

Prevent AdButler TypeErrors and pass bid request object into the bid
response.

* Add optional domain parameter.

Add optional domain parameter to AdButler adapter.

* Update AdButler adapter to Prebid 1.0

* Code Style updates based on lint warnings.

* Removed mutable global, simplified tests, and added markdown file.

* Update c1x adapter tests & remove old adbutler_spec file.
  • Loading branch information
dharton authored and dluxemburg committed Jul 17, 2018
1 parent fb0ee40 commit 2edb25f
Show file tree
Hide file tree
Showing 4 changed files with 343 additions and 619 deletions.
229 changes: 106 additions & 123 deletions modules/adbutlerBidAdapter.js
Original file line number Diff line number Diff line change
@@ -1,130 +1,122 @@
/**
* @overview AdButler Prebid.js adapter.
* @author dkharton
*/

'use strict';

var utils = require('src/utils.js');
var adloader = require('src/adloader.js');
var bidmanager = require('src/bidmanager.js');
var bidfactory = require('src/bidfactory.js');
var adaptermanager = require('src/adaptermanager');

var AdButlerAdapter = function AdButlerAdapter() {
function _callBids(params) {
var bids = params.bids || [];
var callbackData = {};
var zoneCount = {};
var pageID = Math.floor(Math.random() * 10e6);

// Build and send bid requests
for (var i = 0; i < bids.length; i++) {
var bid = bids[i];
var zoneID = utils.getBidIdParameter('zoneID', bid.params);
var callbackID;

if (!(zoneID in zoneCount)) {
zoneCount[zoneID] = 0;
import * as utils from 'src/utils';
import {config} from 'src/config';
import {registerBidder} from 'src/adapters/bidderFactory';

const BIDDER_CODE = 'adbutler';

export const spec = {
code: BIDDER_CODE,
pageID: Math.floor(Math.random() * 10e6),

isBidRequestValid: function (bid) {
return !!(bid.params.accountID && bid.params.zoneID);
},

buildRequests: function (validBidRequests) {
var i;
var zoneID;
var bidRequest;
var accountID;
var keyword;
var domain;
var requestURI;
var serverRequests = [];
var zoneCounters = {};

for (i = 0; i < validBidRequests.length; i++) {
bidRequest = validBidRequests[i];
zoneID = utils.getBidIdParameter('zoneID', bidRequest.params);
accountID = utils.getBidIdParameter('accountID', bidRequest.params);
keyword = utils.getBidIdParameter('keyword', bidRequest.params);
domain = utils.getBidIdParameter('domain', bidRequest.params);

if (!(zoneID in zoneCounters)) {
zoneCounters[zoneID] = 0;
}

// build callbackID to get placementCode later
callbackID = zoneID + '_' + zoneCount[zoneID];
if (typeof domain === 'undefined' || domain.length === 0) {
domain = 'servedbyadbutler.com';
}

callbackData[callbackID] = {};
callbackData[callbackID].bidId = bid.bidId;
requestURI = location.protocol + '//' + domain + '/adserve/;type=hbr;';
requestURI += 'ID=' + encodeURIComponent(accountID) + ';';
requestURI += 'setID=' + encodeURIComponent(zoneID) + ';';
requestURI += 'pid=' + encodeURIComponent(spec.pageID) + ';';
requestURI += 'place=' + encodeURIComponent(zoneCounters[zoneID]) + ';';

var adRequest = buildRequest(bid, zoneCount[zoneID], pageID);
zoneCount[zoneID]++;
// append the keyword for targeting if one was passed in
if (keyword !== '') {
requestURI += 'kw=' + encodeURIComponent(keyword) + ';';
}

adloader.loadScript(adRequest);
zoneCounters[zoneID]++;
serverRequests.push({
method: 'GET',
url: requestURI,
data: {},
bidRequest: bidRequest
});
}
return serverRequests;
},

interpretResponse: function (serverResponse, bidRequest) {
var bidObj = bidRequest.bidRequest;
var bidResponses = [];
var bidResponse = {};
var isCorrectSize = false;
var isCorrectCPM = true;
var CPM;
var minCPM;
var maxCPM;
var width;
var height;

if (serverResponse && serverResponse.status === 'SUCCESS' && bidObj) {
CPM = serverResponse.cpm;
minCPM = utils.getBidIdParameter('minCPM', bidObj.params);
maxCPM = utils.getBidIdParameter('maxCPM', bidObj.params);
width = parseInt(serverResponse.width);
height = parseInt(serverResponse.height);

// Ensure response CPM is within the given bounds
if (minCPM !== '' && CPM < parseFloat(minCPM)) {
isCorrectCPM = false;
}
if (maxCPM !== '' && CPM > parseFloat(maxCPM)) {
isCorrectCPM = false;
}

// Define callback function for bid responses
$$PREBID_GLOBAL$$.adbutlerCB = function(aBResponseObject) {
var bidResponse = {};
var callbackID = aBResponseObject.zone_id + '_' + aBResponseObject.place;
var width = parseInt(aBResponseObject.width);
var height = parseInt(aBResponseObject.height);
var isCorrectSize = false;
var isCorrectCPM = true;
var CPM;
var minCPM;
var maxCPM;
var bidObj = callbackData[callbackID] ? utils.getBidRequest(callbackData[callbackID].bidId) : null;

if (bidObj) {
if (aBResponseObject.status === 'SUCCESS') {
CPM = aBResponseObject.cpm;
minCPM = utils.getBidIdParameter('minCPM', bidObj.params);
maxCPM = utils.getBidIdParameter('maxCPM', bidObj.params);

// Ensure response CPM is within the given bounds
if (minCPM !== '' && CPM < parseFloat(minCPM)) {
isCorrectCPM = false;
}
if (maxCPM !== '' && CPM > parseFloat(maxCPM)) {
isCorrectCPM = false;
}

// Ensure that response ad matches one of the placement sizes.
utils._each(bidObj.sizes, function(size) {
if (width === size[0] && height === size[1]) {
isCorrectSize = true;
}
});

if (isCorrectCPM && isCorrectSize) {
bidResponse = bidfactory.createBid(1, bidObj);
bidResponse.bidderCode = 'adbutler';
bidResponse.cpm = CPM;
bidResponse.width = width;
bidResponse.height = height;
bidResponse.ad = aBResponseObject.ad_code;
bidResponse.ad += addTrackingPixels(aBResponseObject.tracking_pixels);
} else {
bidResponse = bidfactory.createBid(2, bidObj);
bidResponse.bidderCode = 'adbutler';
}
} else {
bidResponse = bidfactory.createBid(2, bidObj);
bidResponse.bidderCode = 'adbutler';
// Ensure that response ad matches one of the placement sizes.
utils._each(bidObj.sizes, function (size) {
if (width === size[0] && height === size[1]) {
isCorrectSize = true;
}

bidmanager.addBidResponse(bidObj.placementCode, bidResponse);
});
if (isCorrectCPM && isCorrectSize) {
bidResponse.requestId = bidObj.bidId;
bidResponse.bidderCode = spec.code;
bidResponse.creativeId = serverResponse.placement_id;
bidResponse.cpm = CPM;
bidResponse.width = width;
bidResponse.height = height;
bidResponse.ad = serverResponse.ad_code;
bidResponse.ad += spec.addTrackingPixels(serverResponse.tracking_pixels);
bidResponse.currency = 'USD';
bidResponse.netRevenue = true;
bidResponse.ttl = config.getConfig('_bidderTimeout');
bidResponse.referrer = utils.getTopWindowUrl();
bidResponses.push(bidResponse);
}
};
}

function buildRequest(bid, adIndex, pageID) {
var accountID = utils.getBidIdParameter('accountID', bid.params);
var zoneID = utils.getBidIdParameter('zoneID', bid.params);
var keyword = utils.getBidIdParameter('keyword', bid.params);
var domain = utils.getBidIdParameter('domain', bid.params);

if (typeof domain === 'undefined' || domain.length === 0) {
domain = 'servedbyadbutler.com';
}
return bidResponses;
},

var requestURI = location.protocol + '//' + domain + '/adserve/;type=hbr;';
requestURI += 'ID=' + encodeURIComponent(accountID) + ';';
requestURI += 'setID=' + encodeURIComponent(zoneID) + ';';
requestURI += 'pid=' + encodeURIComponent(pageID) + ';';
requestURI += 'place=' + encodeURIComponent(adIndex) + ';';

// append the keyword for targeting if one was passed in
if (keyword !== '') {
requestURI += 'kw=' + encodeURIComponent(keyword) + ';';
}
requestURI += 'jsonpfunc=$$PREBID_GLOBAL$$.adbutlerCB;';
requestURI += 'click=CLICK_MACRO_PLACEHOLDER';

return requestURI;
}

function addTrackingPixels(trackingPixels) {
addTrackingPixels: function (trackingPixels) {
var trackingPixelMarkup = '';
utils._each(trackingPixels, function(pixelURL) {
utils._each(trackingPixels, function (pixelURL) {
var trackingPixel = '<img height="0" width="0" border="0" style="display:none;" src="';
trackingPixel += pixelURL;
trackingPixel += '">';
Expand All @@ -133,14 +125,5 @@ var AdButlerAdapter = function AdButlerAdapter() {
});
return trackingPixelMarkup;
}

// Export the callBids function, so that prebid.js can execute this function
// when the page asks to send out bid requests.
return {
callBids: _callBids
};
};

adaptermanager.registerBidAdapter(new AdButlerAdapter(), 'adbutler');

module.exports = AdButlerAdapter;
registerBidder(spec);
31 changes: 31 additions & 0 deletions modules/adbutlerBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Overview

**Module Name**: AdButler Bidder Adapter
**Module Type**: Bidder Adapter
**Maintainer**: dan@sparklit.com

# Description

Module that connects to an AdButler zone to fetch bids.

# Test Parameters
```
var adUnits = [
{
code: 'display-div',
sizes: [[300, 250]], // a display size
bids: [
{
bidder: "adbutler",
params: {
accountID: '167283',
zoneID: '210093',
keyword: 'red', //optional
minCPM: '1.00', //optional
maxCPM: '5.00' //optional
}
}
]
}
];
```
Loading

0 comments on commit 2edb25f

Please sign in to comment.