prebid.js 8.8.0 → 8.9.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 (297) hide show
  1. package/dist/1plusXRtdProvider.js +1 -1
  2. package/dist/33acrossBidAdapter.js +1 -1
  3. package/dist/33acrossIdSystem.js +1 -1
  4. package/dist/adWMGAnalyticsAdapter.js +1 -1
  5. package/dist/adagioBidAdapter.js +1 -1
  6. package/dist/adbookpspBidAdapter.js +1 -1
  7. package/dist/adgenerationBidAdapter.js +1 -1
  8. package/dist/adkernelAdnAnalyticsAdapter.js +1 -1
  9. package/dist/adlooxAdServerVideo.js +1 -1
  10. package/dist/adlooxRtdProvider.js +1 -1
  11. package/dist/admixerIdSystem.js +1 -1
  12. package/dist/adnuntiusRtdProvider.js +1 -1
  13. package/dist/adpartnerBidAdapter.js +1 -1
  14. package/dist/adqueryBidAdapter.js +1 -1
  15. package/dist/adqueryIdSystem.js +1 -1
  16. package/dist/adrelevantisBidAdapter.js +1 -1
  17. package/dist/adriverIdSystem.js +1 -1
  18. package/dist/adtelligentIdSystem.js +1 -1
  19. package/dist/adtrgtmeBidAdapter.js +1 -1
  20. package/dist/adxcgAnalyticsAdapter.js +1 -1
  21. package/dist/adxcgBidAdapter.js +1 -1
  22. package/dist/adxpremiumAnalyticsAdapter.js +1 -1
  23. package/dist/adyoulikeBidAdapter.js +1 -1
  24. package/dist/aidemBidAdapter.js +1 -1
  25. package/dist/ajaBidAdapter.js +1 -1
  26. package/dist/akamaiDapRtdProvider.js +1 -1
  27. package/dist/alkimiBidAdapter.js +1 -1
  28. package/dist/amxBidAdapter.js +1 -1
  29. package/dist/amxIdSystem.js +1 -1
  30. package/dist/analyticsAdapter.js +1 -1
  31. package/dist/appierAnalyticsAdapter.js +1 -1
  32. package/dist/appnexusBidAdapter.js +1 -1
  33. package/dist/asoBidAdapter.js +1 -1
  34. package/dist/atsAnalyticsAdapter.js +1 -1
  35. package/dist/automatadBidAdapter.js +1 -1
  36. package/dist/axonixBidAdapter.js +1 -1
  37. package/dist/bidglassBidAdapter.js +1 -1
  38. package/dist/bidwatchAnalyticsAdapter.js +1 -1
  39. package/dist/big-richmediaBidAdapter.js +1 -1
  40. package/dist/bridBidAdapter.js +1 -1
  41. package/dist/bridgewellBidAdapter.js +1 -1
  42. package/dist/brightMountainMediaBidAdapter.js +1 -1
  43. package/dist/brightcomSSPBidAdapter.js +1 -1
  44. package/dist/britepoolIdSystem.js +1 -1
  45. package/dist/browsiRtdProvider.js +1 -1
  46. package/dist/byDataAnalyticsAdapter.js +1 -1
  47. package/dist/carodaBidAdapter.js +1 -1
  48. package/dist/categoryTranslation.js +1 -1
  49. package/dist/chtnwBidAdapter.js +1 -1
  50. package/dist/colossussspBidAdapter.js +1 -1
  51. package/dist/concertAnalyticsAdapter.js +1 -1
  52. package/dist/concertBidAdapter.js +1 -1
  53. package/dist/connectIdSystem.js +1 -1
  54. package/dist/connectadBidAdapter.js +1 -1
  55. package/dist/consumableBidAdapter.js +1 -1
  56. package/dist/conversantAnalyticsAdapter.js +1 -1
  57. package/dist/conversantBidAdapter.js +1 -1
  58. package/dist/craftBidAdapter.js +1 -1
  59. package/dist/criteoBidAdapter.js +1 -1
  60. package/dist/criteoIdSystem.js +1 -1
  61. package/dist/currency.js +1 -1
  62. package/dist/cwireBidAdapter.js +1 -1
  63. package/dist/dacIdSystem.js +1 -1
  64. package/dist/dailyhuntBidAdapter.js +1 -1
  65. package/dist/datablocksBidAdapter.js +1 -1
  66. package/dist/dgkeywordRtdProvider.js +1 -1
  67. package/dist/dmdIdSystem.js +1 -1
  68. package/dist/dspxBidAdapter.js +1 -1
  69. package/dist/eplanningAnalyticsAdapter.js +1 -1
  70. package/dist/eplanningBidAdapter.js +1 -1
  71. package/dist/euidIdSystem.js +1 -1
  72. package/dist/fabrickIdSystem.js +1 -1
  73. package/dist/feedadBidAdapter.js +1 -1
  74. package/dist/finativeBidAdapter.js +1 -1
  75. package/dist/fintezaAnalyticsAdapter.js +1 -1
  76. package/dist/fledgeForGpt.js +1 -1
  77. package/dist/freewheel-sspBidAdapter.js +1 -1
  78. package/dist/genericAnalyticsAdapter.js +1 -1
  79. package/dist/geoedgeRtdProvider.js +1 -1
  80. package/dist/gmosspBidAdapter.js +1 -1
  81. package/dist/gnetBidAdapter.js +1 -1
  82. package/dist/goldbachBidAdapter.js +1 -1
  83. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  84. package/dist/greenbidsRtdProvider.js +1 -1
  85. package/dist/gridBidAdapter.js +1 -1
  86. package/dist/growthCodeAnalyticsAdapter.js +1 -1
  87. package/dist/growthCodeIdSystem.js +1 -1
  88. package/dist/growthCodeRtdProvider.js +1 -1
  89. package/dist/gumgumBidAdapter.js +1 -1
  90. package/dist/h12mediaBidAdapter.js +1 -1
  91. package/dist/hadronAnalyticsAdapter.js +1 -1
  92. package/dist/hadronIdSystem.js +1 -1
  93. package/dist/hadronRtdProvider.js +1 -1
  94. package/dist/hypelabBidAdapter.js +1 -1
  95. package/dist/iasRtdProvider.js +1 -1
  96. package/dist/id5AnalyticsAdapter.js +1 -1
  97. package/dist/id5IdSystem.js +1 -1
  98. package/dist/idImportLibrary.js +1 -1
  99. package/dist/identityLinkIdSystem.js +1 -1
  100. package/dist/imRtdProvider.js +1 -1
  101. package/dist/imdsBidAdapter.js +1 -1
  102. package/dist/impactifyBidAdapter.js +1 -1
  103. package/dist/improvedigitalBidAdapter.js +1 -1
  104. package/dist/imuIdSystem.js +1 -1
  105. package/dist/insticatorBidAdapter.js +1 -1
  106. package/dist/intentIqIdSystem.js +1 -1
  107. package/dist/invisiblyAnalyticsAdapter.js +1 -1
  108. package/dist/ixBidAdapter.js +1 -1
  109. package/dist/jixieBidAdapter.js +1 -1
  110. package/dist/justpremiumBidAdapter.js +1 -1
  111. package/dist/jwplayerRtdProvider.js +1 -1
  112. package/dist/kargoAnalyticsAdapter.js +1 -1
  113. package/dist/kargoBidAdapter.js +1 -1
  114. package/dist/kinessoIdSystem.js +1 -1
  115. package/dist/konduitAnalyticsAdapter.js +1 -1
  116. package/dist/konduitWrapper.js +1 -1
  117. package/dist/kueezBidAdapter.js +1 -1
  118. package/dist/kueezRtbBidAdapter.js +1 -1
  119. package/dist/kulturemediaBidAdapter.js +1 -1
  120. package/dist/lassoBidAdapter.js +1 -1
  121. package/dist/lifestreetBidAdapter.js +1 -1
  122. package/dist/limelightDigitalBidAdapter.js +1 -1
  123. package/dist/liveIntentAnalyticsAdapter.js +1 -1
  124. package/dist/liveIntentIdSystem.js +1 -1
  125. package/dist/livewrappedAnalyticsAdapter.js +1 -1
  126. package/dist/logicadBidAdapter.js +1 -1
  127. package/dist/loglyliftBidAdapter.js +1 -1
  128. package/dist/lotamePanoramaIdSystem.js +1 -1
  129. package/dist/luponmediaBidAdapter.js +1 -1
  130. package/dist/magniteAnalyticsAdapter.js +1 -1
  131. package/dist/malltvAnalyticsAdapter.js +1 -1
  132. package/dist/mantisBidAdapter.js +1 -1
  133. package/dist/marsmediaAnalyticsAdapter.js +1 -1
  134. package/dist/marsmediaBidAdapter.js +1 -1
  135. package/dist/mediafuseBidAdapter.js +1 -1
  136. package/dist/medianetAnalyticsAdapter.js +1 -1
  137. package/dist/mediasquareBidAdapter.js +1 -1
  138. package/dist/merkleIdSystem.js +1 -1
  139. package/dist/mgidBidAdapter.js +1 -1
  140. package/dist/mgidRtdProvider.js +1 -1
  141. package/dist/minutemediaBidAdapter.js +1 -1
  142. package/dist/minutemediaplusBidAdapter.js +1 -1
  143. package/dist/mspa.js +1 -1
  144. package/dist/mwOpenLinkIdSystem.js +1 -1
  145. package/dist/naveggIdSystem.js +1 -1
  146. package/dist/neuwoRtdProvider.js +1 -1
  147. package/dist/nexx360BidAdapter.js +1 -1
  148. package/dist/not-for-prod/prebid.js +240 -240
  149. package/dist/novatiqIdSystem.js +1 -1
  150. package/dist/oguryBidAdapter.js +1 -1
  151. package/dist/onetagBidAdapter.js +1 -1
  152. package/dist/ooloAnalyticsAdapter.js +1 -1
  153. package/dist/open8BidAdapter.js +1 -1
  154. package/dist/operaadsIdSystem.js +1 -1
  155. package/dist/optidigitalBidAdapter.js +1 -1
  156. package/dist/optimeraRtdProvider.js +1 -1
  157. package/dist/outbrainBidAdapter.js +1 -1
  158. package/dist/oxxionAnalyticsAdapter.js +1 -1
  159. package/dist/oxxionRtdProvider.js +1 -1
  160. package/dist/parrableIdSystem.js +1 -1
  161. package/dist/pixfutureBidAdapter.js +1 -1
  162. package/dist/prebid-core.js +2 -2
  163. package/dist/prebidServerBidAdapter.js +1 -1
  164. package/dist/prebidmanagerAnalyticsAdapter.js +1 -1
  165. package/dist/priceFloors.js +1 -1
  166. package/dist/prismaBidAdapter.js +1 -1
  167. package/dist/pubgeniusBidAdapter.js +1 -1
  168. package/dist/publinkIdSystem.js +1 -1
  169. package/dist/pubmaticAnalyticsAdapter.js +1 -1
  170. package/dist/pubmaticBidAdapter.js +1 -1
  171. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  172. package/dist/pubxaiAnalyticsAdapter.js +1 -1
  173. package/dist/pxyzBidAdapter.js +1 -1
  174. package/dist/quantcastBidAdapter.js +1 -1
  175. package/dist/qwarryBidAdapter.js +1 -1
  176. package/dist/readpeakBidAdapter.js +1 -1
  177. package/dist/reconciliationRtdProvider.js +1 -1
  178. package/dist/relaidoBidAdapter.js +1 -1
  179. package/dist/relevadRtdProvider.js +1 -1
  180. package/dist/retailspotBidAdapter.js +1 -1
  181. package/dist/rhythmoneBidAdapter.js +1 -1
  182. package/dist/riseBidAdapter.js +1 -1
  183. package/dist/rivrAnalyticsAdapter.js +1 -1
  184. package/dist/roxotAnalyticsAdapter.js +1 -1
  185. package/dist/rubiconBidAdapter.js +1 -1
  186. package/dist/scaleableAnalyticsAdapter.js +1 -1
  187. package/dist/seedingAllianceBidAdapter.js +1 -1
  188. package/dist/seedtagBidAdapter.js +1 -1
  189. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  190. package/dist/sharethroughBidAdapter.js +1 -1
  191. package/dist/shinezBidAdapter.js +1 -1
  192. package/dist/silverpushBidAdapter.js +1 -1
  193. package/dist/sirdataRtdProvider.js +1 -1
  194. package/dist/slimcutBidAdapter.js +1 -1
  195. package/dist/smaatoBidAdapter.js +1 -1
  196. package/dist/smartadserverBidAdapter.js +1 -1
  197. package/dist/smartxBidAdapter.js +1 -1
  198. package/dist/smartyadsBidAdapter.js +1 -1
  199. package/dist/smilewantedBidAdapter.js +1 -1
  200. package/dist/sonobiAnalyticsAdapter.js +1 -1
  201. package/dist/sonobiBidAdapter.js +1 -1
  202. package/dist/sovrnAnalyticsAdapter.js +1 -1
  203. package/dist/sovrnBidAdapter.js +1 -1
  204. package/dist/sspBCBidAdapter.js +1 -1
  205. package/dist/staqAnalyticsAdapter.js +1 -1
  206. package/dist/stvBidAdapter.js +1 -1
  207. package/dist/sublimeBidAdapter.js +1 -1
  208. package/dist/taboolaBidAdapter.js +1 -1
  209. package/dist/talkadsBidAdapter.js +1 -1
  210. package/dist/tapadIdSystem.js +1 -1
  211. package/dist/targetVideoBidAdapter.js +1 -1
  212. package/dist/teadsBidAdapter.js +1 -1
  213. package/dist/teadsIdSystem.js +1 -1
  214. package/dist/terceptAnalyticsAdapter.js +1 -1
  215. package/dist/timeoutRtdProvider.js +1 -1
  216. package/dist/trionBidAdapter.js +1 -1
  217. package/dist/tripleliftBidAdapter.js +1 -1
  218. package/dist/ttdBidAdapter.js +1 -1
  219. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  220. package/dist/uid2IdSystem.js +1 -1
  221. package/dist/underdogmediaBidAdapter.js +1 -1
  222. package/dist/undertoneBidAdapter.js +1 -1
  223. package/dist/unifiedIdSystem.js +1 -1
  224. package/dist/verizonMediaIdSystem.js +1 -1
  225. package/dist/vidazooBidAdapter.js +1 -1
  226. package/dist/videobyteBidAdapter.js +1 -1
  227. package/dist/visxBidAdapter.js +1 -1
  228. package/dist/vrtcalBidAdapter.js +1 -1
  229. package/dist/vuukleBidAdapter.js +1 -1
  230. package/dist/weboramaRtdProvider.js +1 -1
  231. package/dist/widespaceBidAdapter.js +1 -1
  232. package/dist/winrBidAdapter.js +1 -1
  233. package/dist/yahoosspBidAdapter.js +1 -1
  234. package/dist/yieldmoBidAdapter.js +1 -1
  235. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  236. package/dist/yuktamediaAnalyticsAdapter.js +1 -1
  237. package/dist/zeta_global_sspAnalyticsAdapter.js +1 -1
  238. package/dist/zeta_global_sspBidAdapter.js +1 -1
  239. package/integrationExamples/gpt/growthcode.html +3 -12
  240. package/libraries/mspa/activityControls.js +3 -1
  241. package/modules/adagioBidAdapter.js +11 -3
  242. package/modules/concertBidAdapter.js +1 -0
  243. package/modules/fledgeForGpt.js +17 -4
  244. package/modules/fledgeForGpt.md +17 -10
  245. package/modules/geoedgeRtdProvider.js +1 -5
  246. package/modules/growthCodeAnalyticsAdapter.js +7 -4
  247. package/modules/growthCodeAnalyticsAdapter.md +1 -7
  248. package/modules/nexx360BidAdapter.js +7 -1
  249. package/modules/prebidServerBidAdapter/index.js +8 -2
  250. package/modules/pubmaticAnalyticsAdapter.js +16 -3
  251. package/package.json +1 -1
  252. package/src/adapters/bidderFactory.js +14 -5
  253. package/src/ajax.js +126 -87
  254. package/src/constants.json +8 -2
  255. package/src/native.js +12 -1
  256. package/test/mocks/xhr.js +256 -9
  257. package/test/spec/libraries/mspa/activityControls_spec.js +6 -0
  258. package/test/spec/modules/adagioBidAdapter_spec.js +15 -0
  259. package/test/spec/modules/adlooxAdServerVideo_spec.js +1 -5
  260. package/test/spec/modules/adlooxRtdProvider_spec.js +1 -5
  261. package/test/spec/modules/categoryTranslation_spec.js +7 -9
  262. package/test/spec/modules/concertBidAdapter_spec.js +1 -1
  263. package/test/spec/modules/conversantAnalyticsAdapter_spec.js +3 -5
  264. package/test/spec/modules/currency_spec.js +2 -2
  265. package/test/spec/modules/dmdIdSystem_spec.js +2 -2
  266. package/test/spec/modules/euidIdSystem_spec.js +10 -9
  267. package/test/spec/modules/feedadBidAdapter_spec.js +1 -1
  268. package/test/spec/modules/fledge_spec.js +117 -43
  269. package/test/spec/modules/geoedgeRtdProvider_spec.js +11 -18
  270. package/test/spec/modules/greenbidsRtdProvider_spec.js +3 -12
  271. package/test/spec/modules/growthCodeAnalyticsAdapter_spec.js +0 -1
  272. package/test/spec/modules/hadronIdSystem_spec.js +1 -1
  273. package/test/spec/modules/id5AnalyticsAdapter_spec.js +1 -7
  274. package/test/spec/modules/id5IdSystem_spec.js +25 -25
  275. package/test/spec/modules/identityLinkIdSystem_spec.js +0 -2
  276. package/test/spec/modules/intentIqIdSystem_spec.js +0 -2
  277. package/test/spec/modules/invisiblyAnalyticsAdapter_spec.js +2 -6
  278. package/test/spec/modules/jwplayerRtdProvider_spec.js +26 -28
  279. package/test/spec/modules/magniteAnalyticsAdapter_spec.js +2 -2
  280. package/test/spec/modules/mgidRtdProvider_spec.js +1 -5
  281. package/test/spec/modules/nexx360BidAdapter_spec.js +48 -1
  282. package/test/spec/modules/oguryBidAdapter_spec.js +5 -19
  283. package/test/spec/modules/ooloAnalyticsAdapter_spec.js +1 -1
  284. package/test/spec/modules/prebidServerBidAdapter_spec.js +33 -2
  285. package/test/spec/modules/priceFloors_spec.js +33 -37
  286. package/test/spec/modules/publinkIdSystem_spec.js +1 -1
  287. package/test/spec/modules/pubmaticAnalyticsAdapter_spec.js +102 -18
  288. package/test/spec/modules/pubwiseAnalyticsAdapter_spec.js +2 -8
  289. package/test/spec/modules/teadsIdSystem_spec.js +1 -1
  290. package/test/spec/modules/uid2IdSystem_helpers.js +5 -5
  291. package/test/spec/modules/uid2IdSystem_spec.js +24 -24
  292. package/test/spec/modules/userId_spec.js +1 -1
  293. package/test/spec/modules/zeta_global_sspAnalyticsAdapter_spec.js +2 -5
  294. package/test/spec/native_spec.js +15 -2
  295. package/test/spec/unit/core/ajax_spec.js +403 -0
  296. package/test/spec/unit/core/bidderFactory_spec.js +80 -8
  297. package/test/spec/videoCache_spec.js +4 -4
