prebid.js 6.1.0 → 6.2.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 (69) hide show
  1. package/README.md +1 -1
  2. package/browsers.json +13 -29
  3. package/karma.conf.maker.js +1 -1
  4. package/modules/admixerBidAdapter.js +2 -1
  5. package/modules/adnuntiusBidAdapter.js +2 -1
  6. package/modules/adplusBidAdapter.js +203 -0
  7. package/modules/adplusBidAdapter.md +39 -0
  8. package/modules/adyoulikeBidAdapter.js +7 -2
  9. package/modules/appnexusBidAdapter.js +19 -2
  10. package/modules/beachfrontBidAdapter.js +14 -17
  11. package/modules/craftBidAdapter.js +5 -3
  12. package/modules/dchain.js +149 -0
  13. package/modules/dchain.md +45 -0
  14. package/modules/emx_digitalBidAdapter.js +9 -1
  15. package/modules/freewheel-sspBidAdapter.js +6 -0
  16. package/modules/goldbachBidAdapter.js +1176 -0
  17. package/modules/goldbachBidAdapter.md +151 -0
  18. package/modules/gumgumBidAdapter.js +5 -1
  19. package/modules/intersectionRtdProvider.js +114 -0
  20. package/modules/invibesBidAdapter.js +15 -9
  21. package/modules/ipromBidAdapter.js +79 -0
  22. package/modules/limelightDigitalBidAdapter.js +2 -1
  23. package/modules/luponmediaBidAdapter.js +570 -0
  24. package/modules/missenaBidAdapter.js +89 -0
  25. package/modules/pubmaticBidAdapter.js +3 -3
  26. package/modules/relaidoBidAdapter.js +86 -65
  27. package/modules/richaudienceBidAdapter.js +1 -1
  28. package/modules/smaatoBidAdapter.js +4 -1
  29. package/modules/smartxBidAdapter.js +17 -1
  30. package/modules/tappxBidAdapter.js +3 -1
  31. package/modules/undertoneBidAdapter.js +8 -1
  32. package/modules/userId/index.js +27 -2
  33. package/modules/ventes.md +71 -0
  34. package/modules/ventesBidAdapter.js +104 -64
  35. package/modules/ventesBidAdapter.md +0 -1
  36. package/modules/visxBidAdapter.js +19 -2
  37. package/modules/visxBidAdapter.md +4 -6
  38. package/modules/yahoosspBidAdapter.md +1 -1
  39. package/modules/yieldoneBidAdapter.js +115 -11
  40. package/package.json +1 -1
  41. package/src/auction.js +3 -2
  42. package/src/targeting.js +2 -2
  43. package/src/utils.js +7 -0
  44. package/test/spec/integration/faker/googletag.js +6 -0
  45. package/test/spec/modules/adnuntiusBidAdapter_spec.js +18 -0
  46. package/test/spec/modules/adplusBidAdapter_spec.js +213 -0
  47. package/test/spec/modules/adyoulikeBidAdapter_spec.js +26 -0
  48. package/test/spec/modules/appnexusBidAdapter_spec.js +49 -1
  49. package/test/spec/modules/beachfrontBidAdapter_spec.js +65 -1
  50. package/test/spec/modules/dchain_spec.js +329 -0
  51. package/test/spec/modules/emx_digitalBidAdapter_spec.js +10 -0
  52. package/test/spec/modules/freewheel-sspBidAdapter_spec.js +19 -0
  53. package/test/spec/modules/goldbachBidAdapter_spec.js +1359 -0
  54. package/test/spec/modules/gumgumBidAdapter_spec.js +6 -0
  55. package/test/spec/modules/intersectionRtdProvider_spec.js +141 -0
  56. package/test/spec/modules/invibesBidAdapter_spec.js +29 -4
  57. package/test/spec/modules/ipromBidAdapter_spec.js +195 -0
  58. package/test/spec/modules/limelightDigitalBidAdapter_spec.js +10 -7
  59. package/test/spec/modules/luponmediaBidAdapter_spec.js +412 -0
  60. package/test/spec/modules/missenaBidAdapter_spec.js +134 -0
  61. package/test/spec/modules/pubmaticBidAdapter_spec.js +1 -1
  62. package/test/spec/modules/relaidoBidAdapter_spec.js +71 -63
  63. package/test/spec/modules/smaatoBidAdapter_spec.js +31 -0
  64. package/test/spec/modules/smartxBidAdapter_spec.js +9 -0
  65. package/test/spec/modules/tappxBidAdapter_spec.js +4 -0
  66. package/test/spec/modules/userId_spec.js +51 -0
  67. package/test/spec/modules/visxBidAdapter_spec.js +120 -4
  68. package/test/spec/modules/yieldoneBidAdapter_spec.js +299 -53
  69. package/test/spec/unit/core/targeting_spec.js +44 -0
