Skip to content

Commit

Permalink
sync with prebid-3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Fawke committed Dec 5, 2019
2 parents 4f6c88a + dc586d1 commit 34b7d72
Show file tree
Hide file tree
Showing 33 changed files with 6,193 additions and 178 deletions.
2 changes: 2 additions & 0 deletions modules/.submodules.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
{
"userId": [
"unifiedIdSystem",
"pubCommonIdSystem",
"digiTrustIdSystem",
"id5IdSystem",
"criteortusIdSystem",
Expand Down
2 changes: 1 addition & 1 deletion modules/adkernelBidAdapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const VERSION = '1.3';
export const spec = {

code: 'adkernel',
aliases: ['headbidding', 'adsolut', 'oftmediahb', 'audiencemedia', 'waardex_ak'],
aliases: ['headbidding', 'adsolut', 'oftmediahb', 'audiencemedia', 'waardex_ak', 'roqoon'],
supportedMediaTypes: [BANNER, VIDEO],
isBidRequestValid: function(bidRequest) {
return 'params' in bidRequest &&
Expand Down
296 changes: 296 additions & 0 deletions modules/adxcgBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,296 @@
import { config } from '../src/config'
import * as utils from '../src/utils'
import * as url from '../src/url'
import { registerBidder } from '../src/adapters/bidderFactory'
import { BANNER, NATIVE, VIDEO } from '../src/mediaTypes'
import includes from 'core-js/library/fn/array/includes'

/**
* Adapter for requesting bids from adxcg.net
* updated to latest prebid repo on 2017.10.20
* updated for gdpr compliance on 2018.05.22 -requires gdpr compliance module
* updated to pass aditional auction and impression level parameters. added pass for video targeting parameters
* updated to fix native support for image width/height and icon 2019.03.17
* updated support for userid - pubcid,ttid 2019.05.28
* updated to support prebid 3.0 -remove non https, move to banner.xx.sizes, remove utils.getTopWindowLocation,remove utils.getTopWindowUrl(),remove utils.getTopWindowReferrer()
*/

const BIDDER_CODE = 'adxcg'
const SUPPORTED_AD_TYPES = [BANNER, VIDEO, NATIVE]
const SOURCE = 'pbjs10'
const VIDEO_TARGETING = ['id', 'mimes', 'minduration', 'maxduration', 'startdelay', 'skippable', 'playback_method', 'frameworks']
const USER_PARAMS_AUCTION = ['forcedDspIds', 'forcedCampaignIds', 'forcedCreativeIds', 'gender', 'dnt', 'language']
const USER_PARAMS_BID = ['lineparam1', 'lineparam2', 'lineparam3']
const BIDADAPTERVERSION = 'r20191128PB30'

export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: SUPPORTED_AD_TYPES,

/**
* Determines whether or not the given bid request is valid.
*
* @param {object} bid The bid params to validate.
* @return boolean True if this is a valid bid, and false otherwise.
*/
isBidRequestValid: function (bid) {
if (!bid || !bid.params) {
utils.logWarn(BIDDER_CODE + ': Missing bid parameters')
return false
}

if (!utils.isStr(bid.params.adzoneid)) {
utils.logWarn(BIDDER_CODE + ': adzoneid must be specified as a string')
return false
}

if (isVideoRequest(bid)) {
if (!bid.params.video.mimes) {
// Give a warning but let it pass
utils.logWarn(BIDDER_CODE + ': mimes should be specified for videos')
} else if (!utils.isArray(bid.params.video.mimes) || !bid.params.video.mimes.every(s => utils.isStr(s))) {
utils.logWarn(BIDDER_CODE + ': mimes must be an array of strings')
return false
}

const context = utils.deepAccess(bid, 'mediaTypes.video.context')
if (context !== 'instream') {
utils.logWarn(BIDDER_CODE + ': video context must be valid - instream')
return false
}
}

return true
},

/**
* Make a server request from the list of BidRequests.
*
* an array of validBidRequests
* Info describing the request to the server.
*/
buildRequests: function (validBidRequests, bidderRequest) {
utils.logMessage(`buildRequests: ${JSON.stringify(validBidRequests)}`)

let dt = new Date()
let ratio = window.devicePixelRatio || 1
let iobavailable = window && window.IntersectionObserver && window.IntersectionObserverEntry && window.IntersectionObserverEntry.prototype && 'intersectionRatio' in window.IntersectionObserverEntry.prototype

let bt = config.getConfig('bidderTimeout')
if (window.PREBID_TIMEOUT) {
bt = Math.min(window.PREBID_TIMEOUT, bt)
}

// add common parameters
let beaconParams = {
renderformat: 'javascript',
ver: BIDADAPTERVERSION,
secure: '1',
source: SOURCE,
uw: window.screen.width,
uh: window.screen.height,
dpr: ratio,
bt: bt,
isinframe: utils.inIframe(),
cookies: utils.checkCookieSupport() ? '1' : '0',
tz: dt.getTimezoneOffset(),
dt: utils.timestamp(),
iob: iobavailable ? '1' : '0',
pbjs: '$prebid.version$',
rndid: Math.floor(Math.random() * (999999 - 100000 + 1)) + 100000
}

const referrer = utils.deepAccess(bidderRequest, 'refererInfo.referer');
const page = utils.deepAccess(bidderRequest, 'refererInfo.canonicalUrl') || config.getConfig('pageUrl') || utils.deepAccess(window, 'location.href');
beaconParams.ref = encodeURIComponent(referrer);
beaconParams.url = encodeURIComponent(page);

if (bidderRequest && bidderRequest.gdprConsent && bidderRequest.gdprConsent.gdprApplies) {
beaconParams.gdpr = bidderRequest.gdprConsent.gdprApplies ? '1' : '0'
beaconParams.gdpr_consent = bidderRequest.gdprConsent.consentString
}

let biddercustom = config.getConfig(BIDDER_CODE)
if (biddercustom) {
Object.keys(biddercustom)
.filter(param => includes(USER_PARAMS_AUCTION, param))
.forEach(param => beaconParams[param] = encodeURIComponent(biddercustom[param]))
}

// per impression parameters
let adZoneIds = []
let prebidBidIds = []
let sizes = []
let bidfloors = []

validBidRequests.forEach((bid, index) => {
adZoneIds.push(utils.getBidIdParameter('adzoneid', bid.params))
prebidBidIds.push(bid.bidId)

if (isBannerRequest(bid)) {
sizes.push(utils.parseSizesInput(bid.mediaTypes.banner.sizes).join('|'))
}

let bidfloor = utils.getBidIdParameter('bidfloor', bid.params) || 0
bidfloors.push(bidfloor)
// copy video params
if (isVideoRequest(bid)) {
if (bid.params.video) {
Object.keys(bid.params.video)
.filter(param => includes(VIDEO_TARGETING, param))
.forEach(param => beaconParams['video.' + param + '.' + index] = encodeURIComponent(bid.params.video[param]))
}
// copy video context params
beaconParams['video.context' + '.' + index] = utils.deepAccess(bid, 'mediaTypes.video.context')
sizes.push(utils.parseSizesInput(bid.mediaTypes.video.playerSize).join('|'))
}

// copy all custom parameters impression level parameters not supported above
let customBidParams = utils.getBidIdParameter('custom', bid.params) || {}
if (customBidParams) {
Object.keys(customBidParams)
.filter(param => includes(USER_PARAMS_BID, param))
.forEach(param => beaconParams[param + '.' + index] = encodeURIComponent(customBidParams[param]))
}
})

beaconParams.adzoneid = adZoneIds.join(',')
beaconParams.format = sizes.join(',')
beaconParams.prebidBidIds = prebidBidIds.join(',')
beaconParams.bidfloors = bidfloors.join(',')

if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.pubcid'))) {
beaconParams.pubcid = validBidRequests[0].userId.pubcid;
}

if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.tdid'))) {
beaconParams.tdid = validBidRequests[0].userId.tdid;
}

if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.id5id'))) {
beaconParams.id5id = validBidRequests[0].userId.id5id;
}

if (utils.isStr(utils.deepAccess(validBidRequests, '0.userId.idl_env'))) {
beaconParams.idl_env = validBidRequests[0].userId.idl_env;
}

let adxcgRequestUrl = url.format({
protocol: 'https',
hostname: 'hbps.adxcg.net',
pathname: '/get/adi',
search: beaconParams
})

return {
contentType: 'text/plain',
method: 'GET',
url: adxcgRequestUrl,
withCredentials: true
}
},
/**
* Unpack the response from the server into a list of bids.
*
* @param {*} serverResponse A successful response from the server.
* @return {bidRequests[]} An array of bids which were nested inside the server.
*/
interpretResponse:

function (serverResponse, bidRequests) {
let bids = []

serverResponse = serverResponse.body
if (serverResponse) {
serverResponse.forEach(serverResponseOneItem => {
let bid = {}

bid.requestId = serverResponseOneItem.bidId
bid.cpm = serverResponseOneItem.cpm
bid.creativeId = parseInt(serverResponseOneItem.creativeId)
bid.currency = serverResponseOneItem.currency ? serverResponseOneItem.currency : 'USD'
bid.netRevenue = serverResponseOneItem.netRevenue ? serverResponseOneItem.netRevenue : true
bid.ttl = serverResponseOneItem.ttl ? serverResponseOneItem.ttl : 300

if (serverResponseOneItem.deal_id != null && serverResponseOneItem.deal_id.trim().length > 0) {
bid.dealId = serverResponseOneItem.deal_id
}

if (serverResponseOneItem.ad) {
bid.ad = serverResponseOneItem.ad
} else if (serverResponseOneItem.vastUrl) {
bid.vastUrl = serverResponseOneItem.vastUrl
bid.mediaType = 'video'
} else if (serverResponseOneItem.nativeResponse) {
bid.mediaType = 'native'

let nativeResponse = serverResponseOneItem.nativeResponse

bid['native'] = {
clickUrl: nativeResponse.link.url,
impressionTrackers: nativeResponse.imptrackers,
clickTrackers: nativeResponse.clktrackers,
javascriptTrackers: nativeResponse.jstrackers
}

nativeResponse.assets.forEach(asset => {
if (asset.title && asset.title.text) {
bid['native'].title = asset.title.text
}

if (asset.img && asset.img.url) {
let nativeImage = {}
nativeImage.url = asset.img.url
nativeImage.height = asset.img.h
nativeImage.width = asset.img.w
bid['native'].image = nativeImage
}

if (asset.icon && asset.icon.url) {
let nativeIcon = {}
nativeIcon.url = asset.icon.url
nativeIcon.height = asset.icon.h
nativeIcon.width = asset.icon.w
bid['native'].icon = nativeIcon
}

if (asset.data && asset.data.label === 'DESC' && asset.data.value) {
bid['native'].body = asset.data.value
}

if (asset.data && asset.data.label === 'SPONSORED' && asset.data.value) {
bid['native'].sponsoredBy = asset.data.value
}
})
}

bid.width = serverResponseOneItem.width
bid.height = serverResponseOneItem.height
utils.logMessage(`submitting bid[${serverResponseOneItem.bidId}]: ${JSON.stringify(bid)}`)
bids.push(bid)
})
} else {
utils.logMessage(`empty bid response`)
}
return bids
},

getUserSyncs: function (syncOptions) {
if (syncOptions.iframeEnabled) {
return [{
type: 'iframe',
url: 'https://cdn.adxcg.net/pb-sync.html'
}]
}
}
}

function isVideoRequest (bid) {
return bid.mediaType === 'video' || !!utils.deepAccess(bid, 'mediaTypes.video')
}

function isBannerRequest (bid) {
return bid.mediaType === 'banner' || !!utils.deepAccess(bid, 'mediaTypes.banner')
}

registerBidder(spec)
Loading

0 comments on commit 34b7d72

Please sign in to comment.