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

Create undertone udapter #1850

Merged
merged 16 commits into from
Nov 29, 2017
73 changes: 73 additions & 0 deletions modules/undertoneBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/**
* Adapter to send bids to Undertone
*/

import * as utils from 'src/utils';
import { registerBidder } from 'src/adapters/bidderFactory';

const BIDDER_CODE = 'undertone';
const URL = '//hb.undertone.com/hb';

export const spec = {
code: BIDDER_CODE,
isBidRequestValid: function(bid) {
if (bid && bid.params && bid.params.publisherId && bid.params.placementId) {
bid.params.publisherId = parseInt(bid.params.publisherId);
return true;
}
},
buildRequests: function(validBidRequests) {
const payload = {
'x-ut-hb-params': []
};
const host = utils.getTopWindowLocation().host;
const domain = /[-\w]+\.(?:[-\w]+\.xn--[-\w]+|[-\w]{3,}|[-\w]+\.[-\w]{2})$/i.exec(host);

const pubid = validBidRequests[0].params.publisherId;
const REQ_URL = `${URL}?pid=${pubid}&domain=${domain}`;

validBidRequests.map(bidReq => {
const bid = {
bidRequestId: bidReq.bidId,
hbadaptor: 'prebid',
domain: domain,
placementId: bidReq.params.placementId,
publisherId: bidReq.params.publisherId,
sizes: bidReq.sizes,
params: bidReq.params
};
payload['x-ut-hb-params'].push(bid);
});
return {
method: 'POST',
url: REQ_URL,
withCredentials: true,
data: JSON.stringify(payload)
};
},
interpretResponse: function(serverResponse, request) {
const bids = [];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#1748 changed the first argument of interpretResponse to:

{
  body: responseBody,
  headers: {
    get: function(header) { /* returns a header from the HTTP response */ }
  }
}

so adding something like

serverResponse = serverResponse.body;

just below this line, or however you'd prefer to grab the body, and updating corresponding tests if needed should get this back to working properly

const body = serverResponse.body;

if (body && Array.isArray(body) && body.length > 0) {
body.forEach((bidRes) => {
if (bidRes.ad && bidRes.cpm > 0) {
const bid = {
requestId: bidRes.bidRequestId,
cpm: bidRes.cpm,
width: bidRes.width,
height: bidRes.height,
creativeId: bidRes.adId,
currency: bidRes.currency,
netRevenue: bidRes.netRevenue,
ttl: bidRes.ttl,
ad: bidRes.ad
};
bids.push(bid);
}
});
}
return bids;
}
};
registerBidder(spec);
29 changes: 29 additions & 0 deletions modules/undertoneBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Overview

```
Module Name: Example Bidder Adapter
Module Type: Bidder Adapter
Maintainer: RampProgrammatic@perion.com
```
# Description

Module that connects to Undertone's demand sources

# Test Parameters
```
var adUnits = [
{
code: 'test-div',
sizes: [[300, 250]],
bids: [
{
bidder: "undertone",
params: {
placementId: '10433394',
publisherId: 12345
}
}
]
}
];
```
140 changes: 140 additions & 0 deletions test/spec/modules/undertoneBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { expect } from 'chai';
import { spec } from 'modules/undertoneBidAdapter';

const URL = '//hb.undertone.com/hb';
const BIDDER_CODE = 'undertone';
const validBidReq = {
bidder: BIDDER_CODE,
params: {
placementId: '10433394',
publisherId: 12345
},
sizes: [[300, 250], [300, 600]],
bidId: '263be71e91dd9d',
requestId: '9ad1fa8d-2297-4660-a018-b39945054746',
auctionId: '1d1a030790a475'
};

const invalidBidReq = {
bidder: BIDDER_CODE,
params: {
placementId: '123456789'
},
sizes: [[300, 250], [300, 600]],
bidId: '263be71e91dd9d',
requestId: '9ad1fa8d-2297-4660-a018-b39945054746'
};

const bidReq = [{
bidder: BIDDER_CODE,
params: {
placementId: '10433394',
publisherId: 12345
},
sizes: [[300, 250], [300, 600]],
bidId: '263be71e91dd9d',
requestId: '9ad1fa8d-2297-4660-a018-b39945054746',
auctionId: '1d1a030790a475'
}];

const validBidRes = {
ad: '<div>Hello</div>',
publisherId: 12345,
bidRequestId: '263be71e91dd9d',
adId: 15,
cpm: 100,
nCampaignId: 2,
creativeId: '123abc',
currency: 'USD',
netRevenue: true,
width: 300,
height: 250,
ttl: 360
};

const bidResponse = [validBidRes];

const bidResArray = [
validBidRes,
{
ad: '',
bidRequestId: '263be71e91dd9d',
cpm: 100,
adId: '123abc',
currency: 'USD',
netRevenue: true,
width: 300,
height: 250,
ttl: 360
},
{
ad: '<div>Hello</div>',
bidRequestId: '',
cpm: 0,
adId: '123abc',
currency: 'USD',
netRevenue: true,
width: 300,
height: 250,
ttl: 360
}
];

describe('Undertone Adapter', () => {
describe('request', () => {
it('should validate bid request', () => {
expect(spec.isBidRequestValid(validBidReq)).to.equal(true);
});
it('should not validate incorrect bid request', () => {
expect(spec.isBidRequestValid(invalidBidReq)).to.equal(undefined);
});
});
describe('build request', () => {
it('should send request to correct url via POST', () => {
const request = spec.buildRequests(bidReq);
const domain = null;
const REQ_URL = `${URL}?pid=${bidReq[0].params.publisherId}&domain=${domain}`;
expect(request.url).to.equal(REQ_URL);
expect(request.method).to.equal('POST');
});
it('should have all relevant fields', () => {
const request = spec.buildRequests(bidReq);
const bid = JSON.parse(request.data)['x-ut-hb-params'][0];
expect(bid.bidRequestId).to.equal('263be71e91dd9d');
expect(bid.sizes.length > 0).to.equal(true);
expect(bid.placementId).to.equal('10433394');
expect(bid.publisherId).to.equal(12345);
expect(bid.params).to.be.an('object');
});
});

describe('interpretResponse', () => {
it('should build bid array', () => {
let result = spec.interpretResponse({body: bidResponse});
expect(result.length).to.equal(1);
});

it('should have all relevant fields', () => {
const result = spec.interpretResponse({body: bidResponse});
const bid = result[0];

expect(bid.requestId).to.equal('263be71e91dd9d');
expect(bid.cpm).to.equal(100);
expect(bid.width).to.equal(300);
expect(bid.height).to.equal(250);
expect(bid.creativeId).to.equal(15);
expect(bid.currency).to.equal('USD');
expect(bid.netRevenue).to.equal(true);
expect(bid.ttl).to.equal(360);
});

it('should return empty array when response is incorrect', () => {
expect(spec.interpretResponse({body: {}}).length).to.equal(0);
expect(spec.interpretResponse({body: []}).length).to.equal(0);
});

it('should only use valid bid responses', () => {
expect(spec.interpretResponse({ body: bidResArray }).length).to.equal(1);
});
});
});