Skip to content
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

Optimize AOL adapter and heavily reduce the size #653

Merged
merged 4 commits into from
Oct 13, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
269 changes: 113 additions & 156 deletions src/adapters/aol.js
Original file line number Diff line number Diff line change
@@ -1,183 +1,140 @@
var utils = require('../utils.js');
var bidfactory = require('../bidfactory.js');
var bidmanager = require('../bidmanager.js');
var adloader = require('../adloader');

var AolAdapter = function AolAdapter() {

// constants
var ADTECH_URI = 'https://secure-ads.pictela.net/rm/marketplace/pubtaglib/0_4_0/pubtaglib_0_4_0.js';
var ADTECH_BIDDER_NAME = 'aol';
var ADTECH_PUBAPI_CONFIG = {
pixelsDivId: 'pixelsDiv',
defaultKey: 'aolBid',
roundingConfig: [
{
from: 0,
to: 999,
roundFunction: 'tenCentsRound'
}, {
from: 1000,
to: -1,
roundValue: 1000
}
],
pubApiOK: _addBid,
pubApiER: _addErrorBid
const utils = require('../utils.js');
const ajax = require('../ajax.js').ajax;
const bidfactory = require('../bidfactory.js');
const bidmanager = require('../bidmanager.js');

const AolAdapter = function AolAdapter() {

const pubapiTemplate = template`${'protocol'}://${'host'}/pubapi/3.0/${'network'}/${'placement'}/${'pageid'}/${'sizeid'}/ADTECH;v=2;cmd=bid;cors=yes;alias=${'alias'}${'bidfloor'};misc=${'misc'}`;
const BIDDER_CODE = 'aol';
const SERVER_MAP = {
us: 'adserver-us.adtech.advertising.com',
eu: 'adserver-eu.adtech.advertising.com',
as: 'adserver-as.adtech.advertising.com'
};

var bids;
var bidsMap = {};
var d = window.document;
var h = d.getElementsByTagName('HEAD')[0];
var dummyUnitIdCount = 0;

/**
* @private create a div that we'll use as the
* location for the AOL unit; AOL will document.write
* if the div is not present in the document.
* @param {String} id to identify the div
* @return {String} the id used with the div
*/
function _dummyUnit(id) {
var div = d.createElement('DIV');

if (!id || !id.length) {
id = 'ad-placeholder-' + (++dummyUnitIdCount);
}

div.id = id + '-head-unit';
h.appendChild(div);
return div.id;
function template(strings, ...keys) {
return function(...values) {
let dict = values[values.length - 1] || {};
let result = [strings[0]];
keys.forEach(function(key, i) {
let value = Number.isInteger(key) ? values[key] : dict[key];
result.push(value, strings[i + 1]);
});
return result.join('');
};
}

/**
* @private Add a succesful bid response for aol
* @param {ADTECHResponse} response the response for the bid
* @param {ADTECHContext} context the context passed from aol
*/
function _addBid(response, context) {
var bid = bidsMap[context.alias];
var cpm;

if (!bid) {
utils.logError('mismatched bid: ' + context.placement, ADTECH_BIDDER_NAME, context);
return;
}
function _buildPubapiUrl(bid) {
const params = bid.params;
const serverParam = params.server;
let regionParam = params.region || 'us';
let server;

cpm = response.getCPM();
if (cpm === null || isNaN(cpm)) {
return _addErrorBid(response, context);
if (!SERVER_MAP.hasOwnProperty(regionParam)) {
console.warn(`Unknown region '${regionParam}' for AOL bidder.`);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

console.warn doesn't play nice in IE 9. Please use utils.logWarn instead for safety.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason for using console.warn() directly is that this warning is meant to be shown when a publisher is configuring a site and uses incorrect region. I want to show the warning even if the debug mode is turned off, so the publisher can see what's wrong. And I expect publisher to be configuring it in a browser other than IE9 🤔. After the site is configured correctly, the warning should go away, so I believe it is safe to use this console.warn(). If you feel otherwise, please let me know.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair enough I suppose. Thanks

regionParam = 'us'; // Default region.
}

// clean up--we no longer need to store the bid
delete bidsMap[context.alias];

var bidResponse = bidfactory.createBid(1);
var ad = response.getCreative();
if (typeof response.getPixels() !== 'undefined') {
ad += response.getPixels();
if (serverParam) {
server = serverParam;
} else {
server = SERVER_MAP[regionParam];
}
bidResponse.bidderCode = ADTECH_BIDDER_NAME;
bidResponse.ad = ad;
bidResponse.cpm = cpm;
bidResponse.width = response.getAdWidth();
bidResponse.height = response.getAdHeight();
bidResponse.creativeId = response.getCreativeId();

// add it to the bid manager
// Set region param, used by AOL analytics.
params.region = regionParam;

return pubapiTemplate({
protocol: (document.location.protocol === 'https:') ? 'https' : 'http',
host: server,
network: params.network,
placement: parseInt(params.placement),
pageid: params.pageId || 0,
sizeid: params.sizeId || 0,
alias: params.alias || utils.getUniqueIdentifierStr(),
bidfloor: (typeof params.bidFloor !== 'undefined') ?
`;bidfloor=${params.bidFloor.toString()}` : '',
misc: new Date().getTime() // cache busting
});
}

function _addErrorBidResponse(bid, response = {}) {
const bidResponse = bidfactory.createBid(2, bid);
bidResponse.bidderCode = BIDDER_CODE;
bidResponse.reason = response.nbr;
bidResponse.raw = response;
bidmanager.addBidResponse(bid.placementCode, bidResponse);
}

/**
* @private Add an error bid response for aol
* @param {ADTECHResponse} response the response for the bid
* @param {ADTECHContext} context the context passed from aol
*/
function _addErrorBid(response, context) {
var bid = bidsMap[context.alias];
function _addBidResponse(bid, response) {
let bidData;

if (!bid) {
utils.logError('mismatched bid: ' + context.placement, ADTECH_BIDDER_NAME, context);
try {
bidData = response.seatbid[0].bid[0];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An empty bid or "no bid" response causes this to fail which throws an error, though a response with an empty seatbid array appears to be common in my testing, so should be handled as other than Error.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When an error is thrown here, addErrorBidResponse() is called, which adds bid response to the bidmanager with status 2 (empty or error bid response). That, I believe, is correct behavior, but I removed error logging, so it won't appear as error in the console when debugging. That was done in 981fb75.

} catch (e) {
_addErrorBidResponse(bid, response);
return;
}

// clean up--we no longer need to store the bid
delete bidsMap[context.alias];
let cpm;

var bidResponse = bidfactory.createBid(2);
bidResponse.bidderCode = ADTECH_BIDDER_NAME;
bidResponse.reason = response.getNbr();
bidResponse.raw = response.getResponse();
bidmanager.addBidResponse(bid.placementCode, bidResponse);
}
if (bidData.ext && bidData.ext.encp) {
cpm = bidData.ext.encp;
} else {
cpm = bidData.price;

/**
* @private map a prebid bidrequest to an ADTECH/aol bid request
* @param {Bid} bid the bid request
* @return {Object} the bid request, formatted for the ADTECH/DAC api
*/
function _mapUnit(bid) {
var alias = bid.params.alias || utils.getUniqueIdentifierStr();

// save the bid
bidsMap[alias] = bid;

return {
adContainerId: _dummyUnit(bid.params.adContainerId),
server: bid.params.server, // By default, DAC.js will use the US region endpoint (adserver.adtechus.com)
sizeid: bid.params.sizeId || 0,
pageid: bid.params.pageId,
secure: document.location.protocol === 'https:',
serviceType: 'pubapi',
performScreenDetection: false,
alias: alias,
network: bid.params.network,
placement: parseInt(bid.params.placement),
gpt: {
adUnitPath: bid.params.adUnitPath || bid.placementCode,
size: bid.params.size || (bid.sizes || [])[0]
},
params: {
cors: 'yes',
cmd: 'bid',
bidfloor: (typeof bid.params.bidFloor !== "undefined") ? bid.params.bidFloor.toString() : ''
},
pubApiConfig: ADTECH_PUBAPI_CONFIG,
placementCode: bid.placementCode
};
}
if (cpm === null || isNaN(cpm)) {
utils.logError('Invalid price in bid response', BIDDER_CODE, bid);
_addErrorBidResponse(bid, response);
return;
}
}

/**
* @private once ADTECH is loaded, request bids by
* calling ADTECH.loadAd
*/
function _reqBids() {
if (!window.ADTECH) {
utils.logError('window.ADTECH is not present!', ADTECH_BIDDER_NAME);
return;
let ad = bidData.adm;
if (bidData.ext && bidData.ext.pixels) {
ad += bidData.ext.pixels;
}

// get the bids
utils._each(bids, function (bid) {
var bidreq = _mapUnit(bid);
window.ADTECH.loadAd(bidreq);
});
const bidResponse = bidfactory.createBid(1, bid);
bidResponse.bidderCode = BIDDER_CODE;
bidResponse.ad = ad;
bidResponse.cpm = cpm;
bidResponse.width = bidData.w;
bidResponse.height = bidData.h;
bidResponse.creativeId = bidData.crid;
bidResponse.pubapiId = response.id;
bidResponse.currencyCode = response.cur;
if (bidData.dealid) {
bidResponse.dealId = bidData.dealid;
}

bidmanager.addBidResponse(bid.placementCode, bidResponse);
}

/**
* @public call the bids
* this requests the specified bids
* from aol marketplace
* @param {Object} params
* @param {Array} params.bids the bids to be requested
*/
function _callBids(params) {
window.bidRequestConfig = window.bidRequestConfig || {};
window.dacBidRequestConfigs = window.dacBidRequestConfigs || {};
bids = params.bids;
if (!bids || !bids.length) return;
adloader.loadScript(ADTECH_URI, _reqBids, true);
utils._each(params.bids, bid => {
const pubapiUrl = _buildPubapiUrl(bid);

ajax(pubapiUrl, response => {
if (!response && response.length <= 0) {
utils.logError('Empty bid response', BIDDER_CODE, bid);
_addErrorBidResponse(bid, response);
return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For an empty bid response, you will still want to add a bid response, likely with _addErrorBidResponse.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the suggestion. This is now fixed.

}

try {
response = JSON.parse(response);
} catch (e) {
utils.logError('Invalid JSON in bid response', BIDDER_CODE, bid);
_addErrorBidResponse(bid, response);
return;
}

_addBidResponse(bid, response);

}, null, { withCredentials: true });
});
}

return {
Expand Down
7 changes: 7 additions & 0 deletions src/polyfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,10 @@ if (!Array.prototype.includes) {
}
});
}

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger
Number.isInteger = Number.isInteger || function(value) {
return typeof value === 'number' &&
isFinite(value) &&
Math.floor(value) === value;
};
Loading