prebid.js 7.24.0 → 7.26.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 (191) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/adagioBidAdapter.js +1 -1
  3. package/dist/adbookpspBidAdapter.js +1 -1
  4. package/dist/adgenerationBidAdapter.js +1 -1
  5. package/dist/admaticBidAdapter.js +1 -1
  6. package/dist/adrelevantisBidAdapter.js +1 -1
  7. package/dist/adtrgtmeBidAdapter.js +1 -1
  8. package/dist/adxcgBidAdapter.js +1 -1
  9. package/dist/ajaBidAdapter.js +1 -1
  10. package/dist/amxBidAdapter.js +1 -1
  11. package/dist/amxIdSystem.js +1 -1
  12. package/dist/appierAnalyticsAdapter.js +1 -1
  13. package/dist/appnexusBidAdapter.js +1 -1
  14. package/dist/asoBidAdapter.js +1 -1
  15. package/dist/axonixBidAdapter.js +1 -1
  16. package/dist/beopBidAdapter.js +1 -1
  17. package/dist/bidglassBidAdapter.js +1 -1
  18. package/dist/big-richmediaBidAdapter.js +1 -1
  19. package/dist/bridgewellBidAdapter.js +1 -1
  20. package/dist/brightMountainMediaBidAdapter.js +1 -1
  21. package/dist/captifyRtdProvider.js +1 -0
  22. package/dist/carodaBidAdapter.js +1 -1
  23. package/dist/chtnwBidAdapter.js +1 -1
  24. package/dist/concertBidAdapter.js +1 -1
  25. package/dist/connectadBidAdapter.js +1 -1
  26. package/dist/consumableBidAdapter.js +1 -1
  27. package/dist/conversantBidAdapter.js +1 -1
  28. package/dist/craftBidAdapter.js +1 -1
  29. package/dist/criteoBidAdapter.js +1 -1
  30. package/dist/discoveryBidAdapter.js +1 -1
  31. package/dist/dspxBidAdapter.js +1 -1
  32. package/dist/eplanningBidAdapter.js +1 -1
  33. package/dist/finativeBidAdapter.js +1 -1
  34. package/dist/glimpseBidAdapter.js +1 -1
  35. package/dist/gmosspBidAdapter.js +1 -1
  36. package/dist/goldbachBidAdapter.js +1 -1
  37. package/dist/gridBidAdapter.js +1 -1
  38. package/dist/gridNMBidAdapter.js +1 -1
  39. package/dist/gumgumBidAdapter.js +1 -1
  40. package/dist/h12mediaBidAdapter.js +1 -1
  41. package/dist/id5IdSystem.js +1 -1
  42. package/dist/improvedigitalBidAdapter.js +1 -1
  43. package/dist/inmarBidAdapter.js +1 -1
  44. package/dist/insticatorBidAdapter.js +1 -1
  45. package/dist/ixBidAdapter.js +1 -1
  46. package/dist/justpremiumBidAdapter.js +1 -1
  47. package/dist/kargoBidAdapter.js +1 -1
  48. package/dist/konduitAnalyticsAdapter.js +1 -1
  49. package/dist/kueezBidAdapter.js +1 -1
  50. package/dist/kueezRtbBidAdapter.js +1 -1
  51. package/dist/lassoBidAdapter.js +1 -1
  52. package/dist/lifestreetBidAdapter.js +1 -1
  53. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  54. package/dist/logicadBidAdapter.js +1 -1
  55. package/dist/loglyliftBidAdapter.js +1 -1
  56. package/dist/magniteAnalyticsAdapter.js +1 -1
  57. package/dist/malltvAnalyticsAdapter.js +1 -1
  58. package/dist/marsmediaBidAdapter.js +1 -1
  59. package/dist/mediafuseBidAdapter.js +1 -1
  60. package/dist/mediasquareBidAdapter.js +1 -1
  61. package/dist/mgidBidAdapter.js +1 -1
  62. package/dist/microadBidAdapter.js +1 -1
  63. package/dist/minutemediaBidAdapter.js +1 -1
  64. package/dist/nextMillenniumBidAdapter.js +1 -1
  65. package/dist/not-for-prod/prebid.js +154 -120
  66. package/dist/oguryBidAdapter.js +1 -1
  67. package/dist/onetagBidAdapter.js +1 -1
  68. package/dist/ooloAnalyticsAdapter.js +1 -1
  69. package/dist/outbrainBidAdapter.js +1 -1
  70. package/dist/parrableIdSystem.js +1 -1
  71. package/dist/pixfutureBidAdapter.js +1 -1
  72. package/dist/prebid-core.js +1 -1
  73. package/dist/publinkIdSystem.js +1 -1
  74. package/dist/pubmaticBidAdapter.js +1 -1
  75. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  76. package/dist/pxyzBidAdapter.js +1 -1
  77. package/dist/quantcastBidAdapter.js +1 -1
  78. package/dist/readpeakBidAdapter.js +1 -1
  79. package/dist/relaidoBidAdapter.js +1 -1
  80. package/dist/rhythmoneBidAdapter.js +1 -1
  81. package/dist/riseBidAdapter.js +1 -1
  82. package/dist/rubiconAnalyticsAdapter.js +1 -1
  83. package/dist/rubiconBidAdapter.js +1 -1
  84. package/dist/seedingAllianceBidAdapter.js +1 -1
  85. package/dist/seedtagBidAdapter.js +1 -1
  86. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  87. package/dist/sharethroughBidAdapter.js +1 -1
  88. package/dist/shinezBidAdapter.js +1 -1
  89. package/dist/smaatoBidAdapter.js +1 -1
  90. package/dist/smartadserverBidAdapter.js +1 -1
  91. package/dist/smartxBidAdapter.js +1 -1
  92. package/dist/smartytechBidAdapter.js +1 -0
  93. package/dist/smilewantedBidAdapter.js +1 -1
  94. package/dist/sonobiBidAdapter.js +1 -1
  95. package/dist/sovrnAnalyticsAdapter.js +1 -1
  96. package/dist/sovrnBidAdapter.js +1 -1
  97. package/dist/sspBCBidAdapter.js +1 -1
  98. package/dist/sublimeBidAdapter.js +1 -1
  99. package/dist/synacormediaBidAdapter.js +1 -1
  100. package/dist/taboolaBidAdapter.js +1 -1
  101. package/dist/tappxBidAdapter.js +1 -1
  102. package/dist/targetVideoBidAdapter.js +1 -1
  103. package/dist/teadsBidAdapter.js +1 -1
  104. package/dist/trionBidAdapter.js +1 -1
  105. package/dist/tripleliftBidAdapter.js +1 -1
  106. package/dist/ttdBidAdapter.js +1 -1
  107. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  108. package/dist/underdogmediaBidAdapter.js +1 -1
  109. package/dist/undertoneBidAdapter.js +1 -1
  110. package/dist/userId.js +1 -1
  111. package/dist/vidazooBidAdapter.js +1 -1
  112. package/dist/videobyteBidAdapter.js +1 -1
  113. package/dist/viqeoBidAdapter.js +1 -0
  114. package/dist/visxBidAdapter.js +1 -1
  115. package/dist/vuukleBidAdapter.js +1 -1
  116. package/dist/widespaceBidAdapter.js +1 -1
  117. package/dist/winrBidAdapter.js +1 -1
  118. package/dist/yahoosspBidAdapter.js +1 -1
  119. package/dist/yieldlabBidAdapter.js +1 -1
  120. package/dist/yieldmoBidAdapter.js +1 -1
  121. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  122. package/dist/zeta_global_sspBidAdapter.js +1 -1
  123. package/dist/zeusPrimeRtdProvider.js +31 -0
  124. package/integrationExamples/gpt/captifyRtdProvider_example.html +167 -0
  125. package/modules/.submodules.json +3 -1
  126. package/modules/adagioBidAdapter.js +1 -1
  127. package/modules/admaticBidAdapter.js +108 -59
  128. package/modules/admaticBidAdapter.md +2 -2
  129. package/modules/beopBidAdapter.js +17 -2
  130. package/modules/captifyRtdProvider.js +146 -0
  131. package/modules/captifyRtdProvider.md +68 -0
  132. package/modules/concertBidAdapter.js +17 -3
  133. package/modules/conversantAnalyticsAdapter.md +12 -13
  134. package/modules/conversantBidAdapter.md +3 -3
  135. package/modules/discoveryBidAdapter.js +38 -17
  136. package/modules/discoveryBidAdapter.md +7 -6
  137. package/modules/gridBidAdapter.js +440 -22
  138. package/modules/kargoBidAdapter.js +14 -8
  139. package/modules/magniteAnalyticsAdapter.js +1 -1
  140. package/modules/microadBidAdapter.js +22 -11
  141. package/modules/nextMillenniumBidAdapter.js +20 -24
  142. package/modules/oguryBidAdapter.js +5 -2
  143. package/modules/pubmaticBidAdapter.js +1 -1
  144. package/modules/seedtagBidAdapter.js +9 -4
  145. package/modules/smartadserverBidAdapter.js +6 -2
  146. package/modules/smartxBidAdapter.js +10 -7
  147. package/modules/smartytechBidAdapter.js +78 -0
  148. package/modules/smartytechBidAdapter.md +44 -0
  149. package/modules/taboolaBidAdapter.js +3 -3
  150. package/modules/taboolaBidAdapter.md +0 -2
  151. package/modules/tappxBidAdapter.js +21 -6
  152. package/modules/ttdBidAdapter.js +4 -3
  153. package/modules/userId/index.js +1 -1
  154. package/modules/vidazooBidAdapter.js +29 -3
  155. package/modules/viqeoBidAdapter.js +180 -0
  156. package/modules/viqeoBidAdapter.md +56 -0
  157. package/modules/yieldlabBidAdapter.js +19 -8
  158. package/modules/yieldmoBidAdapter.js +22 -8
  159. package/modules/yieldoneBidAdapter.js +60 -8
  160. package/modules/yieldoneBidAdapter.md +109 -9
  161. package/modules/zeta_global_sspBidAdapter.js +4 -0
  162. package/modules/zeusPrimeRtdProvider.js +357 -0
  163. package/modules/zeusPrimeRtdProvider.md +60 -0
  164. package/package.json +1 -1
  165. package/src/adloader.js +0 -1
  166. package/test/spec/modules/adagioBidAdapter_spec.js +2 -2
  167. package/test/spec/modules/admaticBidAdapter_spec.js +262 -3
  168. package/test/spec/modules/beopBidAdapter_spec.js +52 -0
  169. package/test/spec/modules/captifyRtdProvider_spec.js +253 -0
  170. package/test/spec/modules/concertBidAdapter_spec.js +26 -15
  171. package/test/spec/modules/discoveryBidAdapter_spec.js +9 -8
  172. package/test/spec/modules/gridBidAdapter_spec.js +289 -1
  173. package/test/spec/modules/kargoBidAdapter_spec.js +76 -4
  174. package/test/spec/modules/magniteAnalyticsAdapter_spec.js +20 -0
  175. package/test/spec/modules/microadBidAdapter_spec.js +48 -0
  176. package/test/spec/modules/nextMillenniumBidAdapter_spec.js +4 -3
  177. package/test/spec/modules/oguryBidAdapter_spec.js +27 -5
  178. package/test/spec/modules/pubmaticBidAdapter_spec.js +2 -2
  179. package/test/spec/modules/seedtagBidAdapter_spec.js +34 -10
  180. package/test/spec/modules/smartadserverBidAdapter_spec.js +80 -0
  181. package/test/spec/modules/smartxBidAdapter_spec.js +32 -0
  182. package/test/spec/modules/smartytechBidAdapter_spec.js +162 -0
  183. package/test/spec/modules/taboolaBidAdapter_spec.js +0 -77
  184. package/test/spec/modules/ttdBidAdapter_spec.js +13 -0
  185. package/test/spec/modules/vidazooBidAdapter_spec.js +1 -0
  186. package/test/spec/modules/viqeoBidAdapter_spec.js +124 -0
  187. package/test/spec/modules/yieldlabBidAdapter_spec.js +125 -0
  188. package/test/spec/modules/yieldmoBidAdapter_spec.js +3 -4
  189. package/test/spec/modules/yieldoneBidAdapter_spec.js +30 -6
  190. package/test/spec/modules/zeta_global_sspBidAdapter_spec.js +16 -1
  191. package/test/spec/modules/zeusPrimeRtdProvider_spec.js +410 -0
