diff --git a/adapters.json b/adapters.json index b9ec1b70cd2..1d513b99899 100644 --- a/adapters.json +++ b/adapters.json @@ -66,6 +66,7 @@ "atomx", "tapsense", "trion", + "eplanning", "prebidServer", "adsupply", { diff --git a/src/adapters/eplanning.js b/src/adapters/eplanning.js new file mode 100644 index 00000000000..fd4acc0e047 --- /dev/null +++ b/src/adapters/eplanning.js @@ -0,0 +1,280 @@ +var bidfactory = require('src/bidfactory.js'); +var bidmanager = require('src/bidmanager.js'); + +var EPlanningAdapter = function EPlanningAdapter() { + (function() { + var win = window, doc = win.document, pbjs = win.pbjs, _global = {}, _default = { 'sv': 'ads.us.e-planning.net', 't': 0 }, rnd, FILE = 'file', CALLBACK_FUNCTION = 'hbpb.rH', NULL_SIZE = '1x1', _csRequested = [], PROTO = location.protocol === 'https:' ? 'https:' : 'http:', ISV = 'aklc.img.e-planning.net'; + function Hbpb() { + var slots = (function() { + var _data = []; + function Slot(slotId) { + var data = _data[slotId]; + function hasAds() { + return _data[slotId].ads.length; + } + function getSizes() { + return data.sizes; + } + function getSizesString() { + var s = [], i, sizes = getSizes(); + if (sizes && sizes.length) { + if (typeof sizes[0] === 'object') { + for (i = 0; i < sizes.length; i++) { + s.push(sizes[i][0] + 'x' + sizes[i][1]); + } + } else { + s.push(sizes[0] + 'x' + sizes[1]); + } + } else { + return NULL_SIZE; + } + return s.join(','); + } + return { + getPlacementCode: function() { + return data.placementCode; + }, + getString: function() { + return this.getPlacementCode() + ':' + getSizesString(); + }, + addAd: function(ad) { + _data[slotId].ads.push(ad); + }, + getFormatedResponse: function() { + var ad, that = this; + if (hasAds()) { + ad = data.ads[0]; + return { + 'placementCode': that.getPlacementCode(), + 'ad': { + 'ad': ad.adm, + 'cpm': ad.pr, + 'width': ad.size.w, + 'height': ad.size.h + } + }; + } else { + return { 'placementCode': that.getPlacementCode() }; + } + } + }; + } + function findAll() { + var i = 0, r = []; + for (i = 0; i < _data.length; i++) { + r.push(new Slot(i)); + } + return r; + } + return { + add: function(slot) { + slot.ads = []; + _data.push(slot); + }, + get: function(slotId) { + return new Slot(slotId); + }, + getString: function() { + var _slots = [], i, slot; + for (i = 0; i < _data.length; i++) { + slot = this.get(i); + _slots.push(slot.getString()); + } + return _slots.join('+'); + }, + findByPlacementCode: function(placementCode) { + var i, _slots = findAll(); + for (i = 0; i < _slots.length; i++) { + if (_slots[i].getPlacementCode() === placementCode) { + return _slots[i]; + } + } + }, + getFormatedResponse: function() { + var _slots = findAll(), i, r = []; + for (i = 0; i < _slots.length; i++) { + r.push(_slots[i].getFormatedResponse()); + } + return { + 'bids': r + }; + } + }; + })(); + function call(params) { + var i, bids = params.bids; + for (i = 0; i < bids.length; i++) { + slots.add({ + _raw: bids[i], + placementCode: bids[i].placementCode, + sizes: bids[i].sizes + }); + setGlobalParam('sv', bids[i]); + setGlobalParam('ci', bids[i]); + setGlobalParam('t', bids[i]); + } + doRequest(); + } + function setGlobalParam(param, bid) { + if (!_global[param]) { + if (bid && bid.params && bid.params[param]) { + _global[param] = bid.params[param]; + } + } + } + function getGlobalParam(param) { + return (_global[param] || _default[param]); + } + function getRandom() { + if (!rnd) { + rnd = Math.random(); + } + return rnd; + } + function getDocURL() { + return escape(win.location.href || FILE); + } + function getReferrerURL() { + return doc.referrer; + } + function getCallbackFunction() { + return CALLBACK_FUNCTION; + } + function doRequest() { + var clienteId = getGlobalParam('ci'), url, dfpClienteId = '1', sec = 'ROS', params = [], t = getGlobalParam('t'); + if (clienteId && !t) { + url = PROTO + '//' + getGlobalParam('sv') + '/hb/1/' + clienteId + '/' + dfpClienteId + '/' + (win.location.hostname || FILE) + '/' + sec + '?'; + params.push('rnd=' + getRandom()); + params.push('e=' + slots.getString()); + if (getDocURL()) { + params.push('ur=' + getDocURL()); + } + if (getReferrerURL()) { + params.push('fr=' + getReferrerURL()); + } + params.push('cb=' + getCallbackFunction()); + params.push('r=pbjs'); + url += params.join('&'); + load(url); + } else if (t) { + url = PROTO + '//' + ISV + '/layers/t_pbjs_' + t + '.js'; + load(url); + } + } + function load(url) { + var script = doc.createElement('script'); + script.src = url; + doc.body.appendChild(script); + } + function callback(response) { + if (pbjs && pbjs.processEPlanningResponse && typeof pbjs.processEPlanningResponse === 'function') { + pbjs.processEPlanningResponse(response); + } + } + function syncUsers(cs) { + var i, e, d; + for (i = 0; i < cs.length; i++) { + if (typeof cs[i] === 'string' && _csRequested.indexOf(cs[i]) === -1) { + (new Image()).src = cs[i]; + _csRequested.push(cs[i]); + } else if (typeof cs[i] === 'object' && _csRequested.indexOf(cs[i].u) === -1) { + if (cs[i].j) { + e = doc.createElement('script'); + e.src = cs[i].u; + } else if (cs[i].ifr) { + e = doc.createElement('iframe'); + e.src = cs[i].u; + e.style.width = e.style.height = '1px'; + e.display = 'none'; + } + if (cs[i].data) { + for (d in cs[i].data) { + if (cs[i].data.hasOwnProperty(d)) { + e.setAttribute('data-' + d, cs[i].data[d]); + } + } + } + doc.body.appendChild(e); + _csRequested.push(cs[i].u); + } + } + } + function rH(response) { + var slot, i, o; + if (response && response.sp && response.sp.length) { + for (i = 0; i < response.sp.length; i++) { + if (response.sp[i].a) { + slot = slots.findByPlacementCode(response.sp[i].k); + if (slot) { + for (o = 0; o < response.sp[i].a.length; o++) { + slot.addAd({ + 'adm': response.sp[i].a[o].adm, + 'pr': response.sp[i].a[o].pr, + 'size': { + 'w': response.sp[i].a[o].w, + 'h': response.sp[i].a[o].h + } + }); + } + } + } + } + callback(slots.getFormatedResponse()); + } + if (response && response.cs && response.cs.length) { + syncUsers(response.cs); + } + } + return { + call: function(params) { + return call(params); + }, + rH: function(response) { + return rH(response); + } + }; + } + win.hbpb = win.hbpb || new Hbpb(); + })(); + + window.pbjs = window.pbjs || {}; + window.pbjs.processEPlanningResponse = function(response) { + var bids, bidObject, i; + if (response) { + bids = response.bids; + for (i = 0; i < bids.length; i++) { + if (bids[i].ad) { + bidObject = getBidObject(bids[i]); + bidmanager.addBidResponse(bids[i].placementCode, bidObject); + } else { + bidObject = bidfactory.createBid(2); + bidObject.bidderCode = 'eplanning'; + bidmanager.addBidResponse(bids[i].placementCode, bidObject); + } + } + } + }; + + function getBidObject(bid) { + var bidObject = bidfactory.createBid(1), i; + bidObject.bidderCode = 'eplanning'; + for (i in bid.ad) { + if (bid.ad.hasOwnProperty(i)) { + bidObject[i] = bid.ad[i]; + } + } + return bidObject; + } + + function _callBids(params) { + if (window.hbpb) { + window.hbpb.call(params); + } + } + + return { + callBids: _callBids + }; +}; + +module.exports = EPlanningAdapter; diff --git a/test/spec/adapters/eplanning_spec.js b/test/spec/adapters/eplanning_spec.js new file mode 100644 index 00000000000..668392c169b --- /dev/null +++ b/test/spec/adapters/eplanning_spec.js @@ -0,0 +1,112 @@ +describe('eplanning adapter tests', function () { + var urlParse = require('url-parse'); + var querystringify = require('querystringify'); + var adapter = require('src/adapters/eplanning'); + var adLoader = require('src/adloader'); + var expect = require('chai').expect; + var bidmanager = require('src/bidmanager'); + var CONSTANTS = require('src/constants.json'); + + var DEFAULT_PARAMS = { + bidderCode: 'eplanning', + bids: [{ + code: 'div-gpt-ad-1460505748561-0', + sizes: [[300, 250], [300, 200]], + bidder: 'eplanning', + params: { + ci: '18f66' + } + }] + }; + + var PARAMS_SERVER_TEST = { + bidderCode: 'eplanning', + bids: [{ + code: 'div-gpt-ad-1460505748561-0', + sizes: [[300, 250], [300, 600]], + bidder: 'eplanning', + params: { + ci: '18f66', + t: '1' + } + }] + }; + + var RESPONSE_AD = { + bids: [{ + placementCode: 'div-gpt-ad-1460505748561-0', + ad: { + ad: '

test ad

', + cpm: 1, + width: 300, + height: 250 + } + }] + }; + + var RESPONSE_EMPTY = { + bids: [{ + placementCode: 'div-gpt-ad-1460505748561-0' + }] + }; + + var stubAddBidResponse; + + describe('eplanning tests', function() { + beforeEach(function() { + stubAddBidResponse = sinon.stub(bidmanager, 'addBidResponse'); + }); + afterEach(function() { + stubAddBidResponse.restore(); + }); + + it('callback function should exist', function() { + expect(pbjs.processEPlanningResponse).to.exist.and.to.be.a('function'); + }); + + it('creates a bid response if bid exists', function() { + adapter().callBids(DEFAULT_PARAMS); + pbjs.processEPlanningResponse(RESPONSE_AD); + + var bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; + var bidObject = stubAddBidResponse.getCall(0).args[1]; + + expect(bidPlacementCode).to.equal('div-gpt-ad-1460505748561-0'); + expect(bidObject.cpm).to.equal(1); + expect(bidObject.ad).to.equal('

test ad

'); + expect(bidObject.width).to.equal(300); + expect(bidObject.height).to.equal(250); + expect(bidObject.getStatusCode()).to.equal(1); + expect(bidObject.bidderCode).to.equal('eplanning'); + }); + + it('creates an empty bid response if there is no bid', function() { + adapter().callBids(DEFAULT_PARAMS); + pbjs.processEPlanningResponse(RESPONSE_EMPTY); + + var bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; + var bidObject = stubAddBidResponse.getCall(0).args[1]; + + expect(bidPlacementCode).to.equal('div-gpt-ad-1460505748561-0'); + expect(bidObject.getStatusCode()).to.equal(2); + expect(bidObject.bidderCode).to.equal('eplanning'); + }); + + it('creates a bid response and sync users register ad', function() { + adapter().callBids(DEFAULT_PARAMS); + window.hbpb.rH({ + 'sI': { 'k': '18f66' }, + 'sec': { 'k': 'ROS' }, + 'sp': [ { 'k': 'div-gpt-ad-1460505748561-0', 'a': [{ 'w': 300, 'h': 250, 'adm': '

test ad

', 'pr': 1 }] } ], + 'cs': [ + '//test.gif', + { 'j': true, u: '//test.js' }, + { 'ifr': true, u: '//test.html', data: { 'test': 1 } } + ] + }); + var bidPlacementCode = stubAddBidResponse.getCall(0).args[0]; + var bidObject = stubAddBidResponse.getCall(0).args[1]; + expect(bidObject.getStatusCode()).to.equal(2); + }); + }); +});