Skip to content
This repository was archived by the owner on Mar 12, 2025. It is now read-only.

Commit ca0c0f1

Browse files
authored
Outbrain bid adapter: added floor module and privacy link support (prebid#8223)
* add floor support * add additional validation for bid request format * add privacy link support * fixes * set privacy in mapper * fix test
1 parent 3015515 commit ca0c0f1

File tree

2 files changed

+137
-6
lines changed

2 files changed

+137
-6
lines changed

modules/outbrainBidAdapter.js

+45-4
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,28 @@ export const spec = {
2727
gvlid: GVLID,
2828
supportedMediaTypes: [ NATIVE, BANNER ],
2929
isBidRequestValid: (bid) => {
30+
if (typeof bid.params !== 'object') {
31+
return false;
32+
}
33+
34+
if (typeof deepAccess(bid, 'params.publisher.id') !== 'string') {
35+
return false;
36+
}
37+
38+
if (!!bid.params.tagid && typeof bid.params.tagid !== 'string') {
39+
return false;
40+
}
41+
42+
if (!!bid.params.bcat && (typeof bid.params.bcat !== 'object' || !bid.params.bcat.every(item => typeof item === 'string'))) {
43+
return false;
44+
}
45+
46+
if (!!bid.params.badv && (typeof bid.params.badv !== 'object' || !bid.params.badv.every(item => typeof item === 'string'))) {
47+
return false;
48+
}
49+
3050
return (
3151
!!config.getConfig('outbrain.bidderUrl') &&
32-
!!deepAccess(bid, 'params.publisher.id') &&
3352
!!(bid.nativeParams || bid.sizes)
3453
);
3554
},
@@ -67,6 +86,13 @@ export const spec = {
6786
}
6887
}
6988

89+
if (typeof bid.getFloor === 'function') {
90+
const floor = _getFloor(bid, bid.nativeParams ? NATIVE : BANNER);
91+
if (floor) {
92+
imp.bidfloor = floor;
93+
}
94+
}
95+
7096
return imp;
7197
});
7298

