-
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.
* added automatad bid adapter * added automatad bid adapter readme * added automatad bidder adapter unit test * updated maintainer email id for automatad adapter * refactored automatadBidAdapter js * refactored automatadBidAdapter unit test * refactored automatadBidAdapter unit test * added usersync code to automatad bid adapter * Added unit test for onBidWon in automatadBidAdapter_spec * removed trailing spaces * removed trailing space * changes for getUserSync function * lint error fixes * updated usersync url * additional test for onBidWon function added * added ajax stub in test
- Loading branch information
1 parent
73d5861
commit 21d1f53
Showing
3 changed files
with
301 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,123 @@ | ||
import {registerBidder} from '../src/adapters/bidderFactory.js' | ||
import * as utils from '../src/utils.js' | ||
import {BANNER} from '../src/mediaTypes.js' | ||
import {ajax} from '../src/ajax.js' | ||
|
||
const BIDDER = 'automatad' | ||
|
||
const ENDPOINT_URL = 'https://rtb2.automatad.com/ortb2' | ||
|
||
const DEFAULT_BID_TTL = 30 | ||
const DEFAULT_CURRENCY = 'USD' | ||
const DEFAULT_NET_REVENUE = true | ||
|
||
export const spec = { | ||
code: BIDDER, | ||
aliases: ['atd'], | ||
supportedMediaTypes: [BANNER], | ||
|
||
isBidRequestValid: function (bid) { | ||
// will receive request bid. check if have necessary params for bidding | ||
return (bid && bid.hasOwnProperty('params') && bid.params.hasOwnProperty('siteId') && bid.params.hasOwnProperty('placementId') && bid.hasOwnProperty('mediaTypes') && bid.mediaTypes.hasOwnProperty('banner')) | ||
}, | ||
|
||
buildRequests: function (validBidRequests, bidderRequest) { | ||
if (!validBidRequests || !bidderRequest) { | ||
return | ||
} | ||
|
||
const siteId = validBidRequests[0].params.siteId | ||
const placementId = validBidRequests[0].params.placementId | ||
|
||
const impressions = validBidRequests.map(bidRequest => ({ | ||
id: bidRequest.bidId, | ||
banner: { | ||
format: bidRequest.sizes.map(sizeArr => ({ | ||
w: sizeArr[0], | ||
h: sizeArr[1], | ||
})) | ||
}, | ||
})) | ||
|
||
// params from bid request | ||
const openrtbRequest = { | ||
id: validBidRequests[0].auctionId, | ||
imp: impressions, | ||
site: { | ||
id: siteId, | ||
placement: placementId, | ||
domain: window.location.hostname, | ||
page: window.location.href, | ||
ref: bidderRequest.refererInfo ? bidderRequest.refererInfo.referer || null : null, | ||
}, | ||
} | ||
|
||
const payloadString = JSON.stringify(openrtbRequest) | ||
return { | ||
method: 'POST', | ||
url: ENDPOINT_URL + '/resp', | ||
data: payloadString, | ||
options: { | ||
contentType: 'application/json', | ||
withCredentials: false, | ||
crossOrigin: true, | ||
}, | ||
} | ||
}, | ||
|
||
interpretResponse: function (serverResponse, request) { | ||
const bidResponses = [] | ||
const response = (serverResponse || {}).body | ||
|
||
if (response && response.seatbid && response.seatbid.length === 1 && response.seatbid[0].bid && response.seatbid[0].bid.length) { | ||
response.seatbid[0].bid.forEach(bid => { | ||
bidResponses.push({ | ||
requestId: bid.impid, | ||
cpm: bid.price, | ||
ad: bid.adm, | ||
adDomain: bid.adomain[0], | ||
currency: DEFAULT_CURRENCY, | ||
ttl: DEFAULT_BID_TTL, | ||
creativeId: bid.crid, | ||
width: bid.w, | ||
height: bid.h, | ||
netRevenue: DEFAULT_NET_REVENUE, | ||
nurl: bid.nurl, | ||
}) | ||
}) | ||
} else { | ||
utils.logInfo('automatad :: no valid responses to interpret') | ||
} | ||
|
||
return bidResponses | ||
}, | ||
getUserSyncs: function(syncOptions, serverResponse) { | ||
return [{ | ||
type: 'iframe', | ||
url: 'https://rtb2.automatad.com/ortb2/async_usersync' | ||
}] | ||
}, | ||
onBidWon: function(bid) { | ||
if (!bid.nurl) { return } | ||
const winUrl = bid.nurl.replace( | ||
/\$\{AUCTION_PRICE\}/, | ||
bid.cpm | ||
).replace( | ||
/\$\{AUCTION_IMP_ID\}/, | ||
bid.requestId | ||
).replace( | ||
/\$\{AUCTION_CURRENCY\}/, | ||
bid.currency | ||
).replace( | ||
/\$\{AUCTION_ID\}/, | ||
bid.auctionId | ||
) | ||
spec.ajaxCall(winUrl, null) | ||
return true | ||
}, | ||
ajaxCall: function(endpoint, data) { | ||
ajax(endpoint, data) | ||
}, | ||
|
||
} | ||
registerBidder(spec) |
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,34 @@ | ||
# Overview | ||
|
||
``` | ||
Module Name: Automatad Bid Adapter | ||
Module Type: Bidder Adapter | ||
Maintainer: tech@automatad.com | ||
``` | ||
|
||
# Description | ||
|
||
Connects to automatad exchange for bids. | ||
|
||
automatad bid adapter supports Banner ads. | ||
|
||
# Test Parameters | ||
``` | ||
var adUnits = [ | ||
{ | ||
code: 'banner-ad-div', | ||
mediaTypes: { | ||
banner: { | ||
sizes: [[300, 250], [300,600]] | ||
} | ||
}, | ||
bids: [{ | ||
bidder: 'automatad', | ||
params: { | ||
siteId: 'someValue', | ||
placementId: 'someValue' | ||
} | ||
}] | ||
} | ||
]; | ||
``` |
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,144 @@ | ||
import { expect } from 'chai' | ||
import { spec } from 'modules/automatadBidAdapter.js' | ||
import { newBidder } from 'src/adapters/bidderFactory.js' | ||
|
||
describe('automatadBidAdapter', function () { | ||
const adapter = newBidder(spec) | ||
|
||
let bidRequest = { | ||
bidder: 'automatad', | ||
params: {siteId: '123ad', placementId: '123abc345'}, | ||
mediaTypes: { | ||
banner: { | ||
sizes: [[300, 600]], | ||
} | ||
}, | ||
adUnitCode: 'some-ad-unit-code', | ||
transactionId: '1465569e-52cc-4c36-88a1-7174cfef4b44', | ||
sizes: [[300, 600]], | ||
bidId: '123abc', | ||
bidderRequestId: '3213887463c059', | ||
auctionId: 'abc-123', | ||
src: 'client', | ||
bidRequestsCount: 1 | ||
} | ||
|
||
let expectedResponse = [{ | ||
'body': { | ||
'id': 'abc-123', | ||
'seatbid': [ | ||
{ | ||
'bid': [ | ||
{ | ||
'adm': '<!-- creative code -->', | ||
'adomain': [ | ||
'someAdDomain' | ||
], | ||
'crid': 123, | ||
'h': 600, | ||
'id': 'bid1', | ||
'impid': '1', | ||
'nurl': 'https://example/win', | ||
'price': 0.5, | ||
'w': 300 | ||
} | ||
] | ||
} | ||
] | ||
} | ||
}] | ||
|
||
describe('codes', function () { | ||
it('should return a bidder code of automatad', function () { | ||
expect(spec.code).to.equal('automatad') | ||
}) | ||
it('should alias atd', function () { | ||
expect(spec.aliases.length > 0 && spec.aliases[0] === 'atd').to.be.true | ||
}) | ||
}) | ||
|
||
describe('isBidRequestValid', function () { | ||
let inValidBid = Object.assign({}, bidRequest) | ||
delete inValidBid.params | ||
it('should return true if all params present', function () { | ||
expect(spec.isBidRequestValid(bidRequest)).to.equal(true) | ||
}) | ||
|
||
it('should return false if any parameter missing', function () { | ||
expect(spec.isBidRequestValid(inValidBid)).to.be.false | ||
}) | ||
}) | ||
|
||
describe('buildRequests', function () { | ||
let req = spec.buildRequests([ bidRequest ], { refererInfo: { } }) | ||
let rdata | ||
|
||
it('should return request object', function () { | ||
expect(req).to.not.be.null | ||
}) | ||
|
||
it('should build request data', function () { | ||
expect(req.data).to.not.be.null | ||
}) | ||
|
||
it('should include one request', function () { | ||
rdata = JSON.parse(req.data) | ||
expect(rdata.imp.length).to.equal(1) | ||
}) | ||
|
||
it('should include media types', function () { | ||
let r = rdata.imp[0] | ||
expect(r.media_types !== null).to.be.true | ||
}) | ||
|
||
it('should include all publisher params', function () { | ||
let r = rdata.imp[0] | ||
expect(r.siteID !== null && r.placementID !== null).to.be.true | ||
}) | ||
}) | ||
|
||
describe('interpretResponse', function () { | ||
it('should get the correct bid response', function () { | ||
let result = spec.interpretResponse(expectedResponse[0]) | ||
expect(result).to.be.an('array').that.is.not.empty | ||
}) | ||
|
||
it('handles empty bid response', function () { | ||
let response = { | ||
body: '' | ||
} | ||
let result = spec.interpretResponse(response) | ||
expect(result.length).to.equal(0) | ||
}) | ||
}) | ||
|
||
describe('getUserSyncs', function () { | ||
it('should return iframe sync', function () { | ||
let sync = spec.getUserSyncs() | ||
expect(sync.length).to.equal(1) | ||
expect(sync[0].type === 'iframe') | ||
expect(typeof sync[0].url === 'string') | ||
}) | ||
}) | ||
|
||
describe('onBidWon', function () { | ||
let serverResponses = spec.interpretResponse(expectedResponse[0]) | ||
let wonbid = serverResponses[0] | ||
let ajaxStub | ||
|
||
beforeEach(() => { | ||
ajaxStub = sinon.stub(spec, 'ajaxCall') | ||
}) | ||
|
||
afterEach(() => { | ||
ajaxStub.restore() | ||
}) | ||
|
||
it('Returns true is nurl is good/not blank', function () { | ||
expect(wonbid.nurl).to.not.equal('') | ||
expect(spec.onBidWon(wonbid)).to.be.true | ||
expect(ajaxStub.calledOnce).to.equal(true) | ||
expect(ajaxStub.firstCall.args[0].indexOf('https://')).to.equal(0) | ||
}) | ||
}) | ||
}) |