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.
AdGrid Bid Adapter : initial release (prebid#12152)
* Added AdGrid Adapter Files * Removed coppa
- Loading branch information
Showing
3 changed files
with
320 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,175 @@ | ||
import { _each, isEmpty, deepAccess } from '../src/utils.js'; | ||
import { config } from '../src/config.js'; | ||
import { registerBidder } from '../src/adapters/bidderFactory.js'; | ||
import { BANNER } from '../src/mediaTypes.js'; | ||
|
||
const BIDDER = Object.freeze({ | ||
CODE: 'adgrid', | ||
HOST: 'https://api-prebid.adgrid.io', | ||
REQUEST_METHOD: 'POST', | ||
REQUEST_ENDPOINT: '/api/v1/auction', | ||
SUPPORTED_MEDIA_TYPES: [BANNER], | ||
}); | ||
|
||
const CURRENCY = Object.freeze({ | ||
KEY: 'currency', | ||
US_DOLLAR: 'USD', | ||
}); | ||
|
||
function isBidRequestValid(bid) { | ||
if (!bid || !bid.params) { | ||
return false; | ||
} | ||
|
||
return !!bid.params.domainId; | ||
} | ||
|
||
/** | ||
* Return some extra params | ||
*/ | ||
function getAudience(validBidRequests, bidderRequest) { | ||
const params = { | ||
domain: deepAccess(bidderRequest, 'refererInfo.page') | ||
}; | ||
|
||
if (deepAccess(bidderRequest, 'gdprConsent.gdprApplies')) { | ||
params.gdpr = 1; | ||
params.gdprConsent = deepAccess(bidderRequest, 'gdprConsent.consentString'); | ||
} | ||
|
||
if (deepAccess(bidderRequest, 'uspConsent')) { | ||
params.usp = deepAccess(bidderRequest, 'uspConsent'); | ||
} | ||
|
||
if (deepAccess(validBidRequests[0], 'schain')) { | ||
params.schain = deepAccess(validBidRequests[0], 'schain'); | ||
} | ||
|
||
if (deepAccess(validBidRequests[0], 'userId')) { | ||
params.userIds = deepAccess(validBidRequests[0], 'userId'); | ||
} | ||
|
||
if (deepAccess(validBidRequests[0], 'userIdAsEids')) { | ||
params.userEids = deepAccess(validBidRequests[0], 'userIdAsEids'); | ||
} | ||
|
||
if (bidderRequest.gppConsent) { | ||
params.gpp = bidderRequest.gppConsent.gppString; | ||
params.gppSid = bidderRequest.gppConsent.applicableSections?.toString(); | ||
} else if (bidderRequest.ortb2?.regs?.gpp) { | ||
params.gpp = bidderRequest.ortb2.regs.gpp; | ||
params.gppSid = bidderRequest.ortb2.regs.gpp_sid; | ||
} | ||
|
||
return params; | ||
} | ||
|
||
function buildRequests(validBidRequests, bidderRequest) { | ||
const currencyObj = config.getConfig(CURRENCY.KEY); | ||
const currency = (currencyObj && currencyObj.adServerCurrency) ? currencyObj.adServerCurrency : 'USD'; | ||
const bids = []; | ||
|
||
_each(validBidRequests, bid => { | ||
bids.push(getBidData(bid)) | ||
}); | ||
|
||
const bidsParams = Object.assign({}, { | ||
url: window.location.href, | ||
timeout: bidderRequest.timeout, | ||
ts: new Date().getTime(), | ||
device: { | ||
size: [ | ||
window.screen.width, | ||
window.screen.height | ||
] | ||
}, | ||
bids | ||
}); | ||
|
||
// Add currency if not USD | ||
if (currency != null && currency != CURRENCY.US_DOLLAR) { | ||
bidsParams.cur = currency; | ||
} | ||
|
||
bidsParams.audience = getAudience(validBidRequests, bidderRequest); | ||
|
||
// Passing geo location data if found in prebid config | ||
bidsParams.geodata = config.getConfig('adgGeodata') || {}; | ||
|
||
return Object.assign({}, bidderRequest, { | ||
method: BIDDER.REQUEST_METHOD, | ||
url: `${BIDDER.HOST}${BIDDER.REQUEST_ENDPOINT}`, | ||
data: bidsParams, | ||
currency: currency, | ||
options: { | ||
withCredentials: false, | ||
contentType: 'application/json' | ||
} | ||
}); | ||
} | ||
|
||
function interpretResponse(response, bidRequest) { | ||
let bids = response.body; | ||
const bidResponses = []; | ||
|
||
if (isEmpty(bids)) { | ||
return bidResponses; | ||
} | ||
|
||
if (typeof bids !== 'object') { | ||
return bidResponses; | ||
} | ||
|
||
bids = bids.bids; | ||
|
||
bids.forEach((adUnit) => { | ||
const bidResponse = { | ||
requestId: adUnit.bidId, | ||
cpm: Number(adUnit.cpm), | ||
width: adUnit.width, | ||
height: adUnit.height, | ||
ttl: 300, | ||
creativeId: adUnit.creativeId, | ||
netRevenue: true, | ||
currency: adUnit.currency || bidRequest.currency, | ||
mediaType: adUnit.mediaType, | ||
ad: adUnit.ad, | ||
}; | ||
|
||
bidResponses.push(bidResponse); | ||
}); | ||
|
||
return bidResponses; | ||
} | ||
|
||
function getBidData(bid) { | ||
const bidData = { | ||
requestId: bid.bidId, | ||
tid: bid.ortb2Imp?.ext?.tid, | ||
deviceW: bid.ortb2?.device?.w, | ||
deviceH: bid.ortb2?.device?.h, | ||
deviceUa: bid.ortb2?.device?.ua, | ||
domain: bid.ortb2?.site?.publisher?.domain, | ||
domainId: bid.params.domainId, | ||
code: bid.adUnitCode | ||
}; | ||
|
||
if (bid.mediaTypes != null) { | ||
if (bid.mediaTypes.banner != null) { | ||
bidData.mediaType = 'banner'; | ||
bidData.sizes = bid.mediaTypes.banner.sizes; | ||
} | ||
} | ||
|
||
return bidData; | ||
} | ||
|
||
export const spec = { | ||
code: BIDDER.CODE, | ||
isBidRequestValid, | ||
buildRequests, | ||
interpretResponse, | ||
supportedMediaTypes: BIDDER.SUPPORTED_MEDIA_TYPES | ||
}; | ||
|
||
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,45 @@ | ||
# Overview | ||
|
||
**Module Name**: AdGrid Bidder Adapter | ||
**Module Type**: Bidder Adapter | ||
**Maintainer**: support@adgrid.io | ||
|
||
# Description | ||
|
||
The AdGrid Bidding Adapter requires setup and approval before beginning. Please reach out to <support@adgrid.io> for more details. | ||
|
||
# Test Parameters | ||
|
||
```javascript | ||
var adUnits = [ | ||
// Banner adUnit | ||
{ | ||
code: 'test-div-1', | ||
mediaTypes:{ | ||
banner:{ | ||
sizes: [[300, 250]] | ||
} | ||
} | ||
bids: [{ | ||
bidder: 'adgrid', | ||
params: { | ||
domainId: 12345 | ||
} | ||
}] | ||
}, | ||
{ | ||
code: 'test-div-2', | ||
mediaTypes:{ | ||
banner:{ | ||
sizes: [[728, 90], [320, 50]] | ||
} | ||
} | ||
bids: [{ | ||
bidder: 'adgrid', | ||
params: { | ||
domainId: 67890 | ||
} | ||
}] | ||
} | ||
]; | ||
``` |
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,100 @@ | ||
import { expect } from 'chai'; | ||
import { spec } from '../../../modules/adgridBidAdapter.js' | ||
|
||
const globalConfig = { | ||
method: 'POST', | ||
endPoint: 'https://api-prebid.adgrid.io/api/v1/auction' | ||
}; | ||
|
||
describe('AdGrid Bid Adapter', function () { | ||
const bannerRequest = [{ | ||
bidId: 123456, | ||
auctionId: 98765, | ||
mediaTypes: { | ||
banner: { | ||
sizes: [[300, 250]], | ||
} | ||
}, | ||
params: { | ||
domainId: 12345 | ||
} | ||
}]; | ||
|
||
describe('isBidRequestValid', function () { | ||
it('Should return true when domainId exist inside params object', function () { | ||
const isBidValid = spec.isBidRequestValid(bannerRequest[0]); | ||
expect(isBidValid).to.be.true; | ||
}); | ||
|
||
it('Should return false when domainId is not exist inside params object', function () { | ||
const isBidNotValid = spec.isBidRequestValid(null); | ||
expect(isBidNotValid).to.be.false; | ||
}); | ||
}); | ||
|
||
describe('buildRequests', function () { | ||
const request = spec.buildRequests(bannerRequest, bannerRequest[0]); | ||
const payload = request.data; | ||
const apiURL = request.url; | ||
const method = request.method; | ||
|
||
it('Test the request is not empty', function () { | ||
expect(request).to.not.be.empty; | ||
}); | ||
|
||
it('Test the request payload is not empty', function () { | ||
expect(payload).to.not.be.empty; | ||
}); | ||
|
||
it('Test the API End Point', function () { | ||
expect(apiURL).to.equal(globalConfig.endPoint); | ||
}); | ||
|
||
it('Test the API Method', function () { | ||
expect(method).to.equal(globalConfig.method); | ||
}); | ||
}); | ||
|
||
describe('interpretResponse', function () { | ||
const responseObj = { | ||
bids: [ | ||
{ | ||
bidId: '4b99f3428651c1', | ||
cpm: 7.7, | ||
ad: '<div>Ad Content</div>', | ||
creativeId: '9004', | ||
currency: 'USD', | ||
mediaType: 'banner', | ||
width: 320, | ||
height: 50, | ||
domainId: '2002', | ||
marketplaceId: '703', | ||
devices: 'desktop' | ||
} | ||
] | ||
}; | ||
|
||
it('Test the interpretResponse function', function () { | ||
const receivedBid = responseObj.bids[0]; | ||
const response = {}; | ||
response.body = responseObj; | ||
|
||
const bidRequest = {}; | ||
bidRequest.currency = 'USD'; | ||
|
||
const bidResponse = spec.interpretResponse(response, bidRequest); | ||
expect(bidResponse).to.not.be.empty; | ||
|
||
const bid = bidResponse[0]; | ||
expect(bid).to.not.be.empty; | ||
expect(bid.requestId).to.equal(receivedBid.bidId); | ||
expect(bid.ad).to.equal(receivedBid.ad); | ||
expect(bid.cpm).to.equal(receivedBid.cpm); | ||
expect(bid.mediaType).to.equal(receivedBid.mediaType); | ||
expect(bid.creativeId).to.equal(receivedBid.creativeId); | ||
expect(bid.width).to.equal(receivedBid.width); | ||
expect(bid.height).to.equal(receivedBid.height); | ||
expect(bid.currency).to.equal(receivedBid.currency); | ||
}); | ||
}); | ||
}); |