prebid.js 5.19.0 → 5.20.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 (53) hide show
  1. package/modules/airgridRtdProvider.js +1 -1
  2. package/modules/appnexusBidAdapter.js +5 -3
  3. package/modules/atsAnalyticsAdapter.js +67 -46
  4. package/modules/atsAnalyticsAdapter.md +1 -0
  5. package/modules/betweenBidAdapter.js +2 -1
  6. package/modules/browsiRtdProvider.js +106 -18
  7. package/modules/cleanioRtdProvider.js +192 -0
  8. package/modules/cleanioRtdProvider.md +59 -0
  9. package/modules/deltaprojectsBidAdapter.js +252 -0
  10. package/modules/deltaprojectsBidAdapter.md +32 -0
  11. package/modules/gridBidAdapter.js +1 -0
  12. package/modules/ixBidAdapter.js +7 -1
  13. package/modules/jixieBidAdapter.js +8 -2
  14. package/modules/justpremiumBidAdapter.js +6 -1
  15. package/modules/livewrappedAnalyticsAdapter.js +5 -0
  16. package/modules/multibid/index.js +3 -3
  17. package/modules/nativoBidAdapter.js +5 -1
  18. package/modules/openxBidAdapter.js +1 -1
  19. package/modules/operaadsBidAdapter.js +21 -1
  20. package/modules/otmBidAdapter.js +146 -0
  21. package/modules/otmBidAdapter.md +27 -26
  22. package/modules/outbrainBidAdapter.js +5 -0
  23. package/modules/playwireBidAdapter.md +61 -0
  24. package/modules/rtdModule/index.js +2 -2
  25. package/modules/sonobiBidAdapter.js +7 -0
  26. package/modules/sortableBidAdapter.js +1 -0
  27. package/modules/teadsBidAdapter.js +3 -0
  28. package/modules/trustxBidAdapter.js +8 -6
  29. package/modules/ventesBidAdapter.js +370 -0
  30. package/modules/ventesBidAdapter.md +94 -0
  31. package/modules/yahoosspBidAdapter.js +6 -6
  32. package/package.json +1 -1
  33. package/src/auction.js +11 -11
  34. package/test/spec/modules/appnexusBidAdapter_spec.js +2 -1
  35. package/test/spec/modules/atsAnalyticsAdapter_spec.js +42 -9
  36. package/test/spec/modules/browsiRtdProvider_spec.js +62 -7
  37. package/test/spec/modules/cleanioRtdProvider_spec.js +188 -0
  38. package/test/spec/modules/deltaprojectsBidAdapter_spec.js +399 -0
  39. package/test/spec/modules/ixBidAdapter_spec.js +3 -3
  40. package/test/spec/modules/jixieBidAdapter_spec.js +13 -11
  41. package/test/spec/modules/justpremiumBidAdapter_spec.js +9 -2
  42. package/test/spec/modules/livewrappedAnalyticsAdapter_spec.js +23 -4
  43. package/test/spec/modules/multibid_spec.js +31 -31
  44. package/test/spec/modules/openxBidAdapter_spec.js +0 -26
  45. package/test/spec/modules/operaadsBidAdapter_spec.js +38 -6
  46. package/test/spec/modules/otmBidAdapter_spec.js +67 -0
  47. package/test/spec/modules/outbrainBidAdapter_spec.js +18 -0
  48. package/test/spec/modules/sonobiBidAdapter_spec.js +34 -1
  49. package/test/spec/modules/sortableBidAdapter_spec.js +11 -0
  50. package/test/spec/modules/teadsBidAdapter_spec.js +132 -0
  51. package/test/spec/modules/trustxBidAdapter_spec.js +3 -3
  52. package/test/spec/modules/ventesBidAdapter_spec.js +845 -0
  53. package/test/spec/unit/core/adapterManager_spec.js +2 -1
@@ -1,36 +1,37 @@
1
1
  # Overview
2
2
 
3
- Module Name: OTM Bidder Adapter
4
- Module Type: Bidder Adapter
5
- Maintainer: ?
3
+ **Module Name**: OTM Bidder Adapter
4
+ **Module Type**: Bidder Adapter
5
+ **Maintainer**: e.kretsu@otm-r.com
6
6
 
7
7
  # Description
8
8
 
9
- You can use this adapter to get a bid from otm-r.com.
9
+ OTM Bidder Adapter for Prebid.js. About: https://otm-r.com
10
10
 
11
- About us : http://otm-r.com
11
+ Use `otm` as bidder:
12
12
 
13
+ # Params
14
+ - `tid` required, specific id AdUnit slot.
15
+ - `domain` optional, specific custom domain.
16
+ - `bidfloor` optional.
13
17
 
14
- # Test Parameters
15
- ```javascript
16
- var adUnits = [
17
- {
18
- code: 'div-otm-example',
19
- sizes: [[320, 480]],
20
- bids: [
21
- {
22
- bidder: "otm",
23
- params: {
24
- tid: "99",
25
- bidfloor: 20
26
- }
27
- }
28
- ]
29
- }
30
- ];
18
+ ## AdUnits configuration example
31
19
  ```
20
+ var adUnits = [{
21
+ code: 'your-slot', //use exactly the same code as your slot div id.
22
+ mediaTypes: {
23
+ banner: {
24
+ sizes: [[320, 480]]
25
+ }
26
+ },
27
+ bids: [{
28
+ bidder: 'otm',
29
+ params: {
30
+ tid: 'XXXXX',
31
+ domain: 'specific custom domain, if needed',
32
+ bidfloor: 20
33
+ }
34
+ }]
35
+ }];
32
36
 
33
- Where:
34
-
35
- * tid - A tag id (should have low cardinality)
36
- * bidfloor - Floor price
37
+ ```
@@ -40,6 +40,7 @@ export const spec = {
40
40
  const publisher = setOnAny(validBidRequests, 'params.publisher');
41
41
  const bcat = setOnAny(validBidRequests, 'params.bcat');
42
42
  const badv = setOnAny(validBidRequests, 'params.badv');
43
+ const eids = setOnAny(validBidRequests, 'userIdAsEids')
43
44
  const cur = CURRENCY;
44
45
  const endpointUrl = config.getConfig('outbrain.bidderUrl');
45
46
  const timeout = bidderRequest.timeout;
@@ -105,6 +106,10 @@ export const spec = {
105
106
  deepSetValue(request, 'regs.coppa', config.getConfig('coppa') & 1)
106
107
  }
107
108
 
109
+ if (eids) {
110
+ deepSetValue(request, 'user.ext.eids', eids);
111
+ }
112
+
108
113
  return {
109
114
  method: 'POST',
110
115
  url: endpointUrl,
@@ -0,0 +1,61 @@
1
+ # Overview
2
+
3
+ Module Name: Playwire Bidder Adapter
4
+ Module Type: Bidder Adapter
5
+ Maintainer: grid-tech@themediagrid.com
6
+
7
+ # Description
8
+
9
+ Module that connects to Grid demand source to fetch bids.
10
+ The adapter is GDPR compliant and supports banner and video (instream and outstream).
11
+
12
+ # Test Parameters
13
+ ```
14
+ var adUnits = [
15
+ {
16
+ code: 'test-div',
17
+ sizes: [[300, 250]],
18
+ bids: [
19
+ {
20
+ bidder: "playwire",
21
+ params: {
22
+ uid: '1',
23
+ bidFloor: 0.5
24
+ }
25
+ }
26
+ ]
27
+ },{
28
+ code: 'test-div',
29
+ sizes: [[728, 90]],
30
+ bids: [
31
+ {
32
+ bidder: "playwire",
33
+ params: {
34
+ uid: 2,
35
+ keywords: {
36
+ brandsafety: ['disaster'],
37
+ topic: ['stress', 'fear']
38
+ }
39
+ }
40
+ }
41
+ ]
42
+ },
43
+ {
44
+ code: 'test-div',
45
+ sizes: [[728, 90]],
46
+ mediaTypes: { video: {
47
+ context: 'instream',
48
+ playerSize: [728, 90],
49
+ mimes: ['video/mp4']
50
+ },
51
+ bids: [
52
+ {
53
+ bidder: "playwire",
54
+ params: {
55
+ uid: 11
56
+ }
57
+ }
58
+ ]
59
+ }
60
+ ];
61
+ ```
@@ -42,10 +42,10 @@
42
42
  * @function?
43
43
  * @summary modify bid request data
44
44
  * @name RtdSubmodule#getBidRequestData
45
- * @param {SubmoduleConfig} config
46
- * @param {UserConsentData} userConsent
47
45
  * @param {Object} reqBidsConfigObj
48
46
  * @param {function} callback
47
+ * @param {SubmoduleConfig} config
48
+ * @param {UserConsentData} userConsent
49
49
  */
50
50
 
51
51
  /**
@@ -83,8 +83,15 @@ export const spec = {
83
83
  'lib_name': 'prebid',
84
84
  'lib_v': '$prebid.version$',
85
85
  'us': 0,
86
+
86
87
  };
87
88
 
89
+ const fpd = config.getConfig('ortb2');
90
+
91
+ if (fpd) {
92
+ payload.fpd = JSON.stringify(fpd);
93
+ }
94
+
88
95
  if (config.getConfig('userSync') && config.getConfig('userSync').syncsPerBidder) {
89
96
  payload.us = config.getConfig('userSync').syncsPerBidder;
90
97
  }
@@ -227,6 +227,7 @@ export const spec = {
227
227
  rv.ext[partner] = params;
228
228
  });
229
229
  }
230
+ rv.ext.gpid = deepAccess(bid, 'ortb2Imp.ext.data.pbadslot');
230
231
  return rv;
231
232
  });
232
233
  const gdprConsent = bidderRequest && bidderRequest.gdprConsent;
@@ -190,6 +190,8 @@ function buildRequestObject(bid) {
190
190
  const reqObj = {};
191
191
  let placementId = getValue(bid.params, 'placementId');
192
192
  let pageId = getValue(bid.params, 'pageId');
193
+ const impressionData = deepAccess(bid, 'ortb2Imp.ext.data');
194
+ const gpid = deepAccess(impressionData, 'pbadslot') || deepAccess(impressionData, 'adserver.adslot');
193
195
 
194
196
  reqObj.sizes = getSizes(bid);
195
197
  reqObj.bidId = getBidIdParameter('bidId', bid);
@@ -199,6 +201,7 @@ function buildRequestObject(bid) {
199
201
  reqObj.adUnitCode = getBidIdParameter('adUnitCode', bid);
200
202
  reqObj.auctionId = getBidIdParameter('auctionId', bid);
201
203
  reqObj.transactionId = getBidIdParameter('transactionId', bid);
204
+ if (gpid) { reqObj.gpid = gpid; }
202
205
  return reqObj;
203
206
  }
204
207
 
@@ -429,9 +429,10 @@ function addSegments(name, segName, segments, data, bidConfigName) {
429
429
  if (segments && segments.length) {
430
430
  data.push({
431
431
  name: name,
432
- segment: segments.map((seg) => {
433
- return {name: segName, value: seg};
434
- })
432
+ segment: segments
433
+ .map((seg) => seg && (seg.id || seg))
434
+ .filter((seg) => seg && (typeof seg === 'string' || typeof seg === 'number'))
435
+ .map((seg) => ({ name: segName, value: seg.toString() }))
435
436
  });
436
437
  } else if (bidConfigName) {
437
438
  const configData = config.getConfig('ortb2.user.data');
@@ -445,9 +446,10 @@ function addSegments(name, segName, segments, data, bidConfigName) {
445
446
  if (segData && segData.length) {
446
447
  data.push({
447
448
  name: name,
448
- segment: segData.map((seg) => {
449
- return {name: segName, value: seg};
450
- })
449
+ segment: segData
450
+ .map((seg) => seg && (seg.id || seg))
451
+ .filter((seg) => seg && (typeof seg === 'string' || typeof seg === 'number'))
452
+ .map((seg) => ({ name: segName, value: seg.toString() }))
451
453
  });
452
454
  }
453
455
  }
@@ -0,0 +1,370 @@
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';
4
+ import find from 'core-js-pure/features/array/find.js';
5
+ import includes from 'core-js-pure/features/array/includes.js';
6
+
7
+ const BID_METHOD = 'POST';
8
+ 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
15
+ const DOMAIN_REGEX = new RegExp('//([^/]*)');
16
+
17
+ function groupBy(values, key) {
18
+ const groups = values.reduce((acc, value) => {
19
+ const groupId = value[key];
20
+
21
+ if (!acc[groupId]) acc[groupId] = [];
22
+ acc[groupId].push(value);
23
+
24
+ return acc;
25
+ }, {});
26
+
27
+ return Object
28
+ .keys(groups)
29
+ .map(id => ({id, key, values: groups[id]}));
30
+ }
31
+
32
+ function validateMediaTypes(mediaTypes, allowedMediaTypes) {
33
+ if (!isPlainObject(mediaTypes)) return false;
34
+ if (!allowedMediaTypes.some(mediaType => mediaType in mediaTypes)) return false;
35
+
36
+ if (isBanner(mediaTypes)) {
37
+ if (!validateBanner(mediaTypes.banner)) return false;
38
+ }
39
+ return true;
40
+ }
41
+
42
+ function isBanner(mediaTypes) {
43
+ return isPlainObject(mediaTypes) && isPlainObject(mediaTypes.banner);
44
+ }
45
+
46
+ function validateBanner(banner) {
47
+ return isPlainObject(banner) &&
48
+ isArray(banner.sizes) &&
49
+ (banner.sizes.length > 0) &&
50
+ banner.sizes.every(validateMediaSizes);
51
+ }
52
+
53
+ function validateMediaSizes(mediaSize) {
54
+ return isArray(mediaSize) &&
55
+ (mediaSize.length === 2) &&
56
+ mediaSize.every(size => (isNumber(size) && size >= 0));
57
+ }
58
+
59
+ function hasUserInfo(bid) {
60
+ return !!bid.params.user;
61
+ }
62
+
63
+ function validateParameters(parameters, adUnit) {
64
+ if (!(parameters.placementId)) {
65
+ return false;
66
+ }
67
+ if (!(parameters.publisherId)) {
68
+ return false;
69
+ }
70
+
71
+ return true;
72
+ }
73
+
74
+ function extractSiteDomainFromURL(url) {
75
+ if (!url || !isStr(url)) return null;
76
+
77
+ const domain = url.match(DOMAIN_REGEX);
78
+
79
+ if (isArray(domain) && domain.length === 2) return domain[1];
80
+
81
+ return null;
82
+ }
83
+
84
+ function generateSiteFromAdUnitContext(bidRequests, adUnitContext) {
85
+ if (!adUnitContext || !adUnitContext.refererInfo) return null;
86
+
87
+ const domain = extractSiteDomainFromURL(adUnitContext.refererInfo.referer);
88
+ const publisherId = bidRequests[0].params.publisherId;
89
+
90
+ if (!domain) return null;
91
+
92
+ return {
93
+ page: adUnitContext.refererInfo.referer,
94
+ domain: domain,
95
+ name: domain,
96
+ publisher: {
97
+ id: publisherId
98
+ }
99
+ };
100
+ }
101
+
102
+ function validateServerRequest(serverRequest) {
103
+ return isPlainObject(serverRequest) &&
104
+ isPlainObject(serverRequest.data) &&
105
+ isArray(serverRequest.data.imp)
106
+ }
107
+
108
+ function createServerRequestFromAdUnits(adUnits, bidRequestId, adUnitContext) {
109
+ return {
110
+ method: BID_METHOD,
111
+ url: BIDDER_URL,
112
+ data: generateBidRequestsFromAdUnits(adUnits, bidRequestId, adUnitContext),
113
+ options: {
114
+ contentType: 'application/json',
115
+ withCredentials: false,
116
+ }
117
+ }
118
+ }
119
+
120
+ function generateBidRequestsFromAdUnits(bidRequests, bidRequestId, adUnitContext) {
121
+ const userObjBid = find(bidRequests, hasUserInfo);
122
+ let userObj = {};
123
+ if (userObjBid) {
124
+ Object.keys(userObjBid.params.user)
125
+ .filter(param => includes(USER_PARAMS, param))
126
+ .forEach((param) => {
127
+ let uparam = convertCamelToUnderscore(param);
128
+ if (param === 'segments' && isArray(userObjBid.params.user[param])) {
129
+ let segs = [];
130
+ userObjBid.params.user[param].forEach(val => {
131
+ if (isNumber(val)) {
132
+ segs.push({'id': val});
133
+ } else if (isPlainObject(val)) {
134
+ segs.push(val);
135
+ }
136
+ });
137
+ userObj[uparam] = segs;
138
+ } else if (param !== 'segments') {
139
+ userObj[uparam] = userObjBid.params.user[param];
140
+ }
141
+ });
142
+ }
143
+
144
+ const deviceObjBid = find(bidRequests, hasDeviceInfo);
145
+ let deviceObj;
146
+ if (deviceObjBid && deviceObjBid.params && deviceObjBid.params.device) {
147
+ deviceObj = {};
148
+ Object.keys(deviceObjBid.params.device)
149
+ .filter(param => includes(DEVICE_PARAMS, param))
150
+ .forEach(param => deviceObj[param] = deviceObjBid.params.device[param]);
151
+ if (!deviceObjBid.hasOwnProperty('ua')) {
152
+ deviceObj.ua = navigator.userAgent;
153
+ }
154
+ if (!deviceObjBid.hasOwnProperty('language')) {
155
+ deviceObj.language = navigator.language;
156
+ }
157
+ } else {
158
+ deviceObj = {};
159
+ deviceObj.ua = navigator.userAgent;
160
+ deviceObj.language = navigator.language;
161
+ }
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
+
170
+ const payload = {}
171
+ payload.id = bidRequestId
172
+ payload.at = FIRST_PRICE
173
+ payload.cur = ['USD']
174
+ payload.imp = bidRequests.reduce(generateImpressionsFromAdUnit, [])
175
+ payload.site = generateSiteFromAdUnitContext(bidRequests, adUnitContext)
176
+ payload.device = deviceObj
177
+ if (appDeviceObjBid && payload.site != null) {
178
+ payload.app = appIdObj;
179
+ }
180
+ payload.user = userObj
181
+ // payload.regs = getRegulationFromAdUnitContext(adUnitContext)
182
+ // payload.ext = generateBidRequestExtension()
183
+
184
+ return payload
185
+ }
186
+
187
+ function generateImpressionsFromAdUnit(acc, adUnit) {
188
+ const {bidId, mediaTypes, params} = adUnit;
189
+ const {placementId} = params;
190
+ const pmp = {};
191
+
192
+ if (placementId) pmp.deals = [{id: placementId}]
193
+
194
+ const imps = Object
195
+ .keys(mediaTypes)
196
+ .reduce((acc, mediaType) => {
197
+ const data = mediaTypes[mediaType];
198
+ const impId = `${bidId}`;
199
+
200
+ if (mediaType === 'banner') return acc.concat(generateBannerFromAdUnit(impId, data, params));
201
+ }, []);
202
+
203
+ return acc.concat(imps);
204
+ }
205
+
206
+ function generateBannerFromAdUnit(impId, data, params) {
207
+ const {position, placementId} = params;
208
+ const pos = position || 0;
209
+ const pmp = {};
210
+ const ext = {placementId};
211
+
212
+ if (placementId) pmp.deals = [{id: placementId}]
213
+
214
+ return data.sizes.map(([w, h]) => ({id: `${impId}`, banner: {format: [{w, h}], w, h, pos}, pmp, ext, tagid: placementId}));
215
+ }
216
+
217
+ function validateServerResponse(serverResponse) {
218
+ return isPlainObject(serverResponse) &&
219
+ isPlainObject(serverResponse.body) &&
220
+ isStr(serverResponse.body.cur) &&
221
+ isArray(serverResponse.body.seatbid);
222
+ }
223
+
224
+ function seatBidsToAds(seatBid, bidResponse, serverRequest) {
225
+ return seatBid.bid
226
+ .filter(bid => validateBids(bid))
227
+ .map(bid => generateAdFromBid(bid, bidResponse));
228
+ }
229
+
230
+ function validateBids(bid) {
231
+ if (!isPlainObject(bid)) return false;
232
+ if (!isStr(bid.impid)) return false;
233
+ if (!isStr(bid.crid)) return false;
234
+ if (!isNumber(bid.price)) return false;
235
+ if (!isNumber(bid.w)) return false;
236
+ if (!isNumber(bid.h)) return false;
237
+ if (!bid.adm) return false;
238
+ if (bid.adm) {
239
+ if (!isStr(bid.adm)) return false;
240
+ }
241
+ return true;
242
+ }
243
+
244
+ const VAST_REGEXP = /VAST\s+version/;
245
+
246
+ function getMediaType(adm) {
247
+ const videoRegex = new RegExp(VAST_REGEXP);
248
+
249
+ if (videoRegex.test(adm)) {
250
+ return VIDEO;
251
+ }
252
+
253
+ const markup = safeJSONparse(adm.replace(/\\/g, ''));
254
+
255
+ if (markup && isPlainObject(markup.native)) {
256
+ return NATIVE;
257
+ }
258
+
259
+ return BANNER;
260
+ }
261
+
262
+ function safeJSONparse(...args) {
263
+ try {
264
+ return JSON.parse(...args);
265
+ } catch (_) {
266
+ return undefined;
267
+ }
268
+ }
269
+
270
+ function generateAdFromBid(bid, bidResponse) {
271
+ const mediaType = getMediaType(bid.adm);
272
+ const base = {
273
+ requestId: bid.impid,
274
+ cpm: bid.price,
275
+ currency: bidResponse.cur,
276
+ ttl: TTL,
277
+ creativeId: bid.crid,
278
+ mediaType: mediaType,
279
+ netRevenue: NET_REVENUE
280
+ };
281
+
282
+ if (bid.adomain) {
283
+ base.meta = { advertiserDomains: bid.adomain };
284
+ }
285
+
286
+ const size = getSizeFromBid(bid);
287
+ const creative = getCreativeFromBid(bid);
288
+
289
+ return {
290
+ ...base,
291
+ height: size.height,
292
+ width: size.width,
293
+ ad: creative.markup,
294
+ adUrl: creative.markupUrl,
295
+ // vastXml: isVideo && !isStr(creative.markupUrl) ? creative.markup : null,
296
+ // vastUrl: isVideo && isStr(creative.markupUrl) ? creative.markupUrl : null,
297
+ renderer: creative.renderer
298
+ };
299
+ }
300
+
301
+ function getSizeFromBid(bid) {
302
+ if (isNumber(bid.w) && isNumber(bid.h)) {
303
+ return { width: bid.w, height: bid.h };
304
+ }
305
+ return { width: null, height: null };
306
+ }
307
+
308
+ function getCreativeFromBid(bid) {
309
+ const shouldUseAdMarkup = !!bid.adm;
310
+ const price = bid.price;
311
+ return {
312
+ markup: shouldUseAdMarkup ? replaceAuctionPrice(bid.adm, price) : null,
313
+ markupUrl: !shouldUseAdMarkup ? replaceAuctionPrice(bid.nurl, price) : null
314
+ };
315
+ }
316
+
317
+ function hasDeviceInfo(bid) {
318
+ if (bid.params) {
319
+ return !!bid.params.device
320
+ }
321
+ }
322
+
323
+ function hasAppInfo(bid) {
324
+ if (bid.params) {
325
+ return !!bid.params.app
326
+ }
327
+ }
328
+
329
+ const venavenBidderSpec = {
330
+ code: 'ventes',
331
+ supportedMediaTypes: [BANNER],
332
+ isBidRequestValid(adUnit) {
333
+ const allowedBidderCodes = [this.code];
334
+
335
+ 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);
342
+ },
343
+ buildRequests(bidRequests, bidderRequest) {
344
+ if (!bidRequests) return null;
345
+
346
+ return groupBy(bidRequests, 'bidderRequestId').map(group => {
347
+ const bidRequestId = group.id;
348
+ const adUnits = groupBy(group.values, 'bidId').map((group) => {
349
+ const length = group.values.length;
350
+ return length > 0 && group.values[length - 1]
351
+ });
352
+
353
+ return createServerRequestFromAdUnits(adUnits, bidRequestId, bidderRequest)
354
+ });
355
+ },
356
+ interpretResponse(serverResponse, serverRequest) {
357
+ if (!validateServerRequest(serverRequest)) return [];
358
+ if (!validateServerResponse(serverResponse)) return [];
359
+
360
+ const bidResponse = serverResponse.body;
361
+
362
+ return bidResponse.seatbid
363
+ .filter(seatBid => isPlainObject(seatBid) && isArray(seatBid.bid))
364
+ .reduce((acc, seatBid) => acc.concat(seatBidsToAds(seatBid, bidResponse, serverRequest)), []);
365
+ }
366
+ };
367
+
368
+ registerBidder(venavenBidderSpec);
369
+
370
+ export {venavenBidderSpec as spec};
@@ -0,0 +1,94 @@
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
+ ip: '123.145.167.189',
59
+ ifa:"AEBE52E7-03EE-455A-B3C4-E57283966239",
60
+ },
61
+ app: {
62
+ id: "agltb3B1Yi1pbmNyDAsSA0FwcBiJkfIUDA",
63
+ name: "Yahoo Weather",
64
+ bundle: 'com.kiloo.subwaysurf',
65
+ storeurl: 'https://play.google.com/store/apps/details?id=com.kiloo.subwaysurf&hl=en',
66
+ domain: 'somoaudience.com',
67
+ }
68
+ }
69
+ }]
70
+ }
71
+ ]
72
+ ```
73
+
74
+ ### Ad Unit Setup for Banner through Websites
75
+ ```javascript
76
+ var adUnits = [
77
+ {
78
+ code: 'test-hb-ad-11111-1',
79
+ mediaTypes: {
80
+ banner: {
81
+ sizes: [
82
+ [300, 250]
83
+ ]
84
+ }
85
+ },
86
+ bids: [{
87
+ bidder: 'ventes',
88
+ params: {
89
+ placementId: 'VA-002-0007-0799',
90
+ publisherId: '5cebea3c9eea646c7b623d5e',
91
+ }
92
+ }]
93
+ }
94
+ ]