Skip to content

Commit

Permalink
added TPMN Bidder Adapter (#4547)
Browse files Browse the repository at this point in the history
* implement TPMN Bidder Adapter

* fixed bug for failed test on CircleCl--added line

* removed comment line for 'config'

* added https protocol
  • Loading branch information
tpmn-admin authored and jsnellbaker committed Dec 12, 2019
1 parent aabb91f commit b615862
Show file tree
Hide file tree
Showing 3 changed files with 301 additions and 0 deletions.
120 changes: 120 additions & 0 deletions modules/tpmnBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/* eslint-disable no-tabs */
import { registerBidder } from '../src/adapters/bidderFactory';
import * as utils from '../src/utils';
import { BANNER } from '../src/mediaTypes';
import {parse as parseUrl} from '../src/url';

export const ADAPTER_VERSION = '1';
const SUPPORTED_AD_TYPES = [BANNER];

const BIDDER_CODE = 'tpmn';
const URL = 'https://ad.tpmn.co.kr/prebidhb.tpmn';

export const spec = {
code: BIDDER_CODE,
supportedMediaTypes: SUPPORTED_AD_TYPES,
/**
*Determines whether or not the given bid request is valid.
*
* @param {object} bid The bid to validate.
* @return boolean True if this is a valid bid, and false otherwise.
*/
isBidRequestValid: function(bid) {
return 'params' in bid &&
'inventoryId' in bid.params &&
'publisherId' in bid.params &&
!isNaN(Number(bid.params.inventoryId)) &&
bid.params.inventoryId > 0 &&
(typeof bid.mediaTypes.banner.sizes != 'undefined'); // only accepting appropriate sizes
},

/**
* @param {BidRequest[]} bidRequests
* @param {*} bidderRequest
* @return {ServerRequest}
*/
buildRequests: (bidRequests, bidderRequest) => {
if (bidRequests.length === 0) {
return [];
}
const bids = bidRequests.map(bidToRequest);
const bidderApiUrl = URL;
const payload = {
'bids': [...bids],
'site': createSite(bidderRequest.refererInfo)
};
return [{
method: 'POST',
url: bidderApiUrl,
data: payload
}];
},
/**
* Unpack the response from the server into a list of bids.
*
* @param {serverResponse} serverResponse A successful response from the server.
* @return {Bid[]} An array of bids which were nested inside the server.
*/
interpretResponse: function (serverResponse, serverRequest) {
if (!Array.isArray(serverResponse.body)) {
return [];
}
// server response body is an array of bid results
const bidResults = serverResponse.body;
// our server directly returns the format needed by prebid.js so no more
// transformation is needed here.
return bidResults;
}
};

registerBidder(spec);

/**
* Creates site description object
*/
function createSite(refInfo) {
let url = parseUrl(refInfo.referer);
let site = {
'domain': url.hostname,
'page': url.protocol + '://' + url.hostname + url.pathname
};
if (self === top && document.referrer) {
site.ref = document.referrer;
}
let keywords = document.getElementsByTagName('meta')['keywords'];
if (keywords && keywords.content) {
site.keywords = keywords.content;
}
return site;
}

function parseSize(size) {
let sizeObj = {}
sizeObj.width = parseInt(size[0], 10);
sizeObj.height = parseInt(size[1], 10);
return sizeObj;
}

function parseSizes(sizes) {
if (Array.isArray(sizes[0])) { // is there several sizes ? (ie. [[728,90],[200,300]])
return sizes.map(size => parseSize(size));
}
return [parseSize(sizes)]; // or a single one ? (ie. [728,90])
}

function getBannerSizes(bidRequest) {
return parseSizes(utils.deepAccess(bidRequest, 'mediaTypes.banner.sizes') || bidRequest.sizes);
}

function bidToRequest(bid) {
const bidObj = {};
bidObj.sizes = getBannerSizes(bid);

bidObj.inventoryId = bid.params.inventoryId;
bidObj.publisherId = bid.params.publisherId;
bidObj.bidId = bid.bidId;
bidObj.adUnitCode = bid.adUnitCode;
bidObj.auctionId = bid.auctionId;

return bidObj;
}
37 changes: 37 additions & 0 deletions modules/tpmnBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Overview

```
Module Name: TPMN Bid Adapter
Module Type: Bidder Adapter
Maintainer: develop@tpmn.co.kr
```

# Description

Connects to TPMN exchange for bids.

NOTE:
- TPMN bid adapter only supports Banner at the moment.
- Multi-currency is not supported.

# Sample Ad Unit Config
```
var adUnits = [{
// Banner adUnit
code: 'banner-div',
mediaTypes: {
banner: {
sizes: [[300, 250], [320, 50]], // banner size
}
},
bids: [
{
bidder: 'tpmn',
params: {
inventoryId: '1',
publisherId: 'TPMN'
}
}
]
}];
```
144 changes: 144 additions & 0 deletions test/spec/tpmnBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/* eslint-disable no-tabs */
import { expect } from 'chai';
import { spec } from 'modules/tpmnBidAdapter';

describe('tpmnAdapterTests', function() {
describe('isBidRequestValid', function() {
let bid = {
adUnitCode: 'temp-unitcode',
bidder: 'tpmn',
params: {
inventoryId: '1',
publisherId: 'TPMN'
},
bidId: '29092404798c9',
bidderRequestId: 'a01',
auctionId: 'da1d7a33-0260-4e83-a621-14674116f3f9',
mediaTypes: {
banner: {
sizes: [[300, 250]]
}
}
};
it('should return true if a bid is valid banner bid request', function() {
expect(spec.isBidRequestValid(bid)).to.be.equal(true);
});

it('should return false where requried param is missing', function() {
let bid = Object.assign({}, bid);
bid.params = {};
expect(spec.isBidRequestValid(bid)).to.be.equal(false);
});

it('should return false when required param values have invalid type', function() {
let bid = Object.assign({}, bid);
bid.params = {
'inventoryId': null,
'publisherId': null
};
expect(spec.isBidRequestValid(bid)).to.be.equal(false);
});
});

describe('buildRequests', function() {
it('should return an empty list if there are no bid requests', function() {
const emptyBidRequests = [];
const bidderRequest = {};
const request = spec.buildRequests(emptyBidRequests, bidderRequest);
expect(request).to.be.an('array').that.is.empty;
});
it('should generate a POST server request with bidder API url, data', function() {
const bid = {
adUnitCode: 'temp-unitcode',
bidder: 'tpmn',
params: {
inventoryId: '1',
publisherId: 'TPMN'
},
bidId: '29092404798c9',
bidderRequestId: 'a01',
auctionId: 'da1d7a33-0260-4e83-a621-14674116f3f9',
mediaTypes: {
banner: {
sizes: [[300, 250]]
}
}
};
const tempBidRequests = [bid];
const tempBidderRequest = {refererInfo: {
referer: 'test',
site: {
domain: 'localhost',
page: 'http://localhost/test'
}
}};
const builtRequest = spec.buildRequests(tempBidRequests, tempBidderRequest);

expect(builtRequest).to.have.lengthOf(1);
expect(builtRequest[0].method).to.equal('POST');
expect(builtRequest[0].url).to.match(/ad.tpmn.co.kr\/prebidhb.tpmn/);
const apiRequest = builtRequest[0].data;
expect(apiRequest.site).to.deep.equal({
domain: 'localhost',
page: 'http://localhost/test'
});
expect(apiRequest.bids).to.have.lengthOf('1');
expect(apiRequest.bids[0].inventoryId).to.equal('1');
expect(apiRequest.bids[0].publisherId).to.equal('TPMN');
expect(apiRequest.bids[0].bidId).to.equal('29092404798c9');
expect(apiRequest.bids[0].adUnitCode).to.equal('temp-unitcode');
expect(apiRequest.bids[0].auctionId).to.equal('da1d7a33-0260-4e83-a621-14674116f3f9');
expect(apiRequest.bids[0].sizes).to.have.lengthOf('1');
expect(apiRequest.bids[0].sizes[0]).to.deep.equal({
width: 300,
height: 250
});
});
});

describe('interpretResponse', function() {
const bid = {
adUnitCode: 'temp-unitcode',
bidder: 'tpmn',
params: {
inventoryId: '1',
publisherId: 'TPMN'
},
bidId: '29092404798c9',
bidderRequestId: 'a01',
auctionId: 'da1d7a33-0260-4e83-a621-14674116f3f9',
mediaTypes: {
banner: {
sizes: [[300, 250]]
}
}
};
const tempBidRequests = [bid];

it('should return an empty aray to indicate no valid bids', function() {
const emptyServerResponse = {};
const bidResponses = spec.interpretResponse(emptyServerResponse, tempBidRequests);
expect(bidResponses).is.an('array').that.is.empty;
});
it('should return an empty array to indicate no valid bids', function() {
const mockBidResult = {
requestId: '9cf19229-34f6-4d06-bc1d-0e44e8d616c8',
cpm: 10.0,
creativeId: '1',
width: 300,
height: 250,
netRevenue: true,
currency: 'USD',
ttl: 1800,
ad: '<div style=\"width:300px;height:250px;margin: auto;background-color:#eee;border:solid 1px #b8b8b8;display:table;\"><span style=\"text-align:center;vertical-align:middle;display:table-cell;\"><a href=\"http://tpmn.co.kr\" target=\"_blank\">TPMN HeaderBidding!</a></span></div>',
adType: 'banner'
};
const testServerResponse = {
headers: [],
body: [mockBidResult]
};
const bidResponses = spec.interpretResponse(testServerResponse, tempBidRequests);
expect(bidResponses).deep.equal([mockBidResult]);
});
});
});

0 comments on commit b615862

Please sign in to comment.