prebid.js 7.35.0 → 7.37.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 (229) hide show
  1. package/.devcontainer/Dockerfile +2 -0
  2. package/dist/33acrossBidAdapter.js +1 -1
  3. package/dist/33acrossIdSystem.js +1 -1
  4. package/dist/adagioBidAdapter.js +1 -1
  5. package/dist/adbookpspBidAdapter.js +1 -1
  6. package/dist/adgenerationBidAdapter.js +1 -1
  7. package/dist/admaruBidAdapter.js +1 -1
  8. package/dist/adrelevantisBidAdapter.js +1 -1
  9. package/dist/adtrgtmeBidAdapter.js +1 -1
  10. package/dist/adxcgBidAdapter.js +1 -1
  11. package/dist/adyoulikeBidAdapter.js +1 -1
  12. package/dist/aidemBidAdapter.js +1 -1
  13. package/dist/ajaBidAdapter.js +1 -1
  14. package/dist/amxBidAdapter.js +1 -1
  15. package/dist/amxIdSystem.js +1 -1
  16. package/dist/aolBidAdapter.js +1 -1
  17. package/dist/appierAnalyticsAdapter.js +1 -1
  18. package/dist/appnexusBidAdapter.js +1 -1
  19. package/dist/asoBidAdapter.js +1 -1
  20. package/dist/audiencerunBidAdapter.js +1 -1
  21. package/dist/axonixBidAdapter.js +1 -1
  22. package/dist/bidglassBidAdapter.js +1 -1
  23. package/dist/big-richmediaBidAdapter.js +1 -1
  24. package/dist/bluebillywigBidAdapter.js +1 -1
  25. package/dist/bridgewellBidAdapter.js +1 -1
  26. package/dist/brightMountainMediaBidAdapter.js +1 -1
  27. package/dist/brightcomBidAdapter.js +1 -1
  28. package/dist/brightcomSSPBidAdapter.js +1 -0
  29. package/dist/carodaBidAdapter.js +1 -1
  30. package/dist/chtnwBidAdapter.js +1 -1
  31. package/dist/concertBidAdapter.js +1 -1
  32. package/dist/connectadBidAdapter.js +1 -1
  33. package/dist/consumableBidAdapter.js +1 -1
  34. package/dist/conversantBidAdapter.js +1 -1
  35. package/dist/craftBidAdapter.js +1 -1
  36. package/dist/criteoBidAdapter.js +1 -1
  37. package/dist/cwireBidAdapter.js +1 -1
  38. package/dist/dependencies.json +3 -0
  39. package/dist/discoveryBidAdapter.js +1 -1
  40. package/dist/dspxBidAdapter.js +1 -1
  41. package/dist/eplanningBidAdapter.js +1 -1
  42. package/dist/feedadBidAdapter.js +1 -1
  43. package/dist/finativeBidAdapter.js +1 -1
  44. package/dist/freewheel-sspBidAdapter.js +1 -1
  45. package/dist/glimpseBidAdapter.js +1 -1
  46. package/dist/gmosspBidAdapter.js +1 -1
  47. package/dist/goldbachBidAdapter.js +1 -1
  48. package/dist/gridBidAdapter.js +1 -1
  49. package/dist/gridNMBidAdapter.js +1 -1
  50. package/dist/gumgumBidAdapter.js +1 -1
  51. package/dist/h12mediaBidAdapter.js +1 -1
  52. package/dist/id5IdSystem.js +1 -1
  53. package/dist/impactifyBidAdapter.js +1 -1
  54. package/dist/improvedigitalBidAdapter.js +1 -1
  55. package/dist/incrxBidAdapter.js +1 -1
  56. package/dist/inmarBidAdapter.js +1 -1
  57. package/dist/insticatorBidAdapter.js +1 -1
  58. package/dist/ixBidAdapter.js +1 -1
  59. package/dist/jixieBidAdapter.js +1 -1
  60. package/dist/justpremiumBidAdapter.js +1 -1
  61. package/dist/konduitAnalyticsAdapter.js +1 -1
  62. package/dist/kueezBidAdapter.js +1 -1
  63. package/dist/kueezRtbBidAdapter.js +1 -1
  64. package/dist/lassoBidAdapter.js +1 -1
  65. package/dist/lifestreetBidAdapter.js +1 -1
  66. package/dist/limelightDigitalBidAdapter.js +1 -1
  67. package/dist/liveIntentIdSystem.js +1 -1
  68. package/dist/livewrappedBidAdapter.js +1 -1
  69. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  70. package/dist/logicadBidAdapter.js +1 -1
  71. package/dist/loglyliftBidAdapter.js +1 -1
  72. package/dist/magniteAnalyticsAdapter.js +1 -1
  73. package/dist/malltvAnalyticsAdapter.js +1 -1
  74. package/dist/marsmediaBidAdapter.js +1 -1
  75. package/dist/mediafuseBidAdapter.js +1 -1
  76. package/dist/mediagoBidAdapter.js +1 -1
  77. package/dist/mediakeysBidAdapter.js +1 -1
  78. package/dist/mediasquareBidAdapter.js +1 -1
  79. package/dist/mgidBidAdapter.js +1 -1
  80. package/dist/minutemediaBidAdapter.js +1 -1
  81. package/dist/minutemediaplusBidAdapter.js +1 -0
  82. package/dist/neuwoRtdProvider.js +1 -0
  83. package/dist/nextMillenniumBidAdapter.js +1 -1
  84. package/dist/nexx360BidAdapter.js +1 -1
  85. package/dist/not-for-prod/prebid.js +141 -137
  86. package/dist/oguryBidAdapter.js +1 -1
  87. package/dist/onetagBidAdapter.js +1 -1
  88. package/dist/ooloAnalyticsAdapter.js +1 -1
  89. package/dist/outbrainBidAdapter.js +1 -1
  90. package/dist/parrableIdSystem.js +1 -1
  91. package/dist/pixfutureBidAdapter.js +1 -1
  92. package/dist/prebid-core.js +1 -1
  93. package/dist/prebidServerBidAdapter.js +1 -1
  94. package/dist/proxistoreBidAdapter.js +1 -1
  95. package/dist/publinkIdSystem.js +1 -1
  96. package/dist/pubmaticBidAdapter.js +1 -1
  97. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  98. package/dist/pubxaiAnalyticsAdapter.js +1 -1
  99. package/dist/pxyzBidAdapter.js +1 -1
  100. package/dist/quantcastBidAdapter.js +1 -1
  101. package/dist/readpeakBidAdapter.js +1 -1
  102. package/dist/relaidoBidAdapter.js +1 -1
  103. package/dist/rhythmoneBidAdapter.js +1 -1
  104. package/dist/riseBidAdapter.js +1 -1
  105. package/dist/rubiconAnalyticsAdapter.js +1 -1
  106. package/dist/rubiconBidAdapter.js +1 -1
  107. package/dist/scatteredBidAdapter.js +1 -0
  108. package/dist/seedingAllianceBidAdapter.js +1 -1
  109. package/dist/seedtagBidAdapter.js +1 -1
  110. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  111. package/dist/sharethroughBidAdapter.js +1 -1
  112. package/dist/shinezBidAdapter.js +1 -1
  113. package/dist/sirdataRtdProvider.js +1 -1
  114. package/dist/smaatoBidAdapter.js +1 -1
  115. package/dist/smartadserverBidAdapter.js +1 -1
  116. package/dist/smartxBidAdapter.js +1 -1
  117. package/dist/smilewantedBidAdapter.js +1 -1
  118. package/dist/sonobiBidAdapter.js +1 -1
  119. package/dist/sovrnAnalyticsAdapter.js +1 -1
  120. package/dist/sovrnBidAdapter.js +1 -1
  121. package/dist/sspBCBidAdapter.js +1 -1
  122. package/dist/sublimeBidAdapter.js +1 -1
  123. package/dist/synacormediaBidAdapter.js +1 -1
  124. package/dist/targetVideoBidAdapter.js +1 -1
  125. package/dist/teadsBidAdapter.js +1 -1
  126. package/dist/trionBidAdapter.js +1 -1
  127. package/dist/tripleliftBidAdapter.js +1 -1
  128. package/dist/ttdBidAdapter.js +1 -1
  129. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  130. package/dist/uid2IdSystem.js +1 -1
  131. package/dist/underdogmediaBidAdapter.js +1 -1
  132. package/dist/undertoneBidAdapter.js +1 -1
  133. package/dist/userId.js +1 -1
  134. package/dist/vidazooBidAdapter.js +1 -1
  135. package/dist/videobyteBidAdapter.js +1 -1
  136. package/dist/visxBidAdapter.js +1 -1
  137. package/dist/vuukleBidAdapter.js +1 -1
  138. package/dist/widespaceBidAdapter.js +1 -1
  139. package/dist/winrBidAdapter.js +1 -1
  140. package/dist/yahoosspBidAdapter.js +1 -1
  141. package/dist/yieldmoBidAdapter.js +1 -1
  142. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  143. package/integrationExamples/gpt/neuwoRtdProvider_example.html +190 -0
  144. package/modules/33acrossBidAdapter.js +13 -4
  145. package/modules/adagioBidAdapter.js +14 -14
  146. package/modules/adagioBidAdapter.md +3 -1
  147. package/modules/admaruBidAdapter.js +19 -1
  148. package/modules/aidemBidAdapter.js +90 -65
  149. package/modules/aidemBidAdapter.md +10 -7
  150. package/modules/ajaBidAdapter.js +6 -1
  151. package/modules/amxIdSystem.md +2 -10
  152. package/modules/aolBidAdapter.js +1 -1
  153. package/modules/appnexusBidAdapter.js +45 -48
  154. package/modules/brightcomBidAdapter.js +1 -0
  155. package/modules/brightcomSSPBidAdapter.js +323 -0
  156. package/modules/brightcomSSPBidAdapter.md +46 -0
  157. package/modules/criteoBidAdapter.js +4 -5
  158. package/modules/cwireBidAdapter.md +9 -3
  159. package/modules/discoveryBidAdapter.js +22 -12
  160. package/modules/feedadBidAdapter.js +35 -15
  161. package/modules/fpdModule/index.md +5 -2
  162. package/modules/freewheel-sspBidAdapter.js +5 -1
  163. package/modules/gridBidAdapter.js +3 -1
  164. package/modules/incrxBidAdapter.js +2 -0
  165. package/modules/ixBidAdapter.js +318 -175
  166. package/modules/kueezRtbBidAdapter.js +54 -20
  167. package/modules/limelightDigitalBidAdapter.js +6 -1
  168. package/modules/limelightDigitalBidAdapter.md +12 -2
  169. package/modules/liveIntentIdSystem.js +1 -1
  170. package/modules/livewrappedBidAdapter.js +28 -16
  171. package/modules/mediagoBidAdapter.js +22 -17
  172. package/modules/minutemediaplusBidAdapter.js +291 -0
  173. package/modules/minutemediaplusBidAdapter.md +35 -0
  174. package/modules/neuwoRtdProvider.js +171 -0
  175. package/modules/neuwoRtdProvider.md +40 -0
  176. package/modules/nextMillenniumBidAdapter.js +9 -1
  177. package/modules/nexx360BidAdapter.js +1 -1
  178. package/modules/prebidServerBidAdapter/ortbConverter.js +6 -0
  179. package/modules/proxistoreBidAdapter.js +2 -2
  180. package/modules/pubmaticBidAdapter.js +4 -0
  181. package/modules/pubxaiAnalyticsAdapter.js +2 -2
  182. package/modules/scatteredBidAdapter.js +72 -0
  183. package/modules/scatteredBidAdapter.md +36 -0
  184. package/modules/sirdataRtdProvider.js +262 -284
  185. package/modules/smartxBidAdapter.js +2 -0
  186. package/modules/smilewantedBidAdapter.js +5 -0
  187. package/modules/sonobiBidAdapter.js +1 -10
  188. package/modules/topicsFpdModule.md +62 -0
  189. package/modules/tripleliftBidAdapter.js +4 -0
  190. package/modules/userId/eids.js +1 -1
  191. package/modules/vidazooBidAdapter.js +3 -1
  192. package/modules/yahoosspBidAdapter.js +1 -1
  193. package/modules/yieldmoBidAdapter.js +1 -0
  194. package/package.json +2 -2
  195. package/src/adapterManager.js +30 -14
  196. package/src/utils.js +1 -1
  197. package/test/spec/modules/33acrossBidAdapter_spec.js +51 -18
  198. package/test/spec/modules/adagioBidAdapter_spec.js +2 -2
  199. package/test/spec/modules/admaruBidAdapter_spec.js +48 -0
  200. package/test/spec/modules/aidemBidAdapter_spec.js +77 -10
  201. package/test/spec/modules/ajaBidAdapter_spec.js +21 -1
  202. package/test/spec/modules/aolBidAdapter_spec.js +2 -2
  203. package/test/spec/modules/appnexusBidAdapter_spec.js +123 -16
  204. package/test/spec/modules/brightcomSSPBidAdapter_spec.js +411 -0
  205. package/test/spec/modules/criteoBidAdapter_spec.js +24 -1
  206. package/test/spec/modules/eids_spec.js +1 -1
  207. package/test/spec/modules/feedadBidAdapter_spec.js +47 -77
  208. package/test/spec/modules/freewheel-sspBidAdapter_spec.js +1 -1
  209. package/test/spec/modules/incrxBidAdapter_spec.js +4 -0
  210. package/test/spec/modules/ixBidAdapter_spec.js +24 -54
  211. package/test/spec/modules/kueezRtbBidAdapter_spec.js +63 -22
  212. package/test/spec/modules/limelightDigitalBidAdapter_spec.js +35 -5
  213. package/test/spec/modules/livewrappedBidAdapter_spec.js +267 -2
  214. package/test/spec/modules/minutemediaplusBidAdapter_spec.js +519 -0
  215. package/test/spec/modules/neuwoRtdProvider_spec.js +123 -0
  216. package/test/spec/modules/nextMillenniumBidAdapter_spec.js +11 -0
  217. package/test/spec/modules/prebidServerBidAdapter_spec.js +56 -0
  218. package/test/spec/modules/proxistoreBidAdapter_spec.js +2 -2
  219. package/test/spec/modules/pubmaticBidAdapter_spec.js +15 -0
  220. package/test/spec/modules/pubxaiAnalyticsAdapter_spec.js +3 -1
  221. package/test/spec/modules/scatteredBidAdapter_spec.js +210 -0
  222. package/test/spec/modules/sirdataRtdProvider_spec.js +116 -22
  223. package/test/spec/modules/smilewantedBidAdapter_spec.js +54 -3
  224. package/test/spec/modules/sonobiBidAdapter_spec.js +3 -25
  225. package/test/spec/modules/tripleliftBidAdapter_spec.js +9 -2
  226. package/test/spec/modules/userId_spec.js +1 -1
  227. package/test/spec/modules/vidazooBidAdapter_spec.js +4 -1
  228. package/test/spec/modules/yahoosspBidAdapter_spec.js +1 -1
  229. package/test/spec/unit/core/adapterManager_spec.js +147 -0