@@ -1,18 +1,38 @@
1
- import { isEmpty, deepAccess, logError, parseGPTSingleSizeArrayToRtbSize, generateUUID, mergeDeep, logWarn } from '../src/utils.js';
1
+ import {
2
+ isEmpty,
3
+ deepAccess,
4
+ logError,
5
+ parseGPTSingleSizeArrayToRtbSize,
6
+ generateUUID,
7
+ mergeDeep,
8
+ logWarn,
9
+ parseUrl, isArray, isNumber
10
+ } from '../src/utils.js';
2
11
  import { registerBidder } from '../src/adapters/bidderFactory.js';
3
12
  import { Renderer } from '../src/Renderer.js';
4
13
  import { VIDEO, BANNER } from '../src/mediaTypes.js';
5
14
  import { config } from '../src/config.js';
6
15
  import { getStorageManager } from '../src/storageManager.js';
16
+ import { find } from '../src/polyfill.js';
7
17
 
8
18
  const BIDDER_CODE = 'grid';
9
19
  const ENDPOINT_URL = 'https://grid.bidswitch.net/hbjson';
20
+
21
+ const ADAPTER_VERSION_FOR_CRITEO_MODE = 34;
22
+ const CDB_ENDPOINT = 'https://bidder.criteo.com/cdb';
23
+ const PROFILE_ID_INLINE = 207;
24
+ const SID_COOKIE_NAME = 'cto_sid';
25
+ const IDCPY_COOKIE_NAME = 'cto_idcpy';
26
+ const OPTOUT_COOKIE_NAME = 'cto_optout';
27
+ const BUNDLE_COOKIE_NAME = 'cto_bundle';
28
+
10
29
  const SYNC_URL = 'https://x.bidswitch.net/sync?ssp=themediagrid';
