Skip to content

Commit

Permalink
Timmedia/timadapter 2.0 (#3497)
Browse files Browse the repository at this point in the history
* add tim adapter

* add tim spec file

* add tim md file

* added tests. change adapter.

* dummy commit for re-running tests

* new code for prebid2.0

* change alias name

* change domain name
  • Loading branch information
borisjaskerovich authored and mike-chowla committed Feb 4, 2019
1 parent e93d17d commit 0be3422
Show file tree
Hide file tree
Showing 3 changed files with 355 additions and 0 deletions.
177 changes: 177 additions & 0 deletions modules/timBidAdapter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
import * as utils from 'src/utils';
import {registerBidder} from 'src/adapters/bidderFactory';
import * as bidfactory from '../src/bidfactory';
var CONSTANTS = require('src/constants.json');
const BIDDER_CODE = 'tim';

function parseBidRequest(bidRequest) {
let params = bidRequest.url.split('?')[1];
var obj = {};
var pairs = params.split('&');
try {
for (var i in pairs) {
var split = pairs[i].split('=');
obj[decodeURIComponent(split[0])] = decodeURIComponent(split[1]);
}
} catch (e) {
utils.logError(e);
}

return JSON.parse(obj.br);
}

function formatAdMarkup(bid) {
var adm = bid.adm;
if ('nurl' in bid) {
adm += createTrackPixelHtml(bid.nurl);
}
return `<!DOCTYPE html><html><head><title></title><body style='margin:0px;padding:0px;'>${adm}</body></head>`;
}

function createTrackPixelHtml(url) {
if (!url) {
return '';
}
let img = '<div style="position:absolute;left:0px;top:0px;visibility:hidden;">';
img += '<img src="' + url + '"></div>';
return img;
}

export const spec = {
code: BIDDER_CODE,
aliases: ['timmedia'],

isBidRequestValid: function(bid) {
if (bid.params && bid.params.publisherid && bid.params.placementCode) {
return true;
} if (!bid.params) {
utils.logError('bid not valid: params were not provided');
} else if (!bid.params.publisherid) {
utils.logError('bid not valid: publisherid was not provided');
} else if (!bid.params.placementCode) {
utils.logError('bid not valid: placementCode was not provided');
} return false;
},

buildRequests: function(validBidRequests, bidderRequest) {
var requests = [];
for (var i = 0; i < validBidRequests.length; i++) {
requests.push(this.createRTBRequestURL(validBidRequests[i]));
}
return requests;
},

createRTBRequestURL: function(bidReq) {
// build bid request object
var domain = window.location.host;
var page = window.location.href;
var publisherid = bidReq.params.publisherid;
var bidFloor = bidReq.params.bidfloor;
var placementCode = bidReq.params.placementCode;

var adW = bidReq.mediaTypes.banner.sizes[0][0];
var adH = bidReq.mediaTypes.banner.sizes[0][1];

// build bid request with impressions
var bidRequest = {
id: utils.getUniqueIdentifierStr(),
imp: [{
id: bidReq.bidId,
banner: {
w: adW,
h: adH
},
tagid: placementCode,
bidfloor: bidFloor
}],
site: {
domain: domain,
page: page,
publisher: {
id: publisherid
}
},
device: {
'language': this.getLanguage(),
'w': adW,
'h': adH,
'js': 1,
'ua': navigator.userAgent
}
};
if (!bidFloor) {
delete bidRequest.imp['bidfloor'];
}

bidRequest.bidId = bidReq.bidId;
var url = '//hb.timmedia-hb.com/api/v2/services/prebid/' + publisherid + '/' + placementCode + '?' + 'br=' + encodeURIComponent(JSON.stringify(bidRequest));
return {
method: 'GET',
url: url,
data: '',
options: {withCredentials: false}
};
},

interpretResponse: function(serverResponse, bidRequest) {
bidRequest = parseBidRequest(bidRequest);
var bidResp = serverResponse.body;
const bidResponses = [];
if ((!bidResp || !bidResp.id) ||
(!bidResp.seatbid || bidResp.seatbid.length === 0 || !bidResp.seatbid[0].bid || bidResp.seatbid[0].bid.length === 0)) {
return [];
}
bidResp.seatbid[0].bid.forEach(function (bidderBid) {
var responseCPM;
var placementCode = '';
if (bidRequest) {
var bidResponse = bidfactory.createBid(1);
placementCode = bidRequest.placementCode;
bidRequest.status = CONSTANTS.STATUS.GOOD;
responseCPM = parseFloat(bidderBid.price);
if (responseCPM === 0) {
var bid = bidfactory.createBid(2);
bid.bidderCode = BIDDER_CODE;
bidResponses.push(bid);
return bidResponses;
}
bidResponse.placementCode = placementCode;
bidResponse.size = bidRequest.sizes;
bidResponse.creativeId = bidderBid.id;
bidResponse.bidderCode = BIDDER_CODE;
bidResponse.cpm = responseCPM;
bidResponse.ad = formatAdMarkup(bidderBid);
bidResponse.width = parseInt(bidderBid.w);
bidResponse.height = parseInt(bidderBid.h);
bidResponse.currency = bidResp.cur;
bidResponse.netRevenue = true;
bidResponse.requestId = bidRequest.bidId;
bidResponse.ttl = 180;
bidResponses.push(bidResponse);
}
});
return bidResponses;
},
getLanguage: function() {
const language = navigator.language ? 'language' : 'userLanguage';
return navigator[language].split('-')[0];
},

getUserSyncs: function(syncOptions, serverResponses) {
const syncs = []
return syncs;
},

onTimeout: function(data) {
// Bidder specifc code
},

onBidWon: function(bid) {
// Bidder specific code
},

onSetTargeting: function(bid) {
// Bidder specific code
},
}
registerBidder(spec);
26 changes: 26 additions & 0 deletions modules/timBidAdapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Overview

```
Module Name: tim Bidder Adapter
Module Type: Bidder Adapter
Maintainer: boris@thetimmedia.com
```

# Description

Module that connects to tim's demand sources

# Test Parameters
```
var adUnits = [{
"code":"99",
"sizes":[[300,250]],
"bids":[{"bidder":"tim",
"params":{
"placementCode":"testPlacementCode",
"publisherid":"testpublisherid"
}
}]
}]
```

152 changes: 152 additions & 0 deletions test/spec/modules/timBidAdapter_spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import { expect } from 'chai';
import { spec } from 'modules/timBidAdapter';

describe('timAdapterTests', function () {
describe('bidRequestValidity', function () {
it('bidRequest with publisherid and placementCode params', function () {
expect(spec.isBidRequestValid({
bidder: 'tim',
params: {
publisherid: 'testid',
placementCode: 'testplacement'
}
})).to.equal(true);
});

it('bidRequest with only publisherid', function () {
expect(spec.isBidRequestValid({
bidder: 'tim',
params: {
publisherid: 'testid'
}
})).to.equal(false);
});

it('bidRequest with only placementCode', function () {
expect(spec.isBidRequestValid({
bidder: 'tim',
params: {
placementCode: 'testplacement'
}
})).to.equal(false);
});

it('bidRequest without params', function () {
expect(spec.isBidRequestValid({
bidder: 'tim',
})).to.equal(false);
});
});

describe('buildRequests', function () {
const validBidRequests = [{
'bidder': 'tim',
'params': {'placementCode': 'placementCode', 'publisherid': 'testpublisherid'},
'mediaTypes': {'banner': {'sizes': [[300, 250]]}},
'adUnitCode': 'adUnitCode',
'transactionId': 'transactionId',
'sizes': [[300, 250]],
'bidId': 'bidId',
'bidderRequestId': 'bidderRequestId',
'auctionId': 'auctionId',
'src': 'client',
'bidRequestsCount': 1
}];

it('bidRequest method', function () {
const requests = spec.buildRequests(validBidRequests);
expect(requests[0].method).to.equal('GET');
});

it('bidRequest url', function () {
const requests = spec.buildRequests(validBidRequests);
expect(requests[0].url).to.exist;
});

it('bidRequest data', function () {
const requests = spec.buildRequests(validBidRequests);
expect(requests[0].data).to.exist;
});

it('bidRequest options', function () {
const requests = spec.buildRequests(validBidRequests);
expect(requests[0].options).to.exist;
});
});

describe('interpretResponse', function () {
const bidRequest = {
'method': 'GET',
'url': '//bidder.url/api/prebid/testpublisherid/header-bid-tag-0?br=%7B%22id%22%3A%223a3ac0d7fc2548%22%2C%22imp%22%3A%5B%7B%22id%22%3A%22251b8a6d3aac3e%22%2C%22banner%22%3A%7B%22w%22%3A300%2C%22h%22%3A250%7D%2C%22tagid%22%3A%22header-bid-tag-0%22%7D%5D%2C%22site%22%3A%7B%22domain%22%3A%22www.chinatimes.com%22%2C%22page%22%3A%22http%3A%2F%2Fwww.chinatimes.com%2Fa%22%2C%22publisher%22%3A%7B%22id%22%3A%22testpublisherid%22%7D%7D%2C%22device%22%3A%7B%22language%22%3A%22en%22%2C%22w%22%3A300%2C%22h%22%3A250%2C%22js%22%3A1%2C%22ua%22%3A%22Mozilla%2F5.0%20(Windows%20NT%2010.0%3B%20Win64%3B%20x64)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F71.0.3578.98%20Safari%2F537.36%22%7D%2C%22bidId%22%3A%22251b8a6d3aac3e%22%7D',
'data': '',
'options': {'withCredentials': false}
};

const serverResponse = {
'body': {
'id': 'id',
'seatbid': []
},
'headers': {}
};

it('check empty array response', function () {
const result = spec.interpretResponse(serverResponse, bidRequest);
expect(result).to.deep.equal([]);
});

const validBidRequest = {
'method': 'GET',
'url': '//bidder.url/api/v2/services/prebid/testpublisherid/placementCodeTest?br=%7B%22id%22%3A%2248640869bd9db94%22%2C%22imp%22%3A%5B%7B%22id%22%3A%224746fcaa11197f3%22%2C%22banner%22%3A%7B%22w%22%3A300%2C%22h%22%3A250%7D%2C%22tagid%22%3A%22placementCodeTest%22%7D%5D%2C%22site%22%3A%7B%22domain%22%3A%22mediamart.tv%22%2C%22page%22%3A%22http%3A%2F%2Fmediamart.tv%2Fsas%2Ftests%2FDesktop%2Fcaesar%2Fdfptest.html%22%2C%22publisher%22%3A%7B%22id%22%3A%22testpublisherid%22%7D%7D%2C%22device%22%3A%7B%22language%22%3A%22en%22%2C%22w%22%3A300%2C%22h%22%3A250%2C%22js%22%3A1%2C%22ua%22%3A%22Mozilla%2F5.0%20(Windows%20NT%2010.0%3B%20Win64%3B%20x64)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F71.0.3578.98%20Safari%2F537.36%22%7D%2C%22bidId%22%3A%224746fcaa11197f3%22%7D',
'data': '',
'options': {'withCredentials': false}
};
const validServerResponse = {
'body': {'id': 'id',
'seatbid': [
{'bid': [{'id': 'id',
'impid': 'impid',
'price': 3,
'nurl': 'https://bidder.url/api/v1/?price=${AUCTION_PRICE}&bidcur=USD&bidid=bidid=true',
'adm': '<script type=\"text/javascript\" src=\"https://domain.com/Player.php"></script>',
'adomain': [''],
'cid': '1',
'crid': '700',
'w': 300,
'h': 250
}]}],
'bidid': 'bidid',
'cur': 'USD'
},
'headers': {}
};
it('required keys', function () {
const result = spec.interpretResponse(validServerResponse, validBidRequest);

let requiredKeys = [
'requestId',
'creativeId',
'adId',
'cpm',
'width',
'height',
'currency',
'netRevenue',
'ttl',
'ad'
];

let resultKeys = Object.keys(result[0]);
requiredKeys.forEach(function(key) {
expect(resultKeys.indexOf(key) !== -1).to.equal(true);
});
})
});

describe('getUserSyncs', function () {
it('check empty response getUserSyncs', function () {
const result = spec.getUserSyncs('', '');
expect(result).to.deep.equal([]);
});
});
});

0 comments on commit 0be3422

Please sign in to comment.