Skip to content

Commit

Permalink
Add buyer bid adapter (#3200)
Browse files Browse the repository at this point in the history
* add adapter and doc

* add test

* fix adapter

* fix adapter

* fix adapter

* correct code after tests

* fix tests

* fix adapter and test

* fix buildQueryString and tests

* fix cpm devisor

* fix cpm devisor test

* fix doc

* fix tests

* add adapter and doc

* add test

* fix adapter

* fix adapter

* fix adapter

* correct code after tests

* fix tests

* fix adapter and test

* fix buildQueryString and tests

* fix cpm devisor

* fix cpm devisor test

* fix doc

* fix tests

* change referer source and remove userSync
  • Loading branch information
avj83 authored and jsnellbaker committed Oct 19, 2018
1 parent 73e7014 commit a62e088
Show file tree
Hide file tree
Showing 3 changed files with 299 additions and 0 deletions.
96 changes: 96 additions & 0 deletions modules/buyerBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import * as utils from 'src/utils';
import {config} from 'src/config';
import {registerBidder} from 'src/adapters/bidderFactory';

const BIDDER_CODE = 'buyer';
const ENDPOINT_URL = 'https://buyer.dspx.tv/request/';

export const spec = {
code: BIDDER_CODE,
aliases: ['buyer'],
isBidRequestValid: function(bid) {
return !!(bid.params.placement);
},
buildRequests: function(validBidRequests, bidderRequest) {
return validBidRequests.map(bidRequest => {
const params = bidRequest.params;
const sizes = utils.parseSizesInput(bidRequest.sizes)[0];
const width = sizes.split('x')[0];
const height = sizes.split('x')[1];
const placementId = params.placement;

const rnd = Math.floor(Math.random() * 99999999999);
const referrer = encodeURIComponent(bidderRequest.refererInfo.referer);
const bidId = bidRequest.bidId;
const payload = {
_f: 'html',
alternative: 'prebid_js',
inventory_item_id: placementId,
srw: width,
srh: height,
idt: 100,
rnd: rnd,
ref: referrer,
bid_id: bidId,
};
if (params.pfilter !== undefined) {
payload.pfilter = params.pfilter;
}
if (params.bcat !== undefined) {
payload.bcat = params.bcat;
}
if (params.dvt !== undefined) {
payload.dvt = params.dvt;
}
return {
method: 'GET',
url: ENDPOINT_URL,
data: objectToQueryString(payload),
}
});
},
interpretResponse: function(serverResponse, bidRequest) {
const bidResponses = [];
const response = serverResponse.body;
const crid = response.crid || 0;
const cpm = response.cpm / 1000000 || 0;
if (cpm !== 0 && crid !== 0) {
const dealId = response.dealid || '';
const currency = response.currency || 'EUR';
const netRevenue = (response.netRevenue === undefined) ? true : response.netRevenue;
const referrer = utils.getTopWindowUrl();
const bidResponse = {
requestId: response.bid_id,
cpm: cpm,
width: response.width,
height: response.height,
creativeId: crid,
dealId: dealId,
currency: currency,
netRevenue: netRevenue,
ttl: config.getConfig('_bidderTimeout'),
referrer: referrer,
ad: response.adTag
};
bidResponses.push(bidResponse);
}
return bidResponses;
}
}

function objectToQueryString(obj, prefix) {
let str = [];
let p;
for (p in obj) {
if (obj.hasOwnProperty(p)) {
let k = prefix ? prefix + '[' + p + ']' : p;
let v = obj[p];
str.push((v !== null && typeof v === 'object')
? objectToQueryString(v, k)
: encodeURIComponent(k) + '=' + encodeURIComponent(v));
}
}
return str.join('&');
}

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

```
Module Name: Buyer Bidder Adapter
Module Type: Bidder Adapter
Maintainer: avj83@list.ru
```

# Description

Buyer adapter for Prebid.js 1.0

# Test Parameters
```
var adUnits = [
{
code: 'test-div',
mediaTypes: {
banner: {
sizes: [
[300, 250],
[300, 600],
], // a display size
}
},
bids: [
{
bidder: "buyer",
params: {
placement: '12345',
pfilter: {
floorprice: 1000000, // EUR * 1,000,000
private_auction: 1, // Is private auction? 0 - no, 1 - yes
deals: [
"666-9315-d58a7f9a-bdb9-4450-a3a2-046ba8ab2489;3;25000000;dspx-tv",// DEAL_ID;at;bidfloor;wseat1,wseat2;wadomain1,wadomain2"
"666-9315-d58a7f9a-bdb9-4450-a6a2-046ba8ab2489;3;25000000;dspx-tv",// DEAL_ID;at;bidfloor;wseat1,wseat2;wadomain1,wadomain2"
],
geo: { // set client geo info manually (empty for auto detect)
lat: 52.52437, // Latitude from -90.0 to +90.0, where negative is south.
lon: 13.41053, // Longitude from -180.0 to +180.0, where negative is west
type: 1, // Source of location data: 1 - GPS/Location Services, 2 - IP Address, 3 - User provided (e.g. registration form)
country: 'DE', // Region of a country using FIPS 10-4 notation
region: 'DE-BE', // Region code using ISO-3166-2; 2-letter state code if USA.
regionfips104: 'GM', // Region of a country using FIPS 10-4 notation
city: 'BER', // City using United Nations Code for Trade and Transport Locations
zip: '10115' // Zip or postal code.
}
},
bcat: "IAB2,IAB4", // List of Blocked Categories (IAB) - comma separated
dvt: "desktop|smartphone|tv|tablet" // DeVice Type (autodetect if not exists)
}
}
]
},{
code: 'test-div',
mediaTypes: {
banner: {
sizes: [[320, 50]], // a mobile size
}
},
bids: [
{
bidder: "buyer",
params: {
placement: 67890
}
}
]
}
];
```

Required param field is only `placement`.
130 changes: 130 additions & 0 deletions test/spec/modules/buyerBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { expect } from 'chai';
import { spec } from 'modules/buyerBidAdapter';
import { newBidder } from 'src/adapters/bidderFactory';

const ENDPOINT_URL = 'https://buyer.dspx.tv/request/';

describe('buyerAdapter', function () {
const adapter = newBidder(spec);

describe('isBidRequestValid', function () {
let bid = {
'bidder': 'buyer',
'params': {
'placement': '6682',
'pfilter': {
'floorprice': 1000000
},
'bcat': 'IAB2,IAB4',
'dvt': 'desktop'
},
'sizes': [
[300, 250]
],
'bidId': '30b31c1838de1e',
'bidderRequestId': '22edbae2733bf6',
'auctionId': '1d1a030790a475'
};

it('should return true when required params found', function () {
expect(spec.isBidRequestValid(bid)).to.equal(true);
});

it('should return false when required params are not passed', function () {
let bid = Object.assign({}, bid);
delete bid.params;
bid.params = {
'someIncorrectParam': 0
};
expect(spec.isBidRequestValid(bid)).to.equal(false);
});
});

describe('buildRequests', function () {
let bidRequests = [{
'bidder': 'buyer',
'params': {
'placement': '6682',
'pfilter': {
'floorprice': 1000000,
'private_auction': 0,
'geo': {
'country': 'DE'
}
},
'bcat': 'IAB2,IAB4',
'dvt': 'desktop'
},
'sizes': [
[300, 250]
],
'bidId': '30b31c1838de1e',
'bidderRequestId': '22edbae2733bf6',
'auctionId': '1d1a030790a475'
}];

let bidderRequest = {
refererInfo: {
referer: 'some_referrer.net'
}
}

const request = spec.buildRequests(bidRequests, bidderRequest);
it('sends bid request to our endpoint via GET', function () {
expect(request[0].method).to.equal('GET');
let data = request[0].data.replace(/rnd=\d+\&/g, '').replace(/ref=.*\&bid/g, 'bid');
expect(data).to.equal('_f=html&alternative=prebid_js&inventory_item_id=6682&srw=300&srh=250&idt=100&bid_id=30b31c1838de1e&pfilter%5Bfloorprice%5D=1000000&pfilter%5Bprivate_auction%5D=0&pfilter%5Bgeo%5D%5Bcountry%5D=DE&bcat=IAB2%2CIAB4&dvt=desktop');
});
});

describe('interpretResponse', function () {
let serverResponse = {
'body': {
'cpm': 5000000,
'crid': 100500,
'width': '300',
'height': '250',
'tag': '<!-- test creative -->',
'requestId': '220ed41385952a',
'currency': 'EUR',
'ttl': 60,
'netRevenue': true,
'zone': '6682'
}
};

let expectedResponse = [{
requestId: '23beaa6af6cdde',
cpm: 0.5,
width: 0,
height: 0,
creativeId: 100500,
dealId: '',
currency: 'EUR',
netRevenue: true,
ttl: 300,
referrer: '',
ad: '<!-- test creative -->'
}];

it('should get the correct bid response by display ad', function () {
let bidRequest = [{
'method': 'GET',
'url': ENDPOINT_URL,
'data': {
'bid_id': '30b31c1838de1e'
}
}];
let result = spec.interpretResponse(serverResponse, bidRequest[0]);
expect(Object.keys(result[0])).to.have.members(Object.keys(expectedResponse[0]));
});

it('handles empty bid response', function () {
let response = {
body: {}
};
let result = spec.interpretResponse(response);
expect(result.length).to.equal(0);
});
});
});

0 comments on commit a62e088

Please sign in to comment.