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.
Delta Projects bid adapter: add new bid adapter (prebid#7564)
* Delta Projects bid adapter: add new bid adapter * Delta Projects bid adapter: revert accidental change to hello_world.html * Remove unsupported functions by IE, add support for floor price remove bidderParams which is not currently supported remove bid parameter floor remove unused function so linting is happy Remove unused params in tests use adservercurrency include .js to make linter happy again Co-authored-by: Boris-Tang <boris.tang@deltaprojects.com>
- Loading branch information
1 parent
11db0de
commit ef70eb7
Showing
3 changed files
with
683 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,252 @@ | ||
import { registerBidder } from '../src/adapters/bidderFactory.js'; | ||
import { BANNER } from '../src/mediaTypes.js'; | ||
import { | ||
_each, _map, isFn, isNumber, createTrackPixelHtml, deepAccess, parseUrl, logWarn, logError | ||
} from '../src/utils.js'; | ||
import {config} from '../src/config.js'; | ||
|
||
export const BIDDER_CODE = 'deltaprojects'; | ||
export const BIDDER_ENDPOINT_URL = 'https://d5p.de17a.com/dogfight/prebid'; | ||
export const USERSYNC_URL = 'https://userservice.de17a.com/getuid/prebid'; | ||
|
||
/** -- isBidRequestValid --**/ | ||
function isBidRequestValid(bid) { | ||
if (!bid) return false; | ||
|
||
if (bid.bidder !== BIDDER_CODE) return false; | ||
|
||
// publisher id is required | ||
const publisherId = deepAccess(bid, 'params.publisherId') | ||
if (!publisherId) { | ||
logError('Invalid bid request, missing publisher id in params'); | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
/** -- Build requests --**/ | ||
function buildRequests(validBidRequests, bidderRequest) { | ||
/** == shared ==**/ | ||
// -- build id | ||
const id = bidderRequest.auctionId; | ||
|
||
// -- build site | ||
const loc = parseUrl(bidderRequest.refererInfo.referer); | ||
const publisherId = setOnAny(validBidRequests, 'params.publisherId'); | ||
const siteId = setOnAny(validBidRequests, 'params.siteId'); | ||
const site = { | ||
id: siteId, | ||
domain: loc.hostname, | ||
page: loc.href, | ||
ref: loc.href, | ||
publisher: { id: publisherId }, | ||
}; | ||
|
||
// -- build device | ||
const ua = navigator.userAgent; | ||
const device = { | ||
ua, | ||
w: screen.width, | ||
h: screen.height | ||
} | ||
|
||
// -- build user, reg | ||
let user = { ext: {} }; | ||
const regs = { ext: {} }; | ||
const gdprConsent = bidderRequest && bidderRequest.gdprConsent; | ||
if (gdprConsent) { | ||
user.ext = { consent: gdprConsent.consentString }; | ||
if (typeof gdprConsent.gdprApplies == 'boolean') { | ||
regs.ext.gdpr = gdprConsent.gdprApplies ? 1 : 0 | ||
} | ||
} | ||
|
||
// -- build tmax | ||
let tmax = (bidderRequest && bidderRequest.timeout > 0) ? bidderRequest.timeout : undefined; | ||
|
||
// build bid specific | ||
return validBidRequests.map(validBidRequest => { | ||
const openRTBRequest = buildOpenRTBRequest(validBidRequest, id, site, device, user, tmax, regs); | ||
return { | ||
method: 'POST', | ||
url: BIDDER_ENDPOINT_URL, | ||
data: openRTBRequest, | ||
options: { contentType: 'application/json' }, | ||
bids: [validBidRequest], | ||
}; | ||
}); | ||
} | ||
|
||
function buildOpenRTBRequest(validBidRequest, id, site, device, user, tmax, regs) { | ||
// build cur | ||
const currency = config.getConfig('currency.adServerCurrency') || deepAccess(validBidRequest, 'params.currency'); | ||
const cur = currency && [currency]; | ||
|
||
// build impression | ||
const impression = buildImpression(validBidRequest, currency); | ||
|
||
// build test | ||
const test = deepAccess(validBidRequest, 'params.test') ? 1 : 0 | ||
|
||
const at = 1 | ||
|
||
// build source | ||
const source = { | ||
tid: validBidRequest.transactionId, | ||
fd: 1, | ||
} | ||
|
||
return { | ||
id, | ||
at, | ||
imp: [impression], | ||
site, | ||
device, | ||
user, | ||
test, | ||
tmax, | ||
cur, | ||
source, | ||
regs, | ||
ext: {}, | ||
}; | ||
} | ||
|
||
function buildImpression(bid, currency) { | ||
const impression = { | ||
id: bid.bidId, | ||
tagid: bid.params.tagId, | ||
ext: {}, | ||
}; | ||
|
||
const bannerMediaType = deepAccess(bid, `mediaTypes.${BANNER}`); | ||
impression.banner = buildImpressionBanner(bid, bannerMediaType); | ||
|
||
// bid floor | ||
const bidFloor = getBidFloor(bid, BANNER, '*', currency); | ||
if (bidFloor) { | ||
impression.bidfloor = bidFloor.floor; | ||
impression.bidfloorcur = bidFloor.currency; | ||
} | ||
|
||
return impression; | ||
} | ||
|
||
function buildImpressionBanner(bid, bannerMediaType) { | ||
const bannerSizes = (bannerMediaType && bannerMediaType.sizes) || bid.sizes; | ||
return { | ||
format: _map(bannerSizes, ([width, height]) => ({ w: width, h: height })), | ||
}; | ||
} | ||
|
||
/** -- Interpret response --**/ | ||
function interpretResponse(serverResponse) { | ||
if (!serverResponse.body) { | ||
logWarn('Response body is invalid, return !!'); | ||
return []; | ||
} | ||
|
||
const { body: { id, seatbid, cur } } = serverResponse; | ||
if (!id || !seatbid) { | ||
logWarn('Id / seatbid of response is invalid, return !!'); | ||
return []; | ||
} | ||
|
||
const bidResponses = []; | ||
|
||
_each(seatbid, seatbid => { | ||
_each(seatbid.bid, bid => { | ||
const bidObj = { | ||
requestId: bid.impid, | ||
cpm: parseFloat(bid.price), | ||
width: parseInt(bid.w), | ||
height: parseInt(bid.h), | ||
creativeId: bid.crid || bid.id, | ||
dealId: bid.dealid || null, | ||
currency: cur, | ||
netRevenue: true, | ||
ttl: 60, | ||
}; | ||
|
||
bidObj.mediaType = BANNER; | ||
bidObj.ad = bid.adm; | ||
if (bid.nurl) { | ||
bidObj.ad += createTrackPixelHtml(decodeURIComponent(bid.nurl)); | ||
} | ||
if (bid.ext) { | ||
bidObj[BIDDER_CODE] = bid.ext; | ||
} | ||
bidResponses.push(bidObj); | ||
}); | ||
}); | ||
return bidResponses; | ||
} | ||
|
||
/** -- On Bid Won -- **/ | ||
function onBidWon(bid) { | ||
let cpm = bid.cpm; | ||
if (bid.currency && bid.currency !== bid.originalCurrency && typeof bid.getCpmInNewCurrency === 'function') { | ||
cpm = bid.getCpmInNewCurrency(bid.originalCurrency); | ||
} | ||
const wonPrice = Math.round(cpm * 1000000); | ||
const wonPriceMacroPatten = /\$\{AUCTION_PRICE:B64\}/g; | ||
bid.ad = bid.ad.replace(wonPriceMacroPatten, wonPrice); | ||
} | ||
|
||
/** -- Get user syncs --**/ | ||
function getUserSyncs(syncOptions, serverResponses, gdprConsent) { | ||
const syncs = [] | ||
|
||
if (syncOptions.pixelEnabled) { | ||
let gdprParams; | ||
if (gdprConsent) { | ||
if (typeof gdprConsent.gdprApplies === 'boolean') { | ||
gdprParams = `?gdpr=${Number(gdprConsent.gdprApplies)}&gdpr_consent=${gdprConsent.consentString}`; | ||
} else { | ||
gdprParams = `?gdpr_consent=${gdprConsent.consentString}`; | ||
} | ||
} else { | ||
gdprParams = ''; | ||
} | ||
syncs.push({ | ||
type: 'image', | ||
url: USERSYNC_URL + gdprParams | ||
}); | ||
} | ||
return syncs; | ||
} | ||
|
||
/** -- Get bid floor --**/ | ||
export function getBidFloor(bid, mediaType, size, currency) { | ||
if (isFn(bid.getFloor)) { | ||
const bidFloorCurrency = currency || 'USD'; | ||
const bidFloor = bid.getFloor({currency: bidFloorCurrency, mediaType: mediaType, size: size}); | ||
if (isNumber(bidFloor.floor)) { | ||
return bidFloor; | ||
} | ||
} | ||
} | ||
|
||
/** -- Helper methods --**/ | ||
function setOnAny(collection, key) { | ||
for (let i = 0, result; i < collection.length; i++) { | ||
result = deepAccess(collection[i], key); | ||
if (result) { | ||
return result; | ||
} | ||
} | ||
} | ||
|
||
/** -- Register -- */ | ||
export const spec = { | ||
code: BIDDER_CODE, | ||
supportedMediaTypes: [BANNER], | ||
isBidRequestValid, | ||
buildRequests, | ||
interpretResponse, | ||
onBidWon, | ||
getUserSyncs, | ||
}; | ||
|
||
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: Delta Projects Bid Adapter | ||
Module Type: Bidder Adapter | ||
Maintainer: dev@deltaprojects.com | ||
``` | ||
|
||
# Description | ||
|
||
Connects to Delta Projects DSP for bids. | ||
|
||
# Test Parameters | ||
``` | ||
// define banner unit | ||
var bannerUnit = { | ||
code: 'div-gpt-ad-1460505748561-0', | ||
mediaTypes: { | ||
banner: { | ||
sizes: [[300, 250], [300,600]], | ||
} | ||
}, | ||
// Replace this object to test a new Adapter! | ||
bids: [{ | ||
bidder: 'deltaprojects', | ||
params: { | ||
publisherId: '4' //required | ||
} | ||
}] | ||
}; | ||
``` | ||
|
Oops, something went wrong.