-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Add ReadPeak Bid Adapter #1838
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
Add ReadPeak Bid Adapter #1838
Changes from 4 commits
bc72367
46a98f0
ff814ad
ce9b2a3
207a9ab
e2449a3
a48760b
75a8208
de02c08
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,237 @@ | ||
import {logError, getTopWindowLocation} from 'src/utils'; | ||
import { registerBidder } from 'src/adapters/bidderFactory'; | ||
|
||
export const ENDPOINT = '//app.readpeak.com/header/prebid'; | ||
|
||
const NATIVE_DEFAULTS = { | ||
TITLE_LEN: 70, | ||
DESCR_LEN: 120, | ||
SPONSORED_BY_LEN: 50, | ||
IMG_MIN: 150, | ||
ICON_MIN: 50, | ||
CTA_LEN: 50, | ||
}; | ||
|
||
const BIDDER_CODE = 'readpeak' | ||
|
||
export const spec = { | ||
|
||
code: BIDDER_CODE, | ||
|
||
supportedMediaTypes: ['native'], | ||
|
||
isBidRequestValid: bid => ( | ||
!!(bid && bid.params && bid.params.publisherId && bid.nativeParams) | ||
), | ||
|
||
buildRequests: bidRequests => { | ||
const request = { | ||
id: bidRequests[0].bidderRequestId, | ||
imp: bidRequests.map(slot => impression(slot)).filter(imp => imp.native != null), | ||
site: site(bidRequests), | ||
app: app(bidRequests), | ||
device: device(), | ||
isPrebid: true, | ||
} | ||
|
||
return { | ||
method: 'POST', | ||
url: ENDPOINT, | ||
data: JSON.stringify(request), | ||
} | ||
}, | ||
|
||
interpretResponse: (response, request) => ( | ||
bidResponseAvailable(request, response) | ||
), | ||
}; | ||
|
||
function bidResponseAvailable(bidRequest, bidResponse) { | ||
const idToImpMap = {}; | ||
const idToBidMap = {}; | ||
if (!bidResponse['body']) { | ||
return [] | ||
} | ||
bidResponse = bidResponse.body | ||
parse(bidRequest.data).imp.forEach(imp => { | ||
idToImpMap[imp.id] = imp; | ||
}); | ||
if (bidResponse) { | ||
bidResponse.seatbid.forEach(seatBid => seatBid.bid.forEach(bid => { | ||
idToBidMap[bid.impid] = bid; | ||
})); | ||
} | ||
const bids = []; | ||
Object.keys(idToImpMap).forEach(id => { | ||
if (idToBidMap[id]) { | ||
const bid = { | ||
requestId: id, | ||
cpm: idToBidMap[id].price, | ||
creativeId: id, | ||
adId: id, | ||
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.
|
||
ttl: 300, | ||
netRevenue: true, | ||
mediaType: 'native', | ||
currency: bidResponse.cur, | ||
bidderCode: BIDDER_CODE, | ||
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. please drop bidder code. This will be added automatically. |
||
}; | ||
bid['native'] = nativeResponse(idToImpMap[id], idToBidMap[id]); | ||
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. no need to use bracket notation here. |
||
bids.push(bid); | ||
} | ||
}); | ||
return bids; | ||
} | ||
|
||
function impression(slot) { | ||
return { | ||
id: slot.bidId, | ||
native: nativeImpression(slot), | ||
bidfloor: slot.params.bidfloor || 0, | ||
bidfloorcur: 'USD' | ||
}; | ||
} | ||
|
||
function nativeImpression(slot) { | ||
if (slot.nativeParams) { | ||
const assets = []; | ||
addAsset(assets, titleAsset(1, slot.nativeParams.title, NATIVE_DEFAULTS.TITLE_LEN)); | ||
addAsset(assets, imageAsset(2, slot.nativeParams.image, 3, NATIVE_DEFAULTS.IMG_MIN, NATIVE_DEFAULTS.IMG_MIN)); | ||
addAsset(assets, dataAsset(3, slot.nativeParams.sponsoredBy, 1, NATIVE_DEFAULTS.SPONSORED_BY_LEN)); | ||
addAsset(assets, dataAsset(4, slot.nativeParams.body, 2, NATIVE_DEFAULTS.DESCR_LEN)); | ||
addAsset(assets, dataAsset(5, slot.nativeParams.cta, 12, NATIVE_DEFAULTS.CTA_LEN)); | ||
return { | ||
request: JSON.stringify({ assets }), | ||
ver: '1.1', | ||
}; | ||
} | ||
return null; | ||
} | ||
|
||
function addAsset(assets, asset) { | ||
if (asset) { | ||
assets.push(asset); | ||
} | ||
} | ||
|
||
function titleAsset(id, params, defaultLen) { | ||
if (params) { | ||
return { | ||
id, | ||
required: params.required ? 1 : 0, | ||
title: { | ||
len: params.len || defaultLen, | ||
}, | ||
}; | ||
} | ||
return null; | ||
} | ||
|
||
function imageAsset(id, params, type, defaultMinWidth, defaultMinHeight) { | ||
return params ? { | ||
id, | ||
required: params.required ? 1 : 0, | ||
img: { | ||
type, | ||
wmin: params.wmin || defaultMinWidth, | ||
hmin: params.hmin || defaultMinHeight, | ||
} | ||
} : null; | ||
} | ||
|
||
function dataAsset(id, params, type, defaultLen) { | ||
return params ? { | ||
id, | ||
required: params.required ? 1 : 0, | ||
data: { | ||
type, | ||
len: params.len || defaultLen, | ||
} | ||
} : null; | ||
} | ||
|
||
function site(bidderRequest) { | ||
const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.publisherId : '0'; | ||
const appParams = bidderRequest[0].params.app; | ||
if (!appParams) { | ||
return { | ||
publisher: { | ||
id: pubId.toString(), | ||
}, | ||
id: pubId.toString(), | ||
ref: referrer(), | ||
page: getTopWindowLocation().href, | ||
domain: getTopWindowLocation().hostname | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
function app(bidderRequest) { | ||
const pubId = bidderRequest && bidderRequest.length > 0 ? bidderRequest[0].params.publisherId : '0'; | ||
const appParams = bidderRequest[0].params.app; | ||
if (appParams) { | ||
return { | ||
publisher: { | ||
id: pubId.toString(), | ||
}, | ||
bundle: appParams.bundle, | ||
storeurl: appParams.storeUrl, | ||
domain: appParams.domain, | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
function referrer() { | ||
try { | ||
return window.top.document.referrer; | ||
} catch (e) { | ||
return document.referrer; | ||
} | ||
} | ||
|
||
function device() { | ||
return { | ||
ua: navigator.userAgent, | ||
language: (navigator.language || navigator.browserLanguage || navigator.userLanguage || navigator.systemLanguage), | ||
}; | ||
} | ||
|
||
function parse(rawResponse) { | ||
try { | ||
if (rawResponse) { | ||
if (typeof rawResponse === 'object') { | ||
return rawResponse | ||
} else { | ||
return JSON.parse(rawResponse); | ||
} | ||
} | ||
} catch (ex) { | ||
logError('readpeakBidAdapter.safeParse', 'ERROR', ex); | ||
} | ||
return null; | ||
} | ||
|
||
function nativeResponse(imp, bid) { | ||
if (imp && imp['native']) { | ||
const nativeAd = parse(bid.adm); | ||
const keys = {}; | ||
if (nativeAd && nativeAd.assets) { | ||
nativeAd.assets.forEach(asset => { | ||
keys.title = asset.title ? asset.title.text : keys.title; | ||
keys.body = asset.data && asset.id === 4 ? asset.data.value : keys.body; | ||
keys.sponsoredBy = asset.data && asset.id === 3 ? asset.data.value : keys.sponsoredBy; | ||
keys.image = asset.img && asset.id === 2 ? asset.img.url : keys.image; | ||
keys.cta = asset.data && asset.id === 5 ? asset.data.value : keys.cta; | ||
}); | ||
if (nativeAd.link) { | ||
keys.clickUrl = encodeURIComponent(nativeAd.link.url); | ||
} | ||
keys.impressionTrackers = nativeAd.imptrackers; | ||
return keys; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
registerBidder(spec); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Overview | ||
|
||
Module Name: ReadPeak Bid Adapter | ||
|
||
Module Type: Bidder Adapter | ||
|
||
Maintainer: [email protected] | ||
|
||
# Description | ||
|
||
Module that connects to ReadPeak's demand sources | ||
|
||
This adapter requires setup and approval from ReadPeak. | ||
Please reach out to your account team or [email protected] for more information. | ||
|
||
# Test Parameters | ||
```javascript | ||
var adUnits = [{ | ||
code: 'test-native', | ||
mediaTypes: { native: { type: 'image' } }, | ||
bids: [{ | ||
bidder: 'readpeak', | ||
params: { | ||
bidfloor: 5.00, | ||
publisherId: '11bc5dd5-7421-4dd8-c926-40fa653bec76' | ||
}, | ||
}] | ||
}]; | ||
``` |
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.
Is the creativeId really just the request id? Doesn't seem correct.