@@ -1,17 +1,24 @@
1
- import {registerBidder} from '../src/adapters/bidderFactory.js';
2
- import {BANNER, NATIVE, VIDEO} from '../src/mediaTypes.js';
3
- import {convertCamelToUnderscore, isStr, isArray, isNumber, isPlainObject, replaceAuctionPrice} from '../src/utils.js';
1
+ import {
2
+ BANNER,
3
+ NATIVE,
4
+ VIDEO
5
+ } from '../src/mediaTypes.js';
6
+ import {
7
+ convertCamelToUnderscore,
8
+ isStr,
9
+ isArray,
10
+ isNumber,
11
+ isPlainObject,
12
+ replaceAuctionPrice
13
+ } from '../src/utils.js';
4
14
  import find from 'core-js-pure/features/array/find.js';
5
- import includes from 'core-js-pure/features/array/includes.js';
15
+ import {
16
+ registerBidder
17
+ } from '../src/adapters/bidderFactory.js';
6
18
 
7
19
  const BID_METHOD = 'POST';
8
20
  const BIDDER_URL = 'http://13.234.201.146:8088/va/ad';
9
- const FIRST_PRICE = 1;
10
- const NET_REVENUE = true;
11
- const TTL = 10;
12
- const USER_PARAMS = ['age', 'externalUid', 'segments', 'gender', 'dnt', 'language'];
13
- const DEVICE_PARAMS = ['ua', 'geo', 'dnt', 'lmt', 'ip', 'ipv6', 'devicetype'];
14
- const APP_DEVICE_PARAMS = ['geo', 'device_id']; // appid is collected separately
21
+
15
22
  const DOMAIN_REGEX = new RegExp('//([^/]*)');
16
23
 
