prebid.js 6.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/.babelrc.js +1 -7
  2. package/gulpfile.js +1 -0
  3. package/modules/adheseBidAdapter.js +7 -2
  4. package/modules/adkernelBidAdapter.js +1 -0
  5. package/modules/adlivetechBidAdapter.md +61 -0
  6. package/modules/adomikAnalyticsAdapter.js +10 -4
  7. package/modules/appnexusBidAdapter.js +4 -0
  8. package/modules/codefuelBidAdapter.js +1 -3
  9. package/modules/codefuelBidAdapter.md +3 -3
  10. package/modules/datablocksBidAdapter.js +3 -3
  11. package/modules/deepintentBidAdapter.js +1 -1
  12. package/modules/engageyaBidAdapter.js +68 -54
  13. package/modules/glimpseBidAdapter.js +31 -16
  14. package/modules/gptPreAuction.js +11 -5
  15. package/modules/gridBidAdapter.js +1 -1
  16. package/modules/id5IdSystem.md +6 -6
  17. package/modules/imRtdProvider.js +31 -0
  18. package/modules/ixBidAdapter.js +166 -21
  19. package/modules/merkleIdSystem.js +5 -0
  20. package/modules/nativoBidAdapter.js +27 -1
  21. package/modules/oguryBidAdapter.js +2 -1
  22. package/modules/openxBidAdapter.js +6 -1
  23. package/modules/prebidServerBidAdapter/index.js +3 -3
  24. package/modules/pubmaticBidAdapter.js +2 -0
  25. package/modules/saambaaBidAdapter.js +420 -0
  26. package/modules/saambaaBidAdapter.md +65 -68
  27. package/modules/seedtagBidAdapter.js +6 -0
  28. package/modules/smaatoBidAdapter.js +6 -1
  29. package/modules/sspBCBidAdapter.js +34 -3
  30. package/modules/trustxBidAdapter.js +10 -1
  31. package/modules/vidoomyBidAdapter.js +51 -100
  32. package/modules/visxBidAdapter.js +1 -1
  33. package/modules/yieldlabBidAdapter.js +41 -10
  34. package/modules/yieldlabBidAdapter.md +91 -48
  35. package/package.json +6 -1
  36. package/src/adapterManager.js +14 -8
  37. package/test/spec/modules/adheseBidAdapter_spec.js +27 -1
  38. package/test/spec/modules/adomikAnalyticsAdapter_spec.js +3 -1
  39. package/test/spec/modules/appnexusBidAdapter_spec.js +14 -0
  40. package/test/spec/modules/codefuelBidAdapter_spec.js +1 -1
  41. package/test/spec/modules/datablocksBidAdapter_spec.js +3 -3
  42. package/test/spec/modules/engageyaBidAdapter_spec.js +231 -95
  43. package/test/spec/modules/eplanningBidAdapter_spec.js +8 -8
  44. package/test/spec/modules/glimpseBidAdapter_spec.js +33 -0
  45. package/test/spec/modules/gptPreAuction_spec.js +58 -4
  46. package/test/spec/modules/imRtdProvider_spec.js +25 -0
  47. package/test/spec/modules/ixBidAdapter_spec.js +285 -2
  48. package/test/spec/modules/konduitWrapper_spec.js +0 -1
  49. package/test/spec/modules/merkleIdSystem_spec.js +18 -0
  50. package/test/spec/modules/nativoBidAdapter_spec.js +35 -18
  51. package/test/spec/modules/oguryBidAdapter_spec.js +13 -11
  52. package/test/spec/modules/openxBidAdapter_spec.js +5 -0
  53. package/test/spec/modules/prebidServerBidAdapter_spec.js +19 -2
  54. package/test/spec/modules/seedtagBidAdapter_spec.js +3 -0
  55. package/test/spec/modules/smaatoBidAdapter_spec.js +30 -0
  56. package/test/spec/modules/sspBCBidAdapter_spec.js +33 -3
  57. package/test/spec/modules/trustxBidAdapter_spec.js +42 -0
  58. package/test/spec/modules/vidoomyBidAdapter_spec.js +32 -13
  59. package/test/spec/modules/visxBidAdapter_spec.js +1 -1
  60. package/test/spec/modules/yieldlabBidAdapter_spec.js +81 -0
  61. package/test/spec/unit/core/adapterManager_spec.js +24 -6
