prebid.js 5.19.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 (161) hide show
  1. package/.babelrc.js +1 -10
  2. package/README.md +4 -2
  3. package/browsers.json +13 -37
  4. package/gulpfile.js +1 -0
  5. package/karma.conf.maker.js +1 -1
  6. package/modules/adheseBidAdapter.js +7 -2
  7. package/modules/adkernelBidAdapter.js +1 -0
  8. package/modules/adlivetechBidAdapter.md +61 -0
  9. package/modules/admixerBidAdapter.js +2 -1
  10. package/modules/adnuntiusBidAdapter.js +2 -1
  11. package/modules/adomikAnalyticsAdapter.js +10 -4
  12. package/modules/adplusBidAdapter.js +203 -0
  13. package/modules/adplusBidAdapter.md +39 -0
  14. package/modules/adyoulikeBidAdapter.js +7 -2
  15. package/modules/airgridRtdProvider.js +1 -1
  16. package/modules/appnexusBidAdapter.js +28 -5
  17. package/modules/atsAnalyticsAdapter.js +67 -46
  18. package/modules/atsAnalyticsAdapter.md +1 -0
  19. package/modules/beachfrontBidAdapter.js +14 -17
  20. package/modules/betweenBidAdapter.js +2 -1
  21. package/modules/browsiRtdProvider.js +106 -18
  22. package/modules/cleanioRtdProvider.js +192 -0
  23. package/modules/cleanioRtdProvider.md +59 -0
  24. package/modules/codefuelBidAdapter.js +1 -3
  25. package/modules/codefuelBidAdapter.md +3 -3
  26. package/modules/craftBidAdapter.js +5 -3
  27. package/modules/datablocksBidAdapter.js +3 -3
  28. package/modules/dchain.js +149 -0
  29. package/modules/dchain.md +45 -0
  30. package/modules/deepintentBidAdapter.js +1 -1
  31. package/modules/deltaprojectsBidAdapter.js +252 -0
  32. package/modules/deltaprojectsBidAdapter.md +32 -0
  33. package/modules/emx_digitalBidAdapter.js +9 -1
  34. package/modules/engageyaBidAdapter.js +68 -54
  35. package/modules/freewheel-sspBidAdapter.js +6 -0
  36. package/modules/glimpseBidAdapter.js +31 -16
  37. package/modules/goldbachBidAdapter.js +1176 -0
  38. package/modules/goldbachBidAdapter.md +151 -0
  39. package/modules/gptPreAuction.js +11 -5
  40. package/modules/gridBidAdapter.js +1 -0
  41. package/modules/gumgumBidAdapter.js +5 -1
  42. package/modules/id5IdSystem.md +6 -6
  43. package/modules/imRtdProvider.js +31 -0
  44. package/modules/intersectionRtdProvider.js +114 -0
  45. package/modules/invibesBidAdapter.js +15 -9
  46. package/modules/ipromBidAdapter.js +79 -0
  47. package/modules/ixBidAdapter.js +173 -22
  48. package/modules/jixieBidAdapter.js +8 -2
  49. package/modules/justpremiumBidAdapter.js +6 -1
  50. package/modules/limelightDigitalBidAdapter.js +2 -1
  51. package/modules/livewrappedAnalyticsAdapter.js +5 -0
  52. package/modules/luponmediaBidAdapter.js +570 -0
  53. package/modules/merkleIdSystem.js +5 -0
  54. package/modules/missenaBidAdapter.js +89 -0
  55. package/modules/multibid/index.js +3 -3
  56. package/modules/nativoBidAdapter.js +32 -2
  57. package/modules/oguryBidAdapter.js +2 -1
  58. package/modules/openxBidAdapter.js +7 -2
  59. package/modules/operaadsBidAdapter.js +21 -1
  60. package/modules/otmBidAdapter.js +146 -0
  61. package/modules/otmBidAdapter.md +27 -26
  62. package/modules/outbrainBidAdapter.js +5 -0
  63. package/modules/playwireBidAdapter.md +61 -0
  64. package/modules/prebidServerBidAdapter/index.js +3 -3
  65. package/modules/pubmaticBidAdapter.js +5 -3
  66. package/modules/relaidoBidAdapter.js +86 -65
  67. package/modules/richaudienceBidAdapter.js +1 -1
  68. package/modules/rtdModule/index.js +2 -2
  69. package/modules/saambaaBidAdapter.js +420 -0
  70. package/modules/saambaaBidAdapter.md +65 -68
  71. package/modules/seedtagBidAdapter.js +6 -0
  72. package/modules/smaatoBidAdapter.js +9 -1
  73. package/modules/smartxBidAdapter.js +17 -1
  74. package/modules/sonobiBidAdapter.js +7 -0
  75. package/modules/sortableBidAdapter.js +1 -0
  76. package/modules/sspBCBidAdapter.js +34 -3
  77. package/modules/tappxBidAdapter.js +3 -1
  78. package/modules/teadsBidAdapter.js +3 -0
  79. package/modules/trustxBidAdapter.js +18 -7
  80. package/modules/undertoneBidAdapter.js +8 -1
  81. package/modules/userId/index.js +27 -2
  82. package/modules/ventes.md +71 -0
  83. package/modules/ventesBidAdapter.js +410 -0
  84. package/modules/ventesBidAdapter.md +93 -0
  85. package/modules/vidoomyBidAdapter.js +51 -100
  86. package/modules/visxBidAdapter.js +20 -3
  87. package/modules/visxBidAdapter.md +4 -6
  88. package/modules/yahoosspBidAdapter.js +6 -6
  89. package/modules/yahoosspBidAdapter.md +1 -1
  90. package/modules/yieldlabBidAdapter.js +41 -10
  91. package/modules/yieldlabBidAdapter.md +91 -48
  92. package/modules/yieldoneBidAdapter.js +115 -11
  93. package/package.json +6 -1
  94. package/src/adapterManager.js +14 -8
  95. package/src/auction.js +14 -13
  96. package/src/targeting.js +2 -2
  97. package/src/utils.js +7 -0
  98. package/test/spec/integration/faker/googletag.js +6 -0
  99. package/test/spec/modules/adheseBidAdapter_spec.js +27 -1
  100. package/test/spec/modules/adnuntiusBidAdapter_spec.js +18 -0
  101. package/test/spec/modules/adomikAnalyticsAdapter_spec.js +3 -1
  102. package/test/spec/modules/adplusBidAdapter_spec.js +213 -0
  103. package/test/spec/modules/adyoulikeBidAdapter_spec.js +26 -0
  104. package/test/spec/modules/appnexusBidAdapter_spec.js +65 -2
  105. package/test/spec/modules/atsAnalyticsAdapter_spec.js +42 -9
  106. package/test/spec/modules/beachfrontBidAdapter_spec.js +65 -1
  107. package/test/spec/modules/browsiRtdProvider_spec.js +62 -7
  108. package/test/spec/modules/cleanioRtdProvider_spec.js +188 -0
  109. package/test/spec/modules/codefuelBidAdapter_spec.js +1 -1
  110. package/test/spec/modules/datablocksBidAdapter_spec.js +3 -3
  111. package/test/spec/modules/dchain_spec.js +329 -0
  112. package/test/spec/modules/deltaprojectsBidAdapter_spec.js +399 -0
  113. package/test/spec/modules/emx_digitalBidAdapter_spec.js +10 -0
  114. package/test/spec/modules/engageyaBidAdapter_spec.js +231 -95
  115. package/test/spec/modules/eplanningBidAdapter_spec.js +8 -8
  116. package/test/spec/modules/freewheel-sspBidAdapter_spec.js +19 -0
  117. package/test/spec/modules/glimpseBidAdapter_spec.js +33 -0
  118. package/test/spec/modules/goldbachBidAdapter_spec.js +1359 -0
  119. package/test/spec/modules/gptPreAuction_spec.js +58 -4
  120. package/test/spec/modules/gumgumBidAdapter_spec.js +6 -0
  121. package/test/spec/modules/imRtdProvider_spec.js +25 -0
  122. package/test/spec/modules/intersectionRtdProvider_spec.js +141 -0
  123. package/test/spec/modules/invibesBidAdapter_spec.js +29 -4
  124. package/test/spec/modules/ipromBidAdapter_spec.js +195 -0
  125. package/test/spec/modules/ixBidAdapter_spec.js +288 -5
  126. package/test/spec/modules/jixieBidAdapter_spec.js +13 -11
  127. package/test/spec/modules/justpremiumBidAdapter_spec.js +9 -2
  128. package/test/spec/modules/konduitWrapper_spec.js +0 -1
  129. package/test/spec/modules/limelightDigitalBidAdapter_spec.js +10 -7
  130. package/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +23 -4
  131. package/test/spec/modules/luponmediaBidAdapter_spec.js +412 -0
  132. package/test/spec/modules/merkleIdSystem_spec.js +18 -0
  133. package/test/spec/modules/missenaBidAdapter_spec.js +134 -0
  134. package/test/spec/modules/multibid_spec.js +31 -31
  135. package/test/spec/modules/nativoBidAdapter_spec.js +35 -18
  136. package/test/spec/modules/oguryBidAdapter_spec.js +13 -11
  137. package/test/spec/modules/openxBidAdapter_spec.js +5 -26
  138. package/test/spec/modules/operaadsBidAdapter_spec.js +38 -6
  139. package/test/spec/modules/otmBidAdapter_spec.js +67 -0
  140. package/test/spec/modules/outbrainBidAdapter_spec.js +18 -0
  141. package/test/spec/modules/prebidServerBidAdapter_spec.js +19 -2
  142. package/test/spec/modules/pubmaticBidAdapter_spec.js +1 -1
  143. package/test/spec/modules/relaidoBidAdapter_spec.js +71 -63
  144. package/test/spec/modules/seedtagBidAdapter_spec.js +3 -0
  145. package/test/spec/modules/smaatoBidAdapter_spec.js +61 -0
  146. package/test/spec/modules/smartxBidAdapter_spec.js +9 -0
  147. package/test/spec/modules/sonobiBidAdapter_spec.js +34 -1
  148. package/test/spec/modules/sortableBidAdapter_spec.js +11 -0
  149. package/test/spec/modules/sspBCBidAdapter_spec.js +33 -3
  150. package/test/spec/modules/tappxBidAdapter_spec.js +4 -0
  151. package/test/spec/modules/teadsBidAdapter_spec.js +132 -0
  152. package/test/spec/modules/trustxBidAdapter_spec.js +45 -3
  153. package/test/spec/modules/userId_spec.js +51 -0
  154. package/test/spec/modules/ventesBidAdapter_spec.js +845 -0
  155. package/test/spec/modules/vidoomyBidAdapter_spec.js +32 -13
  156. package/test/spec/modules/visxBidAdapter_spec.js +121 -5
  157. package/test/spec/modules/yieldlabBidAdapter_spec.js +81 -0
  158. package/test/spec/modules/yieldoneBidAdapter_spec.js +299 -53
  159. package/test/spec/unit/core/adapterManager_spec.js +26 -7
  160. package/test/spec/unit/core/targeting_spec.js +44 -0
  161. package/wdio.conf.js +1 -1
