-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
EngageBDR legacy bid adapter (#2329)
* ebdrBidAdatper * Delete engage_test.html * fix Superfluous trailing arguments issue * add Legacy ebdr adapter test case * add Legacy ebdr adapter test case
- Loading branch information
1 parent
410eacc
commit aa32519
Showing
3 changed files
with
361 additions
and
0 deletions.
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 |
---|---|---|
@@ -0,0 +1,183 @@ | ||
var CONSTANTS = require('src/constants.json'); | ||
var utils = require('src/utils.js'); | ||
var bidfactory = require('src/bidfactory.js'); | ||
var bidmanager = require('src/bidmanager.js'); | ||
var adloader = require('src/adloader'); | ||
var adaptermanager = require('src/adaptermanager'); | ||
|
||
var defaultPlacementForBadBid = null; | ||
|
||
/** | ||
* Adapter for requesting bids from Ebdr | ||
*/ | ||
var EbdrAdapter = function EbdrAdapter() { | ||
var rtbServerDomain = 'dsp.bnmla.com'; | ||
var zoneid; | ||
function _callBids(params) { | ||
var ebdrBids = params.bids || []; | ||
_requestBids(_getTags(ebdrBids)); | ||
} | ||
|
||
// filter bids to de-dupe them? | ||
function _getTags(bids) { | ||
var key; | ||
// var map = {}; | ||
var PubZoneIds = []; | ||
|
||
for (key in bids) { | ||
PubZoneIds.push(bids[key]); | ||
zoneid = utils.getBidIdParameter('zoneid', bids[key].params); | ||
} | ||
|
||
return PubZoneIds; | ||
} | ||
|
||
function getWidthAndHeight(bid) { | ||
var adW = null; | ||
var adH = null; | ||
|
||
var sizeArrayLength = bid.sizes.length; | ||
if (sizeArrayLength === 2 && typeof bid.sizes[0] === 'number' && typeof bid.sizes[1] === 'number') { | ||
adW = bid.sizes[0]; | ||
adH = bid.sizes[1]; | ||
} else { | ||
adW = bid.sizes[0][0]; | ||
adH = bid.sizes[0][1]; | ||
} | ||
|
||
return [adW, adH]; | ||
} | ||
|
||
function _requestBids(bidReqs) { | ||
// build bid request object | ||
var domain = window.location.host; | ||
var page = window.location.pathname + location.search + location.hash; | ||
|
||
var ebdrImps = []; | ||
var ebdrParams = {}; | ||
// assign the first adUnit (placement) for bad bids; | ||
defaultPlacementForBadBid = bidReqs[0].placementCode; | ||
var bidderequestId = bidReqs[0].bidId; | ||
// build impression array for ebdr | ||
utils._each(bidReqs, function(bid) { | ||
var bidFloor = utils.getBidIdParameter('bidfloor', bid.params); | ||
|
||
var whArr = getWidthAndHeight(bid); | ||
ebdrParams['latitude'] = utils.getBidIdParameter('latitude', bid.params); | ||
ebdrParams['longitude'] = utils.getBidIdParameter('longitude', bid.params); | ||
ebdrParams['ifa'] = (utils.getBidIdParameter('IDFA', bid.params).length > utils.getBidIdParameter('ADID', bid.params).length) ? utils.getBidIdParameter('IDFA', bid.params) : utils.getBidIdParameter('ADID', bid.params); | ||
var imp = { | ||
id: bid.bidId, | ||
banner: { | ||
w: whArr[0], | ||
h: whArr[1] | ||
}, | ||
// tagid: tagId, | ||
bidfloor: bidFloor | ||
}; | ||
|
||
ebdrImps.push(imp); | ||
if (bid.params.ebdrDomain != undefined) { | ||
rtbServerDomain = bid.params.ebdrDomain; | ||
} | ||
}); | ||
|
||
// build bid request with impressions | ||
var ebdrBidReq = { | ||
id: bidderequestId, | ||
imp: ebdrImps, | ||
site: { | ||
domain: domain, | ||
page: page | ||
}, | ||
device: { | ||
geo: { | ||
lat: ebdrParams.latitude, | ||
log: ebdrParams.longitude | ||
}, | ||
ifa: ebdrParams.ifa | ||
} | ||
}; | ||
|
||
var scriptUrl = window.location.protocol + '//' + rtbServerDomain + '/hb?callback=window.$$PREBID_GLOBAL$$.ebdrResponse' + | ||
'&zoneid=' + zoneid + '&br=' + encodeURIComponent(JSON.stringify(ebdrBidReq)); | ||
|
||
adloader.loadScript(scriptUrl); | ||
} | ||
|
||
function noBidResponse(bidReqs) { | ||
// no response data | ||
if (!bidReqs.zoneId) { | ||
// no id with which to create an dummy bid | ||
return; | ||
} | ||
|
||
var bid = bidfactory.createBid(2); | ||
bid.bidderCode = 'ebdr'; | ||
bidmanager.addBidResponse(defaultPlacementForBadBid, bid); | ||
} | ||
|
||
// expose the callback to the global object: | ||
$$PREBID_GLOBAL$$.ebdrResponse = function(ebdrResponseObj) { | ||
var bid = {}; | ||
var key; | ||
// valid object? | ||
if (!ebdrResponseObj || !ebdrResponseObj.id) { | ||
return noBidResponse(ebdrResponseObj); | ||
} | ||
|
||
if (!ebdrResponseObj.seatbid || ebdrResponseObj.seatbid.length === 0 || !ebdrResponseObj.seatbid[0].bid || ebdrResponseObj.seatbid[0].bid.length === 0) { | ||
return noBidResponse(ebdrResponseObj); | ||
} | ||
|
||
for (key in ebdrResponseObj.seatbid[0].bid) { | ||
var ebdrBid = ebdrResponseObj.seatbid[0].bid[key]; | ||
|
||
var responseCPM; | ||
var placementCode = ''; | ||
var id = ebdrBid.impid; | ||
// try to fetch the bid request we sent Ebdr | ||
var bidObj = $$PREBID_GLOBAL$$._bidsRequested.find(bidSet => bidSet.bidderCode === 'ebdr').bids.find(bid => bid.bidId === id); | ||
if (!bidObj) { | ||
return noBidResponse(ebdrBid); | ||
} | ||
|
||
placementCode = bidObj.placementCode; | ||
bidObj.status = CONSTANTS.STATUS.GOOD; | ||
|
||
// place ad response on bidmanager._adResponsesByBidderId | ||
responseCPM = parseFloat(ebdrBid.price); | ||
|
||
if (responseCPM === 0) { | ||
noBidResponse(ebdrBid); | ||
} | ||
|
||
ebdrBid.placementCode = placementCode; | ||
ebdrBid.size = bidObj.sizes; | ||
var responseAd = ebdrBid.adm; | ||
|
||
// store bid response | ||
// bid status is good (indicating 1) | ||
bid = bidfactory.createBid(1); | ||
bid.creative_id = ebdrBid.Id; | ||
bid.bidderCode = 'ebdr'; | ||
bid.cpm = responseCPM; | ||
|
||
// The bid is a mock bid, the true bidding process happens after the publisher tag is called | ||
bid.ad = decodeURIComponent(responseAd); | ||
|
||
var whArr = getWidthAndHeight(bidObj); | ||
bid.width = whArr[0]; | ||
bid.height = whArr[1]; | ||
|
||
bidmanager.addBidResponse(placementCode, bid); | ||
} | ||
}; // ebdrResponse | ||
return { | ||
callBids: _callBids | ||
}; | ||
}; | ||
|
||
adaptermanager.registerBidAdapter(new EbdrAdapter(), 'ebdr'); | ||
|
||
module.exports = EbdrAdapter; |
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,43 @@ | ||
# Overview | ||
|
||
**Module Name**: Ebdr Bidder Adapter | ||
**Module Type**: Bidder Adapter | ||
**Maintainer**: tech@engagebdr.com | ||
|
||
# Description | ||
|
||
Module that connects to Ebdr demand source to fetch bids. | ||
|
||
# Test Parameters | ||
``` | ||
var adUnits = [{ | ||
code: 'div-gpt-ad-1460505748561-0', | ||
sizes: [[300, 250], [300,600]], | ||
bids: [{ | ||
bidder: 'ebdr', | ||
params: { | ||
zoneid: '99999', | ||
bidfloor: '1.00', | ||
IDFA:'xxx-xxx', | ||
ADID:'xxx-xxx', | ||
latitude:'34.089811', | ||
longitude:'-118.392805' | ||
} | ||
}] | ||
},{ | ||
code: 'div-gpt-ad-1460505748561-1', | ||
sizes: [[728, 90], [970, 90]], | ||
bids: [{ | ||
bidder: 'ebdr', | ||
params: { | ||
zoneid: '99999', | ||
bidfloor: '1.00', | ||
IDFA:'xxx-xxx', | ||
ADID:'xxx-xxx', | ||
latitude:'34.089811', | ||
longitude:'-118.392805' | ||
} | ||
}] | ||
} | ||
]; | ||
``` |
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,135 @@ | ||
var chai = require('chai'); | ||
var Adapter = require('modules/ebdrBidAdapter')(); | ||
var adLoader = require('src/adloader'); | ||
var bidmanager = require('src/bidmanager.js'); | ||
var CONSTANTS = require('src/constants.json'); | ||
|
||
describe('ebdrBidAdapter', function () { | ||
var sandbox; | ||
var bidsRequestedOriginal; | ||
const validBid_1 = { | ||
bidderCode: 'ebdr', | ||
bids: [ | ||
{ | ||
bidder: 'ebdr', | ||
bidId: 'bid_id', | ||
// bidderRequestId: 'ebdr1', | ||
params: { | ||
zoneid: '99999', | ||
bidfloor: '1.00', | ||
IDFA: 'xxx-xxx', | ||
ADID: 'xxx-xxx', | ||
latitude: '34.089811', | ||
longitude: '-118.392805' | ||
}, | ||
placementCode: 'div-gpt-ad-1460505748561-0', | ||
sizes: [[300, 250], [800, 600]] | ||
} | ||
] | ||
}; | ||
var invalidBid = { | ||
bidderCode: 'ebdr', | ||
bids: [ | ||
{ | ||
bidder: 'ebdr', | ||
bidId: 'bid_id', | ||
params: {}, | ||
placementCode: 'div-gpt-ad-1460505748561-0', | ||
sizes: [[300, 250]] | ||
} | ||
] | ||
}; | ||
|
||
var responseWithAd = {'id': 'bid_id', 'seatbid': [{'bid': [{'id': 'bid_id', 'impid': 'bid_id', 'price': 9.81, 'adid': 'abcde-12345', 'nurl': 'http://rex.bnmla.com/pixel?not=1&sid=LRX8nxQ4gX&z=16&rx=1.3392&d=3&dt=3&s=16&px=1.007999', 'adm': '<div><img src="https://cdn0.bnmla.com/0b1c6e85e9376e3092df8c9fc8ab9095.gif" width=300 height=250 /></div>', 'adomain': ['advertiserdomain.com'], 'iurl': 'http://rex.bnmla.com/pixel?not=1&sid=LRX8nxQ4gX&z=16&rx=1.3392&d=3&dt=3&s=16&px=1.007999', 'cid': 'campaign1', 'crid': 'abcde-12345', 'w': 300, 'h': 250}], 'seat': '3d1ec0495ea735'}], 'bidid': '3d1ec0495ea735', 'cur': 'USD'}; | ||
var responseWithoutAd = JSON.stringify({ | ||
'cpm': 0, | ||
'url': 'http://p.ato.mx/placement?id=1234', | ||
'width': 300, | ||
'height': 250, | ||
'code': 'ad-unit-1' | ||
}); | ||
|
||
var responseEmpty = ''; | ||
var validJsonParams = { | ||
id: '1234', | ||
prebid: 'ad-unit-1', | ||
size: '300x250' | ||
}; | ||
|
||
beforeEach(() => { | ||
bidsRequestedOriginal = $$PREBID_GLOBAL$$._bidsRequested; | ||
$$PREBID_GLOBAL$$._bidsRequested = []; | ||
sandbox = sinon.sandbox.create(); | ||
}); | ||
|
||
afterEach(() => { | ||
sandbox.restore(); | ||
$$PREBID_GLOBAL$$._bidsRequested = bidsRequestedOriginal; | ||
}); | ||
|
||
describe('bid request', function() { | ||
let loadScript; | ||
beforeEach(function () { | ||
loadScript = sinon.stub(adLoader, 'loadScript'); | ||
}); | ||
afterEach(function () { | ||
loadScript.restore(); | ||
}); | ||
it('bid request with valid data', function () { | ||
Adapter.callBids(validBid_1); | ||
sinon.assert.calledOnce(loadScript); | ||
let url = loadScript.firstCall.args[0]; | ||
let callback = loadScript.firstCall.args[1]; | ||
expect(url).to.equal('http://dsp.bnmla.com/hb?callback=window.pbjs.ebdrResponse&zoneid=99999&br=%7B%22id%22%3A%22bid_id%22%2C%22imp%22%3A%5B%7B%22id%22%3A%22bid_id%22%2C%22banner%22%3A%7B%22w%22%3A300%2C%22h%22%3A250%7D%2C%22bidfloor%22%3A%221.00%22%7D%5D%2C%22site%22%3A%7B%22domain%22%3A%22localhost%3A9876%22%2C%22page%22%3A%22%2Fcontext.html%22%7D%2C%22device%22%3A%7B%22geo%22%3A%7B%22lat%22%3A%2234.089811%22%2C%22log%22%3A%22-118.392805%22%7D%2C%22ifa%22%3A%22xxx-xxx%22%7D%7D'); | ||
}); | ||
it('bid request with invalid data', function () { | ||
Adapter.callBids(invalidBid); | ||
sinon.assert.calledOnce(loadScript); | ||
let url = loadScript.firstCall.args[0]; | ||
let callback = loadScript.firstCall.args[1]; | ||
expect(url).to.equal('http://dsp.bnmla.com/hb?callback=window.pbjs.ebdrResponse&zoneid=&br=%7B%22id%22%3A%22bid_id%22%2C%22imp%22%3A%5B%7B%22id%22%3A%22bid_id%22%2C%22banner%22%3A%7B%22w%22%3A300%2C%22h%22%3A250%7D%2C%22bidfloor%22%3A%22%22%7D%5D%2C%22site%22%3A%7B%22domain%22%3A%22localhost%3A9876%22%2C%22page%22%3A%22%2Fcontext.html%22%7D%2C%22device%22%3A%7B%22geo%22%3A%7B%22lat%22%3A%22%22%2C%22log%22%3A%22%22%7D%2C%22ifa%22%3A%22%22%7D%7D'); | ||
}); | ||
}); | ||
describe('ebdrResponse', () => { | ||
it('should exist and be a function', () => { | ||
expect($$PREBID_GLOBAL$$.ebdrResponse).to.be.a('function'); | ||
}); | ||
}); | ||
|
||
describe('add bids to the manager', () => { | ||
let firstBid; | ||
|
||
beforeEach(() => { | ||
sandbox.stub(bidmanager, 'addBidResponse'); | ||
$$PREBID_GLOBAL$$._bidsRequested.push(validBid_1); | ||
$$PREBID_GLOBAL$$.ebdrResponse(responseWithAd); | ||
firstBid = bidmanager.addBidResponse.firstCall.args[1]; | ||
}); | ||
it('should add a bid object for each bid', () => { | ||
sinon.assert.calledOnce(bidmanager.addBidResponse); | ||
}); | ||
|
||
it('should pass the correct placement code as first param', () => { | ||
let firstPlacementCode = bidmanager.addBidResponse.firstCall.args[0]; | ||
|
||
expect(firstPlacementCode).to.eql('div-gpt-ad-1460505748561-0'); | ||
}); | ||
|
||
it('should have a good statusCode', () => { | ||
expect(firstBid.getStatusCode()).to.eql(1); | ||
}); | ||
|
||
it('should add the CPM to the bid object', () => { | ||
expect(firstBid).to.have.property('cpm', 9.81); | ||
}); | ||
|
||
it('should include the ad to the bid object', () => { | ||
expect(firstBid).to.have.property('ad'); | ||
}); | ||
|
||
it('should include the size to the bid object', () => { | ||
expect(firstBid).to.have.property('width', 300); | ||
expect(firstBid).to.have.property('height', 250); | ||
}); | ||
}); | ||
}); |