-
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
Upgrade Quantcast adapter for Prebid 1.0 #1753
Merged
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
b87dc31
Add v1.0 adapter skeleton
275b772
Fix a typo in variable name declaration
017c89c
Change spec dependencies
e94e790
Add new describes for test
08c4300
Move URL detechtion inside buildRequests method
d276ad1
Add necessary cases
642115d
Clean test cases
444a2bf
Export Quantcast adapter constants
d99851e
Implemenent test cases
5a7809e
Fix wrong ports number
553b34d
Correct test cases
abf387a
Make string with single quote
459ca31
Remove unused statements
83a4de0
Revert "Remove unused statements"
6520c69
Remove unused statements
7ad07a0
Change string to single quote
c79279f
Fix sizes type
b95315f
Fix the sizes propty name typo in the spec
1322e00
Remove unused method, key value and comments
4b1aef8
Update the spec
2b56022
Change code using single quote
bee2344
Update the first argument for interpretResponse method and its spec
417852e
Handle undefined Server Response
d6a00e6
Add required params from the server response
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 |
---|---|---|
@@ -1,128 +1,165 @@ | ||
const utils = require('src/utils.js'); | ||
const bidfactory = require('src/bidfactory.js'); | ||
const bidmanager = require('src/bidmanager.js'); | ||
const ajax = require('src/ajax.js'); | ||
const CONSTANTS = require('src/constants.json'); | ||
const adaptermanager = require('src/adaptermanager'); | ||
const QUANTCAST_CALLBACK_URL = 'http://global.qc.rtb.quantserve.com:8080/qchb'; | ||
|
||
var QuantcastAdapter = function QuantcastAdapter() { | ||
const BIDDER_CODE = 'quantcast'; | ||
|
||
const DEFAULT_BID_FLOOR = 0.0000000001; | ||
let bidRequests = {}; | ||
|
||
let returnEmptyBid = function(bidId) { | ||
var bidRequested = utils.getBidRequest(bidId); | ||
if (!utils.isEmpty(bidRequested)) { | ||
let bid = bidfactory.createBid(CONSTANTS.STATUS.NO_BID, bidRequested); | ||
bid.bidderCode = BIDDER_CODE; | ||
bidmanager.addBidResponse(bidRequested.placementCode, bid); | ||
import * as utils from 'src/utils'; | ||
import { registerBidder } from 'src/adapters/bidderFactory'; | ||
|
||
const BIDDER_CODE = 'quantcast'; | ||
const DEFAULT_BID_FLOOR = 0.0000000001; | ||
|
||
export const QUANTCAST_CALLBACK_URL = 'global.qc.rtb.quantserve.com'; | ||
export const QUANTCAST_CALLBACK_URL_TEST = 's2s-canary.quantserve.com'; | ||
export const QUANTCAST_NET_REVENUE = true; | ||
export const QUANTCAST_TEST_PUBLISHER = 'test-publisher'; | ||
export const QUANTCAST_TTL = 4; | ||
|
||
/** | ||
* The documentation for Prebid.js Adapter 1.0 can be found at link below, | ||
* http://prebid.org/dev-docs/bidder-adapter-1.html | ||
*/ | ||
export const spec = { | ||
code: BIDDER_CODE, | ||
|
||
/** | ||
* Verify the `AdUnits.bids` response with `true` for valid request and `false` | ||
* for invalid request. | ||
* | ||
* @param {object} bid | ||
* @return boolean `true` is this is a valid bid, and `false` otherwise | ||
*/ | ||
isBidRequestValid(bid) { | ||
if (!bid) { | ||
return false; | ||
} | ||
}; | ||
|
||
// expose the callback to the global object: | ||
$$PREBID_GLOBAL$$.handleQuantcastCB = function (responseText) { | ||
if (utils.isEmpty(responseText)) { | ||
return; | ||
} | ||
let response = null; | ||
try { | ||
response = JSON.parse(responseText); | ||
} catch (e) { | ||
// Malformed JSON | ||
utils.logError("Malformed JSON received from server - can't do anything here"); | ||
return; | ||
} | ||
|
||
if (response === null || !response.hasOwnProperty('bids') || utils.isEmpty(response.bids)) { | ||
utils.logError("Sub-optimal JSON received from server - can't do anything here"); | ||
return; | ||
if (bid.mediaType === 'video') { | ||
return false; | ||
} | ||
|
||
for (let i = 0; i < response.bids.length; i++) { | ||
let seatbid = response.bids[i]; | ||
let key = seatbid.placementCode; | ||
var request = bidRequests[key]; | ||
if (request === null || request === undefined) { | ||
return returnEmptyBid(seatbid.placementCode); | ||
} | ||
// This line is required since this is the field | ||
// that bidfactory.createBid looks for | ||
request.bidId = request.imp[0].placementCode; | ||
let responseBid = bidfactory.createBid(CONSTANTS.STATUS.GOOD, request); | ||
|
||
responseBid.cpm = seatbid.cpm; | ||
responseBid.ad = seatbid.ad; | ||
responseBid.height = seatbid.height; | ||
responseBid.width = seatbid.width; | ||
responseBid.bidderCode = response.bidderCode; | ||
responseBid.requestId = request.requestId; | ||
responseBid.bidderCode = BIDDER_CODE; | ||
|
||
bidmanager.addBidResponse(request.bidId, responseBid); | ||
return true; | ||
}, | ||
|
||
/** | ||
* Make a server request when the page asks Prebid.js for bids from a list of | ||
* `BidRequests`. | ||
* | ||
* @param {BidRequest[]} bidRequests A non-empty list of bid requests which should be send to Quantcast server | ||
* @return ServerRequest information describing the request to the server. | ||
*/ | ||
buildRequests(bidRequests) { | ||
const bids = bidRequests || []; | ||
|
||
const referrer = utils.getTopWindowUrl(); | ||
const loc = utils.getTopWindowLocation(); | ||
const domain = loc.hostname; | ||
|
||
let publisherTagURL; | ||
let publisherTagURLTest; | ||
|
||
// Switch the callback URL to Quantcast Canary Endpoint for testing purpose | ||
// `//` is not used because we have different port setting at our end | ||
switch (window.location.protocol) { | ||
case 'https:': | ||
publisherTagURL = `https://${QUANTCAST_CALLBACK_URL}:8443/qchb`; | ||
publisherTagURLTest = `https://${QUANTCAST_CALLBACK_URL_TEST}:8443/qchb`; | ||
break; | ||
default: | ||
publisherTagURL = `http://${QUANTCAST_CALLBACK_URL}:8080/qchb`; | ||
publisherTagURLTest = `http://${QUANTCAST_CALLBACK_URL_TEST}:8080/qchb`; | ||
} | ||
}; | ||
|
||
function callBids(params) { | ||
let bids = params.bids || []; | ||
if (bids.length === 0) { | ||
return; | ||
} | ||
|
||
let referrer = utils.getTopWindowUrl(); | ||
let loc = utils.getTopWindowLocation(); | ||
let domain = loc.hostname; | ||
let publisherId = 0; | ||
const bidRequestsList = bids.map(bid => { | ||
const bidSizes = []; | ||
|
||
publisherId = '' + bids[0].params.publisherId; | ||
utils._each(bids, function(bid) { | ||
let key = bid.placementCode; | ||
var bidSizes = []; | ||
utils._each(bid.sizes, function (size) { | ||
bid.sizes.forEach(size => { | ||
bidSizes.push({ | ||
'width': size[0], | ||
'height': size[1] | ||
width: size[0], | ||
height: size[1] | ||
}); | ||
}); | ||
|
||
bidRequests[key] = bidRequests[key] || { | ||
'publisherId': publisherId, | ||
'requestId': bid.bidId, | ||
'bidId': bid.bidId, | ||
'site': { | ||
'page': loc.href, | ||
'referrer': referrer, | ||
'domain': domain, | ||
// Request Data Format can be found at https://wiki.corp.qc/display/adinf/QCX | ||
const requestData = { | ||
publisherId: bid.params.publisherId, | ||
requestId: bid.bidId, | ||
imp: [ | ||
{ | ||
banner: { | ||
battr: bid.params.battr, | ||
sizes: bidSizes | ||
}, | ||
placementCode: bid.placementCode, | ||
bidFloor: bid.params.bidFloor || DEFAULT_BID_FLOOR | ||
} | ||
], | ||
site: { | ||
page: loc.href, | ||
referrer, | ||
domain | ||
}, | ||
'imp': [{ | ||
|
||
'banner': { | ||
'battr': bid.params.battr, | ||
'sizes': bidSizes, | ||
}, | ||
'placementCode': bid.placementCode, | ||
'bidFloor': bid.params.bidFloor || DEFAULT_BID_FLOOR, | ||
}] | ||
bidId: bid.bidId | ||
}; | ||
}); | ||
|
||
utils._each(bidRequests, function (bidRequest) { | ||
ajax.ajax(QUANTCAST_CALLBACK_URL, $$PREBID_GLOBAL$$.handleQuantcastCB, JSON.stringify(bidRequest), { | ||
const data = JSON.stringify(requestData); | ||
|
||
const url = | ||
bid.params.publisherId === QUANTCAST_TEST_PUBLISHER | ||
? publisherTagURLTest | ||
: publisherTagURL; | ||
|
||
return { | ||
data, | ||
method: 'POST', | ||
withCredentials: true | ||
}); | ||
url | ||
}; | ||
}); | ||
} | ||
|
||
// Export the `callBids` function, so that Prebid.js can execute | ||
// this function when the page asks to send out bid requests. | ||
return { | ||
callBids: callBids, | ||
QUANTCAST_CALLBACK_URL: QUANTCAST_CALLBACK_URL | ||
}; | ||
}; | ||
return bidRequestsList; | ||
}, | ||
|
||
/** | ||
* Function get called when the browser has received the response from Quantcast server. | ||
* The function parse the response and create a `bidResponse` object containing one/more bids. | ||
* Returns an empty array if no valid bids | ||
* | ||
* Response Data Format can be found at https://wiki.corp.qc/display/adinf/QCX | ||
* | ||
* @param {*} serverResponse A successful response from Quantcast server. | ||
* @return {Bid[]} An array of bids which were nested inside the server. | ||
* | ||
*/ | ||
interpretResponse(serverResponse) { | ||
if (serverResponse === undefined) { | ||
utils.logError('Server Response is undefined'); | ||
return []; | ||
} | ||
|
||
const response = serverResponse['body']; | ||
|
||
if ( | ||
response === undefined || | ||
!response.hasOwnProperty('bids') || | ||
utils.isEmpty(response.bids) | ||
) { | ||
utils.logError('Sub-optimal JSON received from Quantcast server'); | ||
return []; | ||
} | ||
|
||
adaptermanager.registerBidAdapter(new QuantcastAdapter(), 'quantcast'); | ||
const bidResponsesList = response.bids.map(bid => { | ||
const { ad, cpm, width, height, creativeId, currency } = bid; | ||
|
||
return { | ||
requestId: response.requestId, | ||
cpm, | ||
width, | ||
height, | ||
ad, | ||
ttl: QUANTCAST_TTL, | ||
creativeId, | ||
netRevenue: QUANTCAST_NET_REVENUE, | ||
currency | ||
}; | ||
}); | ||
|
||
return bidResponsesList; | ||
} | ||
}; | ||
|
||
module.exports = QuantcastAdapter; | ||
registerBidder(spec); |
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,31 @@ | ||
# Overview | ||
|
||
``` | ||
Module Name: Quantcast Bidder Adapter | ||
Module Type: Bidder Adapter | ||
Maintainer: xli@quantcast.com | ||
``` | ||
|
||
# Description | ||
|
||
Module that connects to Quantcast demand sources to fetch bids. | ||
|
||
# Test Parameters | ||
|
||
```js | ||
const adUnits = [{ | ||
code: 'banner', | ||
sizes: [ | ||
[300, 250] | ||
], | ||
bids: [ | ||
{ | ||
bidder: 'quantcast', | ||
params: { | ||
publisherId: 'test-publisher', // REQUIRED - Publisher ID provided by Quantcast | ||
battr: [1, 2] // OPTIONAL - Array of blocked creative attributes as per OpenRTB Spec List 5.3 | ||
} | ||
} | ||
] | ||
}]; | ||
``` |
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.
#1742 got merged recently.
The first argument to interpretResponse now looks like this:
{
body: responseBody,
headers: {
get: function(header) { /* returns a header from the HTTP response */ }
}
}
You'll have to pull master and update the spec so that it looks digs into that object as well now.
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.
Updated with bee2344 and 417852e