@@ -0,0 +1,410 @@
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';
14
+ import find from 'core-js-pure/features/array/find.js';
15
+ import {
16
+ registerBidder
17
+ } from '../src/adapters/bidderFactory.js';
18
+
19
+ const BID_METHOD = 'POST';
20
+ const BIDDER_URL = 'http://13.234.201.146:8088/va/ad';
21
+
22
+ const DOMAIN_REGEX = new RegExp('//([^/]*)');
23
+
24
+ function groupBy(values, key) {
25
+ const groups = values.reduce((acc, value) => {
26
+ const groupId = value[key];
27
+
28
+ if (!acc[groupId]) acc[groupId] = [];
29
+ acc[groupId].push(value);
30
+
31
+ return acc;
32
+ }, {});
33
+
34
+ return Object
35
+ .keys(groups)
36
+ .map(id => ({
37
+ id,
38
+ key,
39
+ values: groups[id]
40
+ }));
41
+ }
42
+
43
+ function validateMediaTypes(mediaTypes, allowedMediaTypes) {
44
+ if (!isPlainObject(mediaTypes)) return false;
45
+ if (!allowedMediaTypes.some(mediaType => mediaType in mediaTypes)) return false;
46
+
47
+ if (isBanner(mediaTypes)) {
48
+ if (!validateBanner(mediaTypes.banner)) return false;
49
+ }
50
+ return true;
51
+ }
52
+
53
+ function isBanner(mediaTypes) {
54
+ return isPlainObject(mediaTypes) && isPlainObject(mediaTypes.banner);
55
+ }
56
+
57
+ function validateBanner(banner) {
58
+ return isPlainObject(banner) &&
59
+ isArray(banner.sizes) &&
60
+ (banner.sizes.length > 0) &&
61
+ banner.sizes.every(validateMediaSizes);
62
+ }
63
+
64
+ function validateMediaSizes(mediaSize) {
65
+ return isArray(mediaSize) &&
66
+ (mediaSize.length === 2) &&
67
+ mediaSize.every(size => (isNumber(size) && size >= 0));
68
+ }
69
+
70
+ function hasUserInfo(bid) {
71
+ return !!bid.params.user;
72
+ }
73
+
74
+ function validateParameters(parameters) {
75
+ if (!(parameters.placementId)) {
76
+ return false;
77
+ }
78
+ if (!(parameters.publisherId)) {
79
+ return false;
80
+ }
81
+
82
+ return true;
83
+ }
84
+
85
+ function extractSiteDomainFromURL(url) {
86
+ if (!url || !isStr(url)) return null;
87
+
88
+ const domain = url.match(DOMAIN_REGEX);
89
+
90
+ if (isArray(domain) && domain.length === 2) return domain[1];
91
+
92
+ return null;
93
+ }
94
+
95
+ function generateSiteFromAdUnitContext(bidRequests, adUnitContext) {
96
+ if (!adUnitContext || !adUnitContext.refererInfo) return null;
97
+
98
+ const domain = extractSiteDomainFromURL(adUnitContext.refererInfo.referer);
99
+ const publisherId = bidRequests[0].params.publisherId;
100
+
101
+ if (!domain) return null;
102
+
103
+ return {
104
+ page: adUnitContext.refererInfo.referer,
105
+ domain: domain,
106
+ name: domain,
107
+ publisher: {
108
+ id: publisherId
109
+ }
110
+ };
111
+ }
112
+
113
+ function validateServerRequest(serverRequest) {
114
+ return isPlainObject(serverRequest) &&
115
+ isPlainObject(serverRequest.data) &&
116
+ isArray(serverRequest.data.imp)
117
+ }
118
+
119
+ function createServerRequestFromAdUnits(adUnits, bidRequestId, adUnitContext) {
120
+ return {
121
+ method: BID_METHOD,
122
+ url: BIDDER_URL,
123
+ data: generateBidRequestsFromAdUnits(adUnits, bidRequestId, adUnitContext),
124
+ options: {
125
+ contentType: 'application/json',
126
+ withCredentials: false,
127
+ }
128
+ }
129
+ }
130
+
131
+ function generateBidRequestsFromAdUnits(bidRequests, bidRequestId, adUnitContext) {
132
+ const userObjBid = find(bidRequests, hasUserInfo);
133
+ let userObj = {};
134
+ if (userObjBid) {
135
+ Object.keys(userObjBid.params.user)
136
+ .forEach((param) => {
137
+ let uparam = convertCamelToUnderscore(param);
138
+ if (param === 'segments' && isArray(userObjBid.params.user[param])) {
139
+ let segs = [];
140
+ userObjBid.params.user[param].forEach(val => {
141
+ if (isNumber(val)) {
142
+ segs.push({
143
+ 'id': val
144
+ });
145
+ } else if (isPlainObject(val)) {
146
+ segs.push(val);
147
+ }
148
+ });
149
+ userObj[uparam] = segs;
150
+ } else if (param !== 'segments') {
151
+ userObj[uparam] = userObjBid.params.user[param];
152
+ }
153
+ });
154
+ }
155
+
156
+ const deviceObjBid = find(bidRequests, hasDeviceInfo);
157
+ let deviceObj;
158
+ if (deviceObjBid && deviceObjBid.params && deviceObjBid.params.device) {
159
+ deviceObj = {};
160
+ Object.keys(deviceObjBid.params.device)
161
+ .forEach(param => deviceObj[param] = deviceObjBid.params.device[param]);
162
+ if (!deviceObjBid.hasOwnProperty('ua')) {
163
+ deviceObj.ua = navigator.userAgent;
164
+ }
165
+ if (!deviceObjBid.hasOwnProperty('language')) {
166
+ deviceObj.language = navigator.language;
167
+ }
168
+ } else {
169
+ deviceObj = {};
170
+ deviceObj.ua = navigator.userAgent;
171
+ deviceObj.language = navigator.language;
172
+ }
173
+
174
+ const payload = {}
175
+ payload.id = bidRequestId
176
+ payload.at = 1
177
+ payload.cur = ['USD']
178
+ payload.imp = bidRequests.reduce(generateImpressionsFromAdUnit, [])
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
+ }
189
+ payload.app = appIdObj;
190
+ }
191
+ payload.device = deviceObj;
192
+ payload.user = userObj
193
+ return payload
194
+ }
195
+
196
+ function generateImpressionsFromAdUnit(acc, adUnit) {
197
+ const {
198
+ bidId,
199
+ mediaTypes,
200
+ params
201
+ } = adUnit;
202
+ const {
203
+ placementId
204
+ } = params;
205
+ const pmp = {};
206
+
207
+ if (placementId) pmp.deals = [{ id: placementId }]
208
+
209
+ const imps = Object
210
+ .keys(mediaTypes)
211
+ .reduce((acc, mediaType) => {
212
+ const data = mediaTypes[mediaType];
213
+ const impId = `${bidId}`;
214
+
215
+ if (mediaType === 'banner') return acc.concat(generateBannerFromAdUnit(impId, data, params));
216
+ }, []);
217
+
218
+ return acc.concat(imps);
219
+ }
220
+
221
+ function generateBannerFromAdUnit(impId, data, params) {
222
+ const {
223
+ position,
224
+ placementId
225
+ } = params;
226
+ const pos = position || 0;
227
+ const pmp = {};
228
+ const ext = {
229
+ placementId
230
+ };
231
+
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
+ }));
249
+ }
250
+
251
+ function validateServerResponse(serverResponse) {
252
+ return isPlainObject(serverResponse) &&
253
+ isPlainObject(serverResponse.body) &&
254
+ isStr(serverResponse.body.cur) &&
255
+ isArray(serverResponse.body.seatbid);
256
+ }
257
+
258
+ function seatBidsToAds(seatBid, bidResponse, serverRequest) {
259
+ return seatBid.bid
260
+ .filter(bid => validateBids(bid))
261
+ .map(bid => generateAdFromBid(bid, bidResponse));
262
+ }
263
+
264
+ function validateBids(bid) {
265
+ if (!isPlainObject(bid)) return false;
266
+ if (!isStr(bid.impid)) return false;
267
+ if (!isStr(bid.crid)) return false;
268
+ if (!isNumber(bid.price)) return false;
269
+ if (!isNumber(bid.w)) return false;
270
+ if (!isNumber(bid.h)) return false;
271
+ if (!bid.adm) return false;
272
+ if (bid.adm) {
273
+ if (!isStr(bid.adm)) return false;
274
+ }
275
+ return true;
276
+ }
277
+
278
+ function getMediaType(adm) {
279
+ const videoRegex = new RegExp(/VAST\s+version/);
280
+
281
+ if (videoRegex.test(adm)) {
282
+ return VIDEO;
283
+ }
284
+
285
+ const markup = safeJSONparse(adm.replace(/\\/g, ''));
286
+
287
+ if (markup && isPlainObject(markup.native)) {
288
+ return NATIVE;
289
+ }
290
+
291
+ return BANNER;
292
+ }
293
+
294
+ function safeJSONparse(...args) {
295
+ try {
296
+ return JSON.parse(...args);
297
+ } catch (_) {
298
+ return undefined;
299
+ }
300
+ }
301
+
302
+ function generateAdFromBid(bid, bidResponse) {
303
+ const mediaType = getMediaType(bid.adm);
304
+ const base = {
305
+ requestId: bid.impid,
306
+ cpm: bid.price,
307
+ currency: bidResponse.cur,
308
+ ttl: 10,
309
+ creativeId: bid.crid,
310
+ mediaType: mediaType,
311
+ netRevenue: true
312
+ };
313
+
314
+ if (bid.adomain) {
315
+ base.meta = {
316
+ advertiserDomains: bid.adomain
317
+ };
318
+ }
319
+
320
+ const size = getSizeFromBid(bid);
321
+ const creative = getCreativeFromBid(bid);
322
+
323
+ return {
324
+ ...base,
325
+ height: size.height,
326
+ width: size.width,
327
+ ad: creative.markup,
328
+ adUrl: creative.markupUrl,
329
+ renderer: creative.renderer
330
+ };
331
+ }
332
+
333
+ function getSizeFromBid(bid) {
334
+ if (isNumber(bid.w) && isNumber(bid.h)) {
335
+ return {
336
+ width: bid.w,
337
+ height: bid.h
338
+ };
339
+ }
340
+ return {
341
+ width: null,
342
+ height: null
343
+ };
344
+ }
345
+
346
+ function getCreativeFromBid(bid) {
347
+ const shouldUseAdMarkup = !!bid.adm;
348
+ const price = bid.price;
349
+ return {
350
+ markup: shouldUseAdMarkup ? replaceAuctionPrice(bid.adm, price) : null,
351
+ markupUrl: !shouldUseAdMarkup ? replaceAuctionPrice(bid.nurl, price) : null
352
+ };
353
+ }
354
+
355
+ function hasDeviceInfo(bid) {
356
+ if (bid.params) {
357
+ return !!bid.params.device
358
+ }
359
+ }
360
+
361
+ function hasAppInfo(bid) {
362
+ if (bid.params) {
363
+ return !!bid.params.app
364
+ }
365
+ }
366
+
367
+ const venavenBidderSpec = {
368
+ code: 'ventes',
369
+ supportedMediaTypes: [BANNER],
370
+ isBidRequestValid(adUnit) {
371
+ const allowedBidderCodes = [this.code];
372
+
373
+ return isPlainObject(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);
380
+ },
381
+ buildRequests(bidRequests, bidderRequest) {
382
+ if (!bidRequests) return null;
383
+
384
+ return groupBy(bidRequests, 'bidderRequestId').map(group => {
385
+ const bidRequestId = group.id;
386
+ const adUnits = groupBy(group.values, 'bidId').map((group) => {
387
+ const length = group.values.length;
388
+ return length > 0 && group.values[length - 1]
389
+ });
390
+
391
+ return createServerRequestFromAdUnits(adUnits, bidRequestId, bidderRequest)
392
+ });
393
+ },
394
+ interpretResponse(serverResponse, serverRequest) {
395
+ if (!validateServerRequest(serverRequest)) return [];
396
+ if (!validateServerResponse(serverResponse)) return [];
397
+
398
+ const bidResponse = serverResponse.body;
399
+
400
+ return bidResponse.seatbid
401
+ .filter(seatBid => isPlainObject(seatBid) && isArray(seatBid.bid))
402
+ .reduce((acc, seatBid) => acc.concat(seatBidsToAds(seatBid, bidResponse, serverRequest)), []);
403
+ }
404
+ };
405
+
406
+ registerBidder(venavenBidderSpec);
407
+
408
+ export {
409
+ venavenBidderSpec as spec
410
+ };
@@ -0,0 +1,93 @@
1
+ ---
2
+ layout: bidder
3
+ title: ventes
4
+ description: Prebid ventes Bidder Adapter
5
+ pbjs: false
6
+ biddercode: ventes
7
+ gdpr_supported: false
8
+ usp_supported: false
9
+ media_types: banner
10
+ coppa_supported: false
11
+ schain_supported: false
12
+ dchain_supported: false
13
+ prebid_member: false
14
+ ---
15
+
16
+ ### BidParams
17
+ {: .table .table-bordered .table-striped }
18
+ | Name | Scope | Description | Example | Type |
19
+ |-----------------|----------|-----------------------------------------------------------|----------------------------------------------|---------------|
20
+ | `placementId` | required | Placement ID from Ventes Avenues | `'VA-062-0013-0183'` | `string` |
21
+ | `publisherId` | required | Publisher ID from Ventes Avenues | `'VA-062'` | `string` |
22
+ | `user` | optional | Object that specifies information about an external user. | `user: { age: 25, gender: 0, dnt: true}` | `object` |
23
+ | `app` | required | Object containing mobile app parameters. | `app : { id: 'app-id'}` | `object` |
24
+ | `device` | required | Object containing device info mandatory for mobile devices| `device : { ifa: 'device-id'}` | `object` |
25
+
26
+ #### User Object
27
+
28
+ {: .table .table-bordered .table-striped }
29
+ | Name | Description | Example | Type |
30
+ |-------------------|-------------------------------------------------------------------------------------------|-----------------------|-----------------------|
31
+ | `age` | The age of the user. | `35` | `integer` |
32
+ | `externalUid` | Specifies a string that corresponds to an external user ID for this user. | `'1234567890abcdefg'` | `string` |
33
+ | `segments` | Specifies the segments to which the user belongs. | `[1, 2]` | `Array<integer>` |
34
+ | `gender` | Specifies the gender of the user. Allowed values: Unknown: `0`; Male: `1`; Female: `2` | `1` | `integer` |
35
+ | `dnt` | Do not track flag. Indicates if tracking cookies should be disabled for this auction | `true` | `boolean` |
36
+ | `language` | Two-letter ANSI code for this user's language. | `EN` | `string` |
37
+
38
+
39
+ ### Ad Unit Setup for Banner through mobile devices
40
+ ```javascript
41
+ var adUnits = [
42
+ {
43
+ code: 'test-hb-ad-11111-1',
44
+ mediaTypes: {
45
+ banner: {
46
+ sizes: [
47
+ [300, 250]
48
+ ]
49
+ }
50
+ },
51
+ bids: [{
52
+ bidder: 'ventes',
53
+ params: {
54
+ placementId: 'VA-062-0013-0183',
55
+ publisherId: '5cebea3c9eea646c7b623d5e',
56
+ IABCategories: "['IAB1', 'IAB5']",
57
+ device:{
58
+ ifa:"AEBE52E7-03EE-455A-B3C4-E57283966239",
59
+ },
60
+ app: {
61
+ id: "agltb3B1Yi1pbmNyDAsSA0FwcBiJkfIUDA",
62
+ name: "Yahoo Weather",
63
+ bundle: 'com.kiloo.subwaysurf',
64
+ storeurl: 'https://play.google.com/store/apps/details?id=com.kiloo.subwaysurf&hl=en',
65
+ domain: 'somoaudience.com',
66
+ }
67
+ }
68
+ }]
69
+ }
70
+ ]
71
+ ```
72
+
73
+ ### Ad Unit Setup for Banner through Websites
74
+ ```javascript
75
+ var adUnits = [
76
+ {
77
+ code: 'test-hb-ad-11111-1',
78
+ mediaTypes: {
79
+ banner: {
80
+ sizes: [
81
+ [300, 250]
82
+ ]
83
+ }
84
+ },
85
+ bids: [{
86
+ bidder: 'ventes',
87
+ params: {
88
+ placementId: 'VA-002-0007-0799',
89
+ publisherId: '5cebea3c9eea646c7b623d5e',
90
+ }
91
+ }]
92
+ }
93
+ ]
@@ -9,7 +9,17 @@ const ENDPOINT = `https://d.vidoomy.com/api/rtbserver/prebid/`;
9
9
  const BIDDER_CODE = 'vidoomy';
