Skip to content

Commit

Permalink
Bidtheatre Bidder Adapter: initial release (prebid#12485)
Browse files Browse the repository at this point in the history
  • Loading branch information
andreasgreen authored Nov 23, 2024
1 parent 9361e17 commit e3e9ce0
Show file tree
Hide file tree
Showing 3 changed files with 494 additions and 0 deletions.
117 changes: 117 additions & 0 deletions modules/bidtheatreBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { ortbConverter } from '../libraries/ortbConverter/converter.js'
import { BANNER, VIDEO } from '../src/mediaTypes.js';
import { registerBidder } from '../src/adapters/bidderFactory.js';
import { deepSetValue, logError, replaceAuctionPrice } from '../src/utils.js';
import { getStorageManager } from '../src/storageManager.js';

const GVLID = 30;
export const BIDDER_CODE = 'bidtheatre';
export const ENDPOINT_URL = 'https://prebidjs-bids.bidtheatre.net/prebidjsbid';
const METHOD = 'POST';
const SUPPORTED_MEDIA_TYPES = [BANNER, VIDEO];
export const DEFAULT_CURRENCY = 'USD';
const BIDTHEATRE_COOKIE_NAME = '__kuid';
const storage = getStorageManager({bidderCode: BIDDER_CODE});

const converter = ortbConverter({
context: {
netRevenue: true,
ttl: 120,
currency: DEFAULT_CURRENCY
}
});

export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: SUPPORTED_MEDIA_TYPES,
gvlid: GVLID,
isBidRequestValid: function (bidRequest) {
const isValid = bidRequest &&
bidRequest.params &&
typeof bidRequest.params.publisherId === 'string' &&
bidRequest.params.publisherId.trim().length === 36

if (!isValid) {
logError('Bidtheatre Header Bidding Publisher ID not provided or in incorrect format');
}

return isValid;
},
getUserSyncs: function(syncOptions, serverResponses, gdprConsent, uspConsent) {
const seenUrls = new Set();
const syncs = [];

if (syncOptions.pixelEnabled && serverResponses) {
serverResponses.forEach(response => {
if (response.body && response.body.seatbid) {
response.body.seatbid.forEach(seatbid => {
if (seatbid.bid) {
seatbid.bid.forEach(bid => {
const urls = bid.ext && bid.ext.usersync_urls;
if (Array.isArray(urls)) {
urls.forEach(url => {
if (!seenUrls.has(url)) {
seenUrls.add(url);
syncs.push({
type: 'image',
url: url
});
}
});
}
});
}
});
}
});
}
return syncs;
},
buildRequests(bidRequests, bidderRequest) {
const data = converter.toORTB({bidRequests, bidderRequest});

const cookieValue = storage.getCookie(BIDTHEATRE_COOKIE_NAME);
if (cookieValue) {
deepSetValue(data, 'user.buyeruid', cookieValue);
}

data.imp.forEach((impObj, index) => {
let publisherId = bidRequests[index].params.publisherId;

if (publisherId) {
deepSetValue(impObj, 'ext.bidder.publisherId', publisherId);
}
});

return [{
method: METHOD,
url: ENDPOINT_URL,
data
}]
},
interpretResponse(response, request) {
if (!response || !response.body || !response.body.seatbid) {
return [];
}

const macroReplacedSeatbid = response.body.seatbid.map(seatbidItem => {
const macroReplacedBid = seatbidItem.bid.map((bidItem) => ({
...bidItem,
adm: replaceAuctionPrice(bidItem.adm, bidItem.price),
nurl: replaceAuctionPrice(bidItem.nurl, bidItem.price)
}));
return { ...seatbidItem, bid: macroReplacedBid };
});

const macroReplacedResponseBody = { ...response.body, seatbid: macroReplacedSeatbid };
const bids = converter.fromORTB({response: macroReplacedResponseBody, request: request.data}).bids;
return bids;
},
onTimeout: function(timeoutData) {},
onBidWon: function(bid) {},
onSetTargeting: function(bid) {},
// onBidderError: function({ error, bidderRequest }) {},
onAdRenderSucceeded: function(bid) {}
}

registerBidder(spec);
111 changes: 111 additions & 0 deletions modules/bidtheatreBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
# Overview

```
Module Name : Bidtheatre Bidder Adapter
Module Type : Bidder Adapter
Maintainer : [email protected]
```

# Description

Module that connects to Bidtheatre's demand sources

About us: https://www.bidtheatre.com

The Bidtheatre Bidding adapter requires manual set up before use. Please contact us at [[email protected]](mailto:[email protected]) if you would like to access Bidtheatre demand.

# Bid params
| Name | Scope | Description | Example |
|:--------------| :------- |:---------------------------------------|:-------------------------------------|
| `publisherId` | required | Manually set up publisher ID | `73b20b3a-12a0-4869-b54e-8d42b55786ee`|

In addition to the required bid param above, Bidtheatre will also enforce the following requirements
- All ad slots on a page must belong to the same publisher ID
- The publisher must provide either a client IP and/or explicit geo data in the request

# Test Parameters

## Banner

```javascript
var displayAdUnits = [
{
code: 'test-banner',
mediaTypes: {
banner: {
sizes: [[980,240]]
}
},
bids: [
{
bidder: 'bidtheatre',
params: {
publisherId: '73b20b3a-12a0-4869-b54e-8d42b55786ee'
}
}
]
}
];
```

## Video

```javascript
var videoAdUnits = [
{
code: 'test-video',
mediaTypes: {
video: {
playerSize: [[1280, 720]]
}
},
bids: [
{
bidder: 'bidtheatre',
params: {
publisherId: '73b20b3a-12a0-4869-b54e-8d42b55786ee'
}
}
]
}
];
```

## Multiformat

```javascript
var adUnits = [
{
code: 'test-banner',
mediaTypes: {
banner: {
sizes: [[980,240]]
}
},
bids: [
{
bidder: 'bidtheatre',
params: {
publisherId: '73b20b3a-12a0-4869-b54e-8d42b55786ee'
}
}
]
},
{
code: 'test-video',
mediaTypes: {
video: {
playerSize: [[1280, 720]]
}
},
bids: [
{
bidder: 'bidtheatre',
params: {
publisherId: '73b20b3a-12a0-4869-b54e-8d42b55786ee'
}
}
]
}
];
```
Loading

0 comments on commit e3e9ce0

Please sign in to comment.