11
30
  const TIME_TO_LIVE = 360;
12
31
  const USER_ID_KEY = 'tmguid';
13
32
  const GVLID = 686;
14
33
  const RENDERER_URL = 'https://acdn.adnxs.com/video/outstream/ANOutstreamVideo.js';
15
34
  export const storage = getStorageManager({gvlid: GVLID, bidderCode: BIDDER_CODE});
35
+
16
36
  const LOG_ERROR_MESS = {
17
37
  noAuid: 'Bid from response has no auid parameter - ',
18
38
  noAdm: 'Bid from response has no adm parameter - ',
@@ -49,7 +69,7 @@ export const spec = {
49
69
  * @return boolean True if this is a valid bid, and false otherwise.
50
70
  */
51
71
  isBidRequestValid: function(bid) {
52
- return !!bid.params.uid;
72
+ return bid && Boolean(bid.params.uid || bid.params.secid);
53
73
  },
54
74
  /**
55
75
  * Make a server request from the list of BidRequests.
@@ -79,10 +99,20 @@ export const spec = {
79
99
  const imp = [];
80
100
  const bidsMap = {};
81
101
  const requests = [];
102
+ const criteoBidsMap = {};
103
+ const criteoBidRequests = [];
82
104
  const sources = [];
83
105
  const bidsArray = [];
84
106
 
85
107
  validBidRequests.forEach((bid) => {
108
+ const bidObject = { bid, savedPrebidBid: null };
109
+ if (bid.params.withCriteo && criteoSpec.isBidRequestValid(bid)) {
110
+ criteoBidsMap[bid.bidId] = bidObject;
111
+ criteoBidRequests.push(bid);
112
+ }
113
+ if (!bid.params.uid && !bid.params.secid) {
114
+ return;
115
+ }
86
116
  if (!bidderRequestId) {
87
117
  bidderRequestId = bid.bidderRequestId;
88
118
  }
@@ -100,7 +130,6 @@ export const spec = {
100
130
  }
101
131
  const { params: { uid, keywords, forceBidder, multiRequest }, mediaTypes, bidId, adUnitCode, rtd, ortb2Imp } = bid;
102
132
  const { pubdata, secid, pubid, source, content: bidParamsContent } = bid.params;
103
- bidsMap[bidId] = bid;
104
133
  const bidFloor = _getFloor(mediaTypes || {}, bid);
105
134
  const jwTargeting = rtd && rtd.jwplayer && rtd.jwplayer.targeting;
106
135
  if (jwTargeting) {
@@ -201,8 +230,9 @@ export const spec = {
201
230
 
202
231
  requests.push(request);
203
232
  sources.push(source);
204
- bidsArray.push(bid);
233
+ bidsArray.push(bidObject);
205
234
  } else {
235
+ bidsMap[bidId] = bidObject;
206
236
  imp.push(impObj);
207
237
  }
208
238
  }
@@ -377,6 +407,11 @@ export const spec = {
377
407
  }
378
408
  });
379
409
 
410
+ const criteoRequest = criteoBidRequests.length && criteoSpec.buildRequests(criteoBidRequests, bidderRequest);
411
+ if (criteoRequest) {
412
+ criteoRequest.criteoBidsMap = criteoBidsMap;
413
+ }
414
+
380
415
  return [...requests.map((req, i) => {
381
416
  let sp;
382
417
  const url = (endpoint || ENDPOINT_URL).replace(/[?&]sp=([^?&=]+)/, (i, found) => {
@@ -391,14 +426,14 @@ export const spec = {
391
426
  method: 'POST',
392
427
  url: urlWithParams,
393
428
  data: JSON.stringify(req),
394
- bid: bidsArray[i],
429
+ bidObject: bidsArray[i],
395
430
  };
396
431
  }), ...(mainRequest ? [{
397
432
  method: 'POST',
398
433
  url: endpoint || ENDPOINT_URL,
399
434
  data: JSON.stringify(mainRequest),
400
435
  bidsMap
401
- }] : [])];
436
+ }] : []), ...(criteoRequest ? [criteoRequest] : [])];
402
437
  },
403
438
  /**
404
439
  * Unpack the response from the server into a list of bids.
@@ -409,25 +444,33 @@ export const spec = {
409
444
  * @return {Bid[]} An array of bids which were nested inside the server.
410
445
  */
411
446
  interpretResponse: function(serverResponse, bidRequest, RendererConst = Renderer) {
412
- serverResponse = serverResponse && serverResponse.body;
413
- const bidResponses = [];
447
+ if (bidRequest.criteoBidsMap && bidRequest.bidRequests) {
448
+ const criteoBids = criteoSpec.interpretResponse(serverResponse, bidRequest);
449
+ return criteoBids.filter((bid) => {
450
+ const { savedPrebidBid } = bidRequest.criteoBidsMap[bid.requestId] || {};
451
+ return canPublishResponse(bid.cpm, savedPrebidBid && savedPrebidBid.cpm);
452
+ });
453
+ } else {
454
+ serverResponse = serverResponse && serverResponse.body;
455
+ const bidResponses = [];
414
456
 
415
- let errorMessage;
457
+ let errorMessage;
416
458
 
417
- if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse;
418
- else if (serverResponse.seatbid && !serverResponse.seatbid.length) {
419
- errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray;
420
- }
459
+ if (!serverResponse) errorMessage = LOG_ERROR_MESS.emptyResponse;
460
+ else if (serverResponse.seatbid && !serverResponse.seatbid.length) {
461
+ errorMessage = LOG_ERROR_MESS.hasEmptySeatbidArray;
462
+ }
421
463
 
422
- const bidderCode = this.forceBidderName || this.code;
464
+ const bidderCode = this.forceBidderName || this.code;
423
465
 
424
- if (!errorMessage && serverResponse.seatbid) {
425
- serverResponse.seatbid.forEach(respItem => {
426
- _addBidResponse(_getBidFromResponse(respItem), bidRequest, bidResponses, RendererConst, bidderCode);
427
- });
466
+ if (!errorMessage && serverResponse.seatbid) {
467
+ serverResponse.seatbid.forEach(respItem => {
468
+ _addBidResponse(_getBidFromResponse(respItem), bidRequest, bidResponses, RendererConst, bidderCode);
469
+ });
470
+ }
471
+ if (errorMessage) logError(errorMessage);
472
+ return bidResponses;
428
473
  }
429
- if (errorMessage) logError(errorMessage);
430
- return bidResponses;
431
474
  },
432
475
  getUserSyncs: function (...args) {
433
476
  const [syncOptions,, gdprConsent, uspConsent] = args;
@@ -502,8 +545,9 @@ function _addBidResponse(serverBid, bidRequest, bidResponses, RendererConst, bid
502
545
  if (!serverBid.auid) errorMessage = LOG_ERROR_MESS.noAuid + JSON.stringify(serverBid);
503
546
  if (!errorMessage && !serverBid.adm && !serverBid.nurl) errorMessage = LOG_ERROR_MESS.noAdm + JSON.stringify(serverBid);
504
547
  else {
505
- const bid = bidRequest.bidsMap ? bidRequest.bidsMap[serverBid.impid] : bidRequest.bid;
506
- if (bid) {
548
+ const bidObject = bidRequest.bidsMap ? bidRequest.bidsMap[serverBid.impid] : bidRequest.bidObject;
549
+ const { bid, savedPrebidBid } = bidObject || {};
550
+ if (bid && canPublishResponse(serverBid.price, savedPrebidBid && savedPrebidBid.cpm)) {
507
551
  const bidResponse = {
508
552
  requestId: bid.bidId, // bid.bidderRequestId
509
553
  cpm: serverBid.price,
@@ -519,6 +563,8 @@ function _addBidResponse(serverBid, bidRequest, bidResponses, RendererConst, bid
519
563
  dealId: serverBid.dealid
520
564
  };
521
565
 
566
+ bidObject.savedPrebidBid = bidResponse;
567
+
522
568
  if (serverBid.ext && serverBid.ext.bidder && serverBid.ext.bidder.grid && serverBid.ext.bidder.grid.demandSource) {
523
569
  bidResponse.adserverTargeting = { 'hb_ds': serverBid.ext.bidder.grid.demandSource };
524
570
  bidResponse.meta.demandSource = serverBid.ext.bidder.grid.demandSource;
@@ -664,6 +710,13 @@ function reformatKeywords(pageKeywords) {
664
710
  return Object.keys(formatedPageKeywords).length && formatedPageKeywords;
665
711
  }
666
712
 
713
+ function canPublishResponse(price, savedPrice) {
714
+ if (isNumber(savedPrice)) {
715
+ return price > savedPrice || (price === savedPrice && Math.random() > 0.5);
716
+ }
717
+ return true;
718
+ }
719
+
667
720
  function outstreamRender (bid) {
668
721
  bid.renderer.push(() => {
669
722
  window.ANOutstreamVideo.renderAd({
@@ -697,4 +750,369 @@ export function getSyncUrl() {
697
750
  return SYNC_URL;
698
751
  }
699
752
 
753
+ // ================ Criteo methods ==================
754
+
755
+ const criteoSpec = {
756
+ /** f
757
+ * @param {object} bid
758
+ * @return {boolean}
759
+ */
760
+ isBidRequestValid: (bid) => {
761
+ // either one of zoneId or networkId should be set
762
+ if (!(bid && bid.params && (bid.params.zoneId || bid.params.networkId))) {
763
+ return false;
764
+ }
765
+
766
+ // video media types requires some mandatory params
767
+ if (hasVideoMediaType(bid)) {
768
+ if (!hasValidVideoMediaType(bid)) {
769
+ return false;
770
+ }
771
+ }
772
+
773
+ return true;
774
+ },
775
+
776
+ /**
777
+ * @param {BidRequest[]} bidRequests
778
+ * @param {*} bidderRequest
779
+ * @return {ServerRequest}
780
+ */
781
+ buildRequests: (bidRequests, bidderRequest) => {
782
+ let url;
783
+ let data;
784
+ let fpd = bidderRequest.ortb2 || {};
785
+
786
+ Object.assign(bidderRequest, {
787
+ publisherExt: fpd.site?.ext,
788
+ userExt: fpd.user?.ext,
789
+ ceh: config.getConfig('criteo.ceh'),
790
+ coppa: config.getConfig('coppa')
791
+ });
792
+
793
+ const context = buildContext(bidRequests, bidderRequest);
794
+ url = buildCdbUrl(context);
795
+ data = buildCdbRequest(context, bidRequests, bidderRequest);
796
+
797
+ if (data) {
798
+ return { method: 'POST', url, data, bidRequests };
799
+ }
800
+ },
801
+
802
+ /**
803
+ * @param {*} response
804
+ * @param {ServerRequest} request
805
+ * @return {Bid[]}
806
+ */
807
+ interpretResponse: (response, request) => {
808
+ const body = response.body || response;
809
+ const bids = [];
810
+
811
+ if (body && body.slots && isArray(body.slots)) {
812
+ body.slots.forEach(slot => {
813
+ const bidRequest = find(request.bidRequests, b => b.adUnitCode === slot.impid && (!b.params.zoneId || parseInt(b.params.zoneId) === slot.zoneid));
814
+ const bidId = bidRequest.bidId;
815
+ const bid = {
816
+ requestId: bidId,
817
+ cpm: slot.cpm,
818
+ currency: slot.currency,
819
+ netRevenue: true,
820
+ ttl: slot.ttl || 60,
821
+ creativeId: slot.creativecode,
822
+ width: slot.width,
823
+ height: slot.height,
824
+ dealId: slot.dealCode,
825
+ };
826
+ if (body.ext?.paf?.transmission && slot.ext?.paf?.content_id) {
827
+ const pafResponseMeta = {
828
+ content_id: slot.ext.paf.content_id,
829
+ transmission: response.ext.paf.transmission
830
+ };
831
+ bid.meta = Object.assign({}, bid.meta, { paf: pafResponseMeta });
832
+ }
833
+ if (slot.adomain) {
834
+ bid.meta = Object.assign({}, bid.meta, { advertiserDomains: slot.adomain });
835
+ }
836
+ if (slot.video) {
837
+ bid.vastUrl = slot.displayurl;
838
+ bid.mediaType = VIDEO;
839
+ } else {
840
+ bid.ad = slot.creative;
841
+ }
842
+ bids.push(bid);
843
+ });
844
+ }
845
+
846
+ return bids;
847
+ }
848
+ };
849
+
850
+ function readFromAllStorages(name) {
851
+ const fromCookie = storage.getCookie(name);
852
+ const fromLocalStorage = storage.getDataFromLocalStorage(name);
853
+
854
+ return fromCookie || fromLocalStorage || undefined;
855
+ }
856
+
857
+ /**
858
+ * @param {BidRequest[]} bidRequests
859
+ * @param bidderRequest
860
+ */
861
+ function buildContext(bidRequests, bidderRequest) {
862
+ let referrer = '';
863
+ if (bidderRequest && bidderRequest.refererInfo) {
864
+ referrer = bidderRequest.refererInfo.page;
865
+ }
866
+ const queryString = parseUrl(bidderRequest?.refererInfo?.topmostLocation).search;
867
+
868
+ const context = {
869
+ url: referrer,
870
+ debug: queryString['pbt_debug'] === '1',
871
+ noLog: queryString['pbt_nolog'] === '1',
872
+ amp: false,
873
+ };
874
+
875
+ bidRequests.forEach(bidRequest => {
876
+ if (bidRequest.params.integrationMode === 'amp') {
877
+ context.amp = true;
878
+ }
879
+ });
880
+
881
+ return context;
882
+ }
883
+
884
+ /**
885
+ * @param {CriteoContext} context
886
+ * @return {string}
887
+ */
888
+ function buildCdbUrl(context) {
889
+ let url = CDB_ENDPOINT;
890
+ url += '?profileId=' + PROFILE_ID_INLINE;
891
+ url += '&av=' + String(ADAPTER_VERSION_FOR_CRITEO_MODE);
892
+ url += '&wv=' + encodeURIComponent('$prebid.version$');
893
+ url += '&cb=' + String(Math.floor(Math.random() * 99999999999));
894
+
895
+ if (storage.localStorageIsEnabled()) {
896
+ url += '&lsavail=1';
897
+ } else {
898
+ url += '&lsavail=0';
899
+ }
900
+
901
+ if (context.amp) {
902
+ url += '&im=1';
903
+ }
904
+ if (context.debug) {
905
+ url += '&debug=1';
906
+ }
907
+ if (context.noLog) {
908
+ url += '&nolog=1';
909
+ }
910
+
911
+ const bundle = readFromAllStorages(BUNDLE_COOKIE_NAME);
912
+ if (bundle) {
913
+ url += `&bundle=${bundle}`;
914
+ }
915
+
916
+ const optout = readFromAllStorages(OPTOUT_COOKIE_NAME);
917
+ if (optout) {
918
+ url += `&optout=1`;
919
+ }
920
+
921
+ const sid = readFromAllStorages(SID_COOKIE_NAME);
922
+ if (sid) {
923
+ url += `&sid=${sid}`;
924
+ }
925
+
926
+ const idcpy = readFromAllStorages(IDCPY_COOKIE_NAME);
927
+ if (idcpy) {
928
+ url += `&idcpy=${idcpy}`;
929
+ }
930
+
931
+ return url;
932
+ }
933
+
934
+ /**
935
+ * @param {CriteoContext} context
936
+ * @param {BidRequest[]} bidRequests
937
+ * @param bidderRequest
938
+ * @return {*}
939
+ */
940
+ function buildCdbRequest(context, bidRequests, bidderRequest) {
941
+ let networkId;
942
+ let schain;
943
+ const request = {
944
+ publisher: {
945
+ url: context.url,
946
+ ext: bidderRequest.publisherExt,
947
+ },
948
+ regs: {
949
+ coppa: bidderRequest.coppa === true ? 1 : (bidderRequest.coppa === false ? 0 : undefined)
950
+ },
951
+ slots: bidRequests.map(bidRequest => {
952
+ networkId = bidRequest.params.networkId || networkId;
953
+ schain = bidRequest.schain || schain;
954
+ const slot = {
955
+ impid: bidRequest.adUnitCode,
956
+ transactionid: bidRequest.transactionId,
957
+ auctionId: bidRequest.auctionId,
958
+ };
959
+ if (bidRequest.params.zoneId) {
960
+ slot.zoneid = bidRequest.params.zoneId;
961
+ }
962
+ if (deepAccess(bidRequest, 'ortb2Imp.ext')) {
963
+ slot.ext = bidRequest.ortb2Imp.ext;
964
+ }
965
+ if (bidRequest.params.ext) {
966
+ slot.ext = Object.assign({}, slot.ext, bidRequest.params.ext);
967
+ }
968
+ if (bidRequest.params.publisherSubId) {
969
+ slot.publishersubid = bidRequest.params.publisherSubId;
970
+ }
971
+
972
+ if (hasBannerMediaType(bidRequest)) {
973
+ slot.sizes = parseSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes'), parseSize);
974
+ } else {
975
+ slot.sizes = [];
976
+ }
977
+
978
+ if (hasVideoMediaType(bidRequest)) {
979
+ const video = {
980
+ playersizes: parseSizes(deepAccess(bidRequest, 'mediaTypes.video.playerSize'), parseSize),
981
+ mimes: bidRequest.mediaTypes.video.mimes,
982
+ protocols: bidRequest.mediaTypes.video.protocols,
983
+ maxduration: bidRequest.mediaTypes.video.maxduration,
984
+ api: bidRequest.mediaTypes.video.api,
985
+ skip: bidRequest.mediaTypes.video.skip,
986
+ placement: bidRequest.mediaTypes.video.placement,
987
+ minduration: bidRequest.mediaTypes.video.minduration,
988
+ playbackmethod: bidRequest.mediaTypes.video.playbackmethod,
989
+ startdelay: bidRequest.mediaTypes.video.startdelay
990
+ };
991
+ const paramsVideo = bidRequest.params.video;
992
+ if (paramsVideo !== undefined) {
993
+ video.skip = video.skip || paramsVideo.skip || 0;
994
+ video.placement = video.placement || paramsVideo.placement;
995
+ video.minduration = video.minduration || paramsVideo.minduration;
996
+ video.playbackmethod = video.playbackmethod || paramsVideo.playbackmethod;
997
+ video.startdelay = video.startdelay || paramsVideo.startdelay || 0;
998
+ }
999
+
1000
+ slot.video = video;
1001
+ }
1002
+
1003
+ enrichSlotWithFloors(slot, bidRequest);
1004
+
1005
+ return slot;
1006
+ }),
1007
+ };
1008
+ if (networkId) {
1009
+ request.publisher.networkid = networkId;
1010
+ }
1011
+ if (schain) {
1012
+ request.source = {
1013
+ ext: {
1014
+ schain: schain
1015
+ }
1016
+ };
1017
+ }
1018
+ request.user = {
1019
+ ext: bidderRequest.userExt
1020
+ };
1021
+ if (bidderRequest && bidderRequest.ceh) {
1022
+ request.user.ceh = bidderRequest.ceh;
1023
+ }
1024
+ if (bidderRequest && bidderRequest.gdprConsent) {
1025
+ request.gdprConsent = {};
1026
+ if (typeof bidderRequest.gdprConsent.gdprApplies !== 'undefined') {
1027
+ request.gdprConsent.gdprApplies = !!(bidderRequest.gdprConsent.gdprApplies);
1028
+ }
1029
+ request.gdprConsent.version = bidderRequest.gdprConsent.apiVersion;
1030
+ if (typeof bidderRequest.gdprConsent.consentString !== 'undefined') {
1031
+ request.gdprConsent.consentData = bidderRequest.gdprConsent.consentString;
1032
+ }
1033
+ }
1034
+ if (bidderRequest && bidderRequest.uspConsent) {
1035
+ request.user.uspIab = bidderRequest.uspConsent;
1036
+ }
1037
+ return request;
1038
+ }
1039
+
1040
+ function parseSizes(sizes, parser = s => s) {
1041
+ if (sizes === undefined) {
1042
+ return [];
1043
+ }
1044
+ if (Array.isArray(sizes[0])) { // is there several sizes ? (ie. [[728,90],[200,300]])
1045
+ return sizes.map(size => parser(size));
1046
+ }
1047
+ return [parser(sizes)]; // or a single one ? (ie. [728,90])
1048
+ }
1049
+
1050
+ function parseSize(size) {
1051
+ return size[0] + 'x' + size[1];
1052
+ }
1053
+
1054
+ function hasVideoMediaType(bidRequest) {
1055
+ return deepAccess(bidRequest, 'mediaTypes.video') !== undefined;
1056
+ }
1057
+
1058
+ function hasBannerMediaType(bidRequest) {
1059
+ return deepAccess(bidRequest, 'mediaTypes.banner') !== undefined;
1060
+ }
1061
+
1062
+ function hasValidVideoMediaType(bidRequest) {
1063
+ let isValid = true;
1064
+
1065
+ var requiredMediaTypesParams = ['mimes', 'playerSize', 'maxduration', 'protocols', 'api', 'skip', 'placement', 'playbackmethod'];
1066
+
1067
+ requiredMediaTypesParams.forEach(function (param) {
1068
+ if (deepAccess(bidRequest, 'mediaTypes.video.' + param) === undefined && deepAccess(bidRequest, 'params.video.' + param) === undefined) {
1069
+ isValid = false;
1070
+ logError('TheMediaGrid Bid Adapter (withCriteo mode): mediaTypes.video.' + param + ' is required');
1071
+ }
1072
+ });
1073
+
1074
+ if (isValid) {
1075
+ const videoPlacement = bidRequest.mediaTypes.video.placement || bidRequest.params.video.placement;
1076
+ // We do not support long form for now, also we have to check that context & placement are consistent
1077
+ if (bidRequest.mediaTypes.video.context === 'instream' && videoPlacement === 1) {
1078
+ return true;
1079
+ } else if (bidRequest.mediaTypes.video.context === 'outstream' && videoPlacement !== 1) {
1080
+ return true;
1081
+ }
1082
+ }
1083
+
1084
+ return false;
1085
+ }
1086
+
1087
+ function enrichSlotWithFloors(slot, bidRequest) {
1088
+ try {
1089
+ const slotFloors = {};
1090
+
1091
+ if (bidRequest.getFloor) {
1092
+ if (bidRequest.mediaTypes?.banner) {
1093
+ slotFloors.banner = {};
1094
+ const bannerSizes = parseSizes(deepAccess(bidRequest, 'mediaTypes.banner.sizes'))
1095
+ bannerSizes.forEach(bannerSize => slotFloors.banner[parseSize(bannerSize).toString()] = bidRequest.getFloor({ size: bannerSize, mediaType: BANNER }));
1096
+ }
1097
+
1098
+ if (bidRequest.mediaTypes?.video) {
1099
+ slotFloors.video = {};
1100
+ const videoSizes = parseSizes(deepAccess(bidRequest, 'mediaTypes.video.playerSize'))
1101
+ videoSizes.forEach(videoSize => slotFloors.video[parseSize(videoSize).toString()] = bidRequest.getFloor({ size: videoSize, mediaType: VIDEO }));
1102
+ }
1103
+
1104
+ if (Object.keys(slotFloors).length > 0) {
1105
+ if (!slot.ext) {
1106
+ slot.ext = {}
1107
+ }
1108
+ Object.assign(slot.ext, {
1109
+ floors: slotFloors
1110
+ });
1111
+ }
1112
+ }
1113
+ } catch (e) {
1114
+ logError('Could not parse floors from Prebid: ' + e);
1115
+ }
1116
+ }
1117
+
700
1118
  registerBidder(spec);
@@ -1,4 +1,4 @@
1
- import { _each, buildUrl, triggerPixel } from '../src/utils.js';
1
+ import { _each, buildUrl, deepAccess, pick, triggerPixel } from '../src/utils.js';
2
2
  import { config } from '../src/config.js';
3
3
  import { registerBidder } from '../src/adapters/bidderFactory.js';
4
4
  import { getStorageManager } from '../src/storageManager.js';
@@ -37,10 +37,9 @@ export const spec = {
37
37
  bidSizes[bid.bidId] = bid.sizes;
38
38
  });
39
39
 
40
- let tdid;
41
- if (validBidRequests.length > 0 && validBidRequests[0].userId && validBidRequests[0].userId.tdid) {
42
- tdid = validBidRequests[0].userId.tdid;
43
- }
40
+ const firstBidRequest = validBidRequests[0];
41
+
42
+ const tdid = deepAccess(firstBidRequest, 'userId.tdid')
44
43
 
45
44
  const transformedParams = Object.assign({}, {
46
45
  sessionId: spec._getSessionId(),
@@ -62,10 +61,17 @@ export const spec = {
62
61
  prebidRawBidRequests: validBidRequests
63
62
  }, spec._getAllMetadata(bidderRequest, tdid));
64
63
 
64
+ // User Agent Client Hints / SUA
65
+ const uaClientHints = deepAccess(firstBidRequest, 'ortb2.device.sua');
66
+ if (uaClientHints) {
67
+ transformedParams.device.sua = pick(uaClientHints, ['browsers', 'platform', 'mobile', 'model']);
68
+ }
69
+
65
70
  // Pull Social Canvas segments and embed URL
66
- if (validBidRequests.length > 0 && validBidRequests[0].params.socialCanvas) {
67
- transformedParams.socialCanvasSegments = validBidRequests[0].params.socialCanvas.segments;
68
- transformedParams.socialEmbedURL = validBidRequests[0].params.socialCanvas.embedURL;
71
+ const socialCanvas = deepAccess(firstBidRequest, 'params.socialCanvas');
72
+ if (socialCanvas) {
73
+ transformedParams.socialCanvasSegments = socialCanvas.segments;
74
+ transformedParams.socialEmbedURL = socialCanvas.embedURL;
69
75
  }
70
76
 
71
77
  const encodedParams = encodeURIComponent(JSON.stringify(transformedParams));
@@ -706,7 +706,7 @@ magniteAdapter.track = ({ eventType, args }) => {
706
706
  'code as adUnitCode',
707
707
  'transactionId',
708
708
  'mediaTypes', mediaTypes => Object.keys(mediaTypes),
709
- 'sizes as dimensions', sizes => sizes.map(sizeToDimensions),
709
+ 'sizes as dimensions', sizes => (sizes || [[1, 1]]).map(sizeToDimensions),
710
710
  ]);
711
711
  ad.pbAdSlot = deepAccess(adUnit, 'ortb2Imp.ext.data.pbadslot');
712
712
  ad.pattern = deepAccess(adUnit, 'ortb2Imp.ext.data.aupname');
@@ -1,4 +1,5 @@
1
- import { deepAccess, isEmpty, isStr } from '../src/utils.js';
1
+ import { deepAccess, isArray, isEmpty, isStr } from '../src/utils.js';
2
+ import { find } from '../src/polyfill.js';
2
3
  import { registerBidder } from '../src/adapters/bidderFactory.js';
3
4
  import { BANNER } from '../src/mediaTypes.js';
4
5
  import { convertOrtbRequestToProprietaryNative } from '../src/native.js';
@@ -24,15 +25,16 @@ const NATIVE_CODE = 2;
24
25
  const VIDEO_CODE = 4;
25
26
 
26
27
  const AUDIENCE_IDS = [
27
- {type: 6, bidKey: 'userId.imuid'},
28
- {type: 8, bidKey: 'userId.id5id.uid'},
29
- {type: 9, bidKey: 'userId.tdid'},
30
- {type: 10, bidKey: 'userId.novatiq.snowflake'},
31
- {type: 11, bidKey: 'userId.parrableId.eid'},
32
- {type: 12, bidKey: 'userId.dacId.id'},
33
- {type: 13, bidKey: 'userId.idl_env'},
34
- {type: 14, bidKey: 'userId.criteoId'},
35
- {type: 15, bidKey: 'userId.pubcid'}
28
+ {type: 6, bidKey: 'userId.imuid', source: 'intimatemerger.com'},
29
+ {type: 8, bidKey: 'userId.id5id.uid', source: 'id5-sync.com'},
30
+ {type: 9, bidKey: 'userId.tdid', source: 'adserver.org'},
31
+ {type: 10, bidKey: 'userId.novatiq.snowflake', source: 'novatiq.com'},
32
+ {type: 11, bidKey: 'userId.parrableId.eid', source: 'parrable.com'},
33
+ {type: 12, bidKey: 'userId.dacId.id', source: 'dac.co.jp'},
34
+ {type: 13, bidKey: 'userId.idl_env', source: 'liveramp.com'},
35
+ {type: 14, bidKey: 'userId.criteoId', source: 'criteo.com'},
36
+ {type: 15, bidKey: 'userId.pubcid', source: 'pubcid.org'},
37
+ {type: 17, bidKey: 'userId.uid2.id', source: 'uidapi.com'}
36
38
  ];
37
39
 
38
40
  function createCBT() {
@@ -100,10 +102,19 @@ export const spec = {
100
102
  }
101
103
 
102
104
  const aidsParams = []
105
+ const userIdAsEids = bid.userIdAsEids;
103
106
  AUDIENCE_IDS.forEach((audienceId) => {
104
107
  const bidAudienceId = deepAccess(bid, audienceId.bidKey);
105
108
  if (!isEmpty(bidAudienceId) && isStr(bidAudienceId)) {
106
- aidsParams.push({ type: audienceId.type, id: bidAudienceId });
109
+ const aidParam = { type: audienceId.type, id: bidAudienceId };
110
+ // Set ext
111
+ if (isArray(userIdAsEids)) {
112
+ const targetEid = find(userIdAsEids, (eid) => eid.source === audienceId.source) || {};
113
+ if (!isEmpty(deepAccess(targetEid, 'uids.0.ext'))) {
114
+ aidParam.ext = targetEid.uids[0].ext;
115
+ }
116
+ }
117
+ aidsParams.push(aidParam);
107
118
  // Set Ramp ID
108
119
  if (audienceId.type === 13) params['idl_env'] = bidAudienceId;
109
120
  }