forked from prebid/Prebid.js
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
NextRoll Bidder Adapter (prebid#4829)
* First implementation of the AdRoll adapter (#1) * Fix request and bid id (#5) * Send Zone ID (#6) * Add age check before fastbid eval (#7) * Add age check before fastbid eval * Fix linting * Add date check (#8) * Add date exists check * Remove logging statement * Fix bidRequest validation (#9) * Fix deprecated function usage (#10) * [SENG-2757] remove custom function from adapter (#11) * remove loadExternalScript function * add adroll to the adloader whitelist * Handle nextroll id (#12) * Handle nextroll id * Remove double nesting in user obj * Revert change to publisherTagAvailable * Rename adroll -> nextroll (prebid#14) * Rename fastbid -> pubtag functions and variables (prebid#15) * Improve coverage of tests * Add docs * Add docs * Improve sizes and add sellerid * Add maintainer email * Fix CI problem * Fix IE tests * Replace second instance of find * Fix types used in the doc Match prebid/prebid.github.io#1796 * Remove unused fields in spec * Add ccpa support * Remove external script usage * Remove IP field * Remove pubtag key * Rename imports; Remove getUserSync function; Remove unused code; Use url.parse function Co-authored-by: Juan Bono <juanbono94@gmail.com> Co-authored-by: Ricardo Azpeitia Pimentel <ricardo.azpeitia@nextroll.com>
- Loading branch information
1 parent
303f0e3
commit 0ae0bff
Showing
3 changed files
with
448 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,215 @@ | ||
import * as utils from '../src/utils.js'; | ||
import { registerBidder } from '../src/adapters/bidderFactory.js'; | ||
import { BANNER } from '../src/mediaTypes.js'; | ||
import { parse as parseUrl } from '../src/url.js'; | ||
|
||
import find from 'core-js/library/fn/array/find.js'; | ||
|
||
const BIDDER_CODE = 'nextroll'; | ||
const BIDDER_ENDPOINT = 'https://d.adroll.com/bid/prebid/'; | ||
const ADAPTER_VERSION = 4; | ||
|
||
export const spec = { | ||
code: BIDDER_CODE, | ||
supportedMediaTypes: [BANNER], | ||
|
||
/** | ||
* Determines whether or not the given bid request is valid. | ||
* | ||
* @param {BidRequest} bid The bid params to validate. | ||
* @return boolean True if this is a valid bid, and false otherwise. | ||
*/ | ||
isBidRequestValid: function (bidRequest) { | ||
return bidRequest !== undefined && !!bidRequest.params && !!bidRequest.bidId; | ||
}, | ||
|
||
/** | ||
* Make a server request from the list of BidRequests. | ||
* | ||
* @param {validBidRequests[]} - an array of bids | ||
* @return ServerRequest Info describing the request to the server. | ||
*/ | ||
buildRequests: function (validBidRequests, bidderRequest) { | ||
let topLocation = parseUrl(utils.deepAccess(bidderRequest, 'refererInfo.referer')); | ||
let consent = hasCCPAConsent(bidderRequest); | ||
return validBidRequests.map((bidRequest, index) => { | ||
return { | ||
method: 'POST', | ||
options: { | ||
withCredentials: consent, | ||
}, | ||
url: BIDDER_ENDPOINT, | ||
data: { | ||
id: bidRequest.bidId, | ||
imp: { | ||
id: bidRequest.bidId, | ||
bidfloor: utils.getBidIdParameter('bidfloor', bidRequest.params), | ||
banner: { | ||
format: _getSizes(bidRequest) | ||
}, | ||
ext: { | ||
zone: { | ||
id: utils.getBidIdParameter('zoneId', bidRequest.params) | ||
}, | ||
nextroll: { | ||
adapter_version: ADAPTER_VERSION | ||
} | ||
} | ||
}, | ||
|
||
user: _getUser(validBidRequests), | ||
site: _getSite(bidRequest, topLocation), | ||
seller: _getSeller(bidRequest), | ||
device: _getDevice(bidRequest), | ||
} | ||
} | ||
}) | ||
}, | ||
|
||
/** | ||
* Unpack the response from the server into a list of bids. | ||
* | ||
* @param {ServerResponse} serverResponse A successful response from the server. | ||
* @return {Bid[]} An array of bids which were nested inside the server. | ||
*/ | ||
interpretResponse: function (serverResponse, bidRequest) { | ||
if (!serverResponse.body) { | ||
return []; | ||
} else { | ||
let response = serverResponse.body | ||
let bids = response.seatbid.reduce((acc, seatbid) => acc.concat(seatbid.bid), []); | ||
return bids.map((bid) => _buildResponse(response, bid)); | ||
} | ||
} | ||
} | ||
|
||
function _getUser(requests) { | ||
let id = utils.deepAccess(requests, '0.userId.nextroll'); | ||
if (id === undefined) { | ||
return | ||
} | ||
|
||
return { | ||
ext: { | ||
eid: [{ | ||
'source': 'nextroll', | ||
id | ||
}] | ||
} | ||
} | ||
} | ||
|
||
function _buildResponse(bidResponse, bid) { | ||
const adm = utils.replaceAuctionPrice(bid.adm, bid.price); | ||
return { | ||
requestId: bidResponse.id, | ||
cpm: bid.price, | ||
width: bid.w, | ||
height: bid.h, | ||
creativeId: bid.crid, | ||
dealId: bidResponse.dealId, | ||
currency: 'USD', | ||
netRevenue: true, | ||
ttl: 300, | ||
ad: adm | ||
} | ||
} | ||
|
||
function _getSite(bidRequest, topLocation) { | ||
return { | ||
page: topLocation.href, | ||
domain: topLocation.hostname, | ||
publisher: { | ||
id: utils.getBidIdParameter('publisherId', bidRequest.params) | ||
} | ||
} | ||
} | ||
|
||
function _getSeller(bidRequest) { | ||
return { | ||
id: utils.getBidIdParameter('sellerId', bidRequest.params) | ||
} | ||
} | ||
|
||
function _getSizes(bidRequest) { | ||
return bidRequest.sizes.filter(_isValidSize).map(size => { | ||
return { | ||
w: size[0], | ||
h: size[1] | ||
} | ||
}) | ||
} | ||
|
||
function _isValidSize(size) { | ||
const isNumber = x => typeof x === 'number'; | ||
return (size.length === 2 && isNumber(size[0]) && isNumber(size[1])); | ||
} | ||
|
||
function _getDevice(_bidRequest) { | ||
return { | ||
ua: navigator.userAgent, | ||
language: navigator['language'], | ||
os: _getOs(navigator.userAgent.toLowerCase()), | ||
osv: _getOsVersion(navigator.userAgent) | ||
} | ||
} | ||
|
||
function _getOs(userAgent) { | ||
const osTable = { | ||
'android': /android/i, | ||
'ios': /iphone|ipad/i, | ||
'mac': /mac/i, | ||
'linux': /linux/i, | ||
'windows': /windows/i | ||
}; | ||
|
||
return find(Object.keys(osTable), os => { | ||
if (userAgent.match(osTable[os])) { | ||
return os; | ||
} | ||
}) || 'etc'; | ||
} | ||
|
||
function _getOsVersion(userAgent) { | ||
let clientStrings = [ | ||
{ s: 'Android', r: /Android/ }, | ||
{ s: 'iOS', r: /(iPhone|iPad|iPod)/ }, | ||
{ s: 'Mac OS X', r: /Mac OS X/ }, | ||
{ s: 'Mac OS', r: /(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/ }, | ||
{ s: 'Linux', r: /(Linux|X11)/ }, | ||
{ s: 'Windows 10', r: /(Windows 10.0|Windows NT 10.0)/ }, | ||
{ s: 'Windows 8.1', r: /(Windows 8.1|Windows NT 6.3)/ }, | ||
{ s: 'Windows 8', r: /(Windows 8|Windows NT 6.2)/ }, | ||
{ s: 'Windows 7', r: /(Windows 7|Windows NT 6.1)/ }, | ||
{ s: 'Windows Vista', r: /Windows NT 6.0/ }, | ||
{ s: 'Windows Server 2003', r: /Windows NT 5.2/ }, | ||
{ s: 'Windows XP', r: /(Windows NT 5.1|Windows XP)/ }, | ||
{ s: 'UNIX', r: /UNIX/ }, | ||
{ s: 'Search Bot', r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/ } | ||
]; | ||
let cs = find(clientStrings, cs => cs.r.test(userAgent)); | ||
return cs ? cs.s : 'unknown'; | ||
} | ||
|
||
export function hasCCPAConsent(bidderRequest) { | ||
if (typeof bidderRequest.uspConsent !== 'string') { | ||
return true; | ||
} | ||
const usps = bidderRequest.uspConsent; | ||
const version = usps[0]; | ||
|
||
// If we don't support the consent string, assume no-consent. | ||
if (version !== '1' || usps.length < 3) { | ||
return false; | ||
} | ||
|
||
const notice = usps[1]; | ||
const optOut = usps[2]; | ||
|
||
if (notice === 'N' || optOut === 'Y') { | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
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,50 @@ | ||
# Overview | ||
|
||
``` | ||
Module Name: NextRoll Bid Adapter | ||
Module Type: Bidder Adapter | ||
Maintainer: prebid@nextroll.com | ||
``` | ||
|
||
# Description | ||
|
||
Module that connects to NextRoll's bidders. | ||
The NextRoll bid adapter supports Banner format only. | ||
|
||
# Test Parameters | ||
``` javascript | ||
var adUnits = [ | ||
{ | ||
code: 'div-1', | ||
mediatypes: { | ||
banner: {sizes: [[300, 250], [160, 600]]} | ||
}, | ||
bids: [{ | ||
bidder: 'nextroll', | ||
params: { | ||
bidfloor: 1, | ||
zoneId: "13144370", | ||
publisherId: "publisherid", | ||
sellerId: "sellerid" | ||
} | ||
}] | ||
}, | ||
{ | ||
code: 'div-2', | ||
mediatypes: { | ||
banner: { | ||
sizes: [[728, 90], [970, 250]] | ||
} | ||
}, | ||
bids: [{ | ||
bidder: 'nextroll', | ||
params: { | ||
bidfloor: 2.3, | ||
zoneId: "13144370", | ||
publisherId: "publisherid", | ||
sellerId: "sellerid" | ||
} | ||
}] | ||
} | ||
] | ||
``` |
Oops, something went wrong.