forked from prebid/Prebid.js
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add bid adapter for Ad Up Technology (prebid#2809)
- Loading branch information
1 parent
2bbcd71
commit 41205ac
Showing
3 changed files
with
372 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,79 @@ | ||
import * as utils from 'src/utils'; | ||
import { registerBidder } from 'src/adapters/bidderFactory'; | ||
import { BANNER } from 'src/mediaTypes' | ||
|
||
export const BIDDER_CODE = 'aduptech'; | ||
export const PUBLISHER_PLACEHOLDER = '{PUBLISHER}'; | ||
export const ENDPOINT_URL = window.location.protocol + '//rtb.d.adup-tech.com/prebid/' + PUBLISHER_PLACEHOLDER + '_bid'; | ||
export const ENDPOINT_METHOD = 'POST'; | ||
|
||
export const spec = { | ||
code: BIDDER_CODE, | ||
supportedMediaTypes: [BANNER], | ||
|
||
isBidRequestValid: (bid) => { | ||
return !!(bid && | ||
bid.sizes && | ||
bid.sizes.length > 0 && | ||
bid.params && | ||
bid.params.publisher && | ||
bid.params.placement); | ||
}, | ||
|
||
buildRequests: (validBidRequests, bidderRequest) => { | ||
const bidRequests = []; | ||
|
||
// collect GDPR information | ||
let gdpr = null; | ||
if (bidderRequest && bidderRequest.gdprConsent) { | ||
gdpr = { | ||
consentString: bidderRequest.gdprConsent.consentString, | ||
consentRequired: (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true | ||
}; | ||
} | ||
|
||
validBidRequests.forEach((bidRequest) => { | ||
bidRequests.push({ | ||
url: ENDPOINT_URL.replace(PUBLISHER_PLACEHOLDER, encodeURIComponent(bidRequest.params.publisher)), | ||
method: ENDPOINT_METHOD, | ||
data: { | ||
pageUrl: utils.getTopWindowUrl(), | ||
referrer: utils.getTopWindowReferrer(), | ||
bidId: bidRequest.bidId, | ||
auctionId: bidRequest.auctionId, | ||
transactionId: bidRequest.transactionId, | ||
adUnitCode: bidRequest.adUnitCode, | ||
sizes: bidRequest.sizes, | ||
params: bidRequest.params, | ||
gdpr: gdpr | ||
} | ||
}); | ||
}); | ||
|
||
return bidRequests; | ||
}, | ||
|
||
interpretResponse: (response) => { | ||
const bidResponses = []; | ||
|
||
if (!response.body || !response.body.bid || !response.body.creative) { | ||
return bidResponses; | ||
} | ||
|
||
bidResponses.push({ | ||
requestId: response.body.bid.bidId, | ||
cpm: response.body.bid.price, | ||
netRevenue: response.body.bid.net, | ||
currency: response.body.bid.currency, | ||
ttl: response.body.bid.ttl, | ||
creativeId: response.body.creative.id, | ||
width: response.body.creative.width, | ||
height: response.body.creative.height, | ||
ad: response.body.creative.html | ||
}); | ||
|
||
return bidResponses; | ||
} | ||
}; | ||
|
||
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,32 @@ | ||
# Overview | ||
|
||
``` | ||
Module Name: Ad Up Technology Bid Adapter | ||
Module Type: Bidder Adapter | ||
Maintainer: steffen.anders@adup-tech.com, berlin@adup-tech.com | ||
``` | ||
|
||
# Description | ||
|
||
Connects to Ad Up Technology demand sources to fetch bids. | ||
Please use ```aduptech``` as bidder code. Only banner formats are supported. | ||
|
||
The Ad Up Technology Bidding adapter requires setup and approval before beginning. | ||
For more information visit [www.adup-tech.com](http://www.adup-tech.com/en). | ||
|
||
# Test Parameters | ||
``` | ||
var adUnits = [ | ||
{ | ||
code: 'banner', | ||
sizes: [[300, 250], [300, 600]], | ||
bids: [{ | ||
bidder: 'aduptech', | ||
params: { | ||
publisher: 'prebid', | ||
placement: '12345' | ||
} | ||
}] | ||
} | ||
]; | ||
``` |
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,261 @@ | ||
import { expect } from 'chai'; | ||
import { BIDDER_CODE, PUBLISHER_PLACEHOLDER, ENDPOINT_URL, ENDPOINT_METHOD, spec } from 'modules/aduptechBidAdapter'; | ||
import { newBidder } from 'src/adapters/bidderFactory'; | ||
import * as utils from 'src/utils'; | ||
|
||
describe('AduptechBidAdapter', () => { | ||
const adapter = newBidder(spec); | ||
|
||
describe('inherited functions', () => { | ||
it('exists and is a function', () => { | ||
expect(adapter.callBids).to.exist.and.to.be.a('function'); | ||
}); | ||
}); | ||
|
||
describe('isBidRequestValid', () => { | ||
it('should return true when necessary information is given', () => { | ||
expect(spec.isBidRequestValid({ | ||
sizes: [[100, 200]], | ||
params: { | ||
publisher: 'test', | ||
placement: '1234' | ||
} | ||
})).to.be.true; | ||
}); | ||
|
||
it('should return false on empty bid', () => { | ||
expect(spec.isBidRequestValid({})).to.be.false; | ||
}); | ||
|
||
it('should return false on missing sizes', () => { | ||
expect(spec.isBidRequestValid({ | ||
params: { | ||
publisher: 'test', | ||
placement: '1234' | ||
} | ||
})).to.be.false; | ||
}); | ||
|
||
it('should return false on empty sizes', () => { | ||
expect(spec.isBidRequestValid({ | ||
sizes: [], | ||
params: { | ||
publisher: 'test', | ||
placement: '1234' | ||
} | ||
})).to.be.false; | ||
}); | ||
|
||
it('should return false on missing params', () => { | ||
expect(spec.isBidRequestValid({ | ||
sizes: [[100, 200]], | ||
})).to.be.false; | ||
}); | ||
|
||
it('should return false on invalid params', () => { | ||
expect(spec.isBidRequestValid({ | ||
sizes: [[100, 200]], | ||
params: 'bar' | ||
})).to.be.false; | ||
}); | ||
|
||
it('should return false on empty params', () => { | ||
expect(spec.isBidRequestValid({ | ||
sizes: [[100, 200]], | ||
params: {} | ||
})).to.be.false; | ||
}); | ||
|
||
it('should return false on missing publisher', () => { | ||
expect(spec.isBidRequestValid({ | ||
sizes: [[100, 200]], | ||
params: { | ||
placement: '1234' | ||
} | ||
})).to.be.false; | ||
}); | ||
|
||
it('should return false on missing placement', () => { | ||
expect(spec.isBidRequestValid({ | ||
sizes: [[100, 200]], | ||
params: { | ||
publisher: 'test' | ||
} | ||
})).to.be.false; | ||
}); | ||
}); | ||
|
||
describe('buildRequests', () => { | ||
it('should send one bid request per ad unit to the endpoint via POST', () => { | ||
const bidRequests = [ | ||
{ | ||
bidder: BIDDER_CODE, | ||
bidId: 'bidId1', | ||
adUnitCode: 'adUnitCode1', | ||
transactionId: 'transactionId1', | ||
auctionId: 'auctionId1', | ||
sizes: [[100, 200], [300, 400]], | ||
params: { | ||
publisher: 'publisher1', | ||
placement: 'placement1' | ||
} | ||
}, | ||
{ | ||
bidder: BIDDER_CODE, | ||
bidId: 'bidId2', | ||
adUnitCode: 'adUnitCode2', | ||
transactionId: 'transactionId2', | ||
auctionId: 'auctionId2', | ||
sizes: [[500, 600]], | ||
params: { | ||
publisher: 'publisher2', | ||
placement: 'placement2' | ||
} | ||
} | ||
]; | ||
|
||
const result = spec.buildRequests(bidRequests); | ||
expect(result.length).to.equal(2); | ||
|
||
expect(result[0].url).to.equal(ENDPOINT_URL.replace(PUBLISHER_PLACEHOLDER, bidRequests[0].params.publisher)); | ||
expect(result[0].method).to.equal(ENDPOINT_METHOD); | ||
expect(result[0].data).to.deep.equal({ | ||
pageUrl: utils.getTopWindowUrl(), | ||
referrer: utils.getTopWindowReferrer(), | ||
bidId: bidRequests[0].bidId, | ||
auctionId: bidRequests[0].auctionId, | ||
transactionId: bidRequests[0].transactionId, | ||
adUnitCode: bidRequests[0].adUnitCode, | ||
sizes: bidRequests[0].sizes, | ||
params: bidRequests[0].params, | ||
gdpr: null | ||
}); | ||
|
||
expect(result[1].url).to.equal(ENDPOINT_URL.replace(PUBLISHER_PLACEHOLDER, bidRequests[1].params.publisher)); | ||
expect(result[1].method).to.equal(ENDPOINT_METHOD); | ||
expect(result[1].data).to.deep.equal({ | ||
pageUrl: utils.getTopWindowUrl(), | ||
referrer: utils.getTopWindowReferrer(), | ||
bidId: bidRequests[1].bidId, | ||
auctionId: bidRequests[1].auctionId, | ||
transactionId: bidRequests[1].transactionId, | ||
adUnitCode: bidRequests[1].adUnitCode, | ||
sizes: bidRequests[1].sizes, | ||
params: bidRequests[1].params, | ||
gdpr: null | ||
}); | ||
}); | ||
|
||
it('should pass gdpr informations', () => { | ||
const bidderRequest = { | ||
gdprConsent: { | ||
consentString: 'consentString', | ||
gdprApplies: true | ||
} | ||
}; | ||
const bidRequests = [ | ||
{ | ||
bidder: BIDDER_CODE, | ||
bidId: 'bidId3', | ||
adUnitCode: 'adUnitCode3', | ||
transactionId: 'transactionId3', | ||
auctionId: 'auctionId3', | ||
sizes: [[100, 200], [300, 400]], | ||
params: { | ||
publisher: 'publisher3', | ||
placement: 'placement3' | ||
} | ||
} | ||
]; | ||
|
||
const result = spec.buildRequests(bidRequests, bidderRequest); | ||
expect(result.length).to.equal(1); | ||
expect(result[0].data.gdpr).to.exist; | ||
expect(result[0].data.gdpr.consentRequired).to.exist.and.to.equal(bidderRequest.gdprConsent.gdprApplies); | ||
expect(result[0].data.gdpr.consentString).to.exist.and.to.equal(bidderRequest.gdprConsent.consentString); | ||
}); | ||
|
||
it('should encode publisher param in endpoint url', () => { | ||
const bidRequests = [ | ||
{ | ||
bidder: BIDDER_CODE, | ||
bidId: 'bidId1', | ||
adUnitCode: 'adUnitCode1', | ||
transactionId: 'transactionId1', | ||
auctionId: 'auctionId1', | ||
sizes: [[100, 200]], | ||
params: { | ||
publisher: 'crazy publisher key äÖÜ', | ||
placement: 'placement1' | ||
} | ||
}, | ||
]; | ||
|
||
const result = spec.buildRequests(bidRequests); | ||
|
||
expect(result[0].url).to.equal(ENDPOINT_URL.replace(PUBLISHER_PLACEHOLDER, encodeURIComponent(bidRequests[0].params.publisher))); | ||
}); | ||
|
||
it('should handle empty bidRequests', () => { | ||
expect(spec.buildRequests([])).to.deep.equal([]); | ||
}); | ||
}); | ||
|
||
describe('interpretResponse', () => { | ||
it('should correctly interpret the server response', () => { | ||
const serverResponse = { | ||
body: { | ||
bid: { | ||
bidId: 'bidId1', | ||
price: 0.12, | ||
net: true, | ||
currency: 'EUR', | ||
ttl: 123 | ||
}, | ||
creative: { | ||
id: 'creativeId1', | ||
width: 100, | ||
height: 200, | ||
html: '<div>Hello World</div>' | ||
} | ||
} | ||
}; | ||
|
||
const result = spec.interpretResponse(serverResponse); | ||
|
||
expect(result).to.deep.equal([ | ||
{ | ||
requestId: serverResponse.body.bid.bidId, | ||
cpm: serverResponse.body.bid.price, | ||
netRevenue: serverResponse.body.bid.net, | ||
currency: serverResponse.body.bid.currency, | ||
ttl: serverResponse.body.bid.ttl, | ||
creativeId: serverResponse.body.creative.id, | ||
width: serverResponse.body.creative.width, | ||
height: serverResponse.body.creative.height, | ||
ad: serverResponse.body.creative.html | ||
} | ||
]); | ||
}); | ||
|
||
it('should handle empty serverResponse', () => { | ||
expect(spec.interpretResponse({})).to.deep.equal([]); | ||
}); | ||
|
||
it('should handle missing bid', () => { | ||
expect(spec.interpretResponse({ | ||
body: { | ||
creative: {} | ||
} | ||
})).to.deep.equal([]); | ||
}); | ||
|
||
it('should handle missing creative', () => { | ||
expect(spec.interpretResponse({ | ||
body: { | ||
bid: {} | ||
} | ||
})).to.deep.equal([]); | ||
}); | ||
}); | ||
}); |