Skip to content

Commit 0606e77

Browse files
solta-devos-solta
andauthored
Kimberlite Bidder Adapter: initial commit (#11032)
* Kimberlite bid adapter (#1) * initial: bid adapter * styling * Fix: lint (#2) * Fix: lint (#4) * review fixes (#6) * Change: filling request.ext.prebid section (#7) --------- Co-authored-by: Oleg <[email protected]>
1 parent be08dc8 commit 0606e77

File tree

3 files changed

+278
-0
lines changed

3 files changed

+278
-0
lines changed

modules/kimberliteBidAdapter.js

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { registerBidder } from '../src/adapters/bidderFactory.js';
2+
import { BANNER } from '../src/mediaTypes.js';
3+
import { ortbConverter } from '../libraries/ortbConverter/converter.js'
4+
import { deepSetValue } from '../src/utils.js';
5+
6+
const VERSION = '1.0.0';
7+
8+
const BIDDER_CODE = 'kimberlite';
9+
const METHOD = 'POST';
10+
const ENDPOINT_URL = 'https://kimberlite.io/rtb/bid/pbjs';
11+
12+
const VERSION_INFO = {
13+
ver: '$prebid.version$',
14+
adapterVer: `${VERSION}`
15+
};
16+
17+
const converter = ortbConverter({
18+
context: {
19+
mediaType: BANNER,
20+
netRevenue: true,
21+
ttl: 300
22+
},
23+
24+
request(buildRequest, imps, bidderRequest, context) {
25+
const bidRequest = buildRequest(imps, bidderRequest, context);
26+
deepSetValue(bidRequest, 'site.publisher.domain', bidderRequest.refererInfo.domain);
27+
deepSetValue(bidRequest, 'site.page', bidderRequest.refererInfo.page);
28+
deepSetValue(bidRequest, 'ext.prebid.ver', VERSION_INFO.ver);
29+
deepSetValue(bidRequest, 'ext.prebid.adapterVer', VERSION_INFO.adapterVer);
30+
bidRequest.at = 1;
31+
return bidRequest;
32+
},
33+
34+
imp (buildImp, bidRequest, context) {
35+
const imp = buildImp(bidRequest, context);
36+
imp.tagid = bidRequest.params.placementId;
37+
return imp;
38+
}
39+
});
40+
41+
export const spec = {
42+
code: BIDDER_CODE,
43+
supportedMediaTypes: [BANNER],
44+
45+
isBidRequestValid: (bidRequest = {}) => {
46+
const { params, mediaTypes } = bidRequest;
47+
let isValid = Boolean(params && params.placementId);
48+
if (mediaTypes && mediaTypes[BANNER]) {
49+
isValid = isValid && Boolean(mediaTypes[BANNER].sizes);
50+
} else {
51+
isValid = false;
52+
}
53+
54+
return isValid;
55+
},
56+
57+
buildRequests: function (bidRequests, bidderRequest) {
58+
return {
59+
method: METHOD,
60+
url: ENDPOINT_URL,
61+
data: converter.toORTB({ bidderRequest, bidRequests })
62+
}
63+
},
64+
65+
interpretResponse(serverResponse, bidRequest) {
66+
const bids = converter.fromORTB({response: serverResponse.body, request: bidRequest.data}).bids;
67+
return bids;
68+
}
69+
};
70+
71+
registerBidder(spec);

modules/kimberliteBidAdapter.md

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Overview
2+
3+
```markdown
4+
Module Name: Kimberlite Bid Adapter
5+
Module Type: Bidder Adapter
6+
Maintainer: [email protected]
7+
```
8+
9+
# Description
10+
11+
Kimberlite exchange adapter.
12+
13+
# Test Parameters
14+
15+
## Banner AdUnit
16+
17+
```javascript
18+
var adUnits = [
19+
{
20+
code: 'test-div',
21+
mediaTypes: {
22+
banner: {
23+
sizes: [[320, 250], [640, 480]],
24+
}
25+
},
26+
bids: [
27+
{
28+
bidder: "kimberlite",
29+
params: {
30+
placementId: 'testBanner'
31+
}
32+
}
33+
]
34+
}
35+
]
36+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
import { spec } from 'modules/kimberliteBidAdapter.js';
2+
import { assert } from 'chai';
3+
import { BANNER } from '../../../src/mediaTypes.js';
4+
5+
const BIDDER_CODE = 'kimberlite';
6+
7+
describe('kimberliteBidAdapter', function () {
8+
const sizes = [[640, 480]];
9+
10+
describe('isBidRequestValid', function () {
11+
let bidRequest;
12+
13+
beforeEach(function () {
14+
bidRequest = {
15+
mediaTypes: {
16+
[BANNER]: {
17+
sizes: [[320, 240]]
18+
}
19+
},
20+
params: {
21+
placementId: 'test-placement'
22+
}
23+
};
24+
});
25+
26+
it('pass on valid bidRequest', function () {
27+
assert.isTrue(spec.isBidRequestValid(bidRequest));
28+
});
29+
30+
it('fails on missed placementId', function () {
31+
delete bidRequest.params.placementId;
32+
assert.isFalse(spec.isBidRequestValid(bidRequest));
33+
});
34+
35+
it('fails on empty banner', function () {
36+
delete bidRequest.mediaTypes.banner;
37+
assert.isFalse(spec.isBidRequestValid(bidRequest));
38+
});
39+
40+
it('fails on empty banner.sizes', function () {
41+
delete bidRequest.mediaTypes.banner.sizes;
42+
assert.isFalse(spec.isBidRequestValid(bidRequest));
43+
});
44+
45+
it('fails on empty request', function () {
46+
assert.isFalse(spec.isBidRequestValid());
47+
});
48+
});
49+
50+
describe('buildRequests', function () {
51+
let bidRequests, bidderRequest;
52+
53+
beforeEach(function () {
54+
bidRequests = [{
55+
mediaTypes: {
56+
[BANNER]: {sizes: sizes}
57+
},
58+
params: {
59+
placementId: 'test-placement'
60+
}
61+
}];
62+
63+
bidderRequest = {
64+
refererInfo: {
65+
domain: 'example.com',
66+
page: 'https://www.example.com/test.html',
67+
},
68+
bids: [{
69+
mediaTypes: {
70+
[BANNER]: {sizes: sizes}
71+
}
72+
}]
73+
};
74+
});
75+
76+
it('valid bid request', function () {
77+
const bidRequest = spec.buildRequests(bidRequests, bidderRequest);
78+
assert.equal(bidRequest.method, 'POST');
79+
assert.ok(bidRequest.data);
80+
81+
const requestData = bidRequest.data;
82+
expect(requestData.site.page).to.equal(bidderRequest.refererInfo.page);
83+
expect(requestData.site.publisher.domain).to.equal(bidderRequest.refererInfo.domain);
84+
85+
expect(requestData.imp).to.be.an('array').and.is.not.empty;
86+
87+
expect(requestData.ext).to.be.an('Object').and.have.all.keys('prebid');
88+
expect(requestData.ext.prebid).to.be.an('Object').and.have.all.keys('ver', 'adapterVer');
89+
90+
const impData = requestData.imp[0];
91+
expect(impData.banner).is.to.be.an('Object').and.have.all.keys(['format', 'topframe']);
92+
93+
const bannerData = impData.banner;
94+
expect(bannerData.format).to.be.an('array').and.is.not.empty;
95+
96+
const formatData = bannerData.format[0];
97+
expect(formatData).to.be.an('Object').and.have.all.keys('w', 'h');
98+
99+
assert.equal(formatData.w, sizes[0][0]);
100+
assert.equal(formatData.h, sizes[0][1]);
101+
});
102+
});
103+
104+
describe('interpretResponse', function () {
105+
let bidderResponse, bidderRequest, bidRequest, expectedBid;
106+
107+
const requestId = '07fba8b0-8812-4dc6-b91e-4a525d81729c';
108+
const bidId = '222209853178';
109+
const impId = 'imp-id';
110+
const crId = 'creative-id';
111+
const adm = '<a href="http://test.landing.com">landing</a>';
112+
113+
beforeEach(function () {
114+
bidderResponse = {
115+
body: {
116+
id: requestId,
117+
seatbid: [{
118+
bid: [{
119+
crid: crId,
120+
id: bidId,
121+
impid: impId,
122+
price: 1,
123+
adm: adm
124+
}]
125+
}]
126+
}
127+
};
128+
129+
bidderRequest = {
130+
refererInfo: {
131+
domain: 'example.com',
132+
page: 'https://www.example.com/test.html',
133+
},
134+
bids: [{
135+
bidId: impId,
136+
mediaTypes: {
137+
[BANNER]: {sizes: sizes}
138+
},
139+
params: {
140+
placementId: 'test-placement'
141+
}
142+
}]
143+
};
144+
145+
expectedBid = {
146+
mediaType: 'banner',
147+
requestId: 'imp-id',
148+
seatBidId: '222209853178',
149+
cpm: 1,
150+
creative_id: 'creative-id',
151+
creativeId: 'creative-id',
152+
ttl: 300,
153+
netRevenue: true,
154+
ad: adm,
155+
meta: {}
156+
};
157+
158+
bidRequest = spec.buildRequests(bidderRequest.bids, bidderRequest);
159+
});
160+
161+
it('pass on valid request', function () {
162+
const bids = spec.interpretResponse(bidderResponse, bidRequest);
163+
assert.deepEqual(bids[0], expectedBid);
164+
});
165+
166+
it('fails on empty response', function () {
167+
const bids = spec.interpretResponse({body: ''}, bidRequest);
168+
assert.empty(bids);
169+
});
170+
});
171+
});

0 commit comments

Comments
 (0)