-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from taboola/add-taboola-bid-adapter
Add taboola bid adapter
- Loading branch information
Showing
3 changed files
with
754 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,257 @@ | ||
'use strict'; | ||
|
||
import {registerBidder} from '../src/adapters/bidderFactory.js'; | ||
import {BANNER} from '../src/mediaTypes.js'; | ||
import {config} from '../src/config.js'; | ||
import {getWindowSelf, getWindowTop} from '../src/utils.js' | ||
import {getStorageManager} from '../src/storageManager.js'; | ||
|
||
const BIDDER_CODE = 'taboola'; | ||
const GVLID = 42; | ||
const CURRENCY = 'USD'; | ||
export const END_POINT_URL = 'http://hb.bidder.taboola.com/TaboolaHBOpenRTBRequestHandlerServlet'; | ||
const USER_ID = 'user-id'; | ||
const STORAGE_KEY = `taboola global:${USER_ID}`; | ||
const COOKIE_KEY = 'trc_cookie_storage'; | ||
|
||
/** | ||
* extract User Id by that order: | ||
* 1. local storage | ||
* 2. first party cookie | ||
* 3. rendered trc | ||
* 4. new user set it to 0 | ||
*/ | ||
export const userData = { | ||
storageManager: getStorageManager(GVLID, BIDDER_CODE), | ||
getUserId: () => { | ||
const {getFromLocalStorage, getFromCookie, getFromTRC} = userData; | ||
|
||
try { | ||
return getFromLocalStorage() || getFromCookie() || getFromTRC(); | ||
} catch (ex) { | ||
return 0; | ||
} | ||
}, | ||
getFromCookie() { | ||
const {cookiesAreEnabled, getCookie} = userData.storageManager; | ||
if (cookiesAreEnabled()) { | ||
const cookieData = getCookie(COOKIE_KEY); | ||
const userId = userData.getCookieDataByKey(cookieData, USER_ID); | ||
if (userId) { | ||
return userId; | ||
} | ||
} | ||
}, | ||
getCookieDataByKey(cookieData, key) { | ||
const [, value = ''] = cookieData.split(`${key}=`) | ||
return value; | ||
}, | ||
getFromLocalStorage() { | ||
const {hasLocalStorage, localStorageIsEnabled, getDataFromLocalStorage} = userData.storageManager; | ||
|
||
if (hasLocalStorage() && localStorageIsEnabled()) { | ||
return getDataFromLocalStorage(STORAGE_KEY); | ||
} | ||
}, | ||
getFromTRC() { | ||
return window.TRC ? window.TRC.user_id : 0; | ||
} | ||
} | ||
|
||
export const internal = { | ||
getPageUrl: (refererInfo = {}) => { | ||
if (refererInfo.canonicalUrl) { | ||
return refererInfo.canonicalUrl; | ||
} | ||
|
||
if (config.getConfig('pageUrl')) { | ||
return config.getConfig('pageUrl'); | ||
} | ||
|
||
try { | ||
return getWindowTop().location.href; | ||
} catch (e) { | ||
return getWindowSelf().location.href; | ||
} | ||
}, | ||
getReferrer: (refererInfo = {}) => { | ||
if (refererInfo.referer) { | ||
return refererInfo.referer; | ||
} | ||
|
||
try { | ||
return getWindowTop().document.referrer; | ||
} catch (e) { | ||
return getWindowSelf().document.referrer; | ||
} | ||
} | ||
} | ||
|
||
export const spec = { | ||
supportedMediaTypes: [BANNER], | ||
gvlid: GVLID, | ||
code: BIDDER_CODE, | ||
isBidRequestValid: (bidRequest) => { | ||
return !!(bidRequest.sizes && | ||
bidRequest.params && | ||
bidRequest.params.publisherId && | ||
bidRequest.params.tagId); | ||
}, | ||
buildRequests: (validBidRequests, bidderRequest) => { | ||
const [bidRequest] = validBidRequests; | ||
const {refererInfo, gdprConsent = {}, uspConsent} = bidderRequest; | ||
const {bcat = [], badv = [], publisherId} = bidRequest.params; | ||
const site = getSiteProperties(bidRequest.params, refererInfo); | ||
const device = {ua: navigator.userAgent}; | ||
const imps = getImps(validBidRequests); | ||
const user = { | ||
buyeruid: userData.getUserId(gdprConsent, uspConsent), | ||
ext: {} | ||
}; | ||
const regs = { | ||
coppa: 0, | ||
ext: {} | ||
}; | ||
|
||
if (gdprConsent.gdprApplies) { | ||
user.ext.consent = bidderRequest.gdprConsent.consentString; | ||
regs.ext.gdpr = 1; | ||
} | ||
|
||
if (uspConsent) { | ||
regs.ext.us_privacy = uspConsent; | ||
} | ||
|
||
if (config.getConfig('coppa')) { | ||
regs.coppa = 1 | ||
} | ||
|
||
const request = { | ||
id: bidderRequest.auctionId, | ||
imp: imps, | ||
site, | ||
device, | ||
source: {fd: 1}, | ||
tmax: bidderRequest.timeout, | ||
bcat, | ||
badv, | ||
user, | ||
regs | ||
}; | ||
|
||
const url = [END_POINT_URL, publisherId].join('/'); | ||
|
||
return { | ||
url, | ||
method: 'POST', | ||
data: JSON.stringify(request), | ||
bids: validBidRequests | ||
}; | ||
}, | ||
interpretResponse: (serverResponse, {bids}) => { | ||
if (!bids) { | ||
return []; | ||
} | ||
|
||
const {bidResponses, cur: currency} = getBidResponses(serverResponse); | ||
|
||
if (!bidResponses) { | ||
return []; | ||
} | ||
|
||
return bids.map((bid, id) => getBid(bid.bidId, currency, bidResponses[id])).filter(Boolean); | ||
}, | ||
}; | ||
|
||
function getSiteProperties({publisherId, bcat = []}, refererInfo) { | ||
const {getPageUrl, getReferrer} = internal; | ||
return { | ||
id: publisherId, | ||
name: publisherId, | ||
domain: window.location.host, | ||
page: getPageUrl(refererInfo), | ||
ref: getReferrer(refererInfo), | ||
publisher: { | ||
id: publisherId | ||
}, | ||
content: { | ||
language: navigator.language | ||
} | ||
} | ||
} | ||
|
||
function getImps(validBidRequests) { | ||
return validBidRequests.map((bid, id) => { | ||
const {tagId, bidfloor = null, bidfloorcur = CURRENCY} = bid.params; | ||
|
||
return { | ||
id: id + 1, | ||
banner: getBanners(bid), | ||
tagid: tagId, | ||
bidfloor, | ||
bidfloorcur, | ||
}; | ||
}); | ||
} | ||
|
||
function getBanners(bid) { | ||
return getSizes(bid.sizes); | ||
} | ||
|
||
function getSizes(sizes) { | ||
return { | ||
format: sizes.map(size => { | ||
return { | ||
h: size[0], | ||
w: size[1] | ||
} | ||
}) | ||
} | ||
} | ||
|
||
function getBidResponses({body}) { | ||
if (!body || (body && !body.bidResponse)) { | ||
return []; | ||
} | ||
|
||
const {seatbid, cur} = body.bidResponse; | ||
|
||
if (!seatbid.length || !seatbid[0].bid) { | ||
return []; | ||
} | ||
|
||
return { | ||
bidResponses: seatbid[0].bid, | ||
cur | ||
}; | ||
} | ||
|
||
function getBid(requestId, currency, bidResponse) { | ||
if (!bidResponse) { | ||
return; | ||
} | ||
|
||
const { | ||
price: cpm, crid: creativeId, adm: ad, w: width, h: height, adomain: advertiserDomains, meta = {} | ||
} = bidResponse; | ||
|
||
if (advertiserDomains && advertiserDomains.length > 0) { | ||
meta.advertiserDomains = advertiserDomains | ||
} | ||
|
||
return { | ||
requestId, | ||
ttl: 360, | ||
mediaType: BANNER, | ||
cpm, | ||
creativeId, | ||
currency, | ||
ad, | ||
width, | ||
height, | ||
meta, | ||
netRevenue: false | ||
}; | ||
} | ||
|
||
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,49 @@ | ||
# Overview | ||
|
||
``` | ||
Module Name: Taboola Adapter | ||
Module Type: Bidder Adapter | ||
Maintainer: [email protected] | ||
``` | ||
|
||
# Description | ||
|
||
Module that connects to Taboola bidder to fetch bids. | ||
- Supports `display` format | ||
- Uses `OpenRTB` standard | ||
|
||
The Taboola Bidding adapter requires setup before beginning. Please contact us on [email protected] | ||
|
||
# Test Display Parameters | ||
``` javascript | ||
var adUnits = [{ | ||
code: 'your-unit-container-id', | ||
mediaTypes: { | ||
banner: { | ||
sizes: [[300, 250], [300,600]] | ||
} | ||
}, | ||
bids: [{ | ||
bidder: 'taboola', | ||
params: { | ||
tagId: 'Placement Name', | ||
publisherId: 'your-publisher-id', | ||
bidfloor: 0.25, // Optional - default is null | ||
bcat: ['IAB1-1'], // Optional - default is [] | ||
badv: ['example.com'] // Optional - default is [] | ||
} | ||
}] | ||
}]; | ||
``` | ||
|
||
# Parameters | ||
|
||
| Name | Scope | Description | Example | Type | | ||
|----------------|----------|---------------------------------------------------------|----------------------------|--------------| | ||
| `tagId` | required | Tag ID / Placement Name <br>(as provided by Taboola) | `'Below The Article'` | `String` | | ||
| `publisherId` | required | Alphabetic Publisher ID <br>(as provided by Taboola) | `'acme-publishing'` | `String` | | ||
| `bcat` | optional | List of blocked advertiser categories (IAB) | `['IAB1-1']` | `Array` | | ||
| `badv` | optional | Blocked Advertiser Domains | `'example.com'` | `String Url` | | ||
| `bidfloor` | optional | CPM bid floor | `0.25` | `Integer` | | ||
|
||
|
Oops, something went wrong.