@@ -190,7 +216,7 @@ export const spec = {
190216
registerBidder(spec);
191217

192218
function parseNative(bid) {
193-
const { assets, link, eventtrackers } = JSON.parse(bid.adm);
219+
const { assets, link, privacy, eventtrackers } = JSON.parse(bid.adm);
194220
const result = {
195221
clickUrl: link.url,
196222
clickTrackers: link.clicktrackers || undefined
@@ -202,6 +228,9 @@ function parseNative(bid) {
202228
result[kind] = content.text || content.value || { url: content.url, width: content.w, height: content.h };
203229
}
204230
});
231+
if (privacy) {
232+
result.privacyLink = privacy;
233+
}
205234
if (eventtrackers) {
206235
result.impressionTrackers = [];
207236
eventtrackers.forEach(tracker => {
@@ -251,8 +280,8 @@ function getNativeAssets(bid) {
251280

252281
if (bidParams.sizes) {
253282
const sizes = flatten(bidParams.sizes);
254-
w = sizes[0];
255-
h = sizes[1];
283+
w = parseInt(sizes[0], 10);
284+
h = parseInt(sizes[1], 10);
256285
}
257286

258287
asset[props.name] = {
@@ -291,3 +320,15 @@ function transformSizes(requestSizes) {
291320

292321
return [];
293322
}
323+
324+
function _getFloor(bid, type) {
325+
const floorInfo = bid.getFloor({
326+
currency: CURRENCY,
327+
mediaType: type,
328+
size: '*'
329+
});
330+
if (typeof floorInfo === 'object' && floorInfo.currency === CURRENCY && !isNaN(parseFloat(floorInfo.floor))) {
331+
return parseFloat(floorInfo.floor);
332+
}
333+
return null;
334+
}

test/spec/modules/outbrainBidAdapter_spec.js

+92-2
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,38 @@ describe('Outbrain Adapter', function () {
100100
}
101101
expect(spec.isBidRequestValid(bid)).to.equal(false)
102102
})
103+
it('should fail if tag id is not string', function () {
104+
const bid = {
105+
bidder: 'outbrain',
106+
params: {
107+
tagid: 123
108+
},
109+
...nativeBidRequestParams,
110+
}
111+
expect(spec.isBidRequestValid(bid)).to.equal(false)
112+
})
113+
it('should fail if badv does not include strings', function () {
114+
const bid = {
115+
bidder: 'outbrain',
116+
params: {
117+
tagid: 123,
118+
badv: ['a', 2, 'c']
119+
},
120+
...nativeBidRequestParams,
121+
}
122+
expect(spec.isBidRequestValid(bid)).to.equal(false)
123+
})
124+
it('should fail if bcat does not include strings', function () {
125+
const bid = {
126+
bidder: 'outbrain',
127+
params: {
128+
tagid: 123,
129+
bcat: ['a', 2, 'c']
130+
},
131+
...nativeBidRequestParams,
132+
}
133+
expect(spec.isBidRequestValid(bid)).to.equal(false)
134+
})
103135
it('should succeed with outbrain config', function () {
104136
const bid = {
105137
bidder: 'outbrain',
@@ -362,6 +394,63 @@ describe('Outbrain Adapter', function () {
362394
{source: 'liveramp.com', uids: [{id: 'id-value', atype: 3}]}
363395
]);
364396
});
397+
398+
it('should pass bidfloor', function () {
399+
const bidRequest = {
400+
...commonBidRequest,
401+
...nativeBidRequestParams,
402+
}
403+
bidRequest.getFloor = function() {
404+
return {
405+
currency: 'USD',
406+
floor: 1.23,
407+
}
408+
}
409+
410+
const res = spec.buildRequests([bidRequest], commonBidderRequest)
411+
const resData = JSON.parse(res.data)
412+
expect(resData.imp[0].bidfloor).to.equal(1.23)
413+
});
414+
415+
it('should transform string sizes to numbers', function () {
416+
let bidRequest = {
417+
bidId: 'bidId',
418+
params: {},
419+
...commonBidRequest,
420+
...nativeBidRequestParams,
421+
};
422+
bidRequest.nativeParams.image.sizes = ['120', '100']
423+
424+
const expectedNativeAssets = {
425+
assets: [
426+
{
427+
required: 1,
428+
id: 3,
429+
img: {
430+
type: 3,
431+
w: 120,
432+
h: 100
433+
}
434+
},
435+
{
436+
required: 1,
437+
id: 0,
438+
title: {}
439+
},
440+
{
441+
required: 0,
442+
id: 5,
443+
data: {
444+
type: 1
445+
}
446+
}
447+
]
448+
}
449+
450+
let res = spec.buildRequests([bidRequest], commonBidderRequest);
451+
const resData = JSON.parse(res.data)
452+
expect(resData.imp[0].native.request).to.equal(JSON.stringify(expectedNativeAssets));
453+
});
365454
})
366455

367456
describe('interpretResponse', function () {
@@ -382,7 +471,7 @@ describe('Outbrain Adapter', function () {
382471
impid: '1',
383472
price: 1.1,
384473
nurl: 'http://example.com/win/${AUCTION_PRICE}',
385-
adm: '{"ver":"1.2","assets":[{"id":3,"required":1,"img":{"url":"http://example.com/img/url","w":120,"h":100}},{"id":0,"required":1,"title":{"text":"Test title"}},{"id":5,"data":{"value":"Test sponsor"}}],"link":{"url":"http://example.com/click/url"},"eventtrackers":[{"event":1,"method":1,"url":"http://example.com/impression"}]}',
474+
adm: '{"ver":"1.2","assets":[{"id":3,"required":1,"img":{"url":"http://example.com/img/url","w":120,"h":100}},{"id":0,"required":1,"title":{"text":"Test title"}},{"id":5,"data":{"value":"Test sponsor"}}],"privacy":"http://example.com/privacy","link":{"url":"http://example.com/click/url"},"eventtrackers":[{"event":1,"method":1,"url":"http://example.com/impression"}]}',
386475
adomain: [
387476
'example.com'
388477
],
@@ -435,7 +524,8 @@ describe('Outbrain Adapter', function () {
435524
sponsoredBy: 'Test sponsor',
436525
impressionTrackers: [
437526
'http://example.com/impression',
438-
]
527+
],
528+
privacyLink: 'http://example.com/privacy'
439529
}
440530
}
441531
]

0 commit comments

Comments
 (0)