@@ -283,7 +283,7 @@ function gatherPartnerBidsForAdUnitForLogger(adUnit, adUnitId, highestBid) {
283
283
  'ocpm': bid.bidResponse ? (bid.bidResponse.originalCpm || 0) : 0,
284
284
  'ocry': bid.bidResponse ? (bid.bidResponse.originalCurrency || CURRENCY_USD) : CURRENCY_USD,
285
285
  'piid': bid.bidResponse ? (bid.bidResponse.partnerImpId || EMPTY_STRING) : EMPTY_STRING,
286
- 'frv': (s2sBidders.indexOf(bid.bidder) > -1) ? undefined : (bid.bidResponse ? (bid.bidResponse.floorData ? bid.bidResponse.floorData.floorRuleValue : undefined) : undefined),
286
+ 'frv': (bid.bidResponse ? (bid.bidResponse.floorData ? bid.bidResponse.floorData.floorRuleValue : undefined) : undefined),
287
287
  'md': bid.bidResponse ? getMetadata(bid.bidResponse.meta) : undefined
288
288
  });
289
289
  });
@@ -319,6 +319,17 @@ function getTgId() {
319
319
  return 0;
320
320
  }
321
321
 
322
+ function getFloorFetchStatus(floorData) {
323
+ if (!floorData?.floorRequestData) {
324
+ return false;
325
+ }
326
+ const { location, fetchStatus } = floorData?.floorRequestData;
327
+ const isDataValid = location !== CONSTANTS.FLOOR_VALUES.NO_DATA;
328
+ const isFetchSuccessful = location === CONSTANTS.FLOOR_VALUES.FETCH && fetchStatus === CONSTANTS.FLOOR_VALUES.SUCCESS;
329
+ const isAdUnitOrSetConfig = location === CONSTANTS.FLOOR_VALUES.AD_UNIT || location === CONSTANTS.FLOOR_VALUES.SET_CONFIG;
330
+ return isDataValid && (isAdUnitOrSetConfig || isFetchSuccessful);
331
+ }
332
+
322
333
  function executeBidsLoggerCall(e, highestCpmBids) {
323
334
  let auctionId = e.auctionId;
324
335
  let referrer = config.getConfig('pageUrl') || cache.auctions[auctionId].referer || '';
@@ -326,6 +337,8 @@ function executeBidsLoggerCall(e, highestCpmBids) {
326
337
  let floorData = auctionCache.floorData;
327
338
  let outputObj = { s: [] };
328
339
  let pixelURL = END_POINT_BID_LOGGER;
340
+ // will return true if floor data is present.
341
+ let fetchStatus = getFloorFetchStatus(auctionCache.floorData);
329
342
 
330
343
  if (!auctionCache) {
331
344
  return;
@@ -347,7 +360,7 @@ function executeBidsLoggerCall(e, highestCpmBids) {
347
360
  outputObj['dvc'] = {'plt': getDevicePlatform()};
348
361
  outputObj['tgid'] = getTgId();
349
362
 
350
- if (floorData) {
363
+ if (floorData && fetchStatus) {
351
364
  outputObj['fmv'] = floorData.floorRequestData ? floorData.floorRequestData.modelVersion || undefined : undefined;
352
365
  outputObj['ft'] = floorData.floorResponseData ? (floorData.floorResponseData.enforcements.enforceJS == false ? 0 : 1) : undefined;
353
366
  }
@@ -362,7 +375,7 @@ function executeBidsLoggerCall(e, highestCpmBids) {
362
375
  'mt': getAdUnitAdFormats(origAdUnit),
363
376
  'sz': getSizesForAdUnit(adUnit, adUnitId),
364
377
  'ps': gatherPartnerBidsForAdUnitForLogger(adUnit, adUnitId, highestCpmBids.filter(bid => bid.adUnitCode === adUnitId)),
365
- 'fskp': floorData ? (floorData.floorRequestData ? (floorData.floorRequestData.skipped == false ? 0 : 1) : undefined) : undefined,
378
+ 'fskp': (floorData && fetchStatus) ? (floorData.floorRequestData ? (floorData.floorRequestData.skipped == false ? 0 : 1) : undefined) : undefined,
366
379
  };
367
380
  slotsArray.push(slotObject);
368
381
  return slotsArray;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prebid.js",
3
- "version": "8.8.0",
3
+ "version": "8.9.0",
4
4
  "description": "Header Bidding Management Library",
5
5
  "main": "src/prebid.js",
6
6
  "scripts": {
@@ -25,7 +25,7 @@ import {useMetrics} from '../utils/perfMetrics.js';
25
25
  import {isActivityAllowed} from '../activities/rules.js';
26
26
  import {activityParams} from '../activities/activityParams.js';
27
27
  import {MODULE_TYPE_BIDDER} from '../activities/modules.js';
28
- import {ACTIVITY_TRANSMIT_TID} from '../activities/activities.js';
28
+ import {ACTIVITY_TRANSMIT_TID, ACTIVITY_TRANSMIT_UFPD} from '../activities/activities.js';
29
29
 
30
30
  /**
31
31
  * This file aims to support Adapters during the Prebid 0.x -> 1.x transition.
@@ -454,6 +454,15 @@ export const processBidderRequests = hook('sync', function (spec, bids, bidderRe
454
454
  onRequest(request);
455
455
 
456
456
  const networkDone = requestMetrics.startTiming('net');
457
+
458
+ function getOptions(defaults) {
459
+ const ro = request.options;
460
+ return Object.assign(defaults, ro, {
461
+ browsingTopics: ro?.hasOwnProperty('browsingTopics') && !ro.browsingTopics
462
+ ? false
463
+ : isActivityAllowed(ACTIVITY_TRANSMIT_UFPD, activityParams(MODULE_TYPE_BIDDER, spec.code))
464
+ })
465
+ }
457
466
  switch (request.method) {
458
467
  case 'GET':
459
468
  ajax(
@@ -463,10 +472,10 @@ export const processBidderRequests = hook('sync', function (spec, bids, bidderRe
463
472
  error: onFailure
464
473
  },
465
474
  undefined,
466
- Object.assign({
475
+ getOptions({
467
476
  method: 'GET',
468
477
  withCredentials: true
469
- }, request.options)
478
+ })
470
479
  );
471
480
  break;
472
481
  case 'POST':
@@ -477,11 +486,11 @@ export const processBidderRequests = hook('sync', function (spec, bids, bidderRe
477
486
  error: onFailure
478
487
  },
479
488
  typeof request.data === 'string' ? request.data : JSON.stringify(request.data),
480
- Object.assign({
489
+ getOptions({
481
490
  method: 'POST',
482
491
  contentType: 'text/plain',
483
492
  withCredentials: true
484
- }, request.options)
493
+ })
485
494
  );
486
495
  break;
487
496
  default:
package/src/ajax.js CHANGED
@@ -1,99 +1,138 @@
1
- import { config } from './config.js';
2
- import { logMessage, logError, parseUrl, buildUrl, _each } from './utils.js';
1
+ import {config} from './config.js';
2
+ import {buildUrl, logError, parseUrl} from './utils.js';
3
3
 
4
- const XHR_DONE = 4;
4
+ export const dep = {
5
+ fetch: window.fetch.bind(window),
6
+ makeRequest: (r, o) => new Request(r, o),
7
+ timeout(timeout, resource) {
8
+ const ctl = new AbortController();
9
+ let cancelTimer = setTimeout(() => {
10
+ ctl.abort();
11
+ logError(`Request timeout after ${timeout}ms`, resource);
12
+ cancelTimer = null;
13
+ }, timeout);
14
+ return {
15
+ signal: ctl.signal,
16
+ done() {
17
+ cancelTimer && clearTimeout(cancelTimer)
18
+ }
19
+ }
20
+ }
21
+ }
22
+
23
+ const GET = 'GET';
24
+ const POST = 'POST';
25
+ const CTYPE = 'Content-Type';
5
26
 
6
27
  /**
7
- * Simple IE9+ and cross-browser ajax request function
8
- * Note: x-domain requests in IE9 do not support the use of cookies
9
- *
10
- * @param url string url
11
- * @param callback {object | function} callback
12
- * @param data mixed data
13
- * @param options object
28
+ * transform legacy `ajax` parameters into a fetch request.
29
+ * @returns {Request}
14
30
  */
15
- export const ajax = ajaxBuilder();
16
-
17
- export function ajaxBuilder(timeout = 3000, {request, done} = {}) {
18
- return function(url, callback, data, options = {}) {
19
- try {
20
- let x;
21
- let method = options.method || (data ? 'POST' : 'GET');
22
- let parser = document.createElement('a');
23
- parser.href = url;
24
-
25
- let callbacks = typeof callback === 'object' && callback !== null ? callback : {
26
- success: function() {
27
- logMessage('xhr success');
28
- },
29
- error: function(e) {
30
- logError('xhr error', null, e);
31
- }
32
- };
31
+ export function toFetchRequest(url, data, options = {}) {
32
+ const method = options.method || (data ? POST : GET);
33
+ if (method === GET && data) {
34
+ const urlInfo = parseUrl(url, options);
35
+ Object.assign(urlInfo.search, data);
36
+ url = buildUrl(urlInfo);
37
+ }
38
+ const headers = new Headers(options.customHeaders);
39
+ headers.set(CTYPE, options.contentType || 'text/plain');
40
+ const rqOpts = {
41
+ method,
42
+ headers
43
+ }
44
+ if (method !== GET && data) {
45
+ rqOpts.body = data;
46
+ }
47
+ if (options.withCredentials) {
48
+ rqOpts.credentials = 'include';
49
+ }
50
+ if (options.browsingTopics && isSecureContext) {
51
+ // the Request constructor will throw an exception if the browser supports topics
52
+ // but we're not in a secure context
53
+ rqOpts.browsingTopics = true;
54
+ }
55
+ return dep.makeRequest(url, rqOpts);
56
+ }
33
57
 
34
- if (typeof callback === 'function') {
35
- callbacks.success = callback;
36
- }
58
+ /**
59
+ * Return a version of `fetch` that automatically cancels requests after `timeout` milliseconds.
60
+ *
61
+ * If provided, `request` and `done` should be functions accepting a single argument.
62
+ * `request` is invoked at the beginning of each request, and `done` at the end; both are passed its origin.
63
+ *
64
+ * @returns {function(*, {}?): Promise<Response>}
65
+ */
66
+ export function fetcherFactory(timeout = 3000, {request, done} = {}) {
67
+ let fetcher = (resource, options) => {
68
+ let to;
69
+ if (timeout != null && options?.signal == null && !config.getConfig('disableAjaxTimeout')) {
70
+ to = dep.timeout(timeout, resource);
71
+ options = Object.assign({signal: to.signal}, options);
72
+ }
73
+ let pm = dep.fetch(resource, options);
74
+ if (to?.done != null) pm = pm.finally(to.done);
75
+ return pm;
76
+ };
37
77
 
38
- x = new window.XMLHttpRequest();
78
+ if (request != null || done != null) {
79
+ fetcher = ((fetch) => function (resource, options) {
80
+ const origin = new URL(resource?.url == null ? resource : resource.url, document.location).origin;
81
+ let req = fetch(resource, options);
82
+ request && request(origin);
83
+ if (done) req = req.finally(() => done(origin));
84
+ return req;
85
+ })(fetcher);
86
+ }
87
+ return fetcher;
88
+ }
39
89
 
40
- x.onreadystatechange = function () {
41
- if (x.readyState === XHR_DONE) {
42
- if (typeof done === 'function') {
43
- done(parser.origin);
44
- }
45
- let status = x.status;
46
- if ((status >= 200 && status < 300) || status === 304) {
47
- callbacks.success(x.responseText, x);
48
- } else {
49
- callbacks.error(x.statusText, x);
50
- }
90
+ function toXHR({status, statusText = '', headers, url}, responseText) {
91
+ let xml = 0;
92
+ return {
93
+ readyState: XMLHttpRequest.DONE,
94
+ status,
95
+ statusText,
96
+ responseText,
97
+ response: responseText,
98
+ responseType: '',
99
+ responseURL: url,
100
+ get responseXML() {
101
+ if (xml === 0) {
102
+ try {
103
+ xml = new DOMParser().parseFromString(responseText, headers?.get(CTYPE)?.split(';')?.[0])
104
+ } catch (e) {
105
+ xml = null;
106
+ logError(e);
51
107
  }
52
- };
53
-
54
- // Disabled timeout temporarily to avoid xhr failed requests. https://github.com/prebid/Prebid.js/issues/2648
55
- if (!config.getConfig('disableAjaxTimeout')) {
56
- x.ontimeout = function () {
57
- logError(' xhr timeout after ', x.timeout, 'ms');
58
- };
59
108
  }
109
+ return xml;
110
+ },
111
+ getResponseHeader: (header) => headers?.has(header) ? headers.get(header) : null,
112
+ }
113
+ }
60
114
 
61
- if (method === 'GET' && data) {
62
- let urlInfo = parseUrl(url, options);
63
- Object.assign(urlInfo.search, data);
64
- url = buildUrl(urlInfo);
65
- }
66
-
67
- x.open(method, url, true);
68
- // IE needs timeout to be set after open - see #1410
69
- // Disabled timeout temporarily to avoid xhr failed requests. https://github.com/prebid/Prebid.js/issues/2648
70
- if (!config.getConfig('disableAjaxTimeout')) {
71
- x.timeout = timeout;
72
- }
73
-
74
- if (options.withCredentials) {
75
- x.withCredentials = true;
76
- }
77
- _each(options.customHeaders, (value, header) => {
78
- x.setRequestHeader(header, value);
79
- });
80
- if (options.preflight) {
81
- x.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
82
- }
83
- x.setRequestHeader('Content-Type', options.contentType || 'text/plain');
84
-
85
- if (typeof request === 'function') {
86
- request(parser.origin);
87
- }
115
+ /**
116
+ * attach legacy `ajax` callbacks to a fetch promise.
117
+ */
118
+ export function attachCallbacks(fetchPm, callback) {
119
+ const {success, error} = typeof callback === 'object' && callback != null ? callback : {
120
+ success: typeof callback === 'function' ? callback : () => null,
121
+ error: (e, x) => logError('Network error', e, x)
122
+ };
123
+ fetchPm.then(response => response.text().then((responseText) => [response, responseText]))
124
+ .then(([response, responseText]) => {
125
+ const xhr = toXHR(response, responseText);
126
+ response.ok || response.status === 304 ? success(responseText, xhr) : error(response.statusText, xhr);
127
+ }, () => error('', toXHR({status: 0}, '')));
128
+ }
88
129
 
89
- if (method === 'POST' && data) {
90
- x.send(data);
91
- } else {
92
- x.send();
93
- }
94
- } catch (error) {
95
- logError('xhr construction', error);
96
- typeof callback === 'object' && callback !== null && callback.error(error);
97
- }
98
- }
130
+ export function ajaxBuilder(timeout = 3000, {request, done} = {}) {
131
+ const fetcher = fetcherFactory(timeout, {request, done});
132
+ return function (url, callback, data, options = {}) {
133
+ attachCallbacks(fetcher(toFetchRequest(url, data, options)), callback);
134
+ };
99
135
  }
136
+
137
+ export const ajax = ajaxBuilder();
138
+ export const fetch = fetcherFactory();
@@ -163,11 +163,17 @@
163
163
  "MAIN": 3
164
164
  },
165
165
  "NATIVE_KEYS_THAT_ARE_NOT_ASSETS": [
166
- "privacyLink",
167
166
  "clickUrl",
168
167
  "sendTargetingKeys",
169
168
  "adTemplate",
170
169
  "rendererUrl",
171
170
  "type"
172
- ]
171
+ ],
172
+ "FLOOR_VALUES": {
173
+ "NO_DATA": "noData",
174
+ "AD_UNIT": "adUnit",
175
+ "SET_CONFIG": "setConfig",
176
+ "FETCH": "fetch",
177
+ "SUCCESS": "success"
178
+ }
173
179
  }
package/src/native.js CHANGED
@@ -480,6 +480,11 @@ export function toOrtbNativeRequest(legacyNativeAssets) {
480
480
  continue;
481
481
  }
482
482
 
483
+ if (key === 'privacyLink') {
484
+ ortb.privacy = 1;
485
+ continue;
486
+ }
487
+
483
488
  const asset = legacyNativeAssets[key];
484
489
  let required = 0;
485
490
  if (asset.required && isBoolean(asset.required)) {
@@ -623,6 +628,9 @@ export function fromOrtbNativeRequest(openRTBRequest) {
623
628
  oldNativeObject[prebidAssetName].len = asset.data.len;
624
629
  }
625
630
  }
631
+ if (openRTBRequest.privacy) {
632
+ oldNativeObject.privacyLink = { required: false };
633
+ }
626
634
  // video was not supported by old prebid assets
627
635
  }
628
636
  return oldNativeObject;
@@ -696,8 +704,11 @@ export function legacyPropertiesToOrtbNative(legacyNative) {
696
704
  // in general, native trackers seem to be neglected and/or broken
697
705
  response.jstracker = Array.isArray(value) ? value.join('') : value;
698
706
  break;
707
+ case 'privacyLink':
708
+ response.privacy = value;
709
+ break;
699
710
  }
700
- })
711
+ });
701
712
  return response;
702
713
  }
