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

Adding 33Across adapter #1805

Merged
merged 2 commits into from
Nov 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
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