10
10
  const GVLID = 380;
11
11
 
12
- const COOKIE_SYNC_JSON = 'https://vpaid.vidoomy.com/sync/urls.json';
12
+ const COOKIE_SYNC_FALLBACK_URLS = [
13
+ 'https://x.bidswitch.net/sync?ssp=vidoomy',
14
+ 'https://ib.adnxs.com/getuid?https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dadnxs%26gdpr%3D{{GDPR}}%26gdpr_consent%3D{{GDPR_CONSENT}}%26uid%3D%24UID',
15
+ 'https://pixel-sync.sitescout.com/dmp/pixelSync?nid=120&redir=https%3A%2F%2Fa.vidoomy.com%2Fapi%2Frtbserver%2Fcookie%3Fi%3DCEN%26uid%3D%7BuserId%7D',
16
+ 'https://sync.1rx.io/usersync2/vidoomy?redir=https%3A%2F%2Fa.vidoomy.com%2Fapi%2Frtbserver%2Fcookie%3Fi%3DUN%26uid%3D%5BRX_UUID%5D',
17
+ 'https://rtb.openx.net/sync/prebid?gdpr={{GDPR}}&gdpr_consent={{GDPR_CONSENT}}&r=https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dopenx%26uid%3D$%7BUID%7D',
18
+ 'https://ads.pubmatic.com/AdServer/js/user_sync.html?gdpr={{GDPR}}&gdpr_consent={{GDPR_CONSENT}}&us_privacy=&predirect=https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dpubmatic%26gdpr%3D{{GDPR}}%26gdpr_consent%3D{{GDPR_CONSENT}}%26uid%3D',
19
+ 'https://cm.adform.net/cookie?redirect_url=https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dadf%26gdpr%3D{{GDPR}}%26gdpr_consent%3D{{GDPR_CONSENT}}%26uid%3D%24UID',
20
+ 'https://ups.analytics.yahoo.com/ups/58531/occ?gdpr={{GDPR}}&gdpr_consent={{GDPR_CONSENT}}',
21
+ 'https://ap.lijit.com/pixel?redir=https%3A%2F%2Fa-prebid.vidoomy.com%2Fsetuid%3Fbidder%3Dsovrn%26gdpr%3D{{GDPR}}%26gdpr_consent%3D{{GDPR_CONSENT}}%26uid%3D%24UID'
22
+ ];
13
23
 
