forked from prebid/Prebid.js
-
Notifications
You must be signed in to change notification settings - Fork 1
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
[Internal Code Review] C1X adapter for Prebid v1.0 #3
Closed
Closed
Changes from 17 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
d098a36
add markdown file which includes sample info about our adapter
CathyHuangtw 5fff98d
c1x adapter template + add some to-dos
CathyHuangtw 851ee40
c1x adapter's unit tests template
CathyHuangtw f608158
add .isBidRequestValid() & .buildRequests()
CathyHuangtw e75547f
generate the correct query string for the GET request to c1x bidder
CathyHuangtw 70e8d09
use .getUserSync( ) to register pixels
CathyHuangtw df776bc
use new endpoint for testing
CathyHuangtw f66d428
adding new test cases
CathyHuangtw 5f01516
add floor price mapping for bid requests
CathyHuangtw b382783
add .interpretResponse() and c1x log msg
CathyHuangtw f3d590b
test page
CathyHuangtw 81379f8
use siteId/ pixelId in ad units
CathyHuangtw 180a8b7
update test cases
CathyHuangtw 513154b
fix bug when printing no siteId log
CathyHuangtw d1697f6
update unit tests for .buildRequests() in adapter
CathyHuangtw c3c6e94
add unit test for .interpretBidResponse( )
CathyHuangtw 59c1207
update the test page for testing the current adapter code
CathyHuangtw a02571a
check netRevenue is net or gross; remove logs
CathyHuangtw f0bf779
provide example test unit
CathyHuangtw 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 |
---|---|---|
@@ -0,0 +1,192 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>Prebid.js integration example</title> | ||
<script> | ||
var PREBID_TIMEOUT = 8000; | ||
var MAX_RETRIES = 20; | ||
|
||
var googletag = googletag || {}; | ||
googletag.cmd = googletag.cmd || []; | ||
googletag.cmd.push(function () { | ||
googletag.pubads().disableInitialLoad(); | ||
}); | ||
|
||
var pbjs = pbjs || {}; | ||
pbjs.cmd = pbjs.cmd || []; | ||
pbjs.retries = 0; | ||
|
||
/* pbjs.initAdserver will be called either when all bids are back, or | ||
when the timeout is reached. | ||
*/ | ||
function initAdserver() { | ||
if (pbjs.initAdserverSet) return; | ||
if(!googletag.pubadsReady && pbjs.retries <= MAX_RETRIES) { | ||
setTimeout(initAdserver, 500); //poll ms can be adjusted as desired. | ||
pbjs.retries++; | ||
return; | ||
} | ||
googletag.cmd.push(function () { | ||
pbjs.cmd.push(function () { | ||
pbjs.setTargetingForGPTAsync(); | ||
}); | ||
googletag.pubads().refresh(); | ||
}); | ||
pbjs.initAdserverSet = true; | ||
} | ||
|
||
// Load GPT when timeout is reached. | ||
setTimeout(initAdserver, PREBID_TIMEOUT); | ||
|
||
// Load the Prebid Javascript Library Async. We recommend loading it immediately after the initAdserver() and setTimeout functions. | ||
(function() { | ||
var d = document, pbs = d.createElement('script'), pro = d.location.protocol; | ||
pbs.type = 'text/javascript'; | ||
pbs.src = '../../build/dev/prebid.js'; | ||
var target = document.getElementsByTagName('head')[0]; | ||
target.insertBefore(pbs, target.firstChild); | ||
})(); | ||
|
||
//load GPT library here | ||
(function () { | ||
var gads = document.createElement('script'); | ||
gads.async = true; | ||
gads.type = 'text/javascript'; | ||
var useSSL = 'https:' == document.location.protocol; | ||
gads.src = (useSSL ? 'https:' : 'http:') + | ||
'//www.googletagservices.com/tag/js/gpt.js'; | ||
var node = document.getElementsByTagName('script')[0]; | ||
node.parentNode.insertBefore(gads, node); | ||
})(); | ||
|
||
pbjs.cmd.push(function () { | ||
|
||
/* 1. Register bidder tag Ids | ||
|
||
Registers the bidder tags for your ad units. Once the prebid.js | ||
library loads, it reads the pbjs.adUnits object and sends out | ||
bid requests. | ||
|
||
code: Your GPT slot’s ad unit path. If they don’t match, prebid.js | ||
would not be able to set targeting correctly | ||
sizes: All sizes your ad unit accepts. They should match with GPT. | ||
*/ | ||
var adUnits = [ | ||
{ | ||
code: 'div-gpt-ad-1498193081995-0', | ||
sizes: [[300, 600], [300, 250]], | ||
bids: [ | ||
// 1 ad unit can be targeted by multiple bids. | ||
{ | ||
bidder: 'c1x', | ||
params: { | ||
siteId: '9999', | ||
pixelId: '12345', | ||
floorPriceMap: { | ||
'300x250': 0.20, | ||
'300x600': 0.30 | ||
}, //optional | ||
} | ||
} | ||
] | ||
}, | ||
{ | ||
code: 'div-gpt-ad-test', | ||
sizes: [[300, 600]], | ||
bids: [ | ||
// 1 ad unit can be targeted by multiple bids. | ||
{ | ||
bidder: 'c1x', | ||
params: { | ||
siteId: '9999', | ||
placementID: "234234", | ||
floorPriceMap: { | ||
'300x600': 0.40 | ||
} | ||
} | ||
} | ||
] | ||
}, | ||
]; | ||
|
||
//add the adUnits | ||
pbjs.addAdUnits(adUnits); | ||
|
||
//register a callback handler | ||
pbjs.onEvent('bidResponse', function (bidResponse) { | ||
console.log('A bid response has arrived:'); | ||
}); | ||
|
||
/* Configure Ad Server Targeting | ||
The below section defines what key value targeting will be sent to GPT. | ||
*/ | ||
pbjs.bidderSettings = { | ||
standard: { | ||
adserverTargeting: [ | ||
{ | ||
key: "hb_bidder", | ||
val: function (bidResponse) { | ||
return bidResponse.bidderCode; | ||
} | ||
}, { | ||
key: "hb_adid", | ||
val: function (bidResponse) { | ||
return bidResponse.adId; | ||
} | ||
}, { | ||
key: "hb_pb", | ||
val: function (bidResponse) { | ||
return bidResponse.pbMg; | ||
} | ||
}, { | ||
key: 'hb_size', | ||
val: function (bidResponse) { | ||
return bidResponse.size; | ||
} | ||
} | ||
] | ||
} | ||
}; | ||
|
||
|
||
/* Request bids for the added ad units. If adUnits or adUnitCodes are | ||
not specified, the function will request bids for all added ad units. | ||
*/ | ||
pbjs.requestBids({ | ||
|
||
/* The bidsBack function will be called when either timeout is | ||
reached, or when all bids come back, whichever happens sooner. | ||
*/ | ||
bidsBackHandler: function (bidResponses) { | ||
// c1x.logs.push([new Date().getTime(), 'Bids back handler called.']); | ||
console.log('all the bid responses are back'); | ||
console.log(bidResponses); | ||
initAdserver(); | ||
} | ||
}); | ||
|
||
}); | ||
|
||
googletag.cmd.push(function() { | ||
googletag.defineSlot('/188708772/cathy-test-unit', [[300, 250], [300, 600]], 'div-gpt-ad-1498193081995-0').addService(googletag.pubads()); | ||
googletag.pubads().enableSingleRequest(); | ||
googletag.enableServices(); | ||
}); | ||
|
||
</script> | ||
|
||
</head> | ||
<body> | ||
|
||
<h2>Prebid.js Test</h2> | ||
|
||
<!-- /188708772/cathy-test-unit --> | ||
<div id='div-gpt-ad-1498193081995-0'> | ||
<script type='text/javascript'> | ||
googletag.cmd.push(function() { googletag.display('div-gpt-ad-1498193081995-0'); }); | ||
</script> | ||
</div> | ||
|
||
</body> | ||
|
||
</html> |
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,165 @@ | ||
// import CONSTANTS from 'src/constants.json'; | ||
import { registerBidder } from 'src/adapters/bidderFactory'; | ||
import * as utils from 'src/utils'; | ||
import { userSync } from 'src/userSync'; | ||
|
||
const BIDDER_CODE = 'c1x'; | ||
const URL = 'http://13.58.47.152:8080/ht'; | ||
const PIXEL_ENDPOINT = '//px.c1exchange.com/pubpixel/'; | ||
const LOG_MSG = { | ||
invalidBid: 'C1X: [ERROR] bidder returns an invalid bid', | ||
noSite: 'C1X: [ERROR] no site id supplied', | ||
noBid: 'C1X: [INFO] creating a NO bid for Adunit: ', | ||
bidWin: 'C1X: [INFO] creating a bid for Adunit: ' | ||
}; | ||
|
||
/** | ||
* Adapter for requesting bids from C1X header tag server. | ||
* v3.0 (c) C1X Inc., 2017 | ||
*/ | ||
|
||
export const c1xAdapter = { | ||
code: BIDDER_CODE, | ||
|
||
// check the bids sent to c1x bidder | ||
isBidRequestValid: function(bid) { | ||
const siteId = bid.params.siteId || ''; | ||
if (!siteId) { | ||
utils.logError(LOG_MSG.noSite); | ||
} | ||
return !!(bid.adUnitCode && siteId); | ||
}, | ||
|
||
buildRequests: function(bidRequests) { | ||
let payload = {}; | ||
let tagObj = {}; | ||
const adunits = bidRequests.length; | ||
const rnd = new Date().getTime(); | ||
const c1xTags = bidRequests.map(bidToTag); | ||
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. bidToTag is defined? |
||
const bidIdTags = bidRequests.map(bidToShortTag); // include only adUnitCode and bidId from request obj | ||
|
||
// flattened tags in a tag object | ||
tagObj = c1xTags.reduce((current, next) => Object.assign(current, next)); | ||
const pixelId = tagObj.pixelId; | ||
const useSSL = document.location.protocol; | ||
|
||
payload = { | ||
adunits: adunits.toString(), | ||
rnd: rnd.toString(), | ||
response: 'json', | ||
compress: 'gzip' | ||
} | ||
Object.assign(payload, tagObj); | ||
|
||
let payloadString = stringifyPayload(payload); | ||
|
||
if (pixelId) { | ||
const pixelUrl = (useSSL ? 'https:' : 'http:') + PIXEL_ENDPOINT + pixelId; | ||
userSync.registerSync('image', BIDDER_CODE, pixelUrl); | ||
} | ||
|
||
// ServerRequest object | ||
return { | ||
method: 'GET', | ||
url: URL, | ||
data: payloadString, | ||
bids: bidIdTags | ||
}; | ||
}, | ||
|
||
interpretResponse: function(serverResponse, requests) { | ||
serverResponse = serverResponse.body; | ||
requests = requests.bids || []; | ||
const currency = 'USD'; | ||
const bidResponses = []; | ||
|
||
if (!serverResponse || serverResponse.error) { | ||
let errorMessage = serverResponse.error; | ||
utils.logError(LOG_MSG.invalidBid + errorMessage); | ||
return bidResponses; | ||
} else { | ||
console.log(serverResponse); | ||
serverResponse.forEach(bid => { | ||
if (bid.bid) { | ||
const curBid = { | ||
width: bid.width, | ||
height: bid.height, | ||
cpm: bid.cpm, | ||
ad: bid.ad, | ||
creativeId: bid.crid, | ||
currency: currency, | ||
ttl: 300, | ||
netRevenue: false, // net or gross? | ||
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. Net / Gross both are same for Prebid. |
||
}; | ||
|
||
for (let i = 0; i < requests.length; i++) { | ||
if (bid.adId === requests[i].adUnitCode) { | ||
curBid.requestId = requests[i].bidId; | ||
} | ||
} | ||
utils.logInfo(LOG_MSG.bidWin + bid.adId + ' size: ' + curBid.width + 'x' + curBid.height); | ||
bidResponses.push(curBid); | ||
} else { | ||
// no bid | ||
utils.logInfo(LOG_MSG.noBid + bid.adId); | ||
} | ||
}); | ||
} | ||
|
||
return bidResponses; | ||
} | ||
} | ||
|
||
function bidToTag(bid, index) { | ||
const tag = {}; | ||
const adIndex = 'a' + (index + 1).toString(); // ad unit id for c1x | ||
const sizeKey = adIndex + 's'; | ||
const priceKey = adIndex + 'p'; | ||
// TODO: Multiple Floor Prices | ||
|
||
const sizesArr = bid.sizes; | ||
const floorPriceMap = bid.params.floorPriceMap || ''; | ||
tag['site'] = bid.params.siteId || ''; | ||
|
||
// prevent pixelId becoming undefined when publishers don't fill this param in ad units they have on the same page | ||
if (bid.params.pixelId) { | ||
tag['pixelId'] = bid.params.pixelId | ||
} | ||
|
||
tag[adIndex] = bid.adUnitCode; | ||
tag[sizeKey] = sizesArr.reduce((prev, current) => prev + (prev === '' ? '' : ',') + current.join('x'), ''); | ||
|
||
const newSizeArr = tag[sizeKey].split(','); | ||
if (floorPriceMap) { | ||
newSizeArr.forEach(size => { | ||
if (size in floorPriceMap) { | ||
tag[priceKey] = floorPriceMap[size].toString(); | ||
} // we only accept one cpm price in floorPriceMap | ||
}); | ||
} | ||
if (bid.params.pageurl) { | ||
tag['pageurl'] = bid.params.pageurl; | ||
} | ||
|
||
return tag; | ||
} | ||
|
||
function bidToShortTag(bid) { | ||
const tag = {}; | ||
tag.adUnitCode = bid.adUnitCode; | ||
tag.bidId = bid.bidId; | ||
|
||
return tag; | ||
} | ||
|
||
function stringifyPayload(payload) { | ||
let payloadString = ''; | ||
payloadString = JSON.stringify(payload).replace(/":"|","|{"|"}/g, (foundChar) => { | ||
if (foundChar == '":"') return '='; | ||
else if (foundChar == '","') return '&'; | ||
else return ''; | ||
}); | ||
return payloadString; | ||
} | ||
|
||
registerBidder(c1xAdapter); |
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,27 @@ | ||
# Overview | ||
|
||
Module Name: C1X Bidder Adapter | ||
Module Type: Bidder Adapter | ||
Maintainer: cathy@c1exchange.com | ||
|
||
# Description | ||
|
||
Module that connects to Example's demand sources | ||
|
||
# Test Parameters | ||
``` | ||
var adUnits = [ | ||
{ | ||
code: 'test-div', | ||
sizes: [[300, 250]], // a display size | ||
bids: [ | ||
{ | ||
bidder: 'c1x', | ||
params: { | ||
placement: '12345' | ||
} | ||
} | ||
] | ||
}, | ||
]; | ||
``` |
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.
Latest IP: 18.217.214.190