Skip to content

Commit

Permalink
Add Sortable bid adapter (#2824)
Browse files Browse the repository at this point in the history
* Add Sortable bid adapter

- [x] New bidder adapter

This change adds the Sortable adapter to Prebid.js.

* move global sortable config into its own object

* update siteId

* config can be undefined when module loads

* support floor param
  • Loading branch information
shannonAB authored and jsnellbaker committed Jul 11, 2018
1 parent 72b7240 commit 4ad1a00
Show file tree
Hide file tree
Showing 3 changed files with 399 additions and 0 deletions.
149 changes: 149 additions & 0 deletions modules/sortableBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import * as utils from 'src/utils';
import { registerBidder } from 'src/adapters/bidderFactory';
import { config } from 'src/config';
import { BANNER } from 'src/mediaTypes';
import { REPO_AND_VERSION } from 'src/constants';

const BIDDER_CODE = 'sortable';
const SERVER_URL = 'c.deployads.com';

export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: [BANNER],

isBidRequestValid: function(bid) {
const sortableConfig = config.getConfig('sortable');
const haveSiteId = (sortableConfig && !!sortableConfig.siteId) || bid.params.siteId;
return !!(bid.params.tagId && haveSiteId && bid.sizes &&
bid.sizes.every(sizeArr => sizeArr.length == 2 && sizeArr.every(Number.isInteger)));
},

buildRequests: function(validBidReqs, bidderRequest) {
const sortableConfig = config.getConfig('sortable') || {};
const globalSiteId = sortableConfig.siteId;
let loc = utils.getTopWindowLocation();

const sortableImps = utils._map(validBidReqs, bid => {
let rv = {
id: bid.bidId,
tagid: bid.params.tagId,
banner: {
format: utils._map(bid.sizes, ([width, height]) => ({w: width, h: height}))
},
ext: {}
};
if (bid.params.floor) {
rv.bidfloor = bid.params.floor;
}
if (bid.params.keywords) {
let keywords = utils._map(bid.params.keywords, (foo, bar) => ({name: bar, value: foo}));
rv.ext.keywords = keywords;
}
if (bid.params.bidderParams) {
utils._each(bid.params.bidderParams, (params, partner) => {
rv.ext[partner] = params;
});
}
return rv;
});
const gdprConsent = bidderRequest && bidderRequest.gdprConsent;
const sortableBidReq = {
id: utils.getUniqueIdentifierStr(),
imp: sortableImps,
site: {
domain: loc.hostname,
page: loc.href,
ref: utils.getTopWindowReferrer(),
publisher: {
id: globalSiteId || validBidReqs[0].params.siteId,
},
device: {
w: screen.width,
h: screen.height
},
},
};
if (gdprConsent) {
sortableBidReq.user = {
ext: {
consent: gdprConsent.consentString
}
};
sortableBidReq.regs = {
ext: {
gdpr: gdprConsent.gdprApplies ? 1 : 0
}
};
}

return {
method: 'POST',
url: `//${SERVER_URL}/openrtb2/auction?src=${REPO_AND_VERSION}&host=${loc.host}`,
data: JSON.stringify(sortableBidReq),
options: {contentType: 'text/plain'}
};
},

interpretResponse: function(serverResponse) {
const { body: {id, seatbid} } = serverResponse;
const sortableBids = [];
if (id && seatbid) {
utils._each(seatbid, seatbid => {
utils._each(seatbid.bid, bid => {
const bidObj = {
requestId: bid.impid,
cpm: parseFloat(bid.price),
width: parseInt(bid.w),
height: parseInt(bid.h),
creativeId: bid.id,
dealId: bid.dealid || null,
currency: 'USD',
netRevenue: true,
mediaType: BANNER,
ttl: 60
};
if (bid.adm && bid.nurl) {
bidObj.ad = bid.adm;
bidObj.ad += utils.createTrackPixelHtml(decodeURIComponent(bid.nurl));
} else if (bid.adm) {
bidObj.ad = bid.adm;
} else if (bid.nurl) {
bidObj.adUrl = bid.nurl;
}
sortableBids.push(bidObj);
});
});
}
return sortableBids;
},

getUserSyncs: (syncOptions, responses, gdprConsent) => {
const sortableConfig = config.getConfig('sortable');
if (syncOptions.iframeEnabled && sortableConfig && !!sortableConfig.siteId) {
let syncUrl = `//${SERVER_URL}/sync?f=html&s=${sortableConfig.siteId}&u=${encodeURIComponent(utils.getTopWindowLocation())}`;

if (gdprConsent) {
syncurl += '&g=' + (gdprConsent.gdprApplies ? 1 : 0);
syncurl += '&cs=' + encodeURIComponent(gdprConsent.consentString || '');
}

return [{
type: 'iframe',
url: syncUrl
}];
}
},

onTimeout(details) {
fetch(`//${SERVER_URL}/prebid/timeout`, {
method: 'POST',
body: JSON.stringify(details),
mode: 'no-cors',
headers: new Headers({
'Content-Type': 'text/plain'
})
});
}
};

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

```
Module Name: Sortable Bid Adapter
Module Type: Bidder Adapter
Maintainer: prebid@sortable.com
```

# Description

Sortable's adapter integration to the Prebid library. Posts plain-text JSON to the /openrtb2/auction endpoint.

# Test Parameters

```
var adUnits = [
{
code: 'test-pb-leaderboard',
sizes: [[728, 90]],
bids: [{
bidder: 'sortable',
params: {
tagId: 'test-pb-leaderboard',
siteId: 'prebid.example.com',
'keywords': {
'key1': 'val1',
'key2': 'val2'
}
}
}]
}, {
code: 'test-pb-banner',
sizes: [[300, 250]],
bids: [{
bidder: 'sortable',
params: {
tagId: 'test-pb-banner',
siteId: 'prebid.example.com'
}
}]
}, {
code: 'test-pb-sidebar',
size: [[160, 600]],
bids: [{
bidder: 'sortable',
params: {
tagId: 'test-pb-sidebar',
siteId: 'prebid.example.com',
'keywords': {
'keyA': 'valA'
}
}
}]
}
]
```
Loading

0 comments on commit 4ad1a00

Please sign in to comment.