-
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
Add Sharethrough adapter #865
Changes from 12 commits
24ccb34
ea63844
10c6672
09bbd04
1f59313
9f5ca43
6283cf3
3b9328a
4664f08
aaa8acc
5d68e90
83f7765
1048b22
acf430d
699412f
fff53f1
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 |
---|---|---|
|
@@ -37,6 +37,7 @@ | |
"underdogmedia", | ||
"memeglobal", | ||
"centro", | ||
"sharethrough", | ||
"roxot", | ||
"vertoz", | ||
"widespace", | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import adapter from 'AnalyticsAdapter'; | ||
const utils = require('../../utils'); | ||
|
||
const url = 'https://httpbin.org/post'; | ||
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. You probably don't want to be sending data to |
||
const analyticsType = 'endpoint'; | ||
const STR_BIDDER_CODE = "sharethrough"; | ||
const STR_VERSION = "0.1.0"; | ||
|
||
export default utils.extend(adapter( | ||
{ | ||
url, | ||
analyticsType | ||
} | ||
), | ||
{ | ||
STR_BEACON_HOST: document.location.protocol + "//b.sharethrough.com/butler?", | ||
placementCodeSet: {}, | ||
|
||
track({ eventType, args }) { | ||
if(eventType === 'bidRequested' && args.bidderCode === 'sharethrough') { | ||
var bids = args.bids; | ||
var keys = Object.keys(bids); | ||
for(var i = 0; i < keys.length; i++) { | ||
this.placementCodeSet[bids[keys[i]].placementCode] = args.bids[keys[i]]; | ||
} | ||
} | ||
|
||
if(eventType === 'bidWon') { | ||
this.bidWon(args); | ||
} | ||
}, | ||
|
||
bidWon(args) { | ||
const curBidderCode = args.bidderCode; | ||
|
||
if(curBidderCode !== STR_BIDDER_CODE && (args.adUnitCode in this.placementCodeSet)) { | ||
let strBid = this.placementCodeSet[args.adUnitCode]; | ||
this.fireLoseBeacon(curBidderCode, args.cpm, strBid.adserverRequestId, "headerBidLose"); | ||
} | ||
}, | ||
|
||
fireLoseBeacon(winningBidderCode, winningCPM, arid, type) { | ||
let loseBeaconUrl = this.STR_BEACON_HOST; | ||
loseBeaconUrl = utils.tryAppendQueryString(loseBeaconUrl, "winnerBidderCode", winningBidderCode); | ||
loseBeaconUrl = utils.tryAppendQueryString(loseBeaconUrl, "winnerCpm", winningCPM); | ||
loseBeaconUrl = utils.tryAppendQueryString(loseBeaconUrl, "arid", arid); | ||
loseBeaconUrl = utils.tryAppendQueryString(loseBeaconUrl, "type", type); | ||
loseBeaconUrl = this.appendEnvFields(loseBeaconUrl); | ||
|
||
this.fireBeacon(loseBeaconUrl); | ||
}, | ||
appendEnvFields(url) { | ||
url = utils.tryAppendQueryString(url, 'hbVersion', '$prebid.version$'); | ||
url = utils.tryAppendQueryString(url, 'strVersion', STR_VERSION); | ||
url = utils.tryAppendQueryString(url, 'hbSource', 'prebid'); | ||
|
||
return url; | ||
}, | ||
fireBeacon(theUrl) { | ||
const img = new Image(); | ||
img.src = theUrl; | ||
} | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
var utils = require('../utils.js'); | ||
var bidmanager = require('../bidmanager.js'); | ||
var bidfactory = require('../bidfactory.js'); | ||
|
||
const STR_BIDDER_CODE = "sharethrough"; | ||
const STR_VERSION = "0.1.0"; //Need to check analytics too for version | ||
|
||
var SharethroughAdapter = function SharethroughAdapter() { | ||
|
||
const str = {}; | ||
str.STR_BTLR_HOST = document.location.protocol + "//btlr.sharethrough.com"; | ||
str.STR_TEST_HOST = document.location.protocol + "//btlr-prebid-test.sharethrough.com"; | ||
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. Using a different endpoint for test is not ideal as real issues are discovered in prod. Is there a way to not use a test endpoint here? 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. We have to use a test endpoint here to guarantee that a creative is always return from our exchange. If we used the real endpoint there's no way to guarantee that a DSP will always bid on the impression request. 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. Usually other bidders setup a test creative /placement on the live exchange. Is this possible? |
||
str.STR_BEACON_HOST = document.location.protocol + "//b.sharethrough.com/butler?"; | ||
str.placementCodeSet = {}; | ||
|
||
function _callBids(params) { | ||
const bids = params.bids; | ||
|
||
$$PREBID_GLOBAL$$.onEvent('bidWon', str.bidWon); | ||
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. This line can be removed now that you added your analytics adapter. |
||
|
||
addEventListener("message", _receiveMessage, false); | ||
|
||
// cycle through bids | ||
for (let i = 0; i < bids.length; i += 1) { | ||
const bidRequest = bids[i]; | ||
str.placementCodeSet[bidRequest.placementCode] = bidRequest; | ||
const scriptUrl = _buildSharethroughCall(bidRequest); | ||
str.loadIFrame(scriptUrl); | ||
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. Don't load JSONP inside an iframe. Use 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. We need to put the url inside an iframe so we can drop tracking cookies on publisher's page. This method work for iOS Safari since they block 3rd party cookies. 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. Ok |
||
} | ||
} | ||
|
||
function _buildSharethroughCall(bid) { | ||
const testPkey = 'test'; | ||
const pkey = utils.getBidIdParameter('pkey', bid.params); | ||
|
||
let host = (pkey === testPkey) ? str.STR_TEST_HOST : str.STR_BTLR_HOST; | ||
|
||
let url = host + "/header-bid/v1?"; | ||
url = utils.tryAppendQueryString(url, 'bidId', bid.bidId); | ||
|
||
if(pkey !== testPkey) { | ||
url = utils.tryAppendQueryString(url, 'placement_key', pkey); | ||
url = utils.tryAppendQueryString(url, 'ijson', '$$PREBID_GLOBAL$$.strcallback'); | ||
url = appendEnvFields(url); | ||
} else { | ||
url = url.substring(0, url.length - 1); | ||
} | ||
|
||
return url; | ||
} | ||
|
||
str.loadIFrame = function(url) { | ||
const iframe = document.createElement("iframe"); | ||
iframe.src = url; | ||
iframe.style.cssText = 'display:none;'; | ||
|
||
document.body.appendChild(iframe); | ||
}; | ||
|
||
function _receiveMessage(event) { | ||
if(event.origin === str.STR_BTLR_HOST || event.origin === str.STR_TEST_HOST) { | ||
try { | ||
$$PREBID_GLOBAL$$.strcallback(JSON.parse(event.data).response); | ||
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. this doesn't need to a public function because it's scoped within the adapter itself. Only use a public function if you use JSONP. |
||
} catch(e) { | ||
console.log(e); | ||
} | ||
} | ||
} | ||
|
||
$$PREBID_GLOBAL$$.strcallback = function(bidResponse) { | ||
const bidId = bidResponse.bidId; | ||
const bidObj = utils.getBidRequest(bidId); | ||
try { | ||
const bid = bidfactory.createBid(1, bidObj); | ||
|
||
bid.bidderCode = STR_BIDDER_CODE; | ||
bid.cpm = bidResponse.creatives[0].cpm; | ||
const size = bidObj.sizes[0]; | ||
bid.width = size[0]; | ||
bid.height = size[1]; | ||
bid.adserverRequestId = bidResponse.adserverRequestId; | ||
str.placementCodeSet[bidObj.placementCode].adserverRequestId = bidResponse.adserverRequestId; | ||
bid.winId = bidResponse.creatives[0].auctionWinId; | ||
|
||
bid.pkey = utils.getBidIdParameter('pkey', bidObj.params); | ||
|
||
const windowLocation = `str_response_${bidId}`; | ||
const bidJsonString = JSON.stringify(bidResponse); | ||
bid.ad = `<div data-str-native-key="${bid.pkey}" data-stx-response-name='${windowLocation}'> | ||
</div> | ||
<script>var ${windowLocation} = ${bidJsonString}</script> | ||
<script src="//native.sharethrough.com/assets/sfp-set-targeting.js"></script> | ||
<script type='text/javascript'> | ||
(function() { | ||
var sfp_js = document.createElement('script'); | ||
sfp_js.src = "//native.sharethrough.com/assets/sfp.js"; | ||
sfp_js.type = 'text/javascript'; | ||
sfp_js.charset = 'utf-8'; | ||
try { | ||
window.top.document.getElementsByTagName('body')[0].appendChild(sfp_js); | ||
} catch (e) { | ||
console.log(e); | ||
} | ||
})(); | ||
</script>`; | ||
bidmanager.addBidResponse(bidObj.placementCode, bid); | ||
} catch (e) { | ||
_handleInvalidBid(bidObj); | ||
} | ||
}; | ||
|
||
function _handleInvalidBid(bidObj) { | ||
const bid = bidfactory.createBid(2, bidObj); | ||
bidmanager.addBidResponse(bidObj.placementCode, bid); | ||
} | ||
|
||
function appendEnvFields(url) { | ||
url = utils.tryAppendQueryString(url, 'hbVersion', '$prebid.version$'); | ||
url = utils.tryAppendQueryString(url, 'strVersion', STR_VERSION); | ||
url = utils.tryAppendQueryString(url, 'hbSource', 'prebid'); | ||
|
||
return url; | ||
} | ||
|
||
return { | ||
callBids: _callBids, | ||
str : str, | ||
}; | ||
}; | ||
|
||
module.exports = SharethroughAdapter; | ||
|
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.
Analytics is explicitly turned on by the publisher so this array should be blank by default