-
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
Added adapter for Conversant Media #708
Changes from 5 commits
142f4e9
6057a4a
710c99b
8275d8e
cff5d37
fcd8d95
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 |
---|---|---|
|
@@ -7,6 +7,7 @@ | |
"aol", | ||
"appnexus", | ||
"appnexusAst", | ||
"conversant", | ||
"getintent", | ||
"hiromedia", | ||
"indexExchange", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
'use strict'; | ||
var VERSION = '2.0.0', | ||
CONSTANTS = require('../constants.json'), | ||
utils = require('../utils.js'), | ||
bidfactory = require('../bidfactory.js'), | ||
bidmanager = require('../bidmanager.js'), | ||
adloader = require('../adloader'); | ||
|
||
/** | ||
* Adapter for requesting bids from Conversant | ||
*/ | ||
var ConversantAdapter = function () { | ||
var w = window, | ||
n = navigator; | ||
|
||
// production endpoint | ||
var conversantUrl = '//media.msg.dotomi.com/s2s/header?callback=$$PREBID_GLOBAL$$.conversantResponse'; | ||
|
||
// SSAPI returns JSONP with window.pbjs.conversantResponse as the cb | ||
var appendScript = function (code) { | ||
var script = document.createElement('script'); | ||
script.type = 'text/javascript'; | ||
script.className = 'cnvr-response'; | ||
|
||
try { | ||
script.appendChild(document.createTextNode(code)); | ||
document.getElementsByTagName('head')[0].appendChild(script); | ||
} catch (e) { | ||
script.text = code; | ||
document.getElementsByTagName('head')[0].appendChild(script); | ||
} | ||
}; | ||
|
||
var httpPOSTAsync = function (url, data) { | ||
var xmlHttp = new w.XMLHttpRequest(); | ||
|
||
xmlHttp.onload = function () { | ||
appendScript(xmlHttp.responseText); | ||
}; | ||
xmlHttp.open('POST', url, true); // true for asynchronous | ||
xmlHttp.withCredentials = true; | ||
xmlHttp.send(data); | ||
}; | ||
|
||
var getDNT = function () { | ||
return n.doNotTrack === '1' || w.doNotTrack === '1' || n.msDoNotTrack === '1' || n.doNotTrack === 'yes'; | ||
}; | ||
|
||
var getDevice = function () { | ||
return { | ||
h: screen.height, | ||
w: screen.width, | ||
dnt: getDNT() ? 1 : 0, | ||
language: n.language.split('-')[0], | ||
make: n.vendor ? n.vendor : '', | ||
ua: n.userAgent | ||
}; | ||
}; | ||
|
||
var callBids = function (params) { | ||
var conversantBids = params.bids || []; | ||
requestBids(conversantBids); | ||
}; | ||
|
||
var requestBids = function (bidReqs) { | ||
// build bid request object | ||
var page = location.pathname + location.search + location.hash, | ||
siteId = '', | ||
conversantImps = [], | ||
conversantBidReqs, | ||
secure = 0; | ||
|
||
//build impression array for conversant | ||
utils._each(bidReqs, function (bid) { | ||
var bidfloor = utils.getBidIdParamater('bidloor', bid.params), | ||
sizeArrayLength = bid.sizes.length, | ||
adW = 0, | ||
adH = 0, | ||
imp; | ||
|
||
secure = utils.getBidIdParamater('secure', bid.params) ? 1 : secure; | ||
siteId = utils.getBidIdParamater('site_id', bid.params); | ||
|
||
if (sizeArrayLength === 2 && typeof bid.sizes[0] === 'number' && typeof bid.sizes[1] === 'number') { | ||
adW = bid.sizes[0]; | ||
adH = bid.sizes[1]; | ||
} else { | ||
adW = bid.sizes[0][0]; | ||
adH = bid.sizes[0][1]; | ||
} | ||
|
||
imp = { | ||
id: bid.bidId, | ||
banner: { | ||
w: adW, | ||
h: adH | ||
}, | ||
secure: secure, | ||
bidfloor: bidfloor ? bidfloor : 0, | ||
displaymanager: 'Prebid.js', | ||
displaymanagerver: VERSION | ||
}; | ||
|
||
conversantImps.push(imp); | ||
}); | ||
|
||
conversantBidReqs = { | ||
'id': utils.getUniqueIdentifierStr(), | ||
'imp': conversantImps, | ||
|
||
'site': { | ||
'id': siteId, | ||
'mobile': document.querySelector('meta[name="viewport"][content*="width=device-width"]') !== null ? 1 : 0, | ||
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. is the presence of this meta tag a reliable way to detect mobile clients? Our responsive site at washingtonian.com includes this meta tag for everyone. 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. The mobile field is there to determine if the site's layout can be optimized when on mobile clients. Not necessarily that they are mobile 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 see, thank you @msahagu2! 👍 |
||
'page': page | ||
}, | ||
|
||
'device': getDevice(), | ||
'at': 1 | ||
}; | ||
|
||
var url = secure ? 'https:' + conversantUrl : location.protocol + conversantUrl; | ||
httpPOSTAsync(url, JSON.stringify(conversantBidReqs)); | ||
}; | ||
|
||
var addEmptyBidResponses = function (placementsWithBidsBack) { | ||
var allConversantBidRequests = $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === 'conversant'); | ||
|
||
if (allConversantBidRequests && allConversantBidRequests.bids){ | ||
utils._each(allConversantBidRequests.bids, function (conversantBid) { | ||
if (!utils.contains(placementsWithBidsBack, conversantBid.placementCode)) { | ||
// Add a no-bid response for this placement. | ||
var bid = bidfactory.createBid(2, conversantBid); | ||
bid.bidderCode = 'conversant'; | ||
bidmanager.addBidResponse(conversantBid.placementCode, bid); | ||
} | ||
}); | ||
} | ||
}; | ||
|
||
var parseSeatbid = function (bidResponse) { | ||
var placementsWithBidsBack = []; | ||
utils._each(bidResponse.bid, function (conversantBid) { | ||
var responseCPM, | ||
placementCode = '', | ||
id = conversantBid.impid, | ||
bid = {}, | ||
responseAd, | ||
responseNurl, | ||
sizeArrayLength; | ||
|
||
// Bid request we sent Conversant | ||
var bidRequested = $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === 'conversant').bids.find(bid => bid.bidId === id); | ||
|
||
if (bidRequested) { | ||
placementCode = bidRequested.placementCode; | ||
placementsWithBidsBack.push(placementCode); | ||
bidRequested.status = CONSTANTS.STATUS.GOOD; | ||
|
||
responseCPM = parseFloat(conversantBid.price); | ||
|
||
if (responseCPM !== 0.0) { | ||
conversantBid.placementCode = placementCode; | ||
conversantBid.size = bidRequested.sizes; | ||
responseAd = conversantBid.adm || ''; | ||
responseNurl = conversantBid.nurl || ''; | ||
|
||
// Our bid! | ||
bid = bidfactory.createBid(1); | ||
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. pass the bid object as 2nd argument to sync bid request and response IDs. See #509 |
||
bid.creative_id = conversantBid.id || ''; | ||
bid.bidderCode = 'conversant'; | ||
|
||
bid.cpm = responseCPM; | ||
|
||
// Track impression image onto returned html | ||
bid.ad = responseAd + '<img src=\"' + responseNurl + '\" />'; | ||
|
||
sizeArrayLength = bidRequested.sizes.length; | ||
if (sizeArrayLength === 2 && typeof bidRequested.sizes[0] === 'number' && typeof bidRequested.sizes[1] === 'number') { | ||
bid.width = bidRequested.sizes[0]; | ||
bid.height = bidRequested.sizes[1]; | ||
} else { | ||
bid.width = bidRequested.sizes[0][0]; | ||
bid.height = bidRequested.sizes[0][1]; | ||
} | ||
|
||
bidmanager.addBidResponse(placementCode, bid); | ||
} else { | ||
//0 price bid | ||
//indicate that there is no bid for this placement | ||
bid = bidfactory.createBid(2); | ||
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. pass the bid object as 2nd argument to sync bid request and response IDs. See #509 |
||
bid.bidderCode = 'conversant'; | ||
bidmanager.addBidResponse(placementCode, bid); | ||
} | ||
} | ||
}); | ||
addEmptyBidResponses(placementsWithBidsBack); | ||
}; | ||
|
||
// Register our callback to the global object: | ||
$$PREBID_GLOBAL$$.conversantResponse = function (conversantResponseObj, path) { | ||
// valid object? | ||
if (conversantResponseObj && conversantResponseObj.id) { | ||
if (conversantResponseObj.seatbid && conversantResponseObj.seatbid.length > 0 && conversantResponseObj.seatbid[0].bid && conversantResponseObj.seatbid[0].bid.length > 0) { | ||
utils._each(conversantResponseObj.seatbid, parseSeatbid); | ||
} else { | ||
//no response data for any placements | ||
addEmptyBidResponses([]); | ||
} | ||
} else { | ||
//no response data for any placements | ||
addEmptyBidResponses([]); | ||
} | ||
// for debugging purposes | ||
if (path){ | ||
adloader.loadScript(path, function () { | ||
var allConversantBidRequests = $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === 'conversant'); | ||
|
||
if ($$PREBID_GLOBAL$$.conversantDebugResponse){ | ||
$$PREBID_GLOBAL$$.conversantDebugResponse(allConversantBidRequests); | ||
} | ||
}); | ||
} | ||
}; // conversantResponse | ||
|
||
return { | ||
callBids: callBids | ||
}; | ||
}; | ||
|
||
module.exports = ConversantAdapter; |
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.
@msahagu2 can you request an
Access-Control-Allow-Origin: *
header for this endpoint?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.
Do you know what ad sizes are requested? We're currently working on a fix for the headers of our 204 responses
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.
I am told by T. Rex at Conversant that the site_id numeric value must be passed as a string (buh?) so can you catch this case in the adapter @msahagu2