14
24
  const isBidRequestValid = bid => {
15
25
  if (!bid.params) {
@@ -36,7 +46,7 @@ const isBidRequestValid = bid => {
36
46
  };
37
47
 
38
48
  const isBidResponseValid = bid => {
39
- if (!bid.requestId || !bid.cpm || !bid.ttl || !bid.currency) {
49
+ if (!bid || !bid.requestId || !bid.cpm || !bid.ttl || !bid.currency) {
40
50
  return false;
41
51
  }
42
52
  switch (bid.mediaType) {
@@ -67,35 +77,33 @@ const buildRequests = (validBidRequests, bidderRequest) => {
67
77
 
68
78
  const videoContext = deepAccess(bid, 'mediaTypes.video.context');
69
79
 
70
- const queryParams = [];
71
- queryParams.push(['id', bid.params.id]);
72
- queryParams.push(['adtype', adType]);
73
- queryParams.push(['w', w]);
74
- queryParams.push(['h', h]);
75
- queryParams.push(['pos', parseInt(bid.params.position) || 1]);
76
- queryParams.push(['ua', navigator.userAgent]);
77
- queryParams.push(['l', navigator.language && navigator.language.indexOf('-') !== -1 ? navigator.language.split('-')[0] : '']);
78
- queryParams.push(['dt', /Mobi/.test(navigator.userAgent) ? 2 : 1]);
79
- queryParams.push(['pid', bid.params.pid]);
80
- queryParams.push(['requestId', bid.bidId]);
81
- queryParams.push(['d', getDomainWithoutSubdomain(hostname)]);
82
- queryParams.push(['sp', encodeURIComponent(aElement.href)]);
80
+ const queryParams = {
81
+ id: bid.params.id,
82
+ adtype: adType,
83
+ w,
84
+ h,
85
+ pos: parseInt(bid.params.position) || 1,
86
+ ua: navigator.userAgent,
87
+ l: navigator.language && navigator.language.indexOf('-') !== -1 ? navigator.language.split('-')[0] : '',
88
+ dt: /Mobi/.test(navigator.userAgent) ? 2 : 1,
89
+ pid: bid.params.pid,
90
+ requestId: bid.bidId,
91
+ d: getDomainWithoutSubdomain(hostname),
92
+ sp: encodeURIComponent(aElement.href),
93
+ usp: bidderRequest.uspConsent || '',
94
+ coppa: !!config.getConfig('coppa'),
95
+ videoContext: videoContext || ''
96
+ };
97
+
83
98
  if (bidderRequest.gdprConsent) {
84
- queryParams.push(['gdpr', bidderRequest.gdprConsent.gdprApplies]);
85
- queryParams.push(['gdprcs', bidderRequest.gdprConsent.consentString]);
99
+ queryParams.gdpr = bidderRequest.gdprConsent.gdprApplies;
100
+ queryParams.gdprcs = bidderRequest.gdprConsent.consentString;
86
101
  }
87
- queryParams.push(['usp', bidderRequest.uspConsent || '']);
88
- queryParams.push(['coppa', !!config.getConfig('coppa')]);
89
-
90
- const rawQueryParams = queryParams.map(qp => qp.join('=')).join('&');
91
102
 
92
- cookieSync(bidderRequest)
93
-
94
- const url = `${ENDPOINT}?${rawQueryParams}`;
95
103
  return {
96
104
  method: 'GET',
97
- url: url,
98
- data: {videoContext}
105
+ url: ENDPOINT,
106
+ data: queryParams
99
107
  }
100
108
  });
101
109
  return serverRequests;
@@ -117,6 +125,7 @@ const render = (bid) => {
117
125
  const interpretResponse = (serverResponse, bidRequest) => {
118
126
  try {
119
127
  let responseBody = serverResponse.body;
128
+ if (!responseBody) return;
120
129
  if (responseBody.mediaType === 'video') {
121
130
  responseBody.ad = responseBody.vastUrl;
122
131
  const videoContext = bidRequest.data.videoContext;
@@ -185,6 +194,21 @@ const interpretResponse = (serverResponse, bidRequest) => {
185
194
  }
186
195
  };
187
196
 
197
+ function getUserSyncs (syncOptions, responses, gdprConsent, uspConsent) {
198
+ if (syncOptions.iframeEnabled || syncOptions.pixelEnabled) {
199
+ const pixelType = syncOptions.pixelEnabled ? 'image' : 'iframe';
200
+ const urls = deepAccess(responses, '0.body.pixels') || COOKIE_SYNC_FALLBACK_URLS;
201
+
202
+ return [].concat(urls).map(url => ({
203
+ type: pixelType,
204
+ url: url
205
+ .replace('{{GDPR}}', gdprConsent ? gdprConsent.gdprApplies : '0')
206
+ .replace('{{GDPR_CONSENT}}', gdprConsent ? encodeURIComponent(gdprConsent.consentString) : '')
207
+ .replace('{{USP_CONSENT}}', uspConsent ? encodeURIComponent(uspConsent) : '')
208
+ }));
209
+ }
210
+ };
211
+
188
212
  export const spec = {
189
213
  code: BIDDER_CODE,
190
214
  supportedMediaTypes: [BANNER, VIDEO],
@@ -192,84 +216,11 @@ export const spec = {
192
216
  buildRequests,
193
217
  interpretResponse,
194
218
  gvlid: GVLID,
219
+ getUserSyncs,
195
220
  };
196
221
 
197
222
  registerBidder(spec);
198
223
 
199
- let cookieSynced = false;
200
- function cookieSync(bidderRequest) {
201
- if (cookieSynced) return;
202
- const xhr = new XMLHttpRequest();
203
- xhr.open('GET', COOKIE_SYNC_JSON)
204
- xhr.addEventListener('load', function () {
205
- const macro = Macro({
206
- gpdr: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.gdprApplies : '0',
207
- gpdr_consent: bidderRequest.gdprConsent ? bidderRequest.gdprConsent.consentString : '',
208
- });
209
- JSON.parse(this.responseText).filter(Boolean).forEach(url => {
210
- firePixel(macro.replace(url))
211
- })
212
- })
213
- xhr.send()
214
- cookieSynced = true;
215
- }
216
-
217
- function firePixel(url) {
218
- const img = document.createElement('img');
219
- img.width = 1;
220
- img.height = 1;
221
- img.src = url;
222
- document.body.appendChild(img);
223
- setTimeout(() => {
224
- img.remove();
225
- }, 10000)
226
- }
227
-
228
- function normalizeKey (x) {
229
- return x.replace(/_/g, '').toLowerCase();
230
- }
231
-
232
- function Macro (obj) {
233
- const macros = {};
234
- for (const key in obj) {
235
- macros[normalizeKey(key)] = obj[key];
236
- }
237
-
238
- const set = (key, value) => {
239
- macros[normalizeKey(key)] = typeof value === 'function' ? value : String(value);
240
- };
241
-
242
- return {
243
- set,
244
- setAll (obj) {
245
- for (const key in obj) {
246
- macros[normalizeKey(key)] = set(obj[key]);
247
- }
248
- },
249
- replace (string, extraMacros = {}) {
250
- const allMacros = {
251
- ...macros,
252
- ...extraMacros,
253
- };
254
- const regexes = [
255
- /{{\s*([a-zA-Z0-9_]+)\s*}}/g,
256
- /\$\$\s*([a-zA-Z0-9_]+)\s*\$\$/g,
257
- /\[\s*([a-zA-Z0-9_]+)\s*\]/g,
258
- /\{\s*([a-zA-Z0-9_]+)\s*\}/g,
259
- ];
260
- regexes.forEach(regex => {
261
- string = string.replace(regex, (str, x) => {
262
- x = normalizeKey(x);
263
- let value = allMacros[x];
264
- value = typeof value === 'function' ? value(allMacros) : value;
265
- return !value && value !== 0 ? '' : value;
266
- });
267
- });
268
- return string;
269
- },
270
- };
271
- }
272
-
273
224
  function getDomainWithoutSubdomain (hostname) {
274
225
  const parts = hostname.split('.');
275
226
  const newParts = [];