Skip to content

Commit 29e6f30

Browse files
ReklamStoreITjacekburys-quantcast
authored andcommitted
ReklamStore Bid Adapter (prebid#3634)
* ReklamStore Bid Adapter ReklamStore Bid Adapter * Added unit test for user sync Added unit test for user sync * Update bid adapter Update bid adapter
1 parent 2e274ac commit 29e6f30

File tree

3 files changed

+266
-0
lines changed

3 files changed

+266
-0
lines changed

modules/reklamstoreBidAdapter.js

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
import * as utils from 'src/utils';
2+
import { registerBidder } from 'src/adapters/bidderFactory';
3+
import { BANNER } from 'src/mediaTypes';
4+
5+
const BIDDER_CODE = 'reklamstore';
6+
const ENDPOINT_URL = '//ads.rekmob.com/m/prebid';
7+
const CURRENCY = 'USD';
8+
const TIME_TO_LIVE = 360;
9+
10+
export const spec = {
11+
code: BIDDER_CODE,
12+
supportedMediaTypes: [BANNER],
13+
/**
14+
* Determines whether or not the given bid request is valid.
15+
*
16+
* @param {BidRequest} bid The bid params to validate.
17+
* @return boolean True if this is a valid bid, and false otherwise.
18+
*/
19+
isBidRequestValid: function (bid) {
20+
return !!(bid.params.regionId);
21+
},
22+
/**
23+
* Make a server request from the list of BidRequests.
24+
*
25+
* @param {validBidRequests[]} - an array of bids
26+
* @return ServerRequest Info describing the request to the server.
27+
*/
28+
buildRequests: function (validBidRequests, bidderRequest) {
29+
const url = bidderRequest.refererInfo.referer;
30+
let requests = [];
31+
utils._each(validBidRequests, function(bid) {
32+
requests.push({
33+
method: 'GET',
34+
url: ENDPOINT_URL,
35+
data: {
36+
regionId: bid.params.regionId,
37+
dt: getDeviceType(),
38+
os: getOS(),
39+
dbg: 1,
40+
ref: extractDomain(url),
41+
_: (new Date().getTime()),
42+
mobile_web: 1
43+
},
44+
bidId: bid.bidId
45+
});
46+
});
47+
return requests;
48+
},
49+
50+
/**
51+
* Unpack the response from the server into a list of bids.
52+
*
53+
* @param {ServerResponse} serverResponse A successful response from the server.
54+
* @return {Bid[]} An array of bids which were nested inside the server.
55+
*/
56+
interpretResponse: function (serverResponse, bidRequest) {
57+
try {
58+
const bidResponse = serverResponse.body;
59+
const bidResponses = [];
60+
if (bidResponse) {
61+
bidResponses.push({
62+
requestId: bidRequest.bidId,
63+
cpm: parseFloat(bidResponse.cpm),
64+
width: bidResponse.w,
65+
height: bidResponse.h,
66+
creativeId: bidResponse.adId || 1,
67+
currency: CURRENCY,
68+
netRevenue: false,
69+
ttl: TIME_TO_LIVE,
70+
ad: bidResponse.ad
71+
});
72+
}
73+
return bidResponses;
74+
} catch (err) {
75+
utils.logError(err);
76+
return [];
77+
}
78+
},
79+
/**
80+
* Register the user sync pixels which should be dropped after the auction.
81+
*
82+
* @param {SyncOptions} syncOptions Which user syncs are allowed?
83+
* @param {ServerResponse[]} serverResponses List of server's responses.
84+
* @return {UserSync[]} The user syncs which should be dropped.
85+
*/
86+
getUserSyncs: function(syncOptions, serverResponses) {
87+
const syncs = [];
88+
utils._each(serverResponses, function(bidResponse) {
89+
utils._each(bidResponse.body.syncs, function(sync) {
90+
if (syncOptions.pixelEnabled && sync.type == 'image') {
91+
syncs.push({
92+
type: sync.type,
93+
url: sync.url
94+
});
95+
} else if (syncOptions.iframeEnabled && sync.type == 'iframe') {
96+
syncs.push({
97+
type: sync.type,
98+
url: sync.url
99+
});
100+
}
101+
});
102+
});
103+
return syncs;
104+
}
105+
}
106+
registerBidder(spec);
107+
108+
function getDeviceType() {
109+
let PHONE = 0;
110+
let TABLET = 2;
111+
let DESKTOP = 3;
112+
if (isPhone()) {
113+
return PHONE;
114+
} else if (isTablet()) {
115+
return TABLET;
116+
} else {
117+
return DESKTOP;
118+
}
119+
}
120+
function isPhone() {
121+
var check = false;
122+
(function (a) { if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true })(navigator.userAgent || navigator.vendor || window.opera);
123+
return check;
124+
}
125+
function isTablet() {
126+
var check = false;
127+
(function(a) { if (/ipad|android|android 3.0|xoom|sch-i800|playbook|tablet|kindle/i.test(a)) { check = true; } })(navigator.userAgent || navigator.vendor || window.opera);
128+
return check;
129+
}
130+
function getOS() {
131+
var ua = navigator.userAgent;
132+
if (ua.match(/(iPhone|iPod|iPad)/)) {
133+
return '1';
134+
} else if (ua.match(/Android/)) {
135+
return '0';
136+
} else {
137+
return '3';
138+
}
139+
}
140+
function extractDomain(url) {
141+
var domain;
142+
if (url.indexOf('://') > -1) {
143+
domain = url.split('/')[2];
144+
} else {
145+
domain = url.split('/')[0];
146+
}
147+
domain = domain.split(':')[0];
148+
return domain;
149+
}

modules/reklamstoreBidAdapter.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Overview
2+
3+
Module Name: ReklamStore Bidder Adapter
4+
Module Type: Bidder Adapter
5+
Maintainer: [email protected]
6+
7+
# Description
8+
9+
Module that connects to ReklamStore's demand sources.
10+
11+
ReklamStore supports display.
12+
13+
14+
# Test Parameters
15+
# display
16+
```
17+
18+
var adUnits = [
19+
{
20+
code: 'banner-ad-div',
21+
sizes: [[300, 250]],
22+
bids: [
23+
{
24+
bidder: 'reklamstore',
25+
params: {
26+
regionId:532211
27+
}
28+
}
29+
]
30+
}
31+
];
32+
```
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import { expect } from 'chai';
2+
import { spec } from 'modules/reklamstoreBidAdapter';
3+
4+
describe('reklamstoreBidAdapterTests', function() {
5+
let bidRequestData = {
6+
bids: [
7+
{
8+
bidder: 'reklamstore',
9+
params: {
10+
regionId: 532211
11+
},
12+
sizes: [[300, 250]]
13+
}
14+
]
15+
};
16+
let request = [];
17+
18+
it('validate_params', function() {
19+
expect(
20+
spec.isBidRequestValid({
21+
bidder: 'reklamstore',
22+
params: {
23+
regionId: 532211
24+
}
25+
})
26+
).to.equal(true);
27+
});
28+
29+
it('validate_generated_params', function() {
30+
let bidderRequest = {
31+
refererInfo: {
32+
referer: 'http://reklamstore.com'
33+
}
34+
};
35+
request = spec.buildRequests(bidRequestData.bids, bidderRequest);
36+
let req_data = request[0].data;
37+
38+
expect(req_data.regionId).to.equal(532211);
39+
});
40+
41+
const serverResponse = {
42+
body:
43+
{
44+
cpm: 1.2,
45+
ad: 'Ad html',
46+
w: 300,
47+
h: 250,
48+
syncs: [{
49+
type: 'image',
50+
url: 'http://link1'
51+
},
52+
{
53+
type: 'iframe',
54+
url: 'http://link2'
55+
}
56+
]
57+
}
58+
};
59+
60+
it('validate_response_params', function() {
61+
let bids = spec.interpretResponse(serverResponse, bidRequestData.bids[0]);
62+
expect(bids).to.have.lengthOf(1);
63+
64+
let bid = bids[0];
65+
expect(bid.ad).to.equal('Ad html');
66+
expect(bid.cpm).to.equal(1.2);
67+
expect(bid.width).to.equal(300);
68+
expect(bid.height).to.equal(250);
69+
expect(bid.currency).to.equal('USD');
70+
});
71+
72+
it('should return no syncs when pixel syncing is disabled', function () {
73+
const syncs = spec.getUserSyncs({ pixelEnabled: false }, [serverResponse]);
74+
expect(syncs).to.deep.equal([]);
75+
});
76+
77+
it('should return user syncs', function () {
78+
const syncs = spec.getUserSyncs({pixelEnabled: true, iframeEnabled: true}, [serverResponse]);
79+
const expected = [
80+
{ type: 'image', url: 'http://link1' },
81+
{ type: 'iframe', url: 'http://link2' },
82+
];
83+
expect(syncs).to.deep.equal(expected);
84+
});
85+
});

0 commit comments

Comments
 (0)