@@ -0,0 +1,420 @@
1
+ import { deepAccess, isFn, generateUUID, parseUrl, isEmpty, parseSizesInput } from '../src/utils.js';
2
+ import { config } from '../src/config.js';
3
+ import { registerBidder } from '../src/adapters/bidderFactory.js';
4
+ import { VIDEO, BANNER } from '../src/mediaTypes.js';
5
+ import find from 'core-js-pure/features/array/find.js';
6
+ import includes from 'core-js-pure/features/array/includes.js';
7
+
8
+ const ADAPTER_VERSION = '1.0';
9
+ const BIDDER_CODE = 'saambaa';
10
+
11
+ export const VIDEO_ENDPOINT = 'https://nep.advangelists.com/xp/get?pubid=';
12
+ export const BANNER_ENDPOINT = 'https://nep.advangelists.com/xp/get?pubid=';
13
+ export const OUTSTREAM_SRC = 'https://player-cdn.beachfrontmedia.com/playerapi/loader/outstream.js';
14
+ export const VIDEO_TARGETING = ['mimes', 'playbackmethod', 'maxduration', 'skip', 'playerSize', 'context'];
15
+ export const DEFAULT_MIMES = ['video/mp4', 'application/javascript'];
16
+
17
+ let pubid = '';
18
+
19
+ export const spec = {
20
+ code: BIDDER_CODE,
21
+ supportedMediaTypes: [BANNER, VIDEO],
22
+
23
+ isBidRequestValid(bidRequest) {
24
+ if (typeof bidRequest != 'undefined') {
25
+ if (bidRequest.bidder !== BIDDER_CODE && typeof bidRequest.params === 'undefined') { return false; }
26
+ if (bidRequest === '' || bidRequest.params.placement === '' || bidRequest.params.pubid === '') { return false; }
27
+ return true;
28
+ } else { return false; }
29
+ },
30
+
31
+ buildRequests(bids, bidderRequest) {
32
+ let requests = [];
33
+ let videoBids = bids.filter(bid => isVideoBidValid(bid));
34
+ let bannerBids = bids.filter(bid => isBannerBidValid(bid));
35
+ videoBids.forEach(bid => {
36
+ pubid = getVideoBidParam(bid, 'pubid');
37
+ requests.push({
38
+ method: 'POST',
39
+ url: VIDEO_ENDPOINT + pubid,
40
+ data: createVideoRequestData(bid, bidderRequest),
41
+ bidRequest: bid
42
+ });
43
+ });
44
+
45
+ bannerBids.forEach(bid => {
46
+ pubid = getBannerBidParam(bid, 'pubid');
47
+
48
+ requests.push({
49
+ method: 'POST',
50
+ url: BANNER_ENDPOINT + pubid,
51
+ data: createBannerRequestData(bid, bidderRequest),
52
+ bidRequest: bid
53
+ });
54
+ });
55
+ return requests;
56
+ },
57
+
58
+ interpretResponse(serverResponse, {bidRequest}) {
59
+ let response = serverResponse.body;
60
+ if (response !== null && isEmpty(response) == false) {
61
+ if (isVideoBid(bidRequest)) {
62
+ let bidResponse = {
63
+ requestId: response.id,
64
+ bidderCode: BIDDER_CODE,
65
+ cpm: response.seatbid[0].bid[0].price,
66
+ width: response.seatbid[0].bid[0].w,
67
+ height: response.seatbid[0].bid[0].h,
68
+ ttl: response.seatbid[0].bid[0].ttl || 60,
69
+ creativeId: response.seatbid[0].bid[0].crid,
70
+ currency: response.cur,
71
+ meta: { 'advertiserDomains': response.seatbid[0].bid[0].adomain },
72
+ mediaType: VIDEO,
73
+ netRevenue: true
74
+ }
75
+
76
+ if (response.seatbid[0].bid[0].adm) {
77
+ bidResponse.vastXml = response.seatbid[0].bid[0].adm;
78
+ bidResponse.adResponse = {
79
+ content: response.seatbid[0].bid[0].adm
80
+ };
81
+ } else {
82
+ bidResponse.vastUrl = response.seatbid[0].bid[0].nurl;
83
+ }
84
+
85
+ return bidResponse;
86
+ } else {
87
+ return {
88
+ requestId: response.id,
89
+ bidderCode: BIDDER_CODE,
90
+ cpm: response.seatbid[0].bid[0].price,
91
+ width: response.seatbid[0].bid[0].w,
92
+ height: response.seatbid[0].bid[0].h,
93
+ ad: response.seatbid[0].bid[0].adm,
94
+ ttl: response.seatbid[0].bid[0].ttl || 60,
95
+ creativeId: response.seatbid[0].bid[0].crid,
96
+ currency: response.cur,
97
+ meta: { 'advertiserDomains': response.seatbid[0].bid[0].adomain },
98
+ mediaType: BANNER,
99
+ netRevenue: true
100
+ }
101
+ }
102
+ }
103
+ }
104
+ };
105
+
106
+ function isBannerBid(bid) {
107
+ return deepAccess(bid, 'mediaTypes.banner') || !isVideoBid(bid);
108
+ }
109
+
110
+ function isVideoBid(bid) {
111
+ return deepAccess(bid, 'mediaTypes.video');
112
+ }
113
+
114
+ function getBannerBidFloor(bid) {
115
+ let floorInfo = isFn(bid.getFloor) ? bid.getFloor({ currency: 'USD', mediaType: 'banner', size: '*' }) : {};
116
+ return floorInfo.floor || getBannerBidParam(bid, 'bidfloor');
117
+ }
118
+
119
+ function getVideoBidFloor(bid) {
120
+ let floorInfo = isFn(bid.getFloor) ? bid.getFloor({ currency: 'USD', mediaType: 'video', size: '*' }) : {};
121
+ return floorInfo.floor || getVideoBidParam(bid, 'bidfloor');
122
+ }
123
+
124
+ function isVideoBidValid(bid) {
125
+ return isVideoBid(bid) && getVideoBidParam(bid, 'pubid') && getVideoBidParam(bid, 'placement');
126
+ }
127
+
128
+ function isBannerBidValid(bid) {
129
+ return isBannerBid(bid) && getBannerBidParam(bid, 'pubid') && getBannerBidParam(bid, 'placement');
130
+ }
131
+
132
+ function getVideoBidParam(bid, key) {
133
+ return deepAccess(bid, 'params.video.' + key) || deepAccess(bid, 'params.' + key);
134
+ }
135
+
136
+ function getBannerBidParam(bid, key) {
137
+ return deepAccess(bid, 'params.banner.' + key) || deepAccess(bid, 'params.' + key);
138
+ }
139
+
140
+ function isMobile() {
141
+ return (/(ios|ipod|ipad|iphone|android)/i).test(navigator.userAgent);
142
+ }
143
+
144
+ function isConnectedTV() {
145
+ return (/(smart[-]?tv|hbbtv|appletv|googletv|hdmi|netcast\.tv|viera|nettv|roku|\bdtv\b|sonydtv|inettvbrowser|\btv\b)/i).test(navigator.userAgent);
146
+ }
147
+
148
+ function getDoNotTrack() {
149
+ return navigator.doNotTrack === '1' || window.doNotTrack === '1' || navigator.msDoNoTrack === '1' || navigator.doNotTrack === 'yes';
150
+ }
151
+
152
+ function findAndFillParam(o, key, value) {
153
+ try {
154
+ if (typeof value === 'function') {
155
+ o[key] = value();
156
+ } else {
157
+ o[key] = value;
158
+ }
159
+ } catch (ex) {}
160
+ }
161
+
162
+ function getOsVersion() {
163
+ let clientStrings = [
164
+ { s: 'Android', r: /Android/ },
165
+ { s: 'iOS', r: /(iPhone|iPad|iPod)/ },
166
+ { s: 'Mac OS X', r: /Mac OS X/ },
167
+ { s: 'Mac OS', r: /(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/ },
168
+ { s: 'Linux', r: /(Linux|X11)/ },
169
+ { s: 'Windows 10', r: /(Windows 10.0|Windows NT 10.0)/ },
170
+ { s: 'Windows 8.1', r: /(Windows 8.1|Windows NT 6.3)/ },
171
+ { s: 'Windows 8', r: /(Windows 8|Windows NT 6.2)/ },
172
+ { s: 'Windows 7', r: /(Windows 7|Windows NT 6.1)/ },
173
+ { s: 'Windows Vista', r: /Windows NT 6.0/ },
174
+ { s: 'Windows Server 2003', r: /Windows NT 5.2/ },
175
+ { s: 'Windows XP', r: /(Windows NT 5.1|Windows XP)/ },
176
+ { s: 'UNIX', r: /UNIX/ },
177
+ { s: 'Search Bot', r: /(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/ }
178
+ ];
179
+ let cs = find(clientStrings, cs => cs.r.test(navigator.userAgent));
180
+ return cs ? cs.s : 'unknown';
181
+ }
182
+
183
+ function getFirstSize(sizes) {
184
+ return (sizes && sizes.length) ? sizes[0] : { w: undefined, h: undefined };
185
+ }
186
+
187
+ function parseSizes(sizes) {
188
+ return parseSizesInput(sizes).map(size => {
189
+ let [ width, height ] = size.split('x');
190
+ return {
191
+ w: parseInt(width, 10) || undefined,
192
+ h: parseInt(height, 10) || undefined
193
+ };
194
+ });
195
+ }
196
+
197
+ function getVideoSizes(bid) {
198
+ return parseSizes(deepAccess(bid, 'mediaTypes.video.playerSize') || bid.sizes);
199
+ }
200
+
201
+ function getBannerSizes(bid) {
202
+ return parseSizes(deepAccess(bid, 'mediaTypes.banner.sizes') || bid.sizes);
203
+ }
204
+
205
+ function getTopWindowReferrer() {
206
+ try {
207
+ return window.top.document.referrer;
208
+ } catch (e) {
209
+ return '';
210
+ }
211
+ }
212
+
213
+ function getVideoTargetingParams(bid) {
214
+ const result = {};
215
+ const excludeProps = ['playerSize', 'context', 'w', 'h'];
216
+ Object.keys(Object(bid.mediaTypes.video))
217
+ .filter(key => !includes(excludeProps, key))
218
+ .forEach(key => {
219
+ result[ key ] = bid.mediaTypes.video[ key ];
220
+ });
221
+ Object.keys(Object(bid.params.video))
222
+ .filter(key => includes(VIDEO_TARGETING, key))
223
+ .forEach(key => {
224
+ result[ key ] = bid.params.video[ key ];
225
+ });
226
+ return result;
227
+ }
228
+
229
+ function createVideoRequestData(bid, bidderRequest) {
230
+ let topLocation = getTopWindowLocation(bidderRequest);
231
+ let topReferrer = getTopWindowReferrer();
232
+
233
+ // if size is explicitly given via adapter params
234
+ let paramSize = getVideoBidParam(bid, 'size');
235
+ let sizes = [];
236
+ let coppa = config.getConfig('coppa');
237
+
238
+ if (typeof paramSize !== 'undefined' && paramSize != '') {
239
+ sizes = parseSizes(paramSize);
240
+ } else {
241
+ sizes = getVideoSizes(bid);
242
+ }
243
+ const firstSize = getFirstSize(sizes);
244
+ let floor = (getVideoBidFloor(bid) == null || typeof getVideoBidFloor(bid) == 'undefined') ? 0.5 : getVideoBidFloor(bid);
245
+ let video = getVideoTargetingParams(bid);
246
+ const o = {
247
+ 'device': {
248
+ 'langauge': (global.navigator.language).split('-')[0],
249
+ 'dnt': (global.navigator.doNotTrack === 1 ? 1 : 0),
250
+ 'devicetype': isMobile() ? 4 : isConnectedTV() ? 3 : 2,
251
+ 'js': 1,
252
+ 'os': getOsVersion()
253
+ },
254
+ 'at': 2,
255
+ 'site': {},
256
+ 'tmax': 3000,
257
+ 'cur': ['USD'],
258
+ 'id': bid.bidId,
259
+ 'imp': [],
260
+ 'regs': {
261
+ 'ext': {
262
+ }
263
+ },
264
+ 'user': {
265
+ 'ext': {
266
+ }
267
+ }
268
+ };
269
+
270
+ o.site['page'] = topLocation.href;
271
+ o.site['domain'] = topLocation.hostname;
272
+ o.site['search'] = topLocation.search;
273
+ o.site['domain'] = topLocation.hostname;
274
+ o.site['ref'] = topReferrer;
275
+ o.site['mobile'] = isMobile() ? 1 : 0;
276
+ const secure = topLocation.protocol.indexOf('https') === 0 ? 1 : 0;
277
+
278
+ o.device['dnt'] = getDoNotTrack() ? 1 : 0;
279
+
280
+ findAndFillParam(o.site, 'name', function() {
281
+ return global.top.document.title;
282
+ });
283
+
284
+ findAndFillParam(o.device, 'h', function() {
285
+ return global.screen.height;
286
+ });
287
+ findAndFillParam(o.device, 'w', function() {
288
+ return global.screen.width;
289
+ });
290
+
291
+ let placement = getVideoBidParam(bid, 'placement');
292
+
293
+ for (let j = 0; j < sizes.length; j++) {
294
+ o.imp.push({
295
+ 'id': '' + j,
296
+ 'displaymanager': '' + BIDDER_CODE,
297
+ 'displaymanagerver': '' + ADAPTER_VERSION,
298
+ 'tagId': placement,
299
+ 'bidfloor': floor,
300
+ 'bidfloorcur': 'USD',
301
+ 'secure': secure,
302
+ 'video': Object.assign({
303
+ 'id': generateUUID(),
304
+ 'pos': 0,
305
+ 'w': firstSize.w,
306
+ 'h': firstSize.h,
307
+ 'mimes': DEFAULT_MIMES
308
+ }, video)
309
+
310
+ });
311
+ }
312
+ if (coppa) {
313
+ o.regs.ext = {'coppa': 1};
314
+ }
315
+ if (bidderRequest && bidderRequest.gdprConsent) {
316
+ let { gdprApplies, consentString } = bidderRequest.gdprConsent;
317
+ o.regs.ext = {'gdpr': gdprApplies ? 1 : 0};
318
+ o.user.ext = {'consent': consentString};
319
+ }
320
+
321
+ return o;
322
+ }
323
+
324
+ function getTopWindowLocation(bidderRequest) {
325
+ let url = bidderRequest && bidderRequest.refererInfo && bidderRequest.refererInfo.referer;
326
+ return parseUrl(config.getConfig('pageUrl') || url, { decodeSearchAsString: true });
327
+ }
328
+
329
+ function createBannerRequestData(bid, bidderRequest) {
330
+ let topLocation = getTopWindowLocation(bidderRequest);
331
+ let topReferrer = getTopWindowReferrer();
332
+
333
+ // if size is explicitly given via adapter params
334
+
335
+ let paramSize = getBannerBidParam(bid, 'size');
336
+ let sizes = [];
337
+ let coppa = config.getConfig('coppa');
338
+ if (typeof paramSize !== 'undefined' && paramSize != '') {
339
+ sizes = parseSizes(paramSize);
340
+ } else {
341
+ sizes = getBannerSizes(bid);
342
+ }
343
+
344
+ let floor = (getBannerBidFloor(bid) == null || typeof getBannerBidFloor(bid) == 'undefined') ? 0.1 : getBannerBidFloor(bid);
345
+ const o = {
346
+ 'device': {
347
+ 'langauge': (global.navigator.language).split('-')[0],
348
+ 'dnt': (global.navigator.doNotTrack === 1 ? 1 : 0),
349
+ 'devicetype': isMobile() ? 4 : isConnectedTV() ? 3 : 2,
350
+ 'js': 1
351
+ },
352
+ 'at': 2,
353
+ 'site': {},
354
+ 'tmax': 3000,
355
+ 'cur': ['USD'],
356
+ 'id': bid.bidId,
357
+ 'imp': [],
358
+ 'regs': {
359
+ 'ext': {
360
+ }
361
+ },
362
+ 'user': {
363
+ 'ext': {
364
+ }
365
+ }
366
+ };
367
+
368
+ o.site['page'] = topLocation.href;
369
+ o.site['domain'] = topLocation.hostname;
370
+ o.site['search'] = topLocation.search;
371
+ o.site['domain'] = topLocation.hostname;
372
+ o.site['ref'] = topReferrer;
373
+ o.site['mobile'] = isMobile() ? 1 : 0;
374
+ const secure = topLocation.protocol.indexOf('https') === 0 ? 1 : 0;
375
+
376
+ o.device['dnt'] = getDoNotTrack() ? 1 : 0;
377
+
378
+ findAndFillParam(o.site, 'name', function() {
379
+ return global.top.document.title;
380
+ });
381
+
382
+ findAndFillParam(o.device, 'h', function() {
383
+ return global.screen.height;
384
+ });
385
+ findAndFillParam(o.device, 'w', function() {
386
+ return global.screen.width;
387
+ });
388
+
389
+ let placement = getBannerBidParam(bid, 'placement');
390
+ for (let j = 0; j < sizes.length; j++) {
391
+ let size = sizes[j];
392
+
393
+ o.imp.push({
394
+ 'id': '' + j,
395
+ 'displaymanager': '' + BIDDER_CODE,
396
+ 'displaymanagerver': '' + ADAPTER_VERSION,
397
+ 'tagId': placement,
398
+ 'bidfloor': floor,
399
+ 'bidfloorcur': 'USD',
400
+ 'secure': secure,
401
+ 'banner': {
402
+ 'id': generateUUID(),
403
+ 'pos': 0,
404
+ 'w': size['w'],
405
+ 'h': size['h']
406
+ }
407
+ });
408
+ }
409
+ if (coppa) {
410
+ o.regs.ext = {'coppa': 1};
411
+ }
412
+ if (bidderRequest && bidderRequest.gdprConsent) {
413
+ let { gdprApplies, consentString } = bidderRequest.gdprConsent;
414
+ o.regs.ext = {'gdpr': gdprApplies ? 1 : 0};
415
+ o.user.ext = {'consent': consentString};
416
+ }
417
+
418
+ return o;
419
+ }
420
+ registerBidder(spec);
@@ -1,69 +1,66 @@
1
- # Overview
2
-
3
- ```
4
- Module Name: Saambaa Bidder Adapter
5
- Module Type: Bidder Adapter
6
- Maintainer: matt.voigt@saambaa.com
7
- ```
8
-
9
- # Description
10
-
11
- Connects to Saambaa exchange for bids.
12
-
13
- Saambaa bid adapter supports Banner and Video ads currently.
14
-
15
- For more informatio
16
-
17
- # Sample Display Ad Unit: For Publishers
18
- ```javascript
19
-
20
- var displayAdUnit = [
21
- {
22
- code: 'display',
23
- mediaTypes: {
24
- banner: {
25
- sizes: [[300, 250],[320, 50]]
26
- }
27
- }
28
- bids: [{
29
- bidder: 'saambaa',
30
- params: {
31
- pubid: '121ab139faf7ac67428a23f1d0a9a71b',
32
- placement: 1234,
33
- size: '320x50'
34
- }
35
- }]
36
- }];
37
- ```
38
-
39
- # Sample Video Ad Unit: For Publishers
40
- ```javascript
41
-
42
- var videoAdUnit = {
43
- code: 'video',
44
- sizes: [320,480],
45
- mediaTypes: {
46
- video: {
47
- playerSize : [[320, 480]],
48
- context: 'instream'
49
- }
50
- },
51
- bids: [
52
- {
53
- bidder: 'saambaa',
54
- params: {
55
- pubid: '121ab139faf7ac67428a23f1d0a9a71b',
56
- placement: 1234,
57
- size: "320x480",
58
- video: {
59
- id: 123,
60
- skip: 1,
61
- mimes : ['video/mp4', 'application/javascript'],
62
- playbackmethod : [2,6],
63
- maxduration: 30
64
- }
65
- }
66
- }
67
- ]
68
- };
1
+ # Overview
2
+
3
+ ```
4
+ Module Name: Saambaa Bidder Adapter
5
+ Module Type: Bidder Adapter
6
+ Maintainer: matt.voigt@saambaa.com
7
+ ```
8
+
9
+ # Description
10
+
11
+ Connects to Saambaa exchange for bids.
12
+
13
+ Saambaa bid adapter supports Banner and Video ads currently.
14
+
15
+ For more informatio
16
+
17
+ # Sample Display Ad Unit: For Publishers
18
+ ```javascript
19
+
20
+ var displayAdUnit = [
21
+ {
22
+ code: 'display',
23
+ mediaTypes: {
24
+ banner: {
25
+ sizes: [[300, 250],[320, 50]]
26
+ }
27
+ }
28
+ bids: [{
29
+ bidder: 'saambaa',
30
+ params: {
31
+ pubid: '121ab139faf7ac67428a23f1d0a9a71b',
32
+ placement: 1234,
33
+ size: '320x50'
34
+ }
35
+ }]
36
+ }];
37
+ ```
38
+
39
+ # Sample Video Ad Unit: For Publishers
40
+ ```javascript
41
+
42
+ var videoAdUnit = {
43
+ code: 'video',
44
+ sizes: [320,480],
45
+ mediaTypes: {
46
+ video: {
47
+ playerSize : [[320, 480]],
48
+ context: 'instream',
49
+ skip: 1,
50
+ mimes : ['video/mp4', 'application/javascript'],
51
+ playbackmethod : [2,6],
52
+ maxduration: 30
53
+ }
54
+ },
55
+ bids: [
56
+ {
57
+ bidder: 'saambaa',
58
+ params: {
59
+ pubid: '121ab139faf7ac67428a23f1d0a9a71b',
60
+ placement: 1234,
61
+ size: "320x480"
62
+ }
63
+ }
64
+ ]
65
+ };
69
66
  ```
@@ -13,6 +13,11 @@ const ALLOWED_PLACEMENTS = {
13
13
  banner: true,
14
14
  video: true
15
15
  }
16
+
17
+ // Global Vendor List Id
18
+ // https://iabeurope.eu/vendor-list-tcf-v2-0/
19
+ const GVLID = 157;
20
+
16
21
  const mediaTypesMap = {
17
22
  [BANNER]: 'display',
18
23
  [VIDEO]: 'video'
@@ -158,6 +163,7 @@ export function getTimeoutUrl (data) {
158
163
 
159
164
  export const spec = {
160
165
  code: BIDDER_CODE,
166
+ gvlid: GVLID,
161
167
  aliases: [SEEDTAG_ALIAS],
162
168
  supportedMediaTypes: [BANNER, VIDEO],
163
169
  /**
@@ -5,7 +5,7 @@ import {ADPOD, BANNER, VIDEO} from '../src/mediaTypes.js';
5
5
 
6
6
  const BIDDER_CODE = 'smaato';
7
7
  const SMAATO_ENDPOINT = 'https://prebid.ad.smaato.net/oapi/prebid';
8
- const SMAATO_CLIENT = 'prebid_js_$prebid.version$_1.4'
8
+ const SMAATO_CLIENT = 'prebid_js_$prebid.version$_1.5'
9
9
  const CURRENCY = 'USD';
10
10
 
11
11
  const buildOpenRtbBidRequest = (bidRequest, bidderRequest) => {
@@ -37,6 +37,11 @@ const buildOpenRtbBidRequest = (bidRequest, bidderRequest) => {
37
37
  user: {
38
38
  ext: {}
39
39
  },
40
+ source: {
41
+ ext: {
42
+ schain: bidRequest.schain
43
+ }
44
+ },
40
45
  ext: {
41
46
  client: SMAATO_CLIENT
42
47
  }
@@ -9,11 +9,13 @@ const BIDDER_URL = 'https://ssp.wp.pl/bidder/';
9
9
  const SYNC_URL = 'https://ssp.wp.pl/bidder/usersync';
10
10
  const NOTIFY_URL = 'https://ssp.wp.pl/bidder/notify';
11
11
  const TMAX = 450;
12
- const BIDDER_VERSION = '5.2';
12
+ const BIDDER_VERSION = '5.3';
13
13
  const W = window;
14
14
  const { navigator } = W;
15
15
  const oneCodeDetection = {};
16
+ const adUnitsCalled = {};
16
17
  const adSizesCalled = {};
18
+ const pageView = {};
17
19
  var consentApiVersion;
18
20
 
19
21
  /**
@@ -70,6 +72,7 @@ const cookieSupport = () => {
70
72
  };
71
73
 
72
74
  const applyClientHints = ortbRequest => {
75
+ const { location } = document;
73
76
  const { connection = {}, deviceMemory, userAgentData = {} } = navigator;
74
77
  const viewport = W.visualViewport || false;
75
78
  const segments = [];
@@ -85,6 +88,16 @@ const applyClientHints = ortbRequest => {
85
88
  'CH-isMobile': userAgentData.mobile,
86
89
  };
87
90
 
91
+ /**
92
+ Check / generate page view id
93
+ Should be generated dureing first call to applyClientHints(),
94
+ and re-generated if pathname has changed
95
+ */
96
+ if (!pageView.id || location.pathname !== pageView.path) {
97
+ pageView.path = location.pathname;
98
+ pageView.id = Math.floor(1E20 * Math.random());
99
+ }
100
+
88
101
  Object.keys(hints).forEach(key => {
89
102
  const hint = hints[key];
90
103
 
@@ -100,6 +113,14 @@ const applyClientHints = ortbRequest => {
100
113
  id: '12',
101
114
  name: 'NetInfo',
102
115
  segment: segments,
116
+ }, {
117
+ id: '7',
118
+ name: 'pvid',
119
+ segment: [
120
+ {
121
+ value: `${pageView.id}`
122
+ }
123
+ ]
103
124
  }];
104
125
 
105
126
  ortbRequest.user = Object.assign(ortbRequest.user, { data });
@@ -129,6 +150,7 @@ const setOnAny = (collection, key) => collection.reduce((prev, next) => prev ||
129
150
  */
130
151
  const sendNotification = payload => {
131
152
  ajax(NOTIFY_URL, null, JSON.stringify(payload), {
153
+ contentType: 'application/json',
132
154
  withCredentials: false,
133
155
  method: 'POST',
134
156
  crossOrigin: true
@@ -267,8 +289,14 @@ const mapImpression = slot => {
267
289
  send this info as ext.pbsize
268
290
  */
269
291
  const slotSize = slot.sizes.length ? slot.sizes.reduce((prev, next) => prev[0] * prev[1] <= next[0] * next[1] ? next : prev).join('x') : '1x1';
270
- adSizesCalled[slotSize] = adSizesCalled[slotSize] ? adSizesCalled[slotSize] += 1 : 1;
271
- ext.data = Object.assign({ pbsize: `${slotSize}_${adSizesCalled[slotSize]}` }, ext.data);
292
+
293
+ if (!adUnitsCalled[adUnitCode]) {
294
+ // this is a new adunit - assign & save pbsize
295
+ adSizesCalled[slotSize] = adSizesCalled[slotSize] ? adSizesCalled[slotSize] += 1 : 1;
296
+ adUnitsCalled[adUnitCode] = `${slotSize}_${adSizesCalled[slotSize]}`
297
+ }
298
+
299
+ ext.data = Object.assign({ pbsize: adUnitsCalled[adUnitCode] }, ext.data);
272
300
 
273
301
  const imp = {
274
302
  id: id && siteId ? id : 'bidid-' + bidId,
@@ -325,6 +353,9 @@ const parseNative = nativeData => {
325
353
  case 0:
326
354
  result.title = asset.title.text;
327
355
  break;
356
+ case 1:
357
+ result.cta = asset.data.value;
358
+ break;
328
359
  case 2:
329
360
  result.icon = {
330
361
  url: asset.img.url,