703
714
 
package/test/mocks/xhr.js CHANGED
@@ -1,12 +1,236 @@
1
1
  import {getUniqueIdentifierStr} from '../../src/utils.js';
2
+ import {GreedyPromise} from '../../src/utils/promise.js';
3
+ import {fakeXhr} from 'nise';
4
+ import {dep} from 'src/ajax.js';
2
5
 
3
- export let server = sinon.createFakeServer();
4
- export let xhr = global.XMLHttpRequest;
6
+ export const xhr = sinon.useFakeXMLHttpRequest();
7
+ export const server = mockFetchServer();
5
8
 
6
- beforeEach(function() {
7
- server.restore();
8
- server = sinon.createFakeServer();
9
- xhr = global.XMLHttpRequest;
9
+ /**
10
+ * An (incomplete) replica of nise's fakeServer, but backing fetch used in ajax.js (rather than XHR).
11
+ */
12
+ function mockFetchServer() {
13
+ const sandbox = sinon.createSandbox();
14
+ const bodies = new WeakMap();
15
+ const requests = [];
16
+ const {DONE, UNSENT} = XMLHttpRequest;
17
+
18
+ function makeRequest(resource, options) {
19
+ const requestBody = options?.body || bodies.get(resource);
20
+ const request = new Request(resource, options);
21
+ bodies.set(request, requestBody);
22
+ return request;
23
+ }
24
+
25
+ function mockXHR(resource, options) {
26
+ let resolve, reject;
27
+ const promise = new GreedyPromise((res, rej) => {
28
+ resolve = res;
29
+ reject = rej;
30
+ });
31
+
32
+ function error(reason = new TypeError('Failed to fetch')) {
33
+ mockReq.status = 0;
34
+ reject(reason);
35
+ }
36
+
37
+ const request = makeRequest(resource, options);
38
+ request.signal.onabort = () => error(new DOMException('The user aborted a request'));
39
+ let responseHeaders;
40
+
41
+ const mockReq = {
42
+ fetch: {
43
+ request,
44
+ requestBody: bodies.get(request),
45
+ promise,
46
+ },
47
+ readyState: UNSENT,
48
+ url: request.url,
49
+ method: request.method,
50
+ requestBody: bodies.get(request),
51
+ status: 0,
52
+ statusText: '',
53
+ requestHeaders: new Proxy(request.headers, {
54
+ get(target, prop) {
55
+ return typeof prop === 'string' && target.has(prop) ? target.get(prop) : {}[prop];
56
+ },
57
+ has(target, prop) {
58
+ return typeof prop === 'string' && target.has(prop);
59
+ },
60
+ ownKeys(target) {
61
+ return Array.from(target.keys());
62
+ },
63
+ getOwnPropertyDescriptor(target, prop) {
64
+ if (typeof prop === 'string' && target.has(prop)) {
65
+ return {
66
+ enumerable: true,
67
+ configurable: true,
68
+ writable: false,
69
+ value: target.get(prop)
70
+ }
71
+ }
72
+ }
73
+ }),
74
+ withCredentials: request.credentials === 'include',
75
+ setStatus(status) {
76
+ // nise replaces invalid status with 200
77
+ status = typeof status === 'number' ? status : 200;
78
+ mockReq.status = status;
79
+ mockReq.statusText = fakeXhr.FakeXMLHttpRequest.statusCodes[status] || '';
80
+ },
81
+ setResponseHeaders(headers) {
82
+ responseHeaders = headers;
83
+ },
84
+ setResponseBody(body) {
85
+ if (mockReq.status === 0) {
86
+ error();
87
+ return;
88
+ }
89
+ const resp = Object.defineProperties(new Response(body, {
90
+ status: mockReq.status,
91
+ statusText: mockReq.statusText,
92
+ headers: responseHeaders || {},
93
+ }), {
94
+ url: {
95
+ get: () => mockReq.fetch.request.url,
96
+ }
97
+ });
98
+ mockReq.readyState = DONE;
99
+ // tests expect respond() to run everything immediately,
100
+ // so make body available syncronously
101
+ resp.text = () => GreedyPromise.resolve(body || '');
102
+ Object.assign(mockReq.fetch, {
103
+ response: resp,
104
+ responseBody: body || ''
105
+ })
106
+ resolve(resp);
107
+ },
108
+ respond(status = 200, headers, body) {
109
+ mockReq.setStatus(status);
110
+ mockReq.setResponseHeaders(headers);
111
+ mockReq.setResponseBody(body);
112
+ },
113
+ error
114
+ };
115
+ return mockReq;
116
+ }
117
+
118
+ let enabled = false;
119
+ let timeoutsEnabled = false;
120
+
121
+ function enable() {
122
+ if (!enabled) {
123
+ sandbox.stub(dep, 'fetch').callsFake((resource, options) => {
124
+ const req = mockXHR(resource, options);
125
+ requests.push(req);
126
+ return req.fetch.promise;
127
+ });
128
+ sandbox.stub(dep, 'makeRequest').callsFake(makeRequest);
129
+ const timeout = dep.timeout;
130
+ sandbox.stub(dep, 'timeout').callsFake(function () {
131
+ if (timeoutsEnabled) {
132
+ return timeout.apply(null, arguments);
133
+ } else {
134
+ return {};
135
+ }
136
+ });
137
+ enabled = true;
138
+ }
139
+ }
140
+
141
+ enable();
142
+
143
+ const responders = [];
144
+
145
+ function respondWith() {
146
+ let response, urlMatcher, methodMatcher;
147
+ urlMatcher = methodMatcher = () => true;
148
+ switch (arguments.length) {
149
+ case 1:
150
+ ([response] = arguments);
151
+ break;
152
+ case 2:
153
+ ([urlMatcher, response] = arguments);
154
+ break;
155
+ case 3:
156
+ ([methodMatcher, urlMatcher, response] = arguments);
157
+ methodMatcher = ((toMatch) => (method) => method === toMatch)(methodMatcher);
158
+ break;
159
+ default:
160
+ throw new Error('Invalid respondWith invocation');
161
+ }
162
+ if (typeof urlMatcher.exec === 'function') {
163
+ urlMatcher = ((rx) => (url) => rx.exec(url)?.slice(1))(urlMatcher);
164
+ } else if (typeof urlMatcher === 'string') {
165
+ urlMatcher = ((toMatch) => (url) => url === toMatch)(urlMatcher);
166
+ }
167
+ responders.push((req) => {
168
+ if (req.readyState !== DONE && methodMatcher(req.method)) {
169
+ const arg = urlMatcher(req.url);
170
+ if (arg) {
171
+ if (typeof response === 'function') {
172
+ response(req, ...(Array.isArray(arg) ? arg : []));
173
+ } else if (typeof response === 'string') {
174
+ req.respond(200, null, response);
175
+ } else {
176
+ req.respond.apply(req, response);
177
+ }
178
+ }
179
+ }
180
+ });
181
+ }
182
+
183
+ function resetState() {
184
+ requests.length = 0;
185
+ responders.length = 0;
186
+ timeoutsEnabled = false;
187
+ }
188
+
189
+ return {
190
+ requests,
191
+ enable,
192
+ restore() {
193
+ resetState();
194
+ sandbox.restore();
195
+ enabled = false;
196
+ },
197
+ reset() {
198
+ sandbox.resetHistory();
199
+ resetState();
200
+ },
201
+ respondWith,
202
+ respond() {
203
+ if (arguments.length > 0) {
204
+ respondWith.apply(null, arguments);
205
+ }
206
+ requests.forEach(req => {
207
+ for (let i = responders.length - 1; i >= 0; i--) {
208
+ responders[i](req);
209
+ if (req.readyState === DONE) break;
210
+ }
211
+ if (req.readyState !== DONE) {
212
+ req.respond(404, {}, '');
213
+ }
214
+ });
215
+ },
216
+ /**
217
+ * the timeout mechanism is quite different between XHR and fetch
218
+ * by default, mocked fetch does not time out - to reflect fakeServer XHRs
219
+ * note that many tests will fire requests without caring or waiting for their response -
220
+ * if they are timed out later, during unrelated tests, the log messages might interfere with their
221
+ * assertions
222
+ */
223
+ get autoTimeout() {
224
+ return timeoutsEnabled;
225
+ },
226
+ set autoTimeout(val) {
227
+ timeoutsEnabled = !!val;
228
+ }
229
+ };
230
+ }
231
+
232
+ beforeEach(function () {
233
+ server.reset();
10
234
  });
11
235
 
12
236
  const bid = getUniqueIdentifierStr().substring(4);
@@ -20,12 +244,35 @@ afterEach(function () {
20
244
  return (s) => s.split('\n').map(s => `${preamble} ${s}`).join('\n');
21
245
  })();
22
246
 
247
+ function format(obj, body = null) {
248
+ if (obj == null) return obj;
249
+ const fmt = {};
250
+ let node = obj;
251
+ while (node != null) {
252
+ Object.keys(node).forEach((k) => {
253
+ const val = obj[k];
254
+ if (typeof val !== 'function' && !fmt.hasOwnProperty(k)) {
255
+ fmt[k] = val;
256
+ }
257
+ });
258
+ node = Object.getPrototypeOf(node);
259
+ }
260
+ if (obj.headers != null) {
261
+ fmt.headers = Object.fromEntries(obj.headers.entries())
262
+ }
263
+ fmt.body = body;
264
+ return fmt;
265
+ }
266
+
23
267
 
24
- console.log(prepend(`XHR mock state after failure (for test '${this.currentTest.fullTitle()}'): ${server.requests.length} requests`))
268
+ console.log(prepend(`XHR mock state after failure (for test '${this.currentTest.fullTitle()}'): ${server.requests.length} requests`));
25
269
  server.requests.forEach((req, i) => {
26
270
  console.log(prepend(`Request #${i}:`));
27
- console.log(prepend(JSON.stringify(req, null, 2)));
28
- })
271
+ console.log(prepend(JSON.stringify({
272
+ request: format(req.fetch.request, req.fetch.requestBody),
273
+ response: format(req.fetch.response, req.fetch.responseBody)
274
+ }, null, 2)));
275
+ });
29
276
  }
30
277
  });
31
278
  /* eslint-enable */