-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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 AdButler adapter for Prebid v1.0 #1664
Changes from 24 commits
771b74c
45919de
5e72aac
10ab721
38ad684
79e7045
7fe5aa1
1cf22f4
eca8d59
252ffac
add7a75
35b8180
2cdc25b
f4cac5d
c0ef919
8f85d45
1d4480a
4efc579
42b3c41
28df88d
5cc58bf
cdea438
09804e4
0117275
5af952b
7ef0341
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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), | ||
zoneCounters: {}, | ||
|
||
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 = []; | ||
|
||
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 spec.zoneCounters)) { | ||
spec.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(spec.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); | ||
spec.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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adapters shouldn't add tracking pixels during the auction anymore. Implement getUserSyncs instead. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the info @dbemiller. We offer our customers the option to track impressions on the client-side. If they've chosen this, their impression pixel would have been added here. Just to verify, if the publisher has userSync disabled, this means there is a chance their impression wouldn't be counted in this way. Is that correct? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct. Since tracking pixels affect the publisher's page performance, the prebid leadership decided that they should have the ultimate decision in whether or not to allow them. That said, most publishers leave the default options... so it's not likely to impact you too much. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I understand the desire to improve publisher page performance. My only concern is that when all syncs are blocked, the winning bidder will not have any way to know that they have won a particular auction. Is there any way for us to provide Prebid with a URL that can be pinged or placed if our bid has won the auction? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there might be some confusion here. It's acceptable to add a tracking pixel to a bid response. This will only fire if the bid wins the auction. I think that's what this is so should be fine. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, thanks for the clarification. Yeah, this function just appends the tracking pixel(s) to the ad code in the bid response. |
||
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 += '">'; | ||
|
@@ -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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No mutable globals allowed... see the 1.0 conventions.
Can this be moved inside your
buildRequests
function?