Skip to content

Commit

Permalink
Adding 33Across adapter (#1805)
Browse files Browse the repository at this point in the history
* Adding 33across adapter

* Updated per code review from Prebid. See #1805 (review)
  • Loading branch information
curlyblueeagle authored and jaiminpanchal27 committed Nov 9, 2017
1 parent 4e2c2a9 commit 1895cb3
Show file tree
Hide file tree
Showing 3 changed files with 678 additions and 0 deletions.
140 changes: 140 additions & 0 deletions modules/33acrossBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
const { registerBidder } = require('../src/adapters/bidderFactory');
const utils = require('../src/utils');

const BIDDER_CODE = '33across';
const END_POINT = 'https://ssc.33across.com/api/v1/hb';
const SYNC_ENDPOINT = 'https://de.tynt.com/deb/v2?m=xch';

// All this assumes that only one bid is ever returned by ttx
function _createBidResponse(response) {
return {
requestId: response.id,
bidderCode: BIDDER_CODE,
cpm: response.seatbid[0].bid[0].price,
width: response.seatbid[0].bid[0].w,
height: response.seatbid[0].bid[0].h,
ad: response.seatbid[0].bid[0].adm,
ttl: response.seatbid[0].bid[0].ttl || 60,
creativeId: response.seatbid[0].bid[0].ext.rp.advid,
currency: response.cur,
netRevenue: true
}
}

// infer the necessary data from valid bid for a minimal ttxRequest and create HTTP request
function _createServerRequest(bidRequest) {
const ttxRequest = {};
const params = bidRequest.params;

ttxRequest.imp = [];
ttxRequest.imp[0] = {
banner: {
format: bidRequest.sizes.map(_getFormatSize)
},
ext: {
ttx: {
prod: params.productId
}
}
}

// Allowing site to be a test configuration object or just the id (former required for testing,
// latter when used by publishers)
ttxRequest.site = params.site || { id: params.siteId };

// Go ahead send the bidId in request to 33exchange so it's kept track of in the bid response and
// therefore in ad targetting process
ttxRequest.id = bidRequest.bidId;

const options = {
contentType: 'application/json',
withCredentials: false
};

if (bidRequest.params.customHeaders) {
options.customHeaders = bidRequest.params.customHeaders;
}

return {
'method': 'POST',
'url': bidRequest.params.url || END_POINT,
'data': JSON.stringify(ttxRequest),
'options': options
}
}

// Sync object will always be of type iframe for ttx
function _createSync(bid) {
const syncUrl = bid.params.syncUrl || SYNC_ENDPOINT;

return {
type: 'iframe',
url: `${syncUrl}&id=${bid.params.siteId || bid.params.site.id}`
}
}

function _getFormatSize(sizeArr) {
return {
w: sizeArr[0],
h: sizeArr[1],
ext: {}
}
}

function isBidRequestValid(bid) {
if (bid.bidder !== BIDDER_CODE || typeof bid.params === 'undefined') {
return false;
}

if ((typeof bid.params.site === 'undefined' || typeof bid.params.site.id === 'undefined') &&
(typeof bid.params.siteId === 'undefined')) {
return false;
}

if (typeof bid.params.productId === 'undefined') {
return false;
}

return true;
}

// NOTE: At this point, 33exchange only accepts request for a single impression
function buildRequests(bidRequests) {
return bidRequests.map(_createServerRequest);
}

// NOTE: At this point, the response from 33exchange will only ever contain one bid i.e. the highest bid
function interpretResponse(serverResponse) {
const bidResponses = [];

// If there are bids, look at the first bid of the first seatbid (see NOTE above for assumption about ttx)
if (serverResponse.body.seatbid.length > 0 && serverResponse.body.seatbid[0].bid.length > 0) {
bidResponses.push(_createBidResponse(serverResponse.body));
}

return bidResponses;
}

// Register one sync per bid since each ad unit may potenitally be linked to a uniqe guid
function getUserSyncs(syncOptions) {
let syncs = [];
const ttxBidRequests = utils.getBidderRequestAllAdUnits(BIDDER_CODE).bids;

if (syncOptions.iframeEnabled) {
syncs = ttxBidRequests.map(_createSync);
}

return syncs;
}

const spec = {
code: BIDDER_CODE,
isBidRequestValid,
buildRequests,
interpretResponse,
getUserSyncs
}

registerBidder(spec);

module.exports = spec;
95 changes: 95 additions & 0 deletions modules/33acrossBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Overview

```
Module Name: 33Across Bid Adapter
Module Type: Bidder Adapter
Maintainer: aparna.hegde@33across.com
```

# Description

Connects to 33Across's exchange for bids.

33Across bid adapter supports only Banner at present and follows MRA

# Sample Ad Unit: For Publishers
```
var adUnits = [
{
code: '33across-hb-ad-123456-1',
sizes: [
[300, 250],
[728, 90]
],
bids: [{
bidder: '33across',
params: {
siteId: 'pub1234',
productId: 'infeed'
}
}]
}
```

# Ad Unit and Setup: For Testing
In order to receive bids please map localhost to (any) test domain.

```
<--! Prebid Config section >
<script>
var PREBID_TIMEOUT = 3000;
var adUnits = [
{
code: '33across-hb-ad-123456-1',
sizes: [
[300, 250],
[728, 90]
],
bids: [{
bidder: '33across',
params: {
site: {
id: 'aRlI5W_9yr5jkxacwqm_6r',
page: "http://thinkbabynames.com/baby-mcbabyface",
ext: {
ttx: {
ssp_configs: [
{
"name": "index",
"enabled": false
},
{
"name": "rubicon",
"enabled": true
},
{
"name": "33xchange",
"enabled": false
}
]
}
}
},
productId: 'infeed'
}
}]
}
];
var pbjs = pbjs || {};
pbjs.que = pbjs.que || [];
// Adjust bid CPM to ensure it wins the auction (USED ONLY FOR TESTING). Need to do this since test bids have too low a CPM
pbjs.bidderSettings = {
'33across': {
bidCpmAdjustment : function(bidCpm, bid){
// adjust the bid in real time before the auction takes place, only do so for valid bids ignore no bids
if (bid.w !== 0 && bid.h !== 0 && bidCpm !== 0) {
return bidCpm + 0.50;
}
}
}
};
</script>
<!-- End Prebid Config section>
```
Loading

0 comments on commit 1895cb3

Please sign in to comment.