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

New aliases for AOL adapter. #1371

Merged
merged 2 commits into from Jul 26, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
59 changes: 45 additions & 14 deletions modules/aolBidAdapter.js
Expand Up @@ -4,6 +4,13 @@ const bidfactory = require('src/bidfactory.js');
const bidmanager = require('src/bidmanager.js');
const constants = require('src/constants.json');
const adaptermanager = require('src/adaptermanager');
const BaseAdapter = require('src/adapter');

const AOL_BIDDERS_CODES = {
aol: 'aol',
onemobile: 'onemobile',
onedisplay: 'onedisplay'
};

$$PREBID_GLOBAL$$.aolGlobals = {
pixelsDropped: false
Expand All @@ -14,7 +21,6 @@ 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 nexageBaseApiTemplate = template`${'protocol'}://${'host'}/bidRequest?`;
const nexageGetApiTemplate = template`dcn=${'dcn'}&pos=${'pos'}&cmd=bid${'ext'}`;
const BIDDER_CODE = 'aol';
const MP_SERVER_MAP = {
us: 'adserver-us.adtech.advertising.com',
eu: 'adserver-eu.adtech.advertising.com',
Expand Down Expand Up @@ -175,7 +181,7 @@ const AolAdapter = function AolAdapter() {

function _addErrorBidResponse(bid, response = {}) {
const bidResponse = bidfactory.createBid(2, bid);
bidResponse.bidderCode = BIDDER_CODE;
bidResponse.bidderCode = bid.bidder;
bidResponse.reason = response.nbr;
bidResponse.raw = response;
bidmanager.addBidResponse(bid.placementCode, bidResponse);
Expand All @@ -199,7 +205,7 @@ const AolAdapter = function AolAdapter() {
cpm = bidData.price;

if (cpm === null || isNaN(cpm)) {
utils.logError('Invalid price in bid response', BIDDER_CODE, bid);
utils.logError('Invalid price in bid response', AOL_BIDDERS_CODES.aol, bid);
_addErrorBidResponse(bid, response);
return;
}
Expand All @@ -219,7 +225,7 @@ const AolAdapter = function AolAdapter() {
}

const bidResponse = bidfactory.createBid(1, bid);
bidResponse.bidderCode = BIDDER_CODE;
bidResponse.bidderCode = bid.bidder;
bidResponse.ad = ad;
bidResponse.cpm = cpm;
bidResponse.width = bidData.w;
Expand All @@ -234,15 +240,31 @@ const AolAdapter = function AolAdapter() {
bidmanager.addBidResponse(bid.placementCode, bidResponse);
}

function _isMarketplaceBidder(bidder) {
return bidder === AOL_BIDDERS_CODES.aol || bidder === AOL_BIDDERS_CODES.onedisplay;
}

function _isNexageBidder(bidder) {
return bidder === AOL_BIDDERS_CODES.aol || bidder === AOL_BIDDERS_CODES.onemobile;
}

function _isNexageRequestPost(bid) {
if (bid.params.id && bid.params.imp && bid.params.imp[0]) {
if (_isNexageBidder(bid.bidder) && bid.params.id && bid.params.imp && bid.params.imp[0]) {
let imp = bid.params.imp[0];
return imp.id && imp.tagid &&
((imp.banner && imp.banner.w && imp.banner.h) ||
(imp.video && imp.video.mimes && imp.video.minduration && imp.video.maxduration));
}
}

function _isNexageRequestGet(bid) {
return _isNexageBidder(bid.bidder) && bid.params.dcn && bid.params.pos;
}

function _isMarketplaceRequest(bid) {
return _isMarketplaceBidder(bid.bidder) && bid.params.placement && bid.params.network;
}

function _callBids(params) {
utils._each(params.bids, bid => {
let apiUrl;
Expand All @@ -251,9 +273,10 @@ const AolAdapter = function AolAdapter() {
withCredentials: true
};
let isNexageRequestPost = _isNexageRequestPost(bid);
if (bid.params.placement && bid.params.network) {
apiUrl = _buildMarketplaceUrl(bid);
} else if (bid.params.dcn && bid.params.pos || isNexageRequestPost) {
let isNexageRequestGet = _isNexageRequestGet(bid);
let isMarketplaceRequest = _isMarketplaceRequest(bid);

if (isNexageRequestGet || isNexageRequestPost) {
apiUrl = _buildNexageApiUrl(bid);
if (isNexageRequestPost) {
data = bid.params;
Expand All @@ -263,7 +286,10 @@ const AolAdapter = function AolAdapter() {
options.method = 'POST';
options.contentType = 'application/json';
}
} else if (isMarketplaceRequest) {
apiUrl = _buildMarketplaceUrl(bid);
}

if (apiUrl) {
ajax(apiUrl, response => {
// Needs to be here in case bidderSettings are defined after requestBids() is called
Expand All @@ -279,15 +305,15 @@ const AolAdapter = function AolAdapter() {
showCpmAdjustmentWarning = false; // warning is shown at most once

if (!response && response.length <= 0) {
utils.logError('Empty bid response', BIDDER_CODE, bid);
utils.logError('Empty bid response', AOL_BIDDERS_CODES.aol, bid);
_addErrorBidResponse(bid, response);
return;
}

try {
response = JSON.parse(response);
} catch (e) {
utils.logError('Invalid JSON in bid response', BIDDER_CODE, bid);
utils.logError('Invalid JSON in bid response', AOL_BIDDERS_CODES.aol, bid);
_addErrorBidResponse(bid, response);
return;
}
Expand All @@ -298,11 +324,16 @@ const AolAdapter = function AolAdapter() {
});
}

return {
callBids: _callBids
};
return Object.assign(BaseAdapter.createNew(AOL_BIDDERS_CODES.aol), {
callBids: _callBids,
createNew: function () {
return new AolAdapter();
}
});
};

adaptermanager.registerBidAdapter(new AolAdapter, 'aol');
adaptermanager.registerBidAdapter(new AolAdapter, AOL_BIDDERS_CODES.aol);
adaptermanager.aliasBidAdapter(AOL_BIDDERS_CODES.aol, AOL_BIDDERS_CODES.onedisplay);
adaptermanager.aliasBidAdapter(AOL_BIDDERS_CODES.aol, AOL_BIDDERS_CODES.onemobile);

module.exports = AolAdapter;
177 changes: 133 additions & 44 deletions test/spec/modules/aolBidAdapter_spec.js
Expand Up @@ -22,6 +22,34 @@ let getDefaultBidResponse = () => {
};
};

let getMarketplaceBidParams = () => {
return {
placement: 1234567,
network: '9599.1'
};
};

let getNexageGetBidParams = () => {
return {
dcn: '2c9d2b50015c5ce9db6aeeed8b9500d6',
pos: 'header'
};
};

let getNexagePostBidParams = () => {
return {
id: 'id-1',
imp: [{
id: 'id-2',
banner: {
w: '100',
h: '100'
},
tagid: 'header1'
}]
};
};

let getDefaultBidRequest = () => {
return {
bidderCode: 'aol',
Expand All @@ -34,15 +62,15 @@ let getDefaultBidRequest = () => {
bidderRequestId: '7101db09af0db2',
requestId: 'd3e07445-ab06-44c8-a9dd-5ef9af06d2a6',
placementCode: 'foo',
params: {
placement: 1234567,
network: '9599.1'
}
params: getMarketplaceBidParams()
}]
};
};

describe('AolAdapter', () => {
const MARKETPLACE_URL = 'adserver-us.adtech.advertising.com/pubapi/3.0/';
const NEXAGE_URL = 'hb.nexage.com/bidRequest?';

let adapter;

beforeEach(() => adapter = new AolAdapter());
Expand Down Expand Up @@ -83,7 +111,57 @@ describe('AolAdapter', () => {

it('should hit the Marketplace api endpoint with the Marketplace config', () => {
adapter.callBids(getDefaultBidRequest());
expect(requests[0].url).to.contain('adserver-us.adtech.advertising.com/pubapi/3.0/');
expect(requests[0].url).to.contain(MARKETPLACE_URL);
});

it('should hit the Marketplace via onedisplay bidder code', () => {
let bidRequest = createBidderRequest({
bids: [{
bidder: 'onedisplay'
}],
params: getMarketplaceBidParams()
});

adapter.callBids(bidRequest);
expect(requests[0].url).to.contain(MARKETPLACE_URL);
});

it('should hit the Marketplace via onedisplay bidder code when Marketplace and Nexage params are present', () => {
let bidParams = Object.assign(getMarketplaceBidParams(), getNexageGetBidParams());
let bidRequest = createBidderRequest({
bids: [{
bidder: 'onedisplay'
}],
params: bidParams
});

adapter.callBids(bidRequest);
expect(requests[0].url).to.contain(MARKETPLACE_URL);
});

it('should hit the Marketplace via onedisplay bidder code when Nexage params are present', () => {
let bidParams = Object.assign(getMarketplaceBidParams(), getNexageGetBidParams(), getNexagePostBidParams());
let bidRequest = createBidderRequest({
bids: [{
bidder: 'onedisplay'
}],
params: bidParams
});

adapter.callBids(bidRequest);
expect(requests[0].url).to.contain(MARKETPLACE_URL);
});

it('should not resolve endpoint for onedisplay bidder code when only Nexage params are present', () => {
let bidParams = Object.assign(getNexageGetBidParams(), getNexagePostBidParams());

adapter.callBids(createBidderRequest({
bids: [{
bidder: 'onedisplay'
}],
params: bidParams
}));
expect(requests.length).to.equal(0);
});

it('should hit endpoint based on the region config option', () => {
Expand All @@ -105,7 +183,7 @@ describe('AolAdapter', () => {
region: 'an'
}
}));
expect(requests[0].url).to.contain('adserver-us.adtech.advertising.com/pubapi/3.0/');
expect(requests[0].url).to.contain(MARKETPLACE_URL);
});

it('should hit endpoint based on the server config option', () => {
Expand Down Expand Up @@ -238,33 +316,61 @@ describe('AolAdapter', () => {

it('should hit the nexage api endpoint with the nexage config', () => {
adapter.callBids(createBidderRequest({
params: {
dcn: '11223344',
pos: 'header-2324'
}
params: getNexageGetBidParams()
}));
expect(requests[0].url).to.contain('hb.nexage.com/bidRequest?');

expect(requests[0].url).to.contain(NEXAGE_URL);
});

it('should hit the nexage api custom endpoint if specified in the nexage config', () => {
let bidParams = Object.assign({
host: 'qa-hb.nexage.com'
}, getNexageGetBidParams());

adapter.callBids(createBidderRequest({
params: {
host: 'qa-hb.nexage.com',
dcn: '11223344',
pos: 'header-2324'
}
params: bidParams
}));
expect(requests[0].url).to.contain('qa-hb.nexage.com/bidRequest?');
});

it('should hit nexage api when nexage and marketplace params are present', () => {
let bidParams = Object.assign(getNexageGetBidParams(), getMarketplaceBidParams());

adapter.callBids(createBidderRequest({
params: bidParams
}));
expect(requests[0].url).to.contain(NEXAGE_URL);
});

it('should hit nexage api via onemobile bidder code when nexage and marketplace params are present', () => {
let bidParams = Object.assign(getNexageGetBidParams(), getMarketplaceBidParams());

adapter.callBids(createBidderRequest({
bids: [{
bidder: 'onemobile'
}],
params: bidParams
}));
expect(requests[0].url).to.contain(NEXAGE_URL);
});

it('should not resolve endpoint for onemobile bidder code when only Marketplace params are present', () => {
adapter.callBids(createBidderRequest({
bids: [{
bidder: 'onemobile'
}],
params: getMarketplaceBidParams()
}));

expect(requests.length).to.equal(0);
});

it('should contain required params - dcn & pos', () => {
adapter.callBids(createBidderRequest({
params: {
dcn: '54321123',
pos: 'footer-2324'
}
params: getNexageGetBidParams()
}));
expect(requests[0].url).to.contain('hb.nexage.com/bidRequest?dcn=54321123&pos=footer-2324');

expect(requests[0].url).to.contain(NEXAGE_URL + 'dcn=2c9d2b50015c5ce9db6aeeed8b9500d6&pos=header');
});

it('should contain cmd=bid by default', () => {
Expand Down Expand Up @@ -295,38 +401,21 @@ describe('AolAdapter', () => {
});

it('should hit the nexage api endpoint with post data with the openrtb config', () => {
let bidConfig = {
id: 'id-1',
imp: [{
id: 'id-2',
banner: {
w: '100',
h: '100'
},
tagid: 'header1'
}]
};
let bidConfig = getNexagePostBidParams();

adapter.callBids(createBidderRequest({
params: bidConfig
}));
expect(requests[0].url).to.contain('hb.nexage.com/bidRequest?');
expect(requests[0].url).to.contain(NEXAGE_URL);
expect(requests[0].requestBody).to.deep.equal(bidConfig);
expect(requests[0].requestHeaders).to.have.property('x-openrtb-version');
});

it('should not hit the nexage api endpoint with post data with the openrtb config' +
' if a required parameter is missing', () => {
let bidConfig = {
id: 'id-1',
imp: [{
// id: 'id-2',
banner: {
w: '100',
h: '100'
},
tagid: 'header1'
}]
};
let bidConfig = getNexagePostBidParams();

bidConfig.imp[0].id = null;
adapter.callBids(createBidderRequest({
params: bidConfig
}));
Expand Down