17
24
  function groupBy(values, key) {
@@ -26,7 +33,11 @@ function groupBy(values, key) {
26
33
 
27
34
  return Object
28
35
  .keys(groups)
29
- .map(id => ({id, key, values: groups[id]}));
36
+ .map(id => ({
37
+ id,
38
+ key,
39
+ values: groups[id]
40
+ }));
30
41
  }
31
42
 
32
43
  function validateMediaTypes(mediaTypes, allowedMediaTypes) {
@@ -45,22 +56,22 @@ function isBanner(mediaTypes) {
45
56
 
46
57
  function validateBanner(banner) {
47
58
  return isPlainObject(banner) &&
48
- isArray(banner.sizes) &&
49
- (banner.sizes.length > 0) &&
50
- banner.sizes.every(validateMediaSizes);
59
+ isArray(banner.sizes) &&
60
+ (banner.sizes.length > 0) &&
61
+ banner.sizes.every(validateMediaSizes);
51
62
  }
52
63
 
53
64
  function validateMediaSizes(mediaSize) {
54
65
  return isArray(mediaSize) &&
55
- (mediaSize.length === 2) &&
56
- mediaSize.every(size => (isNumber(size) && size >= 0));
66
+ (mediaSize.length === 2) &&
67
+ mediaSize.every(size => (isNumber(size) && size >= 0));
57
68
  }
58
69
 
59
70
  function hasUserInfo(bid) {
60
71
  return !!bid.params.user;
61
72
  }
62
73
 
63
- function validateParameters(parameters, adUnit) {
74
+ function validateParameters(parameters) {
64
75
  if (!(parameters.placementId)) {
65
76
  return false;
66
77
  }
@@ -101,8 +112,8 @@ function generateSiteFromAdUnitContext(bidRequests, adUnitContext) {
101
112
 
102
113
  function validateServerRequest(serverRequest) {
103
114
  return isPlainObject(serverRequest) &&
104
- isPlainObject(serverRequest.data) &&
105
- isArray(serverRequest.data.imp)
115
+ isPlainObject(serverRequest.data) &&
116
+ isArray(serverRequest.data.imp)
106
117
  }
107
118
 
108
119
  function createServerRequestFromAdUnits(adUnits, bidRequestId, adUnitContext) {
@@ -122,14 +133,15 @@ function generateBidRequestsFromAdUnits(bidRequests, bidRequestId, adUnitContext
122
133
  let userObj = {};
123
134
  if (userObjBid) {
124
135
  Object.keys(userObjBid.params.user)
125
- .filter(param => includes(USER_PARAMS, param))
126
136
  .forEach((param) => {
127
137
  let uparam = convertCamelToUnderscore(param);
128
138
  if (param === 'segments' && isArray(userObjBid.params.user[param])) {
129
139
  let segs = [];
130
140
  userObjBid.params.user[param].forEach(val => {
131
141
  if (isNumber(val)) {
132
- segs.push({'id': val});
142
+ segs.push({
143
+ 'id': val
144
+ });
133
145
  } else if (isPlainObject(val)) {
134
146
  segs.push(val);
135
147
  }
@@ -146,7 +158,6 @@ function generateBidRequestsFromAdUnits(bidRequests, bidRequestId, adUnitContext
146
158
  if (deviceObjBid && deviceObjBid.params && deviceObjBid.params.device) {
147
159
  deviceObj = {};
148
160
  Object.keys(deviceObjBid.params.device)
149
- .filter(param => includes(DEVICE_PARAMS, param))
150
161
  .forEach(param => deviceObj[param] = deviceObjBid.params.device[param]);
151
162
  if (!deviceObjBid.hasOwnProperty('ua')) {
152
163
  deviceObj.ua = navigator.userAgent;
@@ -159,37 +170,41 @@ function generateBidRequestsFromAdUnits(bidRequests, bidRequestId, adUnitContext
159
170
  deviceObj.ua = navigator.userAgent;
160
171
  deviceObj.language = navigator.language;
161
172
  }
162
- const appDeviceObjBid = find(bidRequests, hasAppInfo);
163
- let appIdObj;
164
- if (appDeviceObjBid && appDeviceObjBid.params && appDeviceObjBid.params.app && appDeviceObjBid.params.app.id) {
165
- Object.keys(appDeviceObjBid.params.app)
166
- .filter(param => includes(APP_DEVICE_PARAMS, param))
167
- .forEach(param => appDeviceObjBid[param] = appDeviceObjBid.params.app[param]);
168
- }
169
173
 
170
174
  const payload = {}
171
175
  payload.id = bidRequestId
172
- payload.at = FIRST_PRICE
176
+ payload.at = 1
173
177
  payload.cur = ['USD']
174
178
  payload.imp = bidRequests.reduce(generateImpressionsFromAdUnit, [])
175
- payload.site = generateSiteFromAdUnitContext(bidRequests, adUnitContext)
176
- payload.device = deviceObj
177
- if (appDeviceObjBid && payload.site != null) {
179
+ const appDeviceObjBid = find(bidRequests, hasAppInfo);
180
+ if (!appDeviceObjBid) {
181
+ payload.site = generateSiteFromAdUnitContext(bidRequests, adUnitContext)
182
+ } else {
183
+ let appIdObj;
184
+ if (appDeviceObjBid && appDeviceObjBid.params && appDeviceObjBid.params.app && appDeviceObjBid.params.app.id) {
185
+ appIdObj = {};
186
+ Object.keys(appDeviceObjBid.params.app)
187
+ .forEach(param => appIdObj[param] = appDeviceObjBid.params.app[param]);
188
+ }
178
189
  payload.app = appIdObj;
179
190
  }
191
+ payload.device = deviceObj;
180
192
  payload.user = userObj
181
- // payload.regs = getRegulationFromAdUnitContext(adUnitContext)
182
- // payload.ext = generateBidRequestExtension()
183
-
184
193
  return payload
185
194
  }
186
195
 
187
196
  function generateImpressionsFromAdUnit(acc, adUnit) {
188
- const {bidId, mediaTypes, params} = adUnit;
189
- const {placementId} = params;
197
+ const {
198
+ bidId,
199
+ mediaTypes,
200
+ params
201
+ } = adUnit;
202
+ const {
203
+ placementId
204
+ } = params;
190
205
  const pmp = {};
191
206
 
192
- if (placementId) pmp.deals = [{id: placementId}]
207
+ if (placementId) pmp.deals = [{ id: placementId }]
193
208
 
194
209
  const imps = Object
195
210
  .keys(mediaTypes)
@@ -204,21 +219,40 @@ function generateImpressionsFromAdUnit(acc, adUnit) {
204
219
  }
205
220
 
206
221
  function generateBannerFromAdUnit(impId, data, params) {
207
- const {position, placementId} = params;
222
+ const {
223
+ position,
224
+ placementId
225
+ } = params;
208
226
  const pos = position || 0;
209
227
  const pmp = {};
210
- const ext = {placementId};
211
-
212
- if (placementId) pmp.deals = [{id: placementId}]
228
+ const ext = {
229
+ placementId
230
+ };
213
231
 
214
- return data.sizes.map(([w, h]) => ({id: `${impId}`, banner: {format: [{w, h}], w, h, pos}, pmp, ext, tagid: placementId}));
232
+ if (placementId) pmp.deals = [{ id: placementId }]
233
+
234
+ return data.sizes.map(([w, h]) => ({
235
+ id: `${impId}`,
236
+ banner: {
237
+ format: [{
238
+ w,
239
+ h
240
+ }],
241
+ w,
242
+ h,
243
+ pos
244
+ },
245
+ pmp,
246
+ ext,
247
+ tagid: placementId
248
+ }));
215
249
  }
216
250
 
217
251
  function validateServerResponse(serverResponse) {
218
252
  return isPlainObject(serverResponse) &&
219
- isPlainObject(serverResponse.body) &&
220
- isStr(serverResponse.body.cur) &&
221
- isArray(serverResponse.body.seatbid);
253
+ isPlainObject(serverResponse.body) &&
254
+ isStr(serverResponse.body.cur) &&
255
+ isArray(serverResponse.body.seatbid);
222
256
  }
223
257
 
224
258
  function seatBidsToAds(seatBid, bidResponse, serverRequest) {
@@ -241,10 +275,8 @@ function validateBids(bid) {
241
275
  return true;
242
276
  }
243
277
 
244
- const VAST_REGEXP = /VAST\s+version/;
245
-
246
278
  function getMediaType(adm) {
247
- const videoRegex = new RegExp(VAST_REGEXP);
279
+ const videoRegex = new RegExp(/VAST\s+version/);
248
280
 
249
281
  if (videoRegex.test(adm)) {
250
282
  return VIDEO;
@@ -273,14 +305,16 @@ function generateAdFromBid(bid, bidResponse) {
273
305
  requestId: bid.impid,
274
306
  cpm: bid.price,
275
307
  currency: bidResponse.cur,
276
- ttl: TTL,
308
+ ttl: 10,
277
309
  creativeId: bid.crid,
278
310
  mediaType: mediaType,
279
- netRevenue: NET_REVENUE
311
+ netRevenue: true
280
312
  };
281
313
 
282
314
  if (bid.adomain) {
283
- base.meta = { advertiserDomains: bid.adomain };
315
+ base.meta = {
316
+ advertiserDomains: bid.adomain
317
+ };
284
318
  }
285
319
 
286
320
  const size = getSizeFromBid(bid);
@@ -292,17 +326,21 @@ function generateAdFromBid(bid, bidResponse) {
292
326
  width: size.width,
293
327
  ad: creative.markup,
294
328
  adUrl: creative.markupUrl,
295
- // vastXml: isVideo && !isStr(creative.markupUrl) ? creative.markup : null,
296
- // vastUrl: isVideo && isStr(creative.markupUrl) ? creative.markupUrl : null,
297
329
  renderer: creative.renderer
298
330
  };
299
331
  }
300
332
 
301
333
  function getSizeFromBid(bid) {
302
334
  if (isNumber(bid.w) && isNumber(bid.h)) {
303
- return { width: bid.w, height: bid.h };
335
+ return {
336
+ width: bid.w,
337
+ height: bid.h
338
+ };
304
339
  }
305
- return { width: null, height: null };
340
+ return {
341
+ width: null,
342
+ height: null
343
+ };
306
344
  }
307
345
 
308
346
  function getCreativeFromBid(bid) {
@@ -333,12 +371,12 @@ const venavenBidderSpec = {
333
371
  const allowedBidderCodes = [this.code];
334
372
 
335
373
  return isPlainObject(adUnit) &&
336
- allowedBidderCodes.indexOf(adUnit.bidder) !== -1 &&
337
- isStr(adUnit.adUnitCode) &&
338
- isStr(adUnit.bidderRequestId) &&
339
- isStr(adUnit.bidId) &&
340
- validateMediaTypes(adUnit.mediaTypes, this.supportedMediaTypes) &&
341
- validateParameters(adUnit.params, adUnit);
374
+ allowedBidderCodes.indexOf(adUnit.bidder) !== -1 &&
375
+ isStr(adUnit.adUnitCode) &&
376
+ isStr(adUnit.bidderRequestId) &&
377
+ isStr(adUnit.bidId) &&
378
+ validateMediaTypes(adUnit.mediaTypes, this.supportedMediaTypes) &&
379
+ validateParameters(adUnit.params);
342
380
  },
343
381
  buildRequests(bidRequests, bidderRequest) {
344
382
  if (!bidRequests) return null;
@@ -367,4 +405,6 @@ const venavenBidderSpec = {
367
405
 
368
406
  registerBidder(venavenBidderSpec);
369
407
 
370
- export {venavenBidderSpec as spec};
408
+ export {
409
+ venavenBidderSpec as spec
410
+ };
@@ -55,7 +55,6 @@ var adUnits = [
55
55
  publisherId: '5cebea3c9eea646c7b623d5e',
56
56
  IABCategories: "['IAB1', 'IAB5']",
57
57
  device:{
58
- ip: '123.145.167.189',
59
58
  ifa:"AEBE52E7-03EE-455A-B3C4-E57283966239",
60
59
  },
61
60
  app: {
@@ -1,4 +1,4 @@
1
- import { triggerPixel, parseSizesInput, deepAccess, logError } from '../src/utils.js';
1
+ import { triggerPixel, parseSizesInput, deepAccess, logError, getGptSlotInfoForAdUnitCode } from '../src/utils.js';
2
2
  import { registerBidder } from '../src/adapters/bidderFactory.js';
3
3
  import { config } from '../src/config.js';
4
4
  import { BANNER, VIDEO } from '../src/mediaTypes.js';
@@ -241,7 +241,7 @@ function makeVideo(videoParams = {}) {
241
241
  }
242
242
 
243
243
  function buildImpObject(bid) {
244
- const { params: { uid }, bidId, mediaTypes, sizes } = bid;
244
+ const { params: { uid }, bidId, mediaTypes, sizes, adUnitCode } = bid;
245
245
  const video = mediaTypes && _isVideoBid(bid) && _isValidVideoBid(bid) && makeVideo(mediaTypes.video);
246
246
  const banner = makeBanner((mediaTypes && mediaTypes.banner) || (!video && { sizes }));
247
247
  const impObject = {
@@ -253,6 +253,10 @@ function buildImpObject(bid) {
253
253
  }
254
254
  };
255
255
 
256
+ if (impObject.banner) {
257
+ impObject.ext.bidder.adslotExists = _isAdSlotExists(adUnitCode);
258
+ }
259
+
256
260
  if (impObject.ext.bidder.uid && (impObject.banner || impObject.video)) {
257
261
  return impObject;
258
262
  }
@@ -355,4 +359,17 @@ function _isValidVideoBid(bid, logErrors = false) {
355
359
  return result;
356
360
  }
357
361
 
362
+ function _isAdSlotExists(adUnitCode) {
363
+ if (document.getElementById(adUnitCode)) {
364
+ return true;
365
+ }
366
+
367
+ const gptAdSlot = getGptSlotInfoForAdUnitCode(adUnitCode);
368
+ if (gptAdSlot && gptAdSlot.divId && document.getElementById(gptAdSlot.divId)) {
369
+ return true;
370
+ }
371
+
372
+ return false;
373
+ }
374
+
358
375
  registerBidder(spec);
@@ -3,7 +3,7 @@
3
3
  ```
4
4
  Module Name: YOC VIS.X Bidder Adapter
5
5
  Module Type: Bidder Adapter
6
- Maintainer: service@yoc.com
6
+ Maintainer: supply.partners@yoc.com
7
7
  ```
8
8
 
9
9
  # Description
@@ -47,16 +47,14 @@ var adUnits = [
47
47
  }
48
48
  ]
49
49
  },
50
- // YOC In-stream adUnit
50
+ // In-stream video adUnit
51
51
  {
52
52
  code: 'instream-test-div',
53
53
  mediaTypes: {
54
54
  video: {
55
55
  context: 'instream',
56
- playerSize: [400, 300],
57
- mimes: ['video/mp4'],
58
- protocols: [3, 6]
59
- },
56
+ playerSize: [400, 300]
57
+ }
60
58
  },
61
59
  bids: [
62
60
  {
@@ -57,7 +57,7 @@ At this time, only the following partners/publishers are eligble for pubId integ
57
57
  A. Do not have any display/banner inventory.
58
58
  B. Do not have any existing accounts on Yahoo SSP (aka: aol, oneMobile, oneDisplay).
59
59
 
60
- # Mandaotory Bidder Parameters
60
+ # Mandatory Bidder Parameters
61
61
  ## dcn & pos (DEFAULT)
62
62
  The minimal requirements for the 'yahoossp' bid adapter to generate an outbound bid-request to our Yahoo SSP are:
63
63
  1. At least 1 adUnit including mediaTypes: banner or video
@@ -1,4 +1,4 @@
1
- import { deepAccess, isEmpty, parseSizesInput, isStr, logWarn } from '../src/utils.js';
1
+ import {deepAccess, isEmpty, isStr, logWarn, parseSizesInput} from '../src/utils.js';
2
2
  import {config} from '../src/config.js';
3
3
  import {registerBidder} from '../src/adapters/bidderFactory.js';
4
4
  import { Renderer } from '../src/Renderer.js';
@@ -11,6 +11,8 @@ const VIDEO_PLAYER_URL = 'https://img.ak.impact-ad.jp/ic/pone/ivt/firstview/js/d
11
11
  const CMER_PLAYER_URL = 'https://an.cmertv.com/hb/renderer/cmertv-video-yone-prebid.min.js';
12
12
  const VIEWABLE_PERCENTAGE_URL = 'https://img.ak.impact-ad.jp/ic/pone/ivt/firstview/js/prebid-adformat-config.js';
13
13
 
14
+ const DEFAULT_VIDEO_SIZE = {w: 640, h: 360};
15
+
14
16
  export const spec = {
15
17
  code: BIDDER_CODE,
16
18
  aliases: ['y1'],
@@ -40,16 +42,18 @@ export const spec = {
40
42
  t: 'i'
41
43
  };
42
44
 
43
- const videoMediaType = deepAccess(bidRequest, 'mediaTypes.video');
44
- if ((isEmpty(bidRequest.mediaType) && isEmpty(bidRequest.mediaTypes)) ||
45
- (bidRequest.mediaType === BANNER || (bidRequest.mediaTypes && bidRequest.mediaTypes[BANNER]))) {
46
- const sizes = deepAccess(bidRequest, 'mediaTypes.banner.sizes') || bidRequest.sizes;
47
- payload.sz = parseSizesInput(sizes).join(',');
48
- } else if (bidRequest.mediaType === VIDEO || videoMediaType) {
49
- const sizes = deepAccess(bidRequest, 'mediaTypes.video.playerSize') || bidRequest.sizes;
50
- const size = parseSizesInput(sizes)[0];
51
- payload.w = size.split('x')[0];
52
- payload.h = size.split('x')[1];
45
+ const mediaType = getMediaType(bidRequest);
46
+ switch (mediaType) {
47
+ case BANNER:
48
+ payload.sz = getBannerSizes(bidRequest);
49
+ break;
50
+ case VIDEO:
51
+ const videoSize = getVideoSize(bidRequest);
52
+ payload.w = videoSize.w;
53
+ payload.h = videoSize.h;
54
+ break;
55
+ default:
56
+ break;
53
57
  }
54
58
 
55
59
  // LiveRampID
@@ -167,6 +171,106 @@ export const spec = {
167
171
  },
168
172
  }
169
173
 
174
+ /**
175
+ * NOTE: server side does not yet support multiple formats.
176
+ * @param {Object} bidRequest -
177
+ * @param {boolean} [enabledOldFormat = true] - default: `true`.
178
+ * @return {string|null} - `"banner"` or `"video"` or `null`.
179
+ */
180
+ function getMediaType(bidRequest, enabledOldFormat = true) {
181
+ let hasBannerType = Boolean(deepAccess(bidRequest, 'mediaTypes.banner'));
182
+ let hasVideoType = Boolean(deepAccess(bidRequest, 'mediaTypes.video'));
183
+
184
+ if (enabledOldFormat) {
185
+ hasBannerType = hasBannerType || bidRequest.mediaType === BANNER ||
186
+ (isEmpty(bidRequest.mediaTypes) && isEmpty(bidRequest.mediaType));
187
+ hasVideoType = hasVideoType || bidRequest.mediaType === VIDEO;
188
+ }
189
+
190
+ if (hasBannerType && hasVideoType) {
191
+ const playerParams = deepAccess(bidRequest, 'params.playerParams')
192
+ if (playerParams) {
193
+ return VIDEO;
194
+ } else {
195
+ return BANNER;
196
+ }
197
+ } else if (hasBannerType) {
198
+ return BANNER;
199
+ } else if (hasVideoType) {
200
+ return VIDEO;
201
+ }
202
+
203
+ return null;
204
+ }
205
+
206
+ /**
207
+ * NOTE:
208
+ * If `mediaTypes.banner` exists, then `mediaTypes.banner.sizes` must also exist.
209
+ * The reason for this is that Prebid.js will perform the verification and
210
+ * if `mediaTypes.banner.sizes` is inappropriate, it will delete the entire `mediaTypes.banner`.
211
+ * @param {Object} bidRequest -
212
+ * @param {Object} bidRequest.banner -
213
+ * @param {Array<string>} bidRequest.banner.sizes -
214
+ * @param {boolean} [enabledOldFormat = true] - default: `true`.
215
+ * @return {string} - strings like `"300x250"` or `"300x250,728x90"`.
216
+ */
217
+ function getBannerSizes(bidRequest, enabledOldFormat = true) {
218
+ let sizes = deepAccess(bidRequest, 'mediaTypes.banner.sizes');
219
+
220
+ if (enabledOldFormat) {
221
+ sizes = sizes || bidRequest.sizes;
222
+ }
223
+
224
+ return parseSizesInput(sizes).join(',');
225
+ }
226
+
227
+ /**
228
+ * @param {Object} bidRequest -
229
+ * @param {boolean} [enabledOldFormat = true] - default: `true`.
230
+ * @param {boolean} [enabledFlux = true] - default: `true`.
231
+ * @return {{w: number, h: number}} -
232
+ */
233
+ function getVideoSize(bidRequest, enabledOldFormat = true, enabledFlux = true) {
234
+ /**
235
+ * @param {Array<number, number> | Array<Array<number, number>>} sizes -
236
+ * @return {{w: number, h: number} | null} -
237
+ */
238
+ const _getPlayerSize = (sizes) => {
239
+ let result = null;
240
+
241
+ const size = parseSizesInput(sizes)[0];
242
+ if (isEmpty(size)) {
243
+ return result;
244
+ }
245
+
246
+ const splited = size.split('x');
247
+ const sizeObj = {w: parseInt(splited[0], 10), h: parseInt(splited[1], 10)};
248
+ const _isValidPlayerSize = !(isEmpty(sizeObj)) && (isFinite(sizeObj.w) && isFinite(sizeObj.h));
249
+ if (!_isValidPlayerSize) {
250
+ return result;
251
+ }
252
+
253
+ result = sizeObj;
254
+ return result;
255
+ }
256
+
257
+ let playerSize = _getPlayerSize(deepAccess(bidRequest, 'mediaTypes.video.playerSize'));
258
+
259
+ if (enabledOldFormat) {
260
+ playerSize = playerSize || _getPlayerSize(bidRequest.sizes);
261
+ }
262
+
263
+ if (enabledFlux) {
264
+ // NOTE: `video.playerSize` in Flux is always [1,1].
265
+ if (playerSize && (playerSize.w === 1 && playerSize.h === 1)) {
266
+ // NOTE: `params.playerSize` is a specific object to support `FLUX`.
267
+ playerSize = _getPlayerSize(deepAccess(bidRequest, 'params.playerSize'));
268
+ }
269
+ }
270
+
271
+ return playerSize || DEFAULT_VIDEO_SIZE;
272
+ }
273
+
170
274
  function newRenderer(response) {
171
275
  const renderer = Renderer.install({
172
276
  id: response.uid,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prebid.js",
3
- "version": "6.1.0",
3
+ "version": "6.2.0",
4
4
  "description": "Header Bidding Management Library",
5
5
  "main": "src/prebid.js",
6
6
  "scripts": {
package/src/auction.js CHANGED
@@ -59,7 +59,7 @@
59
59
 
60
60
  import {
61
61
  flatten, timestamp, adUnitsFilter, deepAccess, getBidRequest, getValue, parseUrl, generateUUID,
62
- logMessage, bind, logError, logInfo, logWarn, isEmpty, _each, isFn, isEmptyStr
62
+ logMessage, bind, logError, logInfo, logWarn, isEmpty, _each, isFn, isEmptyStr, isAllowZeroCpmBidsEnabled
63
63
  } from './utils.js';
64
64
  import { getPriceBucketString } from './cpmBucketManager.js';
65
65
  import { getNativeTargeting } from './native.js';
@@ -567,7 +567,8 @@ function getPreparedBidForAuction({adUnitCode, bid, bidderRequest, auctionId}) {
567
567
 
568
568
  function setupBidTargeting(bidObject, bidderRequest) {
569
569
  let keyValues;
570
- if (bidObject.bidderCode && (bidObject.cpm > 0 || bidObject.dealId)) {
570
+ const cpmCheck = (isAllowZeroCpmBidsEnabled(bidObject.bidderCode)) ? bidObject.cpm >= 0 : bidObject.cpm > 0;
571
+ if (bidObject.bidderCode && (cpmCheck || bidObject.dealId)) {
571
572
  let bidReq = find(bidderRequest.bids, bid => bid.adUnitCode === bidObject.adUnitCode);
572
573
  keyValues = getKeyValueTargetingPairs(bidObject.bidderCode, bidObject, bidReq);
573
574
  }
package/src/targeting.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  uniques, isGptPubadsDefined, getHighestCpm, getOldestHighestCpmBid, groupBy, isAdUnitCodeMatchingSlot, timestamp,
3
- deepAccess, deepClone, logError, logWarn, logInfo, isFn, isArray, logMessage, isStr
3
+ deepAccess, deepClone, logError, logWarn, logInfo, isFn, isArray, logMessage, isStr, isAllowZeroCpmBidsEnabled
4
4
  } from './utils.js';
5
5
  import { config } from './config.js';
6
6
  import { NATIVE_TARGETING_KEYS } from './native.js';
@@ -438,7 +438,7 @@ export function newTargeting(auctionManager) {
438
438
  const adUnitCodes = getAdUnitCodes(adUnitCode);
439
439
  return bidsReceived
440
440
  .filter(bid => includes(adUnitCodes, bid.adUnitCode))
441
- .filter(bid => bid.cpm > 0)
441
+ .filter(bid => (isAllowZeroCpmBidsEnabled(bid.bidderCode)) ? bid.cpm >= 0 : bid.cpm > 0)
442
442
  .map(bid => bid.adUnitCode)
443
443
  .filter(uniques)
444
444
  .map(adUnitCode => bidsReceived
package/src/utils.js CHANGED
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable no-console */
2
2
  import { config } from './config.js';
3
+ import { getGlobal } from './prebidGlobal.js';
3
4
  import clone from 'just-clone';
4
5
  import find from 'core-js-pure/features/array/find.js';
5
6
  import includes from 'core-js-pure/features/array/includes.js';
@@ -1294,3 +1295,9 @@ export function cyrb53Hash(str, seed = 0) {
1294
1295
  h2 = imul(h2 ^ (h2 >>> 16), 2246822507) ^ imul(h1 ^ (h1 >>> 13), 3266489909);
1295
1296
  return (4294967296 * (2097151 & h2) + (h1 >>> 0)).toString();
1296
1297
  }
1298
+
1299
+ export function isAllowZeroCpmBidsEnabled(bidderCode) {
1300
+ const bidderSettings = getGlobal().bidderSettings;
1301
+ return ((bidderSettings[bidderCode] && bidderSettings[bidderCode].allowZeroCpmBids === true) ||
1302
+ (bidderSettings.standard && bidderSettings.standard.allowZeroCpmBids === true));
1303
+ }
@@ -51,9 +51,15 @@ export function enable() {
51
51
  window.googletag = {
52
52
  _slots: [],
53
53
  _callbackMap: {},
54
+ _ppid: undefined,
55
+ cmd: [],
54
56
  pubads: function () {
55
57
  var self = this;
56
58
  return {
59
+ setPublisherProvidedId: function (ppid) {
60
+ self._ppid = ppid;
61
+ },
62
+
57
63
  getSlots: function () {
58
64
  return self._slots;
59
65
  },
@@ -251,6 +251,24 @@ describe('adnuntiusBidAdapter', function () {
251
251
  expect(request[0]).to.have.property('url')
252
252
  expect(request[0].url).to.equal(ENDPOINT_URL_SEGMENTS);
253
253
  });
254
+
255
+ it('should user user ID if present in ortb2.user.id field', function () {
256
+ config.setBidderConfig({
257
+ bidders: ['adnuntius', 'other'],
258
+ config: {
259
+ ortb2: {
260
+ user: {
261
+ id: usi
262
+ }
263
+ }
264
+ }
265
+ });
266
+
267
+ const request = config.runWithBidder('adnuntius', () => spec.buildRequests(bidRequests));
268
+ expect(request.length).to.equal(1);
269
+ expect(request[0]).to.have.property('url')
270
+ expect(request[0].url).to.equal(ENDPOINT_URL);
271
+ });
254
272
  });
255
273
 
256
274
  describe('user privacy', function () {