-
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
HIRO Media: Remove batching mechanism and use AJAX instead of JSONP #1133
Merged
jaiminpanchal27
merged 3 commits into
prebid:master
from
hiromedia:hiromedia-adapter-v3
May 17, 2017
Merged
Changes from 1 commit
Commits
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,18 +1,18 @@ | ||
/*jslint white:true, browser:true, single: true*/ | ||
/*global $$PREBID_GLOBAL$$, require, module*/ | ||
/*global require, module*/ | ||
|
||
/** | ||
* Adapter for HIRO Media | ||
* | ||
* @module HiroMediaAdapter | ||
* | ||
* @requires src/adloader | ||
* @requires src/ajax | ||
* @requires src/bidfactory | ||
* @requires src/bidmanager | ||
* @requires src/constants | ||
* @requires src/utils | ||
*/ | ||
var adloader = require('src/adloader'); | ||
var Ajax = require('src/ajax'); | ||
var bidfactory = require('src/bidfactory'); | ||
var bidmanager = require('src/bidmanager'); | ||
var utils = require('src/utils'); | ||
|
@@ -44,7 +44,7 @@ var HiroMediaAdapter = function HiroMediaAdapter() { | |
* Default bid param values | ||
* | ||
* @memberof module:HiroMediaAdapter~ | ||
* @constant {module:HiroMediaAdapter~bidParams} | ||
* @constant {array.<string>} | ||
* @private | ||
*/ | ||
var REQUIRED_BID_PARAMS = ['accountId']; | ||
|
@@ -60,18 +60,6 @@ var HiroMediaAdapter = function HiroMediaAdapter() { | |
bidUrl: 'https://hb-rtb.ktdpublishers.com/bid/get' | ||
}; | ||
|
||
/** | ||
* Storage for bid objects. | ||
* | ||
* Bids need to be stored between requests and response since the response | ||
* is a global callback. | ||
* | ||
* @memberof module:HiroMediaAdapter~ | ||
* @var {array.<module:HiroMediaAdapter~bidInfo>} | ||
* @private | ||
*/ | ||
var _bidStorage = []; | ||
|
||
/** | ||
* Call bidmanager.addBidResponse | ||
* | ||
|
@@ -81,15 +69,15 @@ var HiroMediaAdapter = function HiroMediaAdapter() { | |
* @memberof module:HiroMediaAdapter~ | ||
* @private | ||
* | ||
* @param {module:HiroMediaAdapter~bidInfo} bidInfo bid object wrapper to respond for | ||
* @param {object} bid bid object connected to the response | ||
* @param {object|boolean} [bidResponse] response object for bid, if not | ||
* set the response will be an empty bid response. | ||
*/ | ||
function addBidResponse(bidInfo, bidResponse) { | ||
function addBidResponse(bid, bidResponse) { | ||
|
||
var placementCode = bidInfo.bid.placementCode; | ||
var placementCode = bid.placementCode; | ||
var bidStatus = bidResponse ? STATUS.GOOD : STATUS.NO_BID; | ||
var bidObject = bidfactory.createBid(bidStatus, bidInfo.bid); | ||
var bidObject = bidfactory.createBid(bidStatus, bid); | ||
|
||
bidObject.bidderCode = BIDDER_CODE; | ||
|
||
|
@@ -124,40 +112,20 @@ var HiroMediaAdapter = function HiroMediaAdapter() { | |
* @memberof module:HiroMediaAdapter~ | ||
* @private | ||
* | ||
* @param {object} response [description] | ||
* @param {object} response bid response object | ||
* @param {object} bid bid object connected to response | ||
*/ | ||
function handleResponse(response) { | ||
|
||
_bidStorage.filter(function (bidInfo) { | ||
return bidInfo.batchKey === response.batchKey; | ||
}).forEach(function (bidInfo) { | ||
|
||
// Sample the bid responses according to `response.chance`, | ||
// if `response.chance` is not provided, sample at 100%. | ||
if (response.chance === undefined || checkChance(response.chance)) { | ||
addBidResponse(bidInfo, response); | ||
} else { | ||
addBidResponse(bidInfo, false); | ||
} | ||
function handleResponse(response, bid) { | ||
|
||
}); | ||
|
||
} | ||
|
||
/** | ||
* Call {@linkcode module:HiroMediaAdapter~handleResponse} for valid responses | ||
* | ||
* @global | ||
* | ||
* @param {object} [response] the response from the server | ||
*/ | ||
$$PREBID_GLOBAL$$.hiromedia_callback = function (response) { | ||
|
||
if (response && response.batchKey) { | ||
handleResponse(response); | ||
// Sample the bid responses according to `response.chance`, | ||
// if `response.chance` is not provided, sample at 100%. | ||
if (response.chance === undefined || checkChance(response.chance)) { | ||
addBidResponse(bid, response); | ||
} else { | ||
addBidResponse(bid, false); | ||
} | ||
|
||
}; | ||
} | ||
|
||
/** | ||
* Find browser name and version | ||
|
@@ -250,108 +218,52 @@ var HiroMediaAdapter = function HiroMediaAdapter() { | |
} | ||
|
||
/** | ||
* Calculate and return a batchKey key for a bid | ||
* | ||
* Bid of similar placement can have similar responses, | ||
* we can calculate a key based on the variant properties | ||
* of a bid which can share the same response | ||
* Build a {@linkcode module:HiroMediaAdapter~bidInfo|bidInfo} object based on a | ||
* bid sent to {@linkcode module:HiroMediaAdapter#callBids|callBids} | ||
* | ||
* @memberof module:HiroMediaAdapter~ | ||
* @private | ||
* | ||
* @param {module:HiroMediaAdapter~bidInfo} bidInfo bid information | ||
* @return {string} batch key for bid | ||
* @param {object} bid bid from `Prebid.js` | ||
* @return {module:HiroMediaAdapter~bidInfo} information for bid request | ||
*/ | ||
function getBatchKey(bidInfo) { | ||
|
||
var bidParams = bidInfo.bidParams; | ||
var batchParams = [ | ||
bidParams.bidUrl, | ||
bidParams.accountId, | ||
bidInfo.selectedSize, | ||
bidInfo.additionalSizes | ||
]; | ||
|
||
return batchParams.join('-'); | ||
|
||
} | ||
|
||
/** | ||
* Build a set of {@linkcode module:HiroMediaAdapter~bidInfo|bidInfo} objects based on the | ||
* bids sent to {@linkcode module:HiroMediaAdapter#callBids|callBids} | ||
* | ||
* @memberof module:HiroMediaAdapter~ | ||
* @private | ||
* | ||
* @param {object} bids bids sent from `Prebid.js` | ||
* @return {array.<module:HiroMediaAdapter~bidInfo>} wrapped bids | ||
*/ | ||
function processBids(bids) { | ||
|
||
var result = []; | ||
|
||
if (bids) { | ||
|
||
utils.logMessage('hiromedia.processBids, processing ' + bids.length + ' bids'); | ||
|
||
bids.forEach(function (bid) { | ||
|
||
var sizes = utils.parseSizesInput(bid.sizes); | ||
var bidParams = defaultParams(bid.params); | ||
var hasValidBidRequest = utils.hasValidBidRequest(bidParams, REQUIRED_BID_PARAMS, BIDDER_CODE); | ||
var shouldBid = hasValidBidRequest; | ||
var bidInfo = { | ||
bid: bid, | ||
bidParams: bidParams, | ||
shouldBid: shouldBid, | ||
selectedSize: sizes[0], | ||
additionalSizes: sizes.slice(1).join(',') | ||
}; | ||
|
||
if (shouldBid) { | ||
bidInfo.batchKey = getBatchKey(bidInfo); | ||
} | ||
|
||
result.push(bidInfo); | ||
|
||
}); | ||
|
||
} | ||
function processBid(bid) { | ||
|
||
var sizes = utils.parseSizesInput(bid.sizes); | ||
var bidParams = defaultParams(bid.params); | ||
var hasValidBidRequest = utils.hasValidBidRequest(bidParams, REQUIRED_BID_PARAMS, BIDDER_CODE); | ||
var shouldBid = hasValidBidRequest; | ||
var bidInfo = { | ||
bidParams: bidParams, | ||
shouldBid: shouldBid, | ||
selectedSize: sizes[0], | ||
additionalSizes: sizes.slice(1).join(',') | ||
}; | ||
|
||
return result; | ||
return bidInfo; | ||
|
||
} | ||
|
||
/** | ||
* Send a bid request to the bid server endpoint | ||
* | ||
* Calls `adLoader.loadScript` | ||
* Wrapper around `JSON.parse()` that returns false on error | ||
* | ||
* @memberof module:HiroMediaAdapter~ | ||
* @private | ||
* | ||
* @param {string} url base url, can already contain query parameters | ||
* @param {object} requestParams parameters to add to query | ||
* @param {string} text potential JSON string to convert to object | ||
* @return {object|boolean} object parsed from text or `false` in case of and error | ||
*/ | ||
function sendBidRequest(url,requestParams) { | ||
|
||
if (requestParams) { | ||
function tryJson(text) { | ||
|
||
if (url.indexOf('?') !== -1) { | ||
url = url + '&'; | ||
} else { | ||
url = url + '?'; | ||
} | ||
|
||
Object.keys(requestParams).forEach(function (key) { | ||
url = utils.tryAppendQueryString(url, key, requestParams[key]); | ||
}); | ||
var object = false; | ||
|
||
try { | ||
object = JSON.parse(text); | ||
} catch (ignore) { | ||
// Ignored | ||
} | ||
|
||
utils.logMessage('hiromedia.callBids, url:' + url); | ||
|
||
adloader.loadScript(url); | ||
return object; | ||
|
||
} | ||
|
||
|
@@ -366,61 +278,72 @@ var HiroMediaAdapter = function HiroMediaAdapter() { | |
|
||
var browser = getBrowser(); | ||
var domain = getDomain(); | ||
var bidsRequested = {}; | ||
var bids = params && params.bids; | ||
var ajaxOptions = { | ||
method: 'GET', | ||
withCredentials: true | ||
}; | ||
|
||
// Fixed data, shared by all requests | ||
var fixedRequest = { | ||
adapterVersion: ADAPTER_VERSION, | ||
browser: browser.name, | ||
browserVersion: browser.version, | ||
domain: domain | ||
}; | ||
|
||
utils.logMessage('hiromedia.callBids'); | ||
|
||
if (params) { | ||
if (bids && bids.length) { | ||
|
||
// Processed bids are stored in the adapter scope | ||
_bidStorage = processBids(params.bids); | ||
bids.forEach(function (bid) { | ||
|
||
} else { | ||
var bidInfo = processBid(bid); | ||
|
||
// Ensure we don't run on stale data | ||
_bidStorage = []; | ||
var bidParams = bidInfo.bidParams; | ||
utils.logMessage('hiromedia.callBids, bidInfo ' + bid.placementCode + ' ' + bidInfo.shouldBid); | ||
|
||
} | ||
if (bidInfo.shouldBid) { | ||
|
||
if (_bidStorage.length) { | ||
var url = bidParams.bidUrl; | ||
var requestParams = Object.assign({}, fixedRequest, bidInfo.bidParams, { | ||
placementCode: bid.placementCode, | ||
selectedSize: bidInfo.selectedSize, | ||
additionalSizes: bidInfo.additionalSizes | ||
}); | ||
|
||
// Loop over processed bids and send a request if a request for the bid | ||
// batchKey has not been sent. | ||
_bidStorage.forEach(function (bidInfo) { | ||
Object.keys(requestParams).forEach(function (key){ | ||
if (requestParams[key] === '' || requestParams[key] === undefined) { | ||
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. Same here. |
||
delete requestParams[key]; | ||
} | ||
}); | ||
|
||
var bid = bidInfo.bid; | ||
var batchKey = bidInfo.batchKey; | ||
var bidParams = bidInfo.bidParams; | ||
utils.logMessage('hiromedia.callBids, bid request ' + url + ' ' + JSON.stringify(bidInfo.bidRequest)); | ||
|
||
utils.logMessage('hiromedia.callBids, bidInfo ' + bid.placementCode + ' ' + bidInfo.shouldBid); | ||
Ajax.ajax(url, { | ||
|
||
if (bidInfo.shouldBid) { | ||
success: function(responseText) { | ||
|
||
var url = bidParams.bidUrl; | ||
var response = tryJson(responseText); | ||
|
||
handleResponse(response, bid); | ||
|
||
}, | ||
|
||
error: function(err, xhr) { | ||
|
||
if (!bidsRequested[batchKey]) { | ||
utils.logError('hiromedia.callBids, bid request error', xhr.status, err); | ||
|
||
bidsRequested[batchKey] = true; | ||
addBidResponse(bid, false); | ||
|
||
sendBidRequest(url,{ | ||
adapterVersion: ADAPTER_VERSION, | ||
callback: '$$PREBID_GLOBAL$$.hiromedia_callback', | ||
batchKey: batchKey, | ||
placementCode: bid.placementCode, | ||
accountId: bidParams.accountId, | ||
browser: browser.name, | ||
browserVersion: browser.version, | ||
domain: domain, | ||
selectedSize: bidInfo.selectedSize, | ||
additionalSizes: bidInfo.additionalSizes | ||
}); | ||
} | ||
|
||
} | ||
}, requestParams, ajaxOptions); | ||
|
||
} else { | ||
|
||
// No bid | ||
addBidResponse(bidInfo, false); | ||
addBidResponse(bid, false); | ||
|
||
} | ||
|
||
|
@@ -452,10 +375,8 @@ var HiroMediaAdapter = function HiroMediaAdapter() { | |
* @typedef {object} module:HiroMediaAdapter~bidInfo | ||
* @private | ||
* | ||
* @property {object} bid original bid passed to #callBids | ||
* @property {string} selectedSize the first size in the the placement sizes array | ||
* @property {string} additionalSizes list of sizes in the placement sizes array besides the first | ||
* @property {string} batchKey key used for batching requests which have the same basic properties | ||
* @property {module:HiroMediaAdapter~bidParams} bidParams original params passed for bid in #callBids | ||
* @property {boolean} shouldBid flag to determine if the bid is valid for bidding or not | ||
*/ | ||
|
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.
Should use
typeof
here, in case someone re-definesundefined
on their page.See (6) from the top answer here: https://www.quora.com/What-is-the-best-way-to-check-if-a-property-or-variable-is-undefined