@@ -76,7 +76,8 @@ const SOURCE_RTI_MAPPING = {
76
76
  'epsilon.com': '', // Publisher Link, publinkId
77
77
  'audigent.com': '', // Hadron ID from Audigent, hadronId
78
78
  'pubcid.org': '', // SharedID, pubcid
79
- 'trustpid.com': '' // Trustpid
79
+ 'trustpid.com': '', // Trustpid
80
+ 'intimatemerger.com': ''
80
81
  };
81
82
  const PROVIDERS = [
82
83
  'britepoolid',
@@ -151,6 +152,11 @@ const MEDIA_TYPES = {
151
152
  Native: 4
152
153
  };
153
154
 
155
+ let baseRequestSize = 0;
156
+ let currentRequestSize = 0;
157
+ let wasAdUnitImpressionsTrimmed = false;
158
+ let currentImpressionSize = 0;
159
+
154
160
  /**
155
161
  * Transform valid bid request config object to banner impression object that will be sent to ad server.
156
162
  *
@@ -592,34 +598,23 @@ function getEidInfo(allEids) {
592
598
  *
593
599
  */
594
600
  function buildRequest(validBidRequests, bidderRequest, impressions, version) {
601
+ baseRequestSize = 0;
602
+ currentRequestSize = 0;
603
+ wasAdUnitImpressionsTrimmed = false;
604
+ currentImpressionSize = 0;
605
+
595
606
  // Always use secure HTTPS protocol.
596
607
  let baseUrl = SECURE_BID_URL;
597
608
  // Get ids from Prebid User ID Modules
598
609
  let eidInfo = getEidInfo(deepAccess(validBidRequests, '0.userIdAsEids'));
599
610
  let userEids = eidInfo.toSend;
600
- const pageUrl = deepAccess(bidderRequest, 'refererInfo.page');
601
611
 
602
612
  let MAX_REQUEST_SIZE = 8000;
603
- // Modify request size limit if its FT is enabeld.
604
- if (FEATURE_TOGGLES.isFeatureEnabled('pbjs_use_32kb_size_limit')) {
605
- MAX_REQUEST_SIZE = 32000
606
- }
607
613
 
608
614
  // RTI ids will be included in the bid request if the function getIdentityInfo() is loaded
609
615
  // and if the data for the partner exist
610
616
  if (window.headertag && typeof window.headertag.getIdentityInfo === 'function') {
611
- let identityInfo = window.headertag.getIdentityInfo();
612
- if (identityInfo && typeof identityInfo === 'object') {
613
- for (const partnerName in identityInfo) {
614
- if (identityInfo.hasOwnProperty(partnerName)) {
615
- let response = identityInfo[partnerName];
616
- if (!response.responsePending && response.data && typeof response.data === 'object' &&
617
- Object.keys(response.data).length && !eidInfo.seenSources[response.data.source]) {
618
- userEids.push(response.data);
619
- }
620
- }
621
- }
622
- }
617
+ addRTI(userEids, eidInfo);
623
618
  }
624
619
 
625
620
  // If `roundel` alias bidder, only send requests if liveramp ids exist.
@@ -627,8 +622,123 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
627
622
  return [];
628
623
  }
629
624
 
625
+ const requests = [];
626
+ let r = createRequest(validBidRequests);
627
+
628
+ // getting ixdiags for adunits of the video, outstream & multi format (MF) style
629
+ let ixdiag = buildIXDiag(validBidRequests);
630
+ for (var key in ixdiag) {
631
+ r.ext.ixdiag[key] = ixdiag[key];
632
+ }
633
+
634
+ r = enrichRequest(r, bidderRequest, impressions, validBidRequests, userEids);
635
+
636
+ r = applyRegulations(r, bidderRequest);
637
+
638
+ let payload = {};
639
+ createPayload(validBidRequests, bidderRequest, r, baseUrl, requests, payload, MAX_REQUEST_SIZE);
640
+
641
+ let requestSequenceNumber = 0;
642
+ const transactionIds = Object.keys(impressions);
643
+ let isFpdAdded = false;
644
+
645
+ for (let adUnitIndex = 0; adUnitIndex < transactionIds.length; adUnitIndex++) {
646
+ // buildRequestV2 does not have request spliting logic.
647
+ if (!FEATURE_TOGGLES.isFeatureEnabled('pbjs_use_buildRequestV2')) {
648
+ if (currentRequestSize >= MAX_REQUEST_SIZE) {
649
+ break;
650
+ }
651
+ }
652
+ if (requests.length >= MAX_REQUEST_LIMIT) {
653
+ break;
654
+ }
655
+
656
+ r = addImpressions(impressions, transactionIds, r, adUnitIndex, MAX_REQUEST_SIZE);
657
+ currentRequestSize += currentImpressionSize;
658
+
659
+ const fpd = deepAccess(bidderRequest, 'ortb2') || {};
660
+ const site = { ...(fpd.site || fpd.context) };
661
+ const user = { ...fpd.user };
662
+ if (!isEmpty(fpd) && !isFpdAdded) {
663
+ r = addFPD(bidderRequest, r, fpd, site, user);
664
+
665
+ const clonedRObject = deepClone(r);
666
+
667
+ clonedRObject.site = mergeDeep({}, clonedRObject.site, site);
668
+ clonedRObject.user = mergeDeep({}, clonedRObject.user, user);
669
+
670
+ const requestSize = `${baseUrl}${parseQueryStringParameters({ ...payload, r: JSON.stringify(clonedRObject) })}`.length;
671
+
672
+ if (requestSize < MAX_REQUEST_SIZE) {
673
+ r.site = mergeDeep({}, r.site, site);
674
+ r.user = mergeDeep({}, r.user, user);
675
+ isFpdAdded = true;
676
+ const fpdRequestSize = encodeURIComponent(JSON.stringify({ ...site, ...user })).length;
677
+ currentRequestSize += fpdRequestSize;
678
+ } else {
679
+ logError('IX Bid Adapter: FPD request size has exceeded maximum request size.', { bidder: BIDDER_CODE, code: ERROR_CODES.PB_FPD_EXCEEDS_MAX_SIZE });
680
+ }
681
+ }
682
+
683
+ // add identifiers info to ixDiag
684
+ r = addIdentifiersInfo(impressions, r, transactionIds, adUnitIndex, payload, baseUrl, MAX_REQUEST_SIZE);
685
+
686
+ const isLastAdUnit = adUnitIndex === transactionIds.length - 1;
687
+
688
+ if (wasAdUnitImpressionsTrimmed || isLastAdUnit) {
689
+ if (!isLastAdUnit || requestSequenceNumber) {
690
+ r.ext.ixdiag.sn = requestSequenceNumber;
691
+ }
692
+
693
+ requestSequenceNumber++;
694
+
695
+ requests.push({
696
+ method: 'POST',
697
+ url: baseUrl + '?s=' + siteID,
698
+ data: deepClone(r),
699
+ option: {
700
+ contentType: 'text/plain',
701
+ },
702
+ validBidRequests
703
+ });
704
+
705
+ currentRequestSize = baseRequestSize;
706
+ r.imp = [];
707
+ isFpdAdded = false;
708
+ }
709
+ }
710
+
711
+ return requests;
712
+ }
713
+
714
+ /**
715
+ * addRTI adds RTI info of the partner to retrieved user IDs from prebid ID module.
716
+ *
717
+ * @param {array} userEids userEids info retrieved from prebid
718
+ * @param {array} eidInfo eidInfo info from prebid
719
+ */
720
+ function addRTI(userEids, eidInfo) {
721
+ let identityInfo = window.headertag.getIdentityInfo();
722
+ if (identityInfo && typeof identityInfo === 'object') {
723
+ for (const partnerName in identityInfo) {
724
+ if (identityInfo.hasOwnProperty(partnerName)) {
725
+ let response = identityInfo[partnerName];
726
+ if (!response.responsePending && response.data && typeof response.data === 'object' &&
727
+ Object.keys(response.data).length && !eidInfo.seenSources[response.data.source]) {
728
+ userEids.push(response.data);
729
+ }
730
+ }
731
+ }
732
+ }
733
+ }
734
+
735
+ /**
736
+ * createRequest creates the base request object
737
+ * @param {array} validBidRequests A list of valid bid request config objects.
738
+ * @return {object} Object describing the request to the server.
739
+ */
740
+ function createRequest(validBidRequests) {
630
741
  const r = {};
631
- const tmax = deepAccess(bidderRequest, 'timeout');
632
742
  // Since bidderRequestId are the same for different bid request, just use the first one.
633
743
  r.id = validBidRequests[0].bidderRequestId.toString();
634
744
  r.site = {};
@@ -638,13 +748,21 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
638
748
  r.ext.ixdiag.ls = storage.localStorageIsEnabled();
639
749
  r.imp = [];
640
750
  r.at = 1;
751
+ return r
752
+ }
641
753
 
