Skip to content
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

Taboola bid adapter: initial release #8483

Merged
merged 36 commits into from
May 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
478dc6b
create taboola adapter
mikizi Feb 7, 2022
bb75997
create taboola adapter md
mikizi Feb 7, 2022
a8fe097
taboolaBidAdapter.js - small fixes
mikizi Feb 7, 2022
6314750
taboolaBidAdapter.js - small fixes
mikizi Feb 7, 2022
644ba0f
update the md
mikizi Feb 7, 2022
b09a481
update the Maintainer email
mikizi Feb 8, 2022
0f11f67
* update MD page
mikizi Feb 8, 2022
90b0258
* add privacy to the request builder
mikizi Feb 8, 2022
7b1001c
Merge branch 'master' of https://github.com/prebid/Prebid.js into add…
mikizi Feb 8, 2022
7562ed1
Merge branch 'master' of https://github.com/taboola/Prebid.js into ad…
mikizi Feb 9, 2022
de81396
* code refactoring + add more accurate way to get page url and referer
mikizi Feb 9, 2022
a1dfd88
* code refactoring + gte user id
mikizi Feb 10, 2022
600a9d0
* code refactoring + gte user id
mikizi Feb 13, 2022
7fb1379
* update end point url
mikizi Feb 15, 2022
0cf48ad
small fixes + update epi url
mikizi Feb 21, 2022
2e81b9b
Merge pull request #1 from taboola/add-taboola-bid-adapter
mikizi Apr 24, 2022
7f7a0bc
Merge branch 'master' of https://github.com/prebid/Prebid.js
mikizi May 8, 2022
e6e0235
remove the destruction from the bidResponse property
mikizi May 8, 2022
1dabc41
(update the unit tests) remove the destruction from the bidResponse p…
mikizi May 8, 2022
4e4ff4a
fix tests
mikizi May 9, 2022
9f97222
fix tests - run stubs on each test
mikizi May 9, 2022
40a0cf6
rerun because of another adapter flaky test
mikizi May 9, 2022
07a1508
rerun because of another adapter flaky test
mikizi May 9, 2022
6f73485
fix cors issue, switch between height, width position
mikizi May 10, 2022
c13e0c2
update badv, bcat to be based in the ortb2 to support prebid 7 new pr…
mikizi May 22, 2022
1a81f33
retry run circleci
mikizi May 22, 2022
425281f
retry run circleci
mikizi May 22, 2022
fe9ba64
Merge branch 'master' of https://github.com/prebid/Prebid.js
mikizi May 22, 2022
3196a74
pull from upstream
mikizi May 22, 2022
637c11f
update badv, bcat UT
mikizi May 22, 2022
7ae2995
rerun build
mikizi May 23, 2022
8b56406
rerun build
mikizi May 23, 2022
3ec5b3f
Merge branch 'master' of https://github.com/prebid/Prebid.js
mikizi May 24, 2022
fdc1ca3
support storageAllowed restriction on unit tests for prebid 7
mikizi May 26, 2022
3ea96c1
add it also to the aftereach
mikizi May 26, 2022
c525fc1
add it also to the aftereach
mikizi May 26, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
265 changes: 265 additions & 0 deletions modules/taboolaBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
'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: GVLID, bidderCode: 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 {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 ortb2 = config.getConfig('ortb2') || {
badv: [],
bcat: []
};

const request = {
id: bidderRequest.auctionId,
imp: imps,
site,
device,
source: {fd: 1},
tmax: bidderRequest.timeout,
bcat: ortb2.bcat,
badv: ortb2.badv,
user,
regs
};

const url = [END_POINT_URL, publisherId].join('/');

return {
url,
method: 'POST',
data: JSON.stringify(request),
bids: validBidRequests,
options: {
withCredentials: false
},
};
},
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 {
w: size[0],
h: size[1]
}
})
}
}

function getBidResponses({body}) {
if (!body) {
return [];
}

const {seatbid, cur} = body;

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);
49 changes: 49 additions & 0 deletions modules/taboolaBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Overview

```
Module Name: Taboola Adapter
Module Type: Bidder Adapter
Maintainer: prebid@taboola.com
```

# 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 prebid@taboola.com

# Test Display Parameters
``` javascript
var adUnits = [{
code: 'your-unit-container-id',
mediaTypes: {
banner: {
sizes: [[300, 250], [300,600]]
}
},
bids: [{
bidder: 'taboola',
params: {
tagId: 'tester-placement', // Placement Name
publisherId: 'tester-pub', // 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` |


Loading