-
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
Initial checkin of RhythmOne bidder adapter and unit tests #657
Merged
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
9b30ce0
initial checkin of rhythmone prebid adapter and unit tests
jstocker76 e1f85e6
fixing unit tests
jstocker76 5583c14
removing check of deprecated property
jstocker76 ca77a51
reintroducing cpm check to unit tests
jstocker76 3eb847e
changing direct use of pbjs to the $$PREBID_GLOBAL$$ build macro
jstocker76 0e9e49d
prebid feedback implemented, aviv's GA logging added
jstocker76 9e7449e
altered timeout tracking logic and updated unit tests
jstocker76 a9ed8a0
additional unit test updates
jstocker76 b797e44
Altered rhythmone bid adapter to support either a single get or post …
jstocker76 b0272e0
found another use of top without window. Fixed
jstocker76 685689a
Removed ORTB macros dependent on the use of getBidResponses
jstocker76 19e1003
removing copyright, commented ga code, and used a constant for bid st…
jstocker76 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
"piximedia", | ||
"pubmatic", | ||
"pulsepoint", | ||
"rhythmone", | ||
"rubicon", | ||
"sekindo", | ||
"sonobi", | ||
|
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,343 @@ | ||
var bidmanager = require('../bidmanager.js'), | ||
bidfactory = require('../bidfactory.js'), | ||
utils = require('../utils.js'), | ||
CONSTANTS = require('../constants.json'); | ||
|
||
import {ajax as ajax} from '../ajax'; | ||
|
||
function track(debug, p1, p2, p3) { | ||
if(debug === true){ | ||
console.log('GA: %s %s %s', p1, p2, p3 || ''); | ||
} | ||
} | ||
|
||
var w = (typeof window !== "undefined" ? window : {}); | ||
w.trackR1Impression = track; | ||
|
||
module.exports = function(bidManager, global, loader){ | ||
|
||
var version = "0.9.0.0", | ||
defaultZone = "1r", | ||
defaultPath = "mvo", | ||
bidfloor = 0, | ||
currency = "USD", | ||
debug = false, | ||
auctionEnded = false, | ||
requestCompleted = false, | ||
placementCodes = {}; | ||
|
||
if(typeof global === "undefined") | ||
global = window; | ||
|
||
if(typeof bidManager === "undefined") | ||
bidManager = bidmanager; | ||
|
||
if(typeof loader === "undefined") | ||
loader = ajax; | ||
|
||
function applyMacros(txt, values){ | ||
return txt.replace(/\{([^\}]+)\}/g, function(match){ | ||
var v = values[match.replace(/[\{\}]/g, "").toLowerCase()]; | ||
if(typeof v !== "undefined") return v; | ||
return match; | ||
}); | ||
} | ||
|
||
function load(bidParams, url, postData, callback){ | ||
if(bidParams.method === "get"){ | ||
loader(url, function(responseText, response){ | ||
if(response.status === 200) | ||
callback(200, "success", response.responseText); | ||
else | ||
callback(-1, "http error "+response.status, response.responseText); | ||
}, false, {method:"GET"}); | ||
} | ||
else{ | ||
loader(url, function(responseText, response){ | ||
if(response.status === 200) | ||
callback(200, "success", response.responseText); | ||
else | ||
callback(-1, "http error "+response.status, response.responseText); | ||
}, postData, {method:"POST", contentType: "application/json"}); | ||
} | ||
} | ||
|
||
var bidderCode = "rhythmone", | ||
bidLostTimeout = null; | ||
|
||
function setIfPresent(o, key, value){ | ||
try{ | ||
if(typeof value === "function") | ||
o[key] = value(); | ||
}catch(ex){} | ||
} | ||
|
||
function logToConsole(txt){ | ||
if(debug) | ||
console.log(txt); | ||
} | ||
|
||
function sniffAuctionEnd(){ | ||
|
||
global.$$PREBID_GLOBAL$$.onEvent('bidWon', function (e) { | ||
|
||
if(e.bidderCode === bidderCode){ | ||
placementCodes[e.adUnitCode] = true; | ||
track(debug, 'hb', "bidWon"); | ||
} | ||
|
||
if(auctionEnded){ | ||
clearTimeout(bidLostTimeout); | ||
bidLostTimeout = setTimeout(function(){ | ||
for(var k in placementCodes) | ||
if(placementCodes[k] === false) | ||
track(debug, 'hb', "bidLost"); | ||
}, 50); | ||
} | ||
}); | ||
|
||
global.$$PREBID_GLOBAL$$.onEvent('auctionEnd', function () { | ||
|
||
auctionEnded = true; | ||
|
||
if(requestCompleted === false) | ||
track(debug, 'hb', 'rmpReplyFail', "prebid timeout post auction"); | ||
}); | ||
} | ||
|
||
function getBidParameters(bids){ | ||
for(var i=0;i<bids.length;i++) | ||
if(typeof bids[i].params === "object" && bids[i].params.placementId) | ||
return bids[i].params; | ||
return null; | ||
} | ||
|
||
function noBids(params){ | ||
for(var i=0; i<params.bids.length; i++){ | ||
if(params.bids[i].success !== 1){ | ||
var bid = bidfactory.createBid(CONSTANTS.STATUS.NO_BID); | ||
bid.bidderCode = bidderCode; | ||
track(debug, 'hb', 'bidResponse', 0); | ||
bidmanager.addBidResponse(params.bids[i].placementCode, bid); | ||
} | ||
} | ||
} | ||
|
||
function getRMPURL(bidParams, ortbJSON, bids){ | ||
var endpoint = "//tag.1rx.io/rmp/{placementId}/0/{path}?z={zone}", | ||
query = []; | ||
|
||
if(typeof bidParams.endpoint === "string") | ||
endpoint = bidParams.endpoint; | ||
|
||
if(typeof bidParams.zone === "string") | ||
defaultZone = bidParams.zone; | ||
|
||
if(typeof bidParams.path === "string") | ||
defaultPath = bidParams.path; | ||
|
||
if(bidParams.debug === true) | ||
debug = true; | ||
|
||
if(bidParams.trace === true) | ||
query.push("trace=true"); | ||
|
||
endpoint = applyMacros(endpoint, { | ||
placementid:bidParams.placementId, | ||
zone: defaultZone, | ||
path: defaultPath | ||
}); | ||
|
||
function p(k,v){ | ||
if(typeof v !== "undefined") | ||
query.push(encodeURIComponent(k)+"="+encodeURIComponent(v)); | ||
} | ||
|
||
if(bidParams.method === "get"){ | ||
|
||
p("domain", ortbJSON.site.domain); | ||
p("title", ortbJSON.site.name); | ||
p("url", ortbJSON.site.page); | ||
p("dsh", ortbJSON.device.h); | ||
p("dsw", ortbJSON.device.w); | ||
p("tz", (new Date()).getTimezoneOffset()); | ||
p("dtype", ortbJSON.device.devicetype); | ||
|
||
var placementCodes = [], | ||
heights = [], | ||
widths = [], | ||
floors = []; | ||
|
||
for(var i = 0; i<bids.length; i++){ | ||
|
||
track(debug, 'hb', 'bidRequest'); | ||
var th = [], tw = []; | ||
|
||
for(var j = 0; j<bids[i].sizes.length; j++){ | ||
tw.push(bids[i].sizes[j][0]); | ||
th.push(bids[i].sizes[j][1]); | ||
} | ||
placementCodes.push(bids[i].placementCode); | ||
heights.push(th.join("|")); | ||
widths.push(tw.join("|")); | ||
floors.push(0); | ||
} | ||
|
||
p("imp", placementCodes.join(",")); | ||
p("w", widths.join(",")); | ||
p("h", heights.join(",")); | ||
p("floor", floors.join(",")); | ||
} | ||
|
||
endpoint += "&"+query.join("&"); | ||
|
||
return endpoint; | ||
} | ||
|
||
function getORTBJSON(bids, slotMap, bidParams){ | ||
var o = { | ||
"device": { | ||
"langauge": global.navigator.language, | ||
"dnt": (global.navigator.doNotTrack === 1 ? 1 : 0) | ||
}, | ||
"at": 2, | ||
"site": {}, | ||
"tmax": 3000, | ||
"cur": [currency], | ||
"id": utils.generateUUID(), | ||
"imp":[] | ||
}; | ||
|
||
setIfPresent(o.site, "page", function(){ | ||
var l; | ||
try{l = global.top.document.location.href.toString();} | ||
catch(ex){l = document.location.href.toString();} | ||
return l; | ||
}); | ||
setIfPresent(o.site, "domain", function(){ | ||
var d = document.location.ancestorOrigins; | ||
if(d && d.length > 0) | ||
return d[d.length-1]; | ||
return global.top.document.location.hostname; | ||
}); | ||
setIfPresent(o.site, "name", function(){return global.top.document.title;}); | ||
|
||
o.device.devicetype = ((/(ios|ipod|ipad|iphone|android)/i).test(global.navigator.userAgent) ? 1 : ((/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(global.navigator.userAgent) ? 3 : 2)); | ||
|
||
setIfPresent(o.device, "h", function(){return global.screen.height;}); | ||
setIfPresent(o.device, "w", function(){return global.screen.width;}); | ||
|
||
for(var i = 0; i<bids.length; i++){ | ||
var bidID = utils.generateUUID(); | ||
slotMap[bidID] = bids[i]; | ||
slotMap[bids[i].placementCode] = bids[i]; | ||
|
||
if(bidParams.method === "post") | ||
track(debug, 'hb', 'bidRequest'); | ||
|
||
for(var j = 0; j<bids[i].sizes.length; j++){ | ||
o.imp.push({ | ||
"id": bidID, | ||
"tagId": bids[i].placementCode, | ||
"bidfloor": bidfloor, | ||
"bidfloorcur": currency, | ||
"banner": { | ||
"id": utils.generateUUID(), | ||
"pos": 0, | ||
"w": bids[i].sizes[j][0], | ||
"h": bids[i].sizes[j][1] | ||
} | ||
}); | ||
} | ||
} | ||
|
||
return o; | ||
} | ||
|
||
this.callBids = function(params){ | ||
|
||
var slotMap = {}, | ||
bidParams = getBidParameters(params.bids); | ||
|
||
debug = (bidParams !== null && bidParams.debug === true); | ||
|
||
track(debug, 'hb', 'callBids'); | ||
|
||
if(bidParams === null){ | ||
noBids(params); | ||
track(debug, 'hb', 'misconfiguration'); | ||
return; | ||
} | ||
|
||
// default to GET request | ||
if(typeof bidParams.method !== "string") | ||
bidParams.method = "get"; | ||
|
||
bidParams.method = bidParams.method.toLowerCase(); | ||
|
||
sniffAuctionEnd(); | ||
|
||
track(debug, 'hb', 'rmpRequest'); | ||
|
||
var ortbJSON = getORTBJSON(params.bids, slotMap, bidParams); | ||
|
||
load(bidParams, getRMPURL(bidParams, ortbJSON, params.bids), JSON.stringify(ortbJSON), function(code, msg, txt){ | ||
|
||
if(auctionEnded === true) | ||
return; | ||
|
||
requestCompleted = true; | ||
|
||
logToConsole(txt); | ||
|
||
var bidCount = 0; | ||
|
||
if(code === -1) | ||
track(debug, 'hb', 'rmpReplyFail', msg); | ||
else{ | ||
try{ | ||
var result = JSON.parse(txt), | ||
registerBid = function(bid){ | ||
|
||
slotMap[bid.impid].success = 1; | ||
|
||
var pbResponse = bidfactory.createBid(CONSTANTS.STATUS.GOOD), | ||
placementCode = slotMap[bid.impid].placementCode; | ||
|
||
placementCodes[placementCode] = false; | ||
|
||
pbResponse.bidderCode = bidderCode; | ||
pbResponse.cpm = parseFloat(bid.price); | ||
pbResponse.width = bid.w; | ||
pbResponse.height = bid.h; | ||
pbResponse.ad = bid.adm; | ||
|
||
logToConsole("registering bid "+placementCode+" "+JSON.stringify(pbResponse)); | ||
|
||
track(debug, 'hb', 'bidResponse', 1); | ||
bidManager.addBidResponse(placementCode, pbResponse); | ||
bidCount++; | ||
}; | ||
|
||
track(debug, 'hb', 'rmpReplySuccess'); | ||
|
||
for(var i=0; result.seatbid && i<result.seatbid.length; i++) | ||
for(var j=0; result.seatbid[i].bid && j<result.seatbid[i].bid.length; j++) | ||
registerBid(result.seatbid[i].bid[j]); | ||
} | ||
catch(ex){ | ||
track(debug, 'hb', 'rmpReplyFail', 'invalid json in rmp response'); | ||
} | ||
} | ||
|
||
// if no bids are successful, inform prebid | ||
if(bidCount === 0) | ||
noBids(params); | ||
|
||
// when all bids are complete, log a report | ||
track(debug, 'hb', 'bidsComplete'); | ||
}); | ||
|
||
logToConsole("version: "+version); | ||
}; | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Consider adding this as a function in
utils
as it might be useful for others.