642
- // getting ixdiags for adunits of the video, outstream & multi format (MF) style
643
- let ixdiag = buildIXDiag(validBidRequests);
644
- for (var key in ixdiag) {
645
- r.ext.ixdiag[key] = ixdiag[key];
646
- }
647
-
754
+ /**
755
+ * enrichRequest adds userSync configs, source, and referer info to request and ixDiag objects.
756
+ *
757
+ * @param {object} r Base reuqest object.
758
+ * @param {object} bidderRequest An object containing other info like gdprConsent.
759
+ * @param {array} impressions A list of impressions to be added to the request.
760
+ * @param {array} validBidRequests A list of valid bid request config objects.
761
+ * @param {array} userEids User ID info retrieved from Prebid ID module.
762
+ * @return {object} Enriched object describing the request to the server.
763
+ */
764
+ function enrichRequest(r, bidderRequest, impressions, validBidRequests, userEids) {
765
+ const tmax = deepAccess(bidderRequest, 'timeout');
648
766
  if (tmax) {
649
767
  r.ext.ixdiag.tmax = tmax;
650
768
  }
@@ -683,6 +801,17 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
683
801
  r.site.ref = document.referrer;
684
802
  }
685
803
 
804
+ return r
805
+ }
806
+
807
+ /**
808
+ * applyRegulations applies regulation info such as GDPR and GPP to the reqeust obejct.
809
+ *
810
+ * @param {object} r Base reuqest object.
811
+ * @param {object} bidderRequest An object containing other info like gdprConsent.
812
+ * @return {object} Object enriched with regulation info describing the request to the server.
813
+ */
814
+ function applyRegulations(r, bidderRequest) {
686
815
  // Apply GDPR information to the request if GDPR is enabled.
687
816
  if (bidderRequest) {
688
817
  if (bidderRequest.gdprConsent) {
@@ -715,6 +844,7 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
715
844
  usPrivacy = bidderRequest.uspConsent;
716
845
  }
717
846
 
847
+ const pageUrl = deepAccess(bidderRequest, 'refererInfo.page');
718
848
  if (pageUrl) {
719
849
  r.site.page = pageUrl;
720
850
  }
@@ -729,7 +859,21 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
729
859
  deepSetValue(r, 'regs.coppa', 1);
730
860
  }
731
861
 
732
- const payload = {};
862
+ return r
863
+ }
864
+
865
+ /**
866
+ * createPayload creates the payload to be sent with the request.
867
+ *
868
+ * @param {array} validBidRequests A list of valid bid request config objects.
869
+ * @param {object} bidderRequest An object containing other info like gdprConsent.
870
+ * @param {object} r Reuqest object.
871
+ * @param {string} baseUrl Base exchagne URL.
872
+ * @param {array} requests List of request obejcts.
873
+ * @param {object} payload Request payload object.
874
+ * @param {int} MAX_REQUEST_SIZE Maximum request size limit (buildrequest V1).
875
+ */
876
+ function createPayload(validBidRequests, bidderRequest, r, baseUrl, requests, payload, MAX_REQUEST_SIZE) {
733
877
  // Use the siteId in the first bid request as the main siteId.
734
878
  siteID = validBidRequests[0].params.siteId;
735
879
  payload.s = siteID;
@@ -737,19 +881,16 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
737
881
  // Parse additional runtime configs.
738
882
  const bidderCode = (bidderRequest && bidderRequest.bidderCode) || 'ix';
739
883
  const otherIxConfig = config.getConfig(bidderCode);
740
- const requests = [];
741
- let requestSequenceNumber = 0;
742
- const transactionIds = Object.keys(impressions);
743
- const baseRequestSize = `${baseUrl}${parseQueryStringParameters({ ...payload, r: JSON.stringify(r) })}`.length;
884
+
885
+ baseRequestSize = `${baseUrl}${parseQueryStringParameters({ ...payload, r: JSON.stringify(r) })}`.length;
744
886
 
745
887
  if (baseRequestSize > MAX_REQUEST_SIZE) {
746
888
  logError('IX Bid Adapter: Base request size has exceeded maximum request size.', { bidder: BIDDER_CODE, code: ERROR_CODES.EXCEEDS_MAX_SIZE });
747
889
  return requests;
748
890
  }
749
891
 
750
- let currentRequestSize = baseRequestSize;
892
+ currentRequestSize = baseRequestSize;
751
893
  let fpdRequestSize = 0;
752
- let isFpdAdded = false;
753
894
 
754
895
  if (otherIxConfig) {
755
896
  // Append firstPartyData to r.site.page if firstPartyData exists.
@@ -765,196 +906,198 @@ function buildRequest(validBidRequests, bidderRequest, impressions, version) {
765
906
 
766
907
  fpdRequestSize = encodeURIComponent(firstPartyString).length;
767
908
 
768
- if (fpdRequestSize < MAX_REQUEST_SIZE) {
909
+ if (!FEATURE_TOGGLES.isFeatureEnabled('pbjs_use_buildRequestV2')) {
910
+ if (fpdRequestSize < MAX_REQUEST_SIZE) {
911
+ if ('page' in r.site) {
912
+ r.site.page += firstPartyString;
913
+ } else {
914
+ r.site.page = firstPartyString;
915
+ }
916
+ currentRequestSize += fpdRequestSize;
917
+ } else {
918
+ logError('IX Bid Adapter: IX config FPD request size has exceeded maximum request size.', { bidder: BIDDER_CODE, code: ERROR_CODES.IX_FPD_EXCEEDS_MAX_SIZE });
919
+ }
920
+ } else {
769
921
  if ('page' in r.site) {
770
922
  r.site.page += firstPartyString;
771
923
  } else {
772
924
  r.site.page = firstPartyString;
773
925
  }
774
- currentRequestSize += fpdRequestSize;
775
- } else {
776
- logError('IX Bid Adapter: IX config FPD request size has exceeded maximum request size.', { bidder: BIDDER_CODE, code: ERROR_CODES.IX_FPD_EXCEEDS_MAX_SIZE });
777
926
  }
778
927
  }
779
928
  }
929
+ }
780
930
 
781
- for (let adUnitIndex = 0; adUnitIndex < transactionIds.length; adUnitIndex++) {
782
- if (currentRequestSize >= MAX_REQUEST_SIZE || requests.length >= MAX_REQUEST_LIMIT) {
783
- break;
784
- }
931
+ /**
932
+ * addImpressions adds impressions to request object
933
+ *
934
+ * @param {array} impressions List of impressions to be added to the request.
935
+ * @param {array} transactionIds List of transaction Ids.
936
+ * @param {object} r Reuqest object.
937
+ * @param {int} adUnitIndex Index of the current add unit
938
+ * @param {int} MAX_REQUEST_SIZE Maximum request size limit (buildrequest V1).
939
+ * @return {object} Reqyest object with added impressions describing the request to the server.
940
+ */
941
+ function addImpressions(impressions, transactionIds, r, adUnitIndex, MAX_REQUEST_SIZE) {
942
+ const adUnitImpressions = impressions[transactionIds[adUnitIndex]];
943
+ const { missingImps: missingBannerImpressions = [], ixImps = [] } = adUnitImpressions;
785
944
 
786
- const adUnitImpressions = impressions[transactionIds[adUnitIndex]];
787
- const { missingImps: missingBannerImpressions = [], ixImps = [] } = adUnitImpressions;
788
- let wasAdUnitImpressionsTrimmed = false;
789
- let remainingRequestSize = MAX_REQUEST_SIZE - currentRequestSize;
790
- const sourceImpressions = { ixImps, missingBannerImpressions };
791
- const impressionObjects = Object.keys(sourceImpressions)
792
- .map((key) => sourceImpressions[key])
793
- .filter(item => Array.isArray(item))
794
- .reduce((acc, curr) => acc.concat(...curr), []);
945
+ let remainingRequestSize = MAX_REQUEST_SIZE - currentRequestSize;
946
+ const sourceImpressions = { ixImps, missingBannerImpressions };
947
+ const impressionObjects = Object.keys(sourceImpressions)
948
+ .map((key) => sourceImpressions[key])
949
+ .filter(item => Array.isArray(item))
950
+ .reduce((acc, curr) => acc.concat(...curr), []);
795
951
 
796
- let currentImpressionSize = encodeURIComponent(JSON.stringify({ impressionObjects })).length;
952
+ currentImpressionSize = encodeURIComponent(JSON.stringify({ impressionObjects })).length;
797
953
 
954
+ if (!FEATURE_TOGGLES.isFeatureEnabled('pbjs_use_buildRequestV2')) {
798
955
  while (impressionObjects.length && currentImpressionSize > remainingRequestSize) {
799
956
  wasAdUnitImpressionsTrimmed = true;
800
957
  impressionObjects.pop();
801
958
  currentImpressionSize = encodeURIComponent(JSON.stringify({ impressionObjects })).length;
802
959
  }
960
+ }
803
961
 
804
- const gpid = impressions[transactionIds[adUnitIndex]].gpid;
805
- const dfpAdUnitCode = impressions[transactionIds[adUnitIndex]].dfp_ad_unit_code;
806
- const tid = impressions[transactionIds[adUnitIndex]].tid;
807
- const sid = impressions[transactionIds[adUnitIndex]].sid
808
-
809
- if (impressionObjects.length && BANNER in impressionObjects[0]) {
810
- const { id, banner: { topframe } } = impressionObjects[0];
811
- const _bannerImpression = {
812
- id,
813
- banner: {
814
- topframe,
815
- format: impressionObjects.map(({ banner: { w, h }, ext }) => ({ w, h, ext }))
816
- },
817
- };
818
-
819
- for (let i = 0; i < _bannerImpression.banner.format.length; i++) {
820
- // We add sid in imp.ext.sid therefore, remove from banner.format[].ext
821
- if (_bannerImpression.banner.format[i].ext != null && _bannerImpression.banner.format[i].ext.sid != null) {
822
- delete _bannerImpression.banner.format[i].ext.sid;
823
- }
824
-
825
- // add floor per size
826
- if ('bidfloor' in impressionObjects[i]) {
827
- _bannerImpression.banner.format[i].ext.bidfloor = impressionObjects[i].bidfloor
828
- }
829
- }
830
-
831
- const position = impressions[transactionIds[adUnitIndex]].pos;
832
- if (isInteger(position)) {
833
- _bannerImpression.banner.pos = position;
834
- }
962
+ const gpid = impressions[transactionIds[adUnitIndex]].gpid;
963
+ const dfpAdUnitCode = impressions[transactionIds[adUnitIndex]].dfp_ad_unit_code;
964
+ const tid = impressions[transactionIds[adUnitIndex]].tid;
965
+ const sid = impressions[transactionIds[adUnitIndex]].sid
835
966
 
836
- if (dfpAdUnitCode || gpid || tid || sid) {
837
- _bannerImpression.ext = {};
838
- _bannerImpression.ext.dfp_ad_unit_code = dfpAdUnitCode;
839
- _bannerImpression.ext.gpid = gpid;
840
- _bannerImpression.ext.tid = tid;
841
- _bannerImpression.ext.sid = sid;
842
- }
967
+ if (impressionObjects.length && BANNER in impressionObjects[0]) {
968
+ const { id, banner: { topframe } } = impressionObjects[0];
969
+ const _bannerImpression = {
970
+ id,
971
+ banner: {
972
+ topframe,
973
+ format: impressionObjects.map(({ banner: { w, h }, ext }) => ({ w, h, ext }))
974
+ },
975
+ };
843
976
 
844
- if ('bidfloor' in impressionObjects[0]) {
845
- _bannerImpression.bidfloor = impressionObjects[0].bidfloor;
977
+ for (let i = 0; i < _bannerImpression.banner.format.length; i++) {
978
+ // We add sid in imp.ext.sid therefore, remove from banner.format[].ext
979
+ if (_bannerImpression.banner.format[i].ext != null && _bannerImpression.banner.format[i].ext.sid != null) {
980
+ delete _bannerImpression.banner.format[i].ext.sid;
846
981
  }
847
982
 
848
- if ('bidfloorcur' in impressionObjects[0]) {
849
- _bannerImpression.bidfloorcur = impressionObjects[0].bidfloorcur;
983
+ // add floor per size
984
+ if ('bidfloor' in impressionObjects[i]) {
985
+ _bannerImpression.banner.format[i].ext.bidfloor = impressionObjects[i].bidfloor;
850
986
  }
851
-
852
- r.imp.push(_bannerImpression);
853
- } else {
854
- // set imp.ext.gpid to resolved gpid for each imp
855
- impressionObjects.forEach(imp => deepSetValue(imp, 'ext.gpid', gpid));
856
- r.imp.push(...impressionObjects);
857
987
  }
858
988
 
859
- currentRequestSize += currentImpressionSize;
860
-
861
- const fpd = deepAccess(bidderRequest, 'ortb2') || {};
862
- if (!isEmpty(fpd) && !isFpdAdded) {
863
- r.ext.ixdiag.fpd = true;
989
+ const position = impressions[transactionIds[adUnitIndex]].pos;
990
+ if (isInteger(position)) {
991
+ _bannerImpression.banner.pos = position;
992
+ }
864
993
 
865
- const site = { ...(fpd.site || fpd.context) };
994
+ if (dfpAdUnitCode || gpid || tid || sid) {
995
+ _bannerImpression.ext = {};
996
+ _bannerImpression.ext.dfp_ad_unit_code = dfpAdUnitCode;
997
+ _bannerImpression.ext.gpid = gpid;
998
+ _bannerImpression.ext.tid = tid;
999
+ _bannerImpression.ext.sid = sid;
1000
+ }
866
1001
 
867
- Object.keys(site).forEach(key => {
868
- if (FIRST_PARTY_DATA.SITE.indexOf(key) === -1) {
869
- delete site[key];
870
- }
871
- });
1002
+ if ('bidfloor' in impressionObjects[0]) {
1003
+ _bannerImpression.bidfloor = impressionObjects[0].bidfloor;
1004
+ }
872
1005
 
873
- const user = { ...fpd.user };
1006
+ if ('bidfloorcur' in impressionObjects[0]) {
1007
+ _bannerImpression.bidfloorcur = impressionObjects[0].bidfloorcur;
1008
+ }
874
1009
 
875
- Object.keys(user).forEach(key => {
876
- if (FIRST_PARTY_DATA.USER.indexOf(key) === -1) {
877
- delete user[key];
878
- }
879
- });
1010
+ r.imp.push(_bannerImpression);
1011
+ } else {
1012
+ // set imp.ext.gpid to resolved gpid for each imp
1013
+ impressionObjects.forEach(imp => deepSetValue(imp, 'ext.gpid', gpid));
1014
+ r.imp.push(...impressionObjects);
1015
+ }
880
1016
 
881
- if (fpd.device) {
882
- const sua = {...fpd.device.sua};
883
- if (!isEmpty(sua)) {
884
- deepSetValue(r, 'device.sua', sua);
885
- }
886
- }
1017
+ return r;
1018
+ }
887
1019
 
888
- if (fpd.hasOwnProperty('regs') && !bidderRequest.gppConsent) {
889
- if (fpd.regs.hasOwnProperty('gpp') && typeof fpd.regs.gpp == 'string') {
890
- deepSetValue(r, 'regs.gpp', fpd.regs.gpp)
891
- }
1020
+ /**
1021
+ * addFPD adds ortb2 first party data to request object.
1022
+ *
1023
+ * @param {object} bidderRequest An object containing other info like gdprConsent.
1024
+ * @param {object} r Reuqest object.
1025
+ * @param {object} fpd ortb2 first party data.
1026
+ * @param {object} site First party site data.
1027
+ * @param {object} user First party user data.
1028
+ * @return {object} Reqyest object with added FPD describing the request to the server.
1029
+ */
1030
+ function addFPD(bidderRequest, r, fpd, site, user) {
1031
+ r.ext.ixdiag.fpd = true;
892
1032
 
893
- if (fpd.regs.hasOwnProperty('gpp_sid') && Array.isArray(fpd.regs.gpp_sid)) {
894
- deepSetValue(r, 'regs.gpp_sid', fpd.regs.gpp_sid)
895
- }
896
- }
1033
+ Object.keys(site).forEach(key => {
1034
+ if (FIRST_PARTY_DATA.SITE.indexOf(key) === -1) {
1035
+ delete site[key];
1036
+ }
1037
+ });
897
1038
 
898
- const clonedRObject = deepClone(r);
1039
+ Object.keys(user).forEach(key => {
1040
+ if (FIRST_PARTY_DATA.USER.indexOf(key) === -1) {
1041
+ delete user[key];
1042
+ }
1043
+ });
899
1044
 
900
- clonedRObject.site = mergeDeep({}, clonedRObject.site, site);
901
- clonedRObject.user = mergeDeep({}, clonedRObject.user, user);
1045
+ if (fpd.device) {
1046
+ const sua = {...fpd.device.sua};
1047
+ if (!isEmpty(sua)) {
1048
+ deepSetValue(r, 'device.sua', sua);
1049
+ }
1050
+ }
902
1051
 
903
- const requestSize = `${baseUrl}${parseQueryStringParameters({ ...payload, r: JSON.stringify(clonedRObject) })}`.length;
1052
+ if (fpd.hasOwnProperty('regs') && !bidderRequest.gppConsent) {
1053
+ if (fpd.regs.hasOwnProperty('gpp') && typeof fpd.regs.gpp == 'string') {
1054
+ deepSetValue(r, 'regs.gpp', fpd.regs.gpp)
1055
+ }
904
1056
 
905
- if (requestSize < MAX_REQUEST_SIZE) {
906
- r.site = mergeDeep({}, r.site, site);
907
- r.user = mergeDeep({}, r.user, user);
908
- isFpdAdded = true;
909
- const fpdRequestSize = encodeURIComponent(JSON.stringify({ ...site, ...user })).length;
910
- currentRequestSize += fpdRequestSize;
911
- } else {
912
- logError('IX Bid Adapter: FPD request size has exceeded maximum request size.', { bidder: BIDDER_CODE, code: ERROR_CODES.PB_FPD_EXCEEDS_MAX_SIZE });
913
- }
1057
+ if (fpd.regs.hasOwnProperty('gpp_sid') && Array.isArray(fpd.regs.gpp_sid)) {
1058
+ deepSetValue(r, 'regs.gpp_sid', fpd.regs.gpp_sid)
914
1059
  }
1060
+ }
915
1061
 
916
- // add identifiers info to ixDiag
917
- const pbaAdSlot = impressions[transactionIds[adUnitIndex]].pbadslot;
918
- const tagId = impressions[transactionIds[adUnitIndex]].tagId;
919
- const adUnitCode = impressions[transactionIds[adUnitIndex]].adUnitCode;
920
- const divId = impressions[transactionIds[adUnitIndex]].divId;
921
- if (pbaAdSlot || tagId || adUnitCode || divId) {
922
- const clonedRObject = deepClone(r);
923
- const requestSize = `${baseUrl}${parseQueryStringParameters({ ...payload, r: JSON.stringify(clonedRObject) })}`.length;
1062
+ return r;
1063
+ }
1064
+
1065
+ /**
1066
+ * addIdentifiersInfo adds indentifier info to ixDaig.
1067
+ *
1068
+ * @param {array} impressions List of impressions to be added to the request.
1069
+ * @param {object} r Reuqest object.
1070
+ * @param {array} transactionIds List of transaction Ids.
1071
+ * @param {int} adUnitIndex Index of the current add unit
1072
+ * @param {object} payload Request payload object.
1073
+ * @param {string} baseUrl Base exchagne URL.
1074
+ * @param {int} MAX_REQUEST_SIZE Maximum request size limit (buildrequest V1).
1075
+ * @return {object} Reqyest object with added indentigfier info to ixDiag.
1076
+ */
1077
+ function addIdentifiersInfo(impressions, r, transactionIds, adUnitIndex, payload, baseUrl, MAX_REQUEST_SIZE) {
1078
+ const pbaAdSlot = impressions[transactionIds[adUnitIndex]].pbadslot;
1079
+ const tagId = impressions[transactionIds[adUnitIndex]].tagId;
1080
+ const adUnitCode = impressions[transactionIds[adUnitIndex]].adUnitCode;
1081
+ const divId = impressions[transactionIds[adUnitIndex]].divId;
1082
+ if (pbaAdSlot || tagId || adUnitCode || divId) {
1083
+ const clonedRObject = deepClone(r);
1084
+ const requestSize = `${baseUrl}${parseQueryStringParameters({ ...payload, r: JSON.stringify(clonedRObject) })}`.length;
1085
+ if (!FEATURE_TOGGLES.isFeatureEnabled('pbjs_use_buildRequestV2')) {
924
1086
  if (requestSize < MAX_REQUEST_SIZE) {
925
1087
  r.ext.ixdiag.pbadslot = pbaAdSlot;
926
1088
  r.ext.ixdiag.tagid = tagId;
927
1089
  r.ext.ixdiag.adunitcode = adUnitCode;
928
1090
  r.ext.ixdiag.divId = divId;
929
1091
  }
930
- }
931
-
932
- const isLastAdUnit = adUnitIndex === transactionIds.length - 1;
933
-
934
- if (wasAdUnitImpressionsTrimmed || isLastAdUnit) {
935
- if (!isLastAdUnit || requestSequenceNumber) {
936
- r.ext.ixdiag.sn = requestSequenceNumber;
937
- }
938
-
939
- requestSequenceNumber++;
940
-
941
- requests.push({
942
- method: 'POST',
943
- url: baseUrl + '?s=' + siteID,
944
- data: deepClone(r),
945
- option: {
946
- contentType: 'text/plain',
947
- },
948
- validBidRequests
949
- });
950
-
951
- currentRequestSize = baseRequestSize;
952
- r.imp = [];
953
- isFpdAdded = false;
1092
+ } else {
1093
+ r.ext.ixdiag.pbadslot = pbaAdSlot;
1094
+ r.ext.ixdiag.tagid = tagId;
1095
+ r.ext.ixdiag.adunitcode = adUnitCode;
1096
+ r.ext.ixdiag.divId = divId;
954
1097
  }
955
1098
  }
956
1099
 
957
- return requests;
1100
+ return r;
958
1101
  }
959
1102
 
960
1103
  /**