prebid.js 6.6.0 → 6.7.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 (36) hide show
  1. package/integrationExamples/gpt/amp/creative.html +11 -33
  2. package/modules/adbookpspBidAdapter.js +27 -10
  3. package/modules/adhashBidAdapter.js +3 -3
  4. package/modules/colossussspBidAdapter.js +12 -8
  5. package/modules/colossussspBidAdapter.md +15 -1
  6. package/modules/compassBidAdapter.js +1 -1
  7. package/modules/consumableBidAdapter.md +1 -1
  8. package/modules/gnetBidAdapter.js +3 -3
  9. package/modules/gnetBidAdapter.md +4 -4
  10. package/modules/gumgumBidAdapter.js +4 -4
  11. package/modules/jwplayerRtdProvider.js +71 -6
  12. package/modules/jwplayerRtdProvider.md +27 -11
  13. package/modules/kargoBidAdapter.js +2 -2
  14. package/modules/pilotxBidAdapter.js +147 -0
  15. package/modules/pilotxBidAdapter.md +50 -0
  16. package/modules/rtdModule/index.js +8 -10
  17. package/modules/rubiconAnalyticsAdapter.js +3 -2
  18. package/modules/seedingAllianceBidAdapter.js +3 -3
  19. package/modules/sharethroughBidAdapter.js +12 -17
  20. package/modules/synacormediaBidAdapter.js +31 -10
  21. package/modules/viewability.js +177 -0
  22. package/modules/viewability.md +87 -0
  23. package/package.json +1 -1
  24. package/src/secureCreatives.js +3 -2
  25. package/test/spec/modules/adbookpspBidAdapter_spec.js +17 -3
  26. package/test/spec/modules/adhashBidAdapter_spec.js +2 -2
  27. package/test/spec/modules/colossussspBidAdapter_spec.js +5 -2
  28. package/test/spec/modules/gnetBidAdapter_spec.js +6 -6
  29. package/test/spec/modules/jwplayerRtdProvider_spec.js +195 -2
  30. package/test/spec/modules/kargoBidAdapter_spec.js +1 -1
  31. package/test/spec/modules/pilotxBidAdapter_spec.js +244 -0
  32. package/test/spec/modules/realTimeDataModule_spec.js +51 -2
  33. package/test/spec/modules/rubiconAnalyticsAdapter_spec.js +30 -0
  34. package/test/spec/modules/sharethroughBidAdapter_spec.js +91 -6
  35. package/test/spec/modules/synacormediaBidAdapter_spec.js +70 -0
  36. package/test/spec/modules/viewability_spec.js +280 -0
@@ -1,38 +1,16 @@
1
1
  <!-- This script tag should be returned by your ad server -->
2
2
 
3
+ <script src="https://cdn.jsdelivr.net/npm/prebid-universal-creative@latest/dist/creative.js"></script>
3
4
  <script>
4
- // This is the `renderAd` function from Prebid.js moved within the creative iframe
5
- var renderAd = function (ev) {
6
- var key = ev.message ? "message" : "data";
7
- var data = {};
8
- try {
9
- data = JSON.parse(ev[key]);
10
- } catch (e) {
11
- // Do nothing. No ad found.
12
- }
13
- if (data.ad || data.adUrl) {
14
- if (data.ad) {
15
- document.write(data.ad);
16
- document.close();
17
- } else if (data.adUrl) {
18
- document.write('<IFRAME SRC="' + data.adUrl + '" WIDTH="'+ data.width +'" HEIGHT="'+ data.height +'" FRAMEBORDER="0" SCROLLING="no" MARGINHEIGHT="0" MARGINWIDTH="0" TOPMARGIN="0" LEFTMARGIN="0" ALLOWTRANSPARENCY="true"></IFRAME>');
19
- document.close();
20
- }
21
- }
22
- };
5
+ var ucTagData = {};
6
+ ucTagData.adServerDomain = "";
7
+ ucTagData.pubUrl = "%%PATTERN:url%%";
8
+ ucTagData.targetingMap = "%%PATTERN:TARGETINGMAP%%";
9
+ ucTagData.hbPb = "%%PATTERN:hb_pb%%";
23
10
 
24
- var requestAdFromPrebid = function () {
25
- var message = JSON.stringify({
26
- message: 'Prebid creative requested: %%PATTERN:hb_adid%%',
27
- adId: '%%PATTERN:hb_adid%%'
28
- });
29
- window.parent.postMessage(message, '*');
30
- };
31
-
32
- var listenAdFromPrebid = function () {
33
- window.addEventListener("message", renderAd, false);
34
- };
35
-
36
- listenAdFromPrebid();
37
- requestAdFromPrebid();
11
+ try {
12
+ ucTag.renderAd(document, ucTagData);
13
+ } catch (e) {
14
+ console.log(e);
15
+ }
38
16
  </script>
@@ -363,7 +363,7 @@ function impBidsToPrebidBids(
363
363
  }
364
364
 
365
365
  const impToPrebidBid =
366
- (bidderRequestBody, bidResponseCurrency, referrer, targetingMap) => (bid) => {
366
+ (bidderRequestBody, bidResponseCurrency, referrer, targetingMap) => (bid, bidIndex) => {
367
367
  try {
368
368
  const bidRequest = findBidRequest(bidderRequestBody, bid);
369
369
 
@@ -377,7 +377,7 @@ const impToPrebidBid =
377
377
  let prebidBid = {
378
378
  ad: bid.adm,
379
379
  adId: bid.adid,
380
- adserverTargeting: targetingMap[bid.impid],
380
+ adserverTargeting: targetingMap[bidIndex],
381
381
  adUnitCode: bidRequest.tagid,
382
382
  bidderRequestId: bidderRequestBody.id,
383
383
  bidId: bid.id,
@@ -408,6 +408,9 @@ const impToPrebidBid =
408
408
  };
409
409
  }
410
410
 
411
+ if (deepAccess(bid, 'ext.pa_win') === true) {
412
+ prebidBid.auctionWinner = true;
413
+ }
411
414
  return prebidBid;
412
415
  } catch (error) {
413
416
  logError(`${BIDDER_CODE}: Error while building bid`, error);
@@ -429,29 +432,43 @@ function buildTargetingMap(bids) {
429
432
  const values = impIds.reduce((result, id) => {
430
433
  result[id] = {
431
434
  lineItemIds: [],
435
+ orderIds: [],
432
436
  dealIds: [],
433
437
  adIds: [],
438
+ adAndOrderIndexes: []
434
439
  };
435
440
 
436
441
  return result;
437
442
  }, {});
438
443
 
439
- bids.forEach((bid) => {
440
- values[bid.impid].lineItemIds.push(bid.ext.liid);
441
- values[bid.impid].dealIds.push(bid.dealid);
442
- values[bid.impid].adIds.push(bid.adid);
444
+ bids.forEach((bid, bidIndex) => {
445
+ let impId = bid.impid;
446
+ values[impId].lineItemIds.push(bid.ext.liid);
447
+ values[impId].dealIds.push(bid.dealid);
448
+ values[impId].adIds.push(bid.adid);
449
+
450
+ if (deepAccess(bid, 'ext.ordid')) {
451
+ values[impId].orderIds.push(bid.ext.ordid);
452
+ bid.ext.ordid.split(TARGETING_VALUE_SEPARATOR).forEach((ordid, ordIndex) => {
453
+ let adIdIndex = values[impId].adIds.indexOf(bid.adid);
454
+ values[impId].adAndOrderIndexes.push(adIdIndex + '_' + ordIndex)
455
+ })
456
+ }
443
457
  });
444
458
 
445
459
  const targetingMap = {};
446
460
 
447
- for (const id of impIds) {
448
- targetingMap[id] = {
461
+ bids.forEach((bid, bidIndex) => {
462
+ let id = bid.impid;
463
+
464
+ targetingMap[bidIndex] = {
449
465
  hb_liid_adbookpsp: values[id].lineItemIds.join(TARGETING_VALUE_SEPARATOR),
450
466
  hb_deal_adbookpsp: values[id].dealIds.join(TARGETING_VALUE_SEPARATOR),
467
+ hb_ad_ord_adbookpsp: values[id].adAndOrderIndexes.join(TARGETING_VALUE_SEPARATOR),
451
468
  hb_adid_c_adbookpsp: values[id].adIds.join(TARGETING_VALUE_SEPARATOR),
469
+ hb_ordid_adbookpsp: values[id].orderIds.join(TARGETING_VALUE_SEPARATOR),
452
470
  };
453
- }
454
-
471
+ })
455
472
  return targetingMap;
456
473
  }
457
474
 
@@ -6,7 +6,7 @@ const VERSION = '1.0';
6
6
 
7
7
  export const spec = {
8
8
  code: 'adhash',
9
- url: 'https://bidder.adhash.org/rtb?version=' + VERSION + '&prebid=true',
9
+ url: 'https://bidder.adhash.com/rtb?version=' + VERSION + '&prebid=true',
10
10
  supportedMediaTypes: [ BANNER ],
11
11
 
12
12
  isBidRequestValid: (bid) => {
@@ -37,7 +37,7 @@ export const spec = {
37
37
  var size = validBidRequests[i].sizes[index].join('x');
38
38
  bidRequests.push({
39
39
  method: 'POST',
40
- url: url,
40
+ url: url + '&publisher=' + validBidRequests[i].params.publisherId,
41
41
  bidRequest: validBidRequests[i],
42
42
  data: {
43
43
  timezone: new Date().getTimezoneOffset() / 60,
@@ -87,7 +87,7 @@ export const spec = {
87
87
  cpm: responseBody.creatives[0].costEUR,
88
88
  ad:
89
89
  `<div id="${oneTimeId}"></div>
90
- <script src="https://bidder.adhash.org/static/scripts/creative.min.js"></script>
90
+ <script src="https://bidder.adhash.com/static/scripts/creative.min.js"></script>
91
91
  <script>callAdvertiser(${bidderResponse},['${oneTimeId}'],${requestData},${publisherURL})</script>`,
92
92
  width: request.bidRequest.sizes[0][0],
93
93
  height: request.bidRequest.sizes[0][1],
@@ -47,7 +47,10 @@ export const spec = {
47
47
  * @return boolean True if this is a valid bid, and false otherwise.
48
48
  */
49
49
  isBidRequestValid: (bid) => {
50
- return Boolean(bid.bidId && bid.params && !isNaN(bid.params.placement_id));
50
+ const validPlacamentId = bid.params && !isNaN(bid.params.placement_id);
51
+ const validGroupId = bid.params && !isNaN(bid.params.group_id);
52
+
53
+ return Boolean(bid.bidId && (validPlacamentId || validGroupId));
51
54
  },
52
55
 
53
56
  /**
@@ -61,13 +64,13 @@ export const spec = {
61
64
  const location = winTop.location;
62
65
  let placements = [];
63
66
  let request = {
64
- 'deviceWidth': winTop.screen.width,
65
- 'deviceHeight': winTop.screen.height,
66
- 'language': (navigator && navigator.language) ? navigator.language : '',
67
- 'secure': location.protocol === 'https:' ? 1 : 0,
68
- 'host': location.host,
69
- 'page': location.pathname,
70
- 'placements': placements,
67
+ deviceWidth: winTop.screen.width,
68
+ deviceHeight: winTop.screen.height,
69
+ language: (navigator && navigator.language) ? navigator.language : '',
70
+ secure: location.protocol === 'https:' ? 1 : 0,
71
+ host: location.host,
72
+ page: location.pathname,
73
+ placements: placements,
71
74
  };
72
75
 
73
76
  if (bidderRequest) {
@@ -85,6 +88,7 @@ export const spec = {
85
88
  let traff = bid.params.traffic || BANNER
86
89
  let placement = {
87
90
  placementId: bid.params.placement_id,
91
+ groupId: bid.params.group_id,
88
92
  bidId: bid.bidId,
89
93
  sizes: bid.mediaTypes[traff].sizes,
90
94
  traffic: traff,
@@ -26,5 +26,19 @@ Module that connects to Colossus SSP demand sources
26
26
  traffic: 'banner'
27
27
  }
28
28
  }]
29
- ];
29
+ }, {
30
+ code: 'placementid_1',
31
+ mediaTypes: {
32
+ banner: {
33
+ sizes: [[300, 250], [300,600]]
34
+ }
35
+ },
36
+ bids: [{
37
+ bidder: 'colossusssp',
38
+ params: {
39
+ group_id: 0,
40
+ traffic: 'banner'
41
+ }
42
+ }]
43
+ }];
30
44
  ```
@@ -97,7 +97,7 @@ export const spec = {
97
97
 
98
98
  isBidRequestValid: (bid = {}) => {
99
99
  const { params, bidId, mediaTypes } = bid;
100
- let valid = Boolean(bidId && params && params.placementId);
100
+ let valid = Boolean(bidId && params && (params.placementId || params.endpointId));
101
101
 
102
102
  if (mediaTypes && mediaTypes[BANNER]) {
103
103
  valid = valid && Boolean(mediaTypes[BANNER] && mediaTypes[BANNER].sizes);
@@ -4,7 +4,7 @@ Module Name: Consumable Bid Adapter
4
4
 
5
5
  Module Type: Consumable Adapter
6
6
 
7
- Maintainer: naffis@consumable.com
7
+ Maintainer: prebid@consumable.com
8
8
 
9
9
  # Description
10
10
 
@@ -1,9 +1,9 @@
1
- import { _each, parseSizesInput, isEmpty } from '../src/utils.js';
2
1
  import { registerBidder } from '../src/adapters/bidderFactory.js';
2
+ import { _each, isEmpty, parseSizesInput } from '../src/utils.js';
3
3
  import { BANNER } from '../src/mediaTypes.js';
4
4
 
5
5
  const BIDDER_CODE = 'gnet';
6
- const ENDPOINT = 'https://adserver.gnetproject.com/prebid.php';
6
+ const ENDPOINT = 'https://service.gnetrtb.com/api/adrequest';
7
7
 
8
8
  export const spec = {
9
9
  code: BIDDER_CODE,
@@ -16,7 +16,7 @@ export const spec = {
16
16
  * @return boolean True if this is a valid bid, and false otherwise.
17
17
  */
18
18
  isBidRequestValid: function (bid) {
19
- return !!(bid.params.websiteId);
19
+ return !!(bid.params.websiteId && bid.params.adunitId);
20
20
  },
21
21
 
22
22
  /**
@@ -1,14 +1,14 @@
1
1
  # Overview
2
2
 
3
3
  ```
4
- Module Name: Gnet Bidder Adapter
4
+ Module Name: Gnet RTB Bidder Adapter
5
5
  Module Type: Bidder Adapter
6
- Maintainer: roberto.wu@grumft.com
6
+ Maintainer: bruno.bonanho@grumft.com
7
7
  ```
8
8
 
9
9
  # Description
10
10
 
11
- Connect to Gnet Project exchange for bids.
11
+ Connect to Gnet RTB exchange for bids.
12
12
 
13
13
  # Test Parameters
14
14
  ```
@@ -24,7 +24,7 @@ Connect to Gnet Project exchange for bids.
24
24
  {
25
25
  bidder: 'gnet',
26
26
  params: {
27
- websiteId: '4'
27
+ websiteId: '1', adunitId: '1'
28
28
  }
29
29
  }
30
30
  ]
@@ -298,10 +298,10 @@ function buildRequests(validBidRequests, bidderRequest) {
298
298
  const date = new Date();
299
299
  const lt = date.getTime();
300
300
  const to = date.getTimezoneOffset();
301
- if (to) {
302
- lt && (data.lt = lt);
303
- data.to = to;
304
- }
301
+
302
+ // ADTS-174 Removed unnecessary checks to fix failing test
303
+ data.lt = lt;
304
+ data.to = to;
305
305
 
306
306
  // ADTS-169 add adUnitCode to requests
307
307
  if (adUnitCode) data.aun = adUnitCode
@@ -155,8 +155,10 @@ export function enrichAdUnits(adUnits) {
155
155
  if (!vat) {
156
156
  return;
157
157
  }
158
+ const contentId = getContentId(vat.mediaID);
159
+ const contentData = getContentData(vat.segments);
158
160
  const targeting = formatTargetingResponse(vat);
159
- addTargetingToBids(adUnit.bids, targeting);
161
+ enrichBids(adUnit.bids, targeting, contentId, contentData);
160
162
  };
161
163
  loadVat(jwTargeting, onVatResponse);
162
164
  });
@@ -235,6 +237,9 @@ export function getVatFromPlayer(playerID, mediaID) {
235
237
  };
236
238
  }
237
239
 
240
+ /*
241
+ deprecated
242
+ */
238
243
  export function formatTargetingResponse(vat) {
239
244
  const { segments, mediaID } = vat;
240
245
  const targeting = {};
@@ -243,23 +248,83 @@ export function formatTargetingResponse(vat) {
243
248
  }
244
249
 
245
250
  if (mediaID) {
246
- const id = 'jw_' + mediaID;
247
251
  targeting.content = {
248
- id
252
+ id: getContentId(mediaID)
249
253
  }
250
254
  }
251
255
  return targeting;
252
256
  }
253
257
 
254
- function addTargetingToBids(bids, targeting) {
255
- if (!bids || !targeting) {
258
+ export function getContentId(mediaID) {
259
+ if (!mediaID) {
260
+ return;
261
+ }
262
+
263
+ return 'jw_' + mediaID;
264
+ }
265
+
266
+ export function getContentData(segments) {
267
+ if (!segments || !segments.length) {
268
+ return;
269
+ }
270
+
271
+ const formattedSegments = segments.reduce((convertedSegments, rawSegment) => {
272
+ convertedSegments.push({
273
+ id: rawSegment,
274
+ value: rawSegment
275
+ });
276
+ return convertedSegments;
277
+ }, []);
278
+
279
+ return {
280
+ name: 'jwplayer',
281
+ ext: {
282
+ segtax: 502
283
+ },
284
+ segment: formattedSegments
285
+ };
286
+ }
287
+
288
+ export function addOrtbSiteContent(bid, contentId, contentData) {
289
+ if (!contentId && !contentData) {
256
290
  return;
257
291
  }
258
292
 
259
- bids.forEach(bid => addTargetingToBid(bid, targeting));
293
+ let ortb2 = bid.ortb2 || {};
294
+ let site = ortb2.site = ortb2.site || {};
295
+ let content = site.content = site.content || {};
296
+
297
+ if (contentId) {
298
+ content.id = contentId;
299
+ }
300
+
301
+ if (contentData) {
302
+ const data = content.data = content.data || [];
303
+ data.push(contentData);
304
+ }
305
+
306
+ bid.ortb2 = ortb2;
260
307
  }
261
308
 
309
+ function enrichBids(bids, targeting, contentId, contentData) {
310
+ if (!bids) {
311
+ return;
312
+ }
313
+
314
+ bids.forEach(bid => {
315
+ addTargetingToBid(bid, targeting);
316
+ addOrtbSiteContent(bid, contentId, contentData);
317
+ });
318
+ }
319
+
320
+ /*
321
+ deprecated
322
+ */
262
323
  export function addTargetingToBid(bid, targeting) {
324
+ if (!targeting) {
325
+ return;
326
+ }
327
+
263
328
  const rtd = bid.rtd || {};
264
329
  const jwRtd = {};
265
330
  jwRtd[SUBMODULE_NAME] = Object.assign({}, rtd[SUBMODULE_NAME], { targeting });
@@ -81,20 +81,30 @@ realTimeData = {
81
81
  # Usage for Bid Adapters:
82
82
 
83
83
  Implement the `buildRequests` function. When it is called, the `bidRequests` param will be an array of bids.
84
- Each bid for which targeting information was found will conform to the following object structure:
84
+ Each bid for which targeting information was found will have a ortb2 param conforming to the [oRTB v2 object structure](https://www.iab.com/wp-content/uploads/2016/03/OpenRTB-API-Specification-Version-2-5-FINAL.pdf). The `ortb2` object will contain our proprietaty targeting segments in a format compliant with the [IAB's segment taxonomy structure](https://github.com/InteractiveAdvertisingBureau/openrtb/blob/master/extensions/community_extensions/segtax.md).
85
+
86
+ Example:
85
87
 
86
88
  ```javascript
87
89
  {
88
90
  adUnitCode: 'xyz',
89
91
  bidId: 'abc',
90
92
  ...,
91
- rtd: {
92
- jwplayer: {
93
- targeting: {
94
- segments: ['123', '456'],
95
- content: {
96
- id: 'jw_abc123'
97
- }
93
+ ortb2: {
94
+ site: {
95
+ content: {
96
+ id: 'jw_abc123',
97
+ data: [{
98
+ name: 'jwplayer',
99
+ ext: {
100
+ segtax: 502
101
+ },
102
+ segment: [{
103
+ id: '123'
104
+ }, {
105
+ id: '456'
106
+ }]
107
+ }]
98
108
  }
99
109
  }
100
110
  }
@@ -102,9 +112,15 @@ Each bid for which targeting information was found will conform to the following
102
112
  ```
103
113
 
104
114
  where:
105
- - `segments` is an array of jwpseg targeting segments, of type string.
106
- - `content` is an object containing metadata for the media. It may contain the following information:
107
- - `id` is a unique identifier for the specific media asset.
115
+ - `ortb2` is an object containing first party data
116
+ - `site` is an object containing page specific information
117
+ - `content` is an object containing metadata for the media. It may contain the following information:
118
+ - `id` is a unique identifier for the specific media asset
119
+ - `data` is an array containing segment taxonomy objects that have the following parameters:
120
+ - `name` is the `jwplayer` string indicating the provider name
121
+ - `ext.segtax` whose `502` value is the unique identifier for JW Player's proprietary taxonomy
122
+ - `segment` is an array containing the segment taxonomy values as an object where:
123
+ - `id` is the string representation of the data segment value.
108
124
 
109
125
  **Example:**
110
126
 
@@ -73,8 +73,8 @@ export const spec = {
73
73
  let meta;
74
74
  if (adUnit.metadata && adUnit.metadata.landingPageDomain) {
75
75
  meta = {
76
- clickUrl: adUnit.metadata.landingPageDomain,
77
- advertiserDomains: [adUnit.metadata.landingPageDomain]
76
+ clickUrl: adUnit.metadata.landingPageDomain[0],
77
+ advertiserDomains: adUnit.metadata.landingPageDomain
78
78
  };
79
79
  }
80
80
  bidResponses.push({
@@ -0,0 +1,147 @@
1
+ import { registerBidder } from '../src/adapters/bidderFactory.js';
2
+ const BIDDER_CODE = 'pilotx';
3
+ const ENDPOINT_URL = '//adn.pilotx.tv/hb'
4
+ export const spec = {
5
+ code: BIDDER_CODE,
6
+ supportedMediaTypes: ['banner', 'video'],
7
+ aliases: ['pilotx'], // short code
8
+ /**
9
+ * Determines whether or not the given bid request is valid.
10
+ *
11
+ * @param {BidRequest} bid The bid params to validate.
12
+ * @return boolean True if this is a valid bid, and false otherwise.
13
+ */
14
+ isBidRequestValid: function (bid) {
15
+ let sizesCheck = !!bid.sizes
16
+ let paramSizesCheck = !!bid.params.sizes
17
+ var sizeConfirmed = false
18
+ if (sizesCheck) {
19
+ if (bid.sizes.length < 1) {
20
+ return false
21
+ } else {
22
+ sizeConfirmed = true
23
+ }
24
+ }
25
+ if (paramSizesCheck) {
26
+ if (bid.params.sizes.length < 1 && !sizeConfirmed) {
27
+ return false
28
+ } else {
29
+ sizeConfirmed = true
30
+ }
31
+ }
32
+ if (!sizeConfirmed) {
33
+ return false
34
+ }
35
+ return !!(bid.params.placementId);
36
+ },
37
+ /**
38
+ * Make a server request from the list of BidRequests.
39
+ *
40
+ * @param {validBidRequests[]} - an array of bids
41
+ * @return ServerRequest Info describing the request to the server.
42
+ */
43
+ buildRequests: function (validBidRequests, bidderRequest) {
44
+ let payloadItems = {};
45
+ validBidRequests.forEach(bidRequest => {
46
+ let sizes = [];
47
+ let placementId = this.setPlacementID(bidRequest.params.placementId)
48
+ payloadItems[placementId] = {}
49
+ if (bidRequest.sizes.length > 0) {
50
+ if (Array.isArray(bidRequest.sizes[0])) {
51
+ for (let i = 0; i < bidRequest.sizes.length; i++) {
52
+ sizes[i] = [(bidRequest.sizes[i])[0], (bidRequest.sizes[i])[1]]
53
+ }
54
+ } else {
55
+ sizes[0] = [bidRequest.sizes[0], bidRequest.sizes[1]]
56
+ }
57
+ payloadItems[placementId]['sizes'] = sizes
58
+ }
59
+ if (bidRequest.mediaTypes != null) {
60
+ for (let i in bidRequest.mediaTypes) {
61
+ payloadItems[placementId][i] = {
62
+ ...bidRequest.mediaTypes[i]
63
+ }
64
+ }
65
+ }
66
+ let consentTemp = ''
67
+ let consentRequiredTemp = false
68
+ if (bidderRequest && bidderRequest.gdprConsent) {
69
+ consentTemp = bidderRequest.gdprConsent.consentString
70
+ // will check if the gdprApplies field was populated with a boolean value (ie from page config). If it's undefined, then default to true
71
+ consentRequiredTemp = (typeof bidderRequest.gdprConsent.gdprApplies === 'boolean') ? bidderRequest.gdprConsent.gdprApplies : true
72
+ }
73
+
74
+ payloadItems[placementId]['gdprConsentString'] = consentTemp
75
+ payloadItems[placementId]['gdprConsentRequired'] = consentRequiredTemp
76
+ payloadItems[placementId]['bidId'] = bidRequest.bidId
77
+ });
78
+ const payload = payloadItems;
79
+ const payloadString = JSON.stringify(payload);
80
+ return {
81
+ method: 'POST',
82
+ url: ENDPOINT_URL,
83
+ data: payloadString,
84
+ };
85
+ },
86
+ /**
87
+ * Unpack the response from the server into a list of bids.
88
+ *
89
+ * @param {ServerResponse} serverResponse A successful response from the server.
90
+ * @return {Bid[]} An array of bids which were nested inside the server.
91
+ */
92
+ interpretResponse: function (serverResponse, bidRequest) {
93
+ const serverBody = serverResponse.body;
94
+ const bidResponses = [];
95
+ if (serverBody.mediaType == 'banner') {
96
+ const bidResponse = {
97
+ requestId: serverBody.requestId,
98
+ cpm: serverBody.cpm,
99
+ width: serverBody.width,
100
+ height: serverBody.height,
101
+ creativeId: serverBody.creativeId,
102
+ currency: serverBody.currency,
103
+ netRevenue: false,
104
+ ttl: serverBody.ttl,
105
+ ad: serverBody.ad,
106
+ mediaType: 'banner',
107
+ meta: {
108
+ mediaType: 'banner',
109
+ advertiserDomains: serverBody.advertiserDomains
110
+ }
111
+ }
112
+ bidResponses.push(bidResponse)
113
+ } else if (serverBody.mediaType == 'video') {
114
+ const bidResponse = {
115
+ requestId: serverBody.requestId,
116
+ cpm: serverBody.cpm,
117
+ width: serverBody.width,
118
+ height: serverBody.height,
119
+ creativeId: serverBody.creativeId,
120
+ currency: serverBody.currency,
121
+ netRevenue: false,
122
+ ttl: serverBody.ttl,
123
+ vastUrl: serverBody.vastUrl,
124
+ mediaType: 'video',
125
+ meta: {
126
+ mediaType: 'video',
127
+ advertiserDomains: serverBody.advertiserDomains
128
+ }
129
+ }
130
+ bidResponses.push(bidResponse)
131
+ }
132
+
133
+ return bidResponses;
134
+ },
135
+
136
+ /**
137
+ * Formats placement ids for adserver ingestion purposes
138
+ * @param {string[]} The placement ID/s in an array
139
+ */
140
+ setPlacementID: function (placementId) {
141
+ if (Array.isArray(placementId)) {
142
+ return placementId.join('#')
143
+ }
144
+ return placementId
145
+ },
146
+ }
147
+ registerBidder(spec);
@@ -0,0 +1,50 @@
1
+ # Overview
2
+
3
+ ```
4
+ Module Name: Pilotx Prebid Adapter
5
+ Module Type: Bidder Adapter
6
+ Maintainer: tony@pilotx.tv
7
+ ```
8
+
9
+ # Description
10
+
11
+ Connects to Pilotx
12
+
13
+ Pilotx's bid adapter supports banner and video.
14
+
15
+ # Test Parameters
16
+ ```
17
+ // Banner adUnit
18
+ var adUnits = [{
19
+ code: 'div-gpt-ad-1460505748561-0',
20
+ mediaTypes: {
21
+ banner: {
22
+ sizes: [[300, 250], [300,600]],
23
+ }
24
+ },
25
+ bids: [{
26
+ bidder: 'pilotx',
27
+ params: {
28
+ placementId: ["1423"]
29
+ }
30
+ }]
31
+
32
+ }];
33
+
34
+ // Video adUnit
35
+ var videoAdUnit = {
36
+ code: 'video1',
37
+ mediaTypes: {
38
+ video: {
39
+ context: 'instream',
40
+ playerSize: [640, 480],
41
+ }
42
+ },
43
+ bids: [{
44
+ bidder: 'pilotx',
45
+ params: {
46
+ placementId: '1422',
47
+ }
48
+ }]
49
+ };
50
+ ```