-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
initial version of ozone adapter for review #3307
Changes from 1 commit
6e128a2
63337de
16933c8
38daa6e
d010e09
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,230 @@ | ||
import * as utils from 'src/utils'; | ||
import { registerBidder } from 'src/adapters/bidderFactory'; | ||
|
||
const BIDDER_CODE = 'ozone'; | ||
|
||
var OZONEURI = 'https://elb.the-ozone-project.com/openrtb2/auction'; | ||
var OZONECOOKIESYNC = 'https://elb.the-ozone-project.com/static/load-cookie.html'; | ||
|
||
export const spec = { | ||
code: BIDDER_CODE, | ||
supportedFormat: ['banner'], | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. banner is default. No need to add supportedFormat if you only support banner There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
/** | ||
* Basic check to see whether required parameters are in the request. | ||
* @param bid | ||
* @returns {boolean} | ||
*/ | ||
isBidRequestValid(bid) { | ||
if (!(bid.params.hasOwnProperty('placementId'))) { | ||
console.log('OZONE BID ADAPTER VALIDATION FAILED : missing placementId : siteId, placementId and publisherId are REQUIRED'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use utils.logInfo here and all other places where console.log is used There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
return false; | ||
} | ||
if (!(bid.params.placementId).toString().match(/^[0-9]{10}$/)) { | ||
console.log('OZONE BID ADAPTER VALIDATION FAILED : placementId must be exactly 10 numeric characters'); | ||
return false; | ||
} | ||
if (!(bid.params.hasOwnProperty('publisherId'))) { | ||
console.log('OZONE BID ADAPTER VALIDATION FAILED : missing publisherId : siteId, placementId and publisherId are REQUIRED'); | ||
return false; | ||
} | ||
if (!(bid.params.publisherId).toString().match(/^[a-zA-Z0-9\-]{12}$/)) { | ||
console.log('OZONE BID ADAPTER VALIDATION FAILED : publisherId must be exactly 12 alphanumieric characters including hyphens'); | ||
return false; | ||
} | ||
if (!(bid.params.hasOwnProperty('siteId'))) { | ||
console.log('OZONE BID ADAPTER VALIDATION FAILED : missing siteId : siteId, placementId and publisherId are REQUIRED'); | ||
return false; | ||
} | ||
if (!(bid.params.siteId).toString().match(/^[0-9]{10}$/)) { | ||
console.log('OZONE BID ADAPTER VALIDATION FAILED : siteId must be exactly 10 numeric characters'); | ||
return false; | ||
} | ||
if (bid.params.hasOwnProperty('customData')) { | ||
if (typeof bid.params.customData !== 'object') { | ||
console.log('OZONE BID ADAPTER VALIDATION FAILED : customData is not an object'); | ||
return false; | ||
} | ||
} | ||
if (bid.params.hasOwnProperty('customParams')) { | ||
console.log('OZONE BID ADAPTER VALIDATION FAILED : customParams should be renamed to customData'); | ||
return false; | ||
} | ||
if (bid.params.hasOwnProperty('ozoneData')) { | ||
if (typeof bid.params.ozoneData !== 'object') { | ||
console.log('OZONE BID ADAPTER VALIDATION FAILED : ozoneData is not an object'); | ||
return false; | ||
} | ||
} | ||
if (bid.params.hasOwnProperty('lotameData')) { | ||
if (typeof bid.params.lotameData !== 'object') { | ||
console.log('OZONE BID ADAPTER VALIDATION FAILED : lotameData is not an object'); | ||
return false; | ||
} | ||
} | ||
return true; | ||
}, | ||
/** | ||
* @param serverResponse | ||
* @param request | ||
* @returns {*} | ||
*/ | ||
interpretResponse(serverResponse, request) { | ||
serverResponse = serverResponse.body || {}; | ||
if (serverResponse.seatbid) { | ||
if (utils.isArray(serverResponse.seatbid)) { | ||
const {seatbid: arrSeatbid} = serverResponse; | ||
let winnerAds = arrSeatbid.reduce((bid, ads) => { | ||
var _seat = ads.seat; | ||
let ad = ads.bid.reduce(function(currentWinningBid, considerBid) { | ||
if (currentWinningBid.price < considerBid.price) { | ||
const bid = matchRequest(considerBid.impid, request); | ||
const {width, height} = defaultSize(bid); | ||
considerBid.cpm = considerBid.price; | ||
considerBid.bidId = considerBid.impid; | ||
considerBid.requestId = considerBid.impid; | ||
considerBid.width = considerBid.w || width; | ||
considerBid.height = considerBid.h || height; | ||
considerBid.ad = considerBid.adm; | ||
considerBid.netRevenue = true; | ||
considerBid.creativeId = considerBid.crid; | ||
considerBid.currency = 'USD'; | ||
considerBid.ttl = 60; | ||
considerBid.seat = _seat; | ||
|
||
return considerBid; | ||
} else { | ||
currentWinningBid.cpm = currentWinningBid.price; | ||
return currentWinningBid; | ||
} | ||
}, {price: 0}); | ||
if (ad.adm) { | ||
bid.push(ad) | ||
} | ||
return bid; | ||
}, []) | ||
let winnersClean = winnerAds.filter(w => { | ||
if (w.bidId) { | ||
return true; | ||
} | ||
return false; | ||
}); | ||
console.log(['going to return winnersClean:', winnersClean]); | ||
return winnersClean; | ||
} else { | ||
return []; | ||
} | ||
} else { | ||
return []; | ||
} | ||
}, | ||
buildRequests(validBidRequests, bidderRequest) { | ||
let ozoneRequest = validBidRequests[0].params; | ||
ozoneRequest['id'] = utils.generateUUID(); | ||
ozoneRequest['auctionId'] = bidderRequest['auctionId']; | ||
|
||
if (bidderRequest.hasOwnProperty('placementId')) { | ||
bidderRequest.placementId = (bidderRequest.placementId).toString(); | ||
} | ||
if (bidderRequest.hasOwnProperty('siteId')) { | ||
bidderRequest.siteId = (bidderRequest.siteId).toString(); | ||
} | ||
if (bidderRequest.hasOwnProperty('publisherId')) { | ||
bidderRequest.publisherId = (bidderRequest.publisherId).toString(); | ||
} | ||
|
||
if (!ozoneRequest.test) { | ||
delete ozoneRequest.test; | ||
} | ||
if (bidderRequest.gdprConsent) { | ||
ozoneRequest.regs = {}; | ||
ozoneRequest.regs.ext = {}; | ||
ozoneRequest.regs.ext.gdpr = bidderRequest.gdprConsent.gdprApplies === true ? 1 : 0; | ||
if (ozoneRequest.regs.ext.gdpr) { | ||
ozoneRequest.regs.ext.consent = bidderRequest.gdprConsent.consentString; | ||
} | ||
} | ||
let tosendtags = validBidRequests.map(ozone => { | ||
var obj = {}; | ||
obj.id = ozone.bidId; | ||
obj.tagid = String(ozone.params.ozoneid); | ||
obj.secure = window.location.protocol === 'https:' ? 1 : 0; | ||
obj.banner = { | ||
topframe: 1, | ||
w: ozone.sizes[0][0] || 0, | ||
h: ozone.sizes[0][1] || 0, | ||
format: ozone.sizes.map(s => { | ||
return {w: s[0], h: s[1]}; | ||
}) | ||
}; | ||
if (ozone.params.hasOwnProperty('customData')) { | ||
obj.customData = ozone.params.customData; | ||
} | ||
if (ozone.params.hasOwnProperty('ozoneData')) { | ||
obj.ozoneData = ozone.params.ozoneData; | ||
} | ||
if (ozone.params.hasOwnProperty('lotameData')) { | ||
obj.lotameData = ozone.params.lotameData; | ||
} | ||
if (ozone.params.hasOwnProperty('publisherId')) { | ||
obj.publisherId = (ozone.params.publisherId).toString(); | ||
} | ||
if (ozone.params.hasOwnProperty('siteId')) { | ||
obj.siteId = (ozone.params.siteId).toString(); | ||
} | ||
obj.ext = {'prebid': {'storedrequest': {'id': (ozone.params.placementId).toString()}}}; | ||
return obj; | ||
}); | ||
ozoneRequest.imp = tosendtags; | ||
var ret = { | ||
method: 'POST', | ||
url: OZONEURI, | ||
data: JSON.stringify(ozoneRequest), | ||
bidderRequest: bidderRequest | ||
}; | ||
console.log(['buildRequests going to return', ret]); | ||
return ret; | ||
}, | ||
getUserSyncs(optionsType) { | ||
if (optionsType.iframeEnabled) { | ||
return [{ | ||
type: 'iframe', | ||
url: OZONECOOKIESYNC | ||
}]; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Function matchRequest(id: string, BidRequest: object) | ||
* @param id | ||
* @type string | ||
* @param bidRequest | ||
* @type Object | ||
* @returns Object | ||
* | ||
*/ | ||
export function matchRequest(id, bidRequest) { | ||
const {bids} = bidRequest.bidderRequest; | ||
const [returnValue] = bids.filter(bid => bid.bidId === id); | ||
return returnValue; | ||
} | ||
|
||
export function checkDeepArray(Arr) { | ||
if (Array.isArray(Arr)) { | ||
if (Array.isArray(Arr[0])) { | ||
return Arr[0]; | ||
} else { | ||
return Arr; | ||
} | ||
} else { | ||
return Arr; | ||
} | ||
} | ||
export function defaultSize(thebidObj) { | ||
const {sizes} = thebidObj; | ||
const returnObject = {}; | ||
returnObject.width = checkDeepArray(sizes)[0]; | ||
returnObject.height = checkDeepArray(sizes)[1]; | ||
return returnObject; | ||
} | ||
registerBidder(spec); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
|
||
# Overview | ||
|
||
``` | ||
Module Name: Ozone Project Bidder Adapter | ||
Module Type: Bidder Adapter | ||
Maintainer: engineering@ozoneproject.com | ||
``` | ||
|
||
# Description | ||
|
||
Module that connects to the Ozone Project's demand source(s). | ||
|
||
The Ozone Project bid adapter supports Banner mediaTypes ONLY. | ||
|
||
# Test Parameters | ||
|
||
|
||
A test ad unit that will consistently return test creatives: | ||
|
||
``` | ||
//Banner adUnit | ||
adUnits = [{ | ||
code: 'id-of-your-banner-div', | ||
mediaTypes: { | ||
banner: { | ||
sizes: [[300, 250], [300,600]] | ||
} | ||
}, | ||
bids: [{ | ||
bidder: 'ozone', | ||
params: { | ||
publisherId: 'OZONENUK0001', /* an ID to identify the publisher account - required */ | ||
siteId: '4204204201', /* An ID used to identify a site within a publisher account - required */ | ||
placementId: '0420420421', /* an ID used to identify the piece of inventory - required - for appnexus test use 13144370. */ | ||
customData: {"key1": "value1", "key2": "value2}, /* optional JSON placeholder for passing publisher key-values for targeting. */ | ||
ozoneData: {"key1": "value1", "key2": "value2"}, /* optional JSON placeholder for for passing ozone project key-values for targeting. */ | ||
lotameData: {"key1": "value1", "key2": "value2} /* optional JSON placeholder for passing Lotame DMP data */ | ||
} | ||
}] | ||
}]; | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here const can be used. Also use let/const wherever applicable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