prebid.js 7.22.0 → 7.23.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 (273) hide show
  1. package/dist/33acrossBidAdapter.js +1 -1
  2. package/dist/aaxBlockmeterRtdProvider.js +1 -0
  3. package/dist/adagioBidAdapter.js +1 -1
  4. package/dist/adbookpspBidAdapter.js +1 -1
  5. package/dist/adgenerationBidAdapter.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/analyticsAdapter.js +1 -1
  13. package/dist/appierAnalyticsAdapter.js +1 -1
  14. package/dist/appnexusBidAdapter.js +1 -1
  15. package/dist/asoBidAdapter.js +1 -1
  16. package/dist/axonixBidAdapter.js +1 -1
  17. package/dist/bidViewability.js +1 -1
  18. package/dist/bidViewabilityIO.js +1 -1
  19. package/dist/bidglassBidAdapter.js +1 -1
  20. package/dist/big-richmediaBidAdapter.js +1 -1
  21. package/dist/bridgewellBidAdapter.js +1 -1
  22. package/dist/brightMountainMediaBidAdapter.js +1 -1
  23. package/dist/browsiRtdProvider.js +1 -1
  24. package/dist/carodaBidAdapter.js +1 -1
  25. package/dist/chtnwBidAdapter.js +1 -0
  26. package/dist/cleanioRtdProvider.js +1 -1
  27. package/dist/concertBidAdapter.js +1 -1
  28. package/dist/connectadBidAdapter.js +1 -1
  29. package/dist/consentManagement.js +1 -1
  30. package/dist/consentManagementUsp.js +1 -1
  31. package/dist/consumableBidAdapter.js +1 -1
  32. package/dist/conversantBidAdapter.js +1 -1
  33. package/dist/craftBidAdapter.js +1 -1
  34. package/dist/criteoBidAdapter.js +1 -1
  35. package/dist/currency.js +1 -1
  36. package/dist/dependencies.json +19 -0
  37. package/dist/dfpAdServerVideo.js +1 -1
  38. package/dist/dgkeywordRtdProvider.js +1 -1
  39. package/dist/dspxBidAdapter.js +1 -1
  40. package/dist/eplanningBidAdapter.js +1 -1
  41. package/dist/finativeBidAdapter.js +1 -1
  42. package/dist/gdprEnforcement.js +1 -1
  43. package/dist/glimpseBidAdapter.js +1 -1
  44. package/dist/gmosspBidAdapter.js +1 -1
  45. package/dist/goldbachBidAdapter.js +1 -1
  46. package/dist/googleAnalyticsAdapter.js +1 -1
  47. package/dist/gridBidAdapter.js +1 -1
  48. package/dist/gridNMBidAdapter.js +1 -1
  49. package/dist/gumgumBidAdapter.js +1 -1
  50. package/dist/h12mediaBidAdapter.js +1 -1
  51. package/dist/id5AnalyticsAdapter.js +1 -1
  52. package/dist/id5IdSystem.js +1 -1
  53. package/dist/improvedigitalBidAdapter.js +1 -1
  54. package/dist/inmarBidAdapter.js +1 -1
  55. package/dist/insticatorBidAdapter.js +1 -1
  56. package/dist/instreamTracking.js +1 -1
  57. package/dist/ixBidAdapter.js +1 -1
  58. package/dist/justpremiumBidAdapter.js +1 -1
  59. package/dist/jwplayerVideoProvider.js +1 -0
  60. package/dist/kargoBidAdapter.js +1 -1
  61. package/dist/konduitAnalyticsAdapter.js +1 -1
  62. package/dist/kueezBidAdapter.js +1 -1
  63. package/dist/lassoBidAdapter.js +1 -1
  64. package/dist/lifestreetBidAdapter.js +1 -1
  65. package/dist/liveyieldAnalyticsAdapter.js +1 -1
  66. package/dist/logicadBidAdapter.js +1 -1
  67. package/dist/loglyliftBidAdapter.js +1 -1
  68. package/dist/magniteAnalyticsAdapter.js +1 -1
  69. package/dist/malltvAnalyticsAdapter.js +1 -1
  70. package/dist/marsmediaBidAdapter.js +1 -1
  71. package/dist/mediafuseBidAdapter.js +1 -1
  72. package/dist/mediasquareBidAdapter.js +1 -1
  73. package/dist/mgidBidAdapter.js +1 -1
  74. package/dist/minutemediaBidAdapter.js +1 -1
  75. package/dist/multibid.js +1 -1
  76. package/dist/not-for-prod/prebid.js +141 -132
  77. package/dist/oguryBidAdapter.js +1 -1
  78. package/dist/onetagBidAdapter.js +1 -1
  79. package/dist/ooloAnalyticsAdapter.js +1 -1
  80. package/dist/openxOrtbBidAdapter.js +1 -1
  81. package/dist/ortbConverter.js +1 -0
  82. package/dist/outbrainBidAdapter.js +1 -1
  83. package/dist/oxxionRtdProvider.js +1 -0
  84. package/dist/parrableIdSystem.js +1 -1
  85. package/dist/pbsExtensions.js +1 -0
  86. package/dist/pixfutureBidAdapter.js +1 -1
  87. package/dist/prebid-core.js +1 -1
  88. package/dist/prebidServerBidAdapter.js +1 -1
  89. package/dist/priceFloors.js +1 -1
  90. package/dist/pubCommonId.js +1 -1
  91. package/dist/publinkIdSystem.js +1 -1
  92. package/dist/pubmaticBidAdapter.js +1 -1
  93. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  94. package/dist/pxyzBidAdapter.js +1 -1
  95. package/dist/quantcastBidAdapter.js +1 -1
  96. package/dist/readpeakBidAdapter.js +1 -1
  97. package/dist/relaidoBidAdapter.js +1 -1
  98. package/dist/rhythmoneBidAdapter.js +1 -1
  99. package/dist/riseBidAdapter.js +1 -1
  100. package/dist/rtdModule.js +1 -1
  101. package/dist/rubiconAnalyticsAdapter.js +1 -1
  102. package/dist/rubiconBidAdapter.js +1 -1
  103. package/dist/schain.js +1 -1
  104. package/dist/seedingAllianceBidAdapter.js +1 -1
  105. package/dist/seedtagBidAdapter.js +1 -1
  106. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  107. package/dist/sharethroughBidAdapter.js +1 -1
  108. package/dist/shinezBidAdapter.js +1 -1
  109. package/dist/smaatoBidAdapter.js +1 -1
  110. package/dist/smartadserverBidAdapter.js +1 -1
  111. package/dist/smartxBidAdapter.js +1 -1
  112. package/dist/smilewantedBidAdapter.js +1 -1
  113. package/dist/sonobiBidAdapter.js +1 -1
  114. package/dist/sovrnAnalyticsAdapter.js +1 -1
  115. package/dist/sovrnBidAdapter.js +1 -1
  116. package/dist/spotxBidAdapter.js +1 -1
  117. package/dist/sspBCBidAdapter.js +1 -1
  118. package/dist/sublimeBidAdapter.js +1 -1
  119. package/dist/synacormediaBidAdapter.js +1 -1
  120. package/dist/targetVideoBidAdapter.js +1 -1
  121. package/dist/teadsBidAdapter.js +1 -1
  122. package/dist/teadsIdSystem.js +1 -1
  123. package/dist/trionBidAdapter.js +1 -1
  124. package/dist/tripleliftBidAdapter.js +1 -1
  125. package/dist/ttdBidAdapter.js +1 -1
  126. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  127. package/dist/underdogmediaBidAdapter.js +1 -1
  128. package/dist/undertoneBidAdapter.js +1 -1
  129. package/dist/userId.js +1 -1
  130. package/dist/vidazooBidAdapter.js +1 -1
  131. package/dist/video.js +1 -0
  132. package/dist/videoModule.js +1 -0
  133. package/dist/videobyteBidAdapter.js +1 -1
  134. package/dist/videojsVideoProvider.js +1 -0
  135. package/dist/visxBidAdapter.js +1 -1
  136. package/dist/vuukleBidAdapter.js +1 -1
  137. package/dist/widespaceBidAdapter.js +1 -1
  138. package/dist/winrBidAdapter.js +1 -1
  139. package/dist/yahoosspBidAdapter.js +1 -1
  140. package/dist/yieldmoBidAdapter.js +1 -1
  141. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  142. package/integrationExamples/videoModule/jwplayer/bidMarkedAsUsed.html +98 -0
  143. package/integrationExamples/videoModule/jwplayer/bidRequestScheduling.html +89 -0
  144. package/integrationExamples/videoModule/jwplayer/eventListeners.html +244 -0
  145. package/integrationExamples/videoModule/jwplayer/gamAdServerMediation.html +122 -0
  146. package/integrationExamples/videoModule/jwplayer/mediaMetadata.html +80 -0
  147. package/integrationExamples/videoModule/jwplayer/playlist.html +122 -0
  148. package/integrationExamples/videoModule/videojs/bidMarkedAsUsed.html +126 -0
  149. package/integrationExamples/videoModule/videojs/bidRequestScheduling.html +132 -0
  150. package/integrationExamples/videoModule/videojs/eventListeners.html +238 -0
  151. package/integrationExamples/videoModule/videojs/gamAdServerMediation.html +138 -0
  152. package/integrationExamples/videoModule/videojs/mediaMetadata.html +103 -0
  153. package/integrationExamples/videoModule/videojs/playlist.html +151 -0
  154. package/libraries/ortbConverter/README.md +378 -0
  155. package/libraries/ortbConverter/converter.js +135 -0
  156. package/libraries/ortbConverter/lib/composer.js +43 -0
  157. package/libraries/ortbConverter/lib/mergeProcessors.js +9 -0
  158. package/libraries/ortbConverter/lib/sizes.js +14 -0
  159. package/libraries/ortbConverter/processors/banner.js +40 -0
  160. package/libraries/ortbConverter/processors/default.js +167 -0
  161. package/libraries/ortbConverter/processors/mediaType.js +21 -0
  162. package/libraries/ortbConverter/processors/native.js +37 -0
  163. package/libraries/ortbConverter/processors/video.js +66 -0
  164. package/libraries/pbsExtensions/pbsExtensions.js +12 -0
  165. package/libraries/pbsExtensions/processors/aliases.js +17 -0
  166. package/libraries/pbsExtensions/processors/mediaType.js +23 -0
  167. package/libraries/pbsExtensions/processors/params.js +22 -0
  168. package/libraries/pbsExtensions/processors/pbs.js +99 -0
  169. package/libraries/pbsExtensions/processors/requestExtPrebid.js +30 -0
  170. package/libraries/pbsExtensions/processors/video.js +23 -0
  171. package/libraries/video/constants/enums.js +5 -0
  172. package/libraries/video/constants/events.js +97 -0
  173. package/libraries/video/constants/ortb.js +169 -0
  174. package/libraries/video/constants/vendorCodes.js +6 -0
  175. package/libraries/video/shared/eventHandler.js +18 -0
  176. package/libraries/video/shared/parentModule.js +82 -0
  177. package/libraries/video/shared/state.js +47 -0
  178. package/libraries/video/shared/vastXmlBuilder.js +77 -0
  179. package/libraries/video/shared/vastXmlEditor.js +115 -0
  180. package/modules/.submodules.json +6 -1
  181. package/modules/aaxBlockmeterRtdProvider.js +59 -0
  182. package/modules/aaxBlockmeterRtdProvider.md +48 -0
  183. package/modules/appnexusBidAdapter.js +38 -1
  184. package/modules/chtnwBidAdapter.js +110 -0
  185. package/modules/chtnwBidAdapter.md +31 -0
  186. package/modules/concertBidAdapter.js +44 -2
  187. package/modules/consentManagement.js +22 -1
  188. package/modules/consentManagementUsp.js +29 -7
  189. package/modules/criteoBidAdapter.js +25 -5
  190. package/modules/currency.js +9 -0
  191. package/modules/dgkeywordRtdProvider.js +3 -3
  192. package/modules/gridNMBidAdapter.js +10 -14
  193. package/modules/improvedigitalBidAdapter.js +191 -470
  194. package/modules/ixBidAdapter.js +24 -64
  195. package/modules/jwplayerVideoProvider.js +929 -0
  196. package/modules/jwplayerVideoProvider.md +25 -0
  197. package/modules/kargoBidAdapter.js +1 -1
  198. package/modules/multibid/index.js +12 -0
  199. package/modules/openxOrtbBidAdapter.js +120 -275
  200. package/modules/oxxionRtdProvider.js +119 -0
  201. package/modules/oxxionRtdProvider.md +48 -0
  202. package/modules/prebidServerBidAdapter/index.js +19 -716
  203. package/modules/prebidServerBidAdapter/ortbConverter.js +274 -0
  204. package/modules/priceFloors.js +73 -1
  205. package/modules/rtdModule/index.js +22 -1
  206. package/modules/schain.js +24 -1
  207. package/modules/spotxBidAdapter.js +16 -15
  208. package/modules/synacormediaBidAdapter.js +1 -1
  209. package/modules/teadsIdSystem.js +5 -0
  210. package/modules/userId/index.js +64 -6
  211. package/modules/videoModule/addingSubmodule.md +521 -0
  212. package/modules/videoModule/coreVideo.js +234 -0
  213. package/modules/videoModule/gamAdServerSubmodule.js +27 -0
  214. package/modules/videoModule/index.js +244 -0
  215. package/modules/videoModule/videoImpressionVerifier.js +206 -0
  216. package/modules/videojsVideoProvider.js +854 -0
  217. package/modules/videojsVideoProvider.md +17 -0
  218. package/package.json +5 -1
  219. package/src/adapterManager.js +56 -7
  220. package/src/adloader.js +2 -1
  221. package/src/auction.js +5 -0
  222. package/src/events.js +5 -1
  223. package/src/pbjsORTB.js +35 -0
  224. package/src/prebid.js +166 -145
  225. package/src/targeting.js +10 -2
  226. package/src/utils/currency.js +16 -0
  227. package/src/utils.js +21 -0
  228. package/test/spec/auctionmanager_spec.js +6 -0
  229. package/test/spec/modules/aaxBlockmeter_spec.js +58 -0
  230. package/test/spec/modules/chtnwBidAdapter_spec.js +105 -0
  231. package/test/spec/modules/concertBidAdapter_spec.js +56 -0
  232. package/test/spec/modules/consentManagementUsp_spec.js +64 -18
  233. package/test/spec/modules/criteoBidAdapter_spec.js +28 -0
  234. package/test/spec/modules/dgkeywordRtdProvider_spec.js +3 -3
  235. package/test/spec/modules/improvedigitalBidAdapter_spec.js +231 -211
  236. package/test/spec/modules/ixBidAdapter_spec.js +230 -371
  237. package/test/spec/modules/openxOrtbBidAdapter_spec.js +77 -49
  238. package/test/spec/modules/oxxionRtdProvider_spec.js +142 -0
  239. package/test/spec/modules/prebidServerBidAdapter_spec.js +139 -137
  240. package/test/spec/modules/realTimeDataModule_spec.js +65 -0
  241. package/test/spec/modules/userId_spec.js +67 -1
  242. package/test/spec/modules/videoModule/coreVideo_spec.js +98 -0
  243. package/test/spec/modules/videoModule/pbVideo_spec.js +362 -0
  244. package/test/spec/modules/videoModule/shared/parentModule_spec.js +73 -0
  245. package/test/spec/modules/videoModule/shared/state_spec.js +26 -0
  246. package/test/spec/modules/videoModule/shared/vastXmlBuilder_spec.js +103 -0
  247. package/test/spec/modules/videoModule/shared/vastXmlEditor_spec.js +209 -0
  248. package/test/spec/modules/videoModule/submodules/jwplayerVideoProvider_spec.js +846 -0
  249. package/test/spec/modules/videoModule/submodules/videojsVideoProvider_spec.js +391 -0
  250. package/test/spec/modules/videoModule/videoImpressionVerifier_spec.js +112 -0
  251. package/test/spec/ortbConverter/banner_spec.js +203 -0
  252. package/test/spec/ortbConverter/composer_spec.js +69 -0
  253. package/test/spec/ortbConverter/converter_spec.js +283 -0
  254. package/test/spec/ortbConverter/currency_spec.js +40 -0
  255. package/test/spec/ortbConverter/default_processors_spec.js +61 -0
  256. package/test/spec/ortbConverter/gdpr_spec.js +38 -0
  257. package/test/spec/ortbConverter/mediaTypes_spec.js +67 -0
  258. package/test/spec/ortbConverter/mergeProcessors_spec.js +59 -0
  259. package/test/spec/ortbConverter/multibid_spec.js +35 -0
  260. package/test/spec/ortbConverter/native_spec.js +95 -0
  261. package/test/spec/ortbConverter/pbjsORTB_spec.js +67 -0
  262. package/test/spec/ortbConverter/pbsExtensions/aliases_spec.js +57 -0
  263. package/test/spec/ortbConverter/pbsExtensions/params_spec.js +96 -0
  264. package/test/spec/ortbConverter/pbsExtensions/video_spec.js +52 -0
  265. package/test/spec/ortbConverter/priceFloors_spec.js +143 -0
  266. package/test/spec/ortbConverter/schain_spec.js +33 -0
  267. package/test/spec/ortbConverter/userId_spec.js +21 -0
  268. package/test/spec/ortbConverter/usp_spec.js +15 -0
  269. package/test/spec/ortbConverter/video_spec.js +189 -0
  270. package/test/spec/unit/core/adapterManager_spec.js +102 -0
  271. package/test/spec/unit/core/targeting_spec.js +34 -0
  272. package/test/spec/unit/pbjs_api_spec.js +108 -45
  273. package/test/spec/utils_spec.js +45 -1
@@ -0,0 +1,17 @@
1
+ # Overview
2
+
3
+ Module Name: Video.js Video Provider
4
+ Module Type: Video Submodule
5
+ Video Player: video.js
6
+ Player website: https://videojs.com/
7
+ Maintainer: Prebid Video Task Force
8
+
9
+ # Description
10
+
11
+ Video provider to connect the Prebid Video Module to video.js.
12
+
13
+ # Requirements
14
+
15
+ - Your page must include a build of video.js. For instructions see https://videojs.com/getting-started .
16
+ - Your video.js instance must include the Google IMA plugin.
17
+ - The Google IMA plugin must be accessible publicly in order for the Video.js Video Provider to reference it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prebid.js",
3
- "version": "7.22.0",
3
+ "version": "7.23.0",
4
4
  "description": "Header Bidding Management Library",
5
5
  "main": "src/prebid.js",
6
6
  "scripts": {
@@ -105,6 +105,10 @@
105
105
  "through2": "^4.0.2",
106
106
  "url": "^0.11.0",
107
107
  "url-parse": "^1.0.5",
108
+ "video.js": "^7.17.0",
109
+ "videojs-contrib-ads": "^6.9.0",
110
+ "videojs-ima": "^1.11.0",
111
+ "videojs-playlist": "^5.0.0",
108
112
  "webdriverio": "^7.6.1",
109
113
  "webpack": "^5.70.0",
110
114
  "webpack-bundle-analyzer": "^4.5.0",
@@ -35,6 +35,7 @@ import {GdprConsentHandler, UspConsentHandler} from './consentHandler.js';
35
35
  import * as events from './events.js';
36
36
  import CONSTANTS from './constants.json';
37
37
  import {useMetrics} from './utils/perfMetrics.js';
38
+ import {auctionManager} from './auctionManager.js';
38
39
 
39
40
  export const PARTITIONS = {
40
41
  CLIENT: 'client',
@@ -553,19 +554,30 @@ adapterManager.getAnalyticsAdapter = function(code) {
553
554
  return _analyticsRegistry[code];
554
555
  }
555
556
 
556
- function tryCallBidderMethod(bidder, method, param) {
557
+ function getBidderMethod(bidder, method) {
558
+ const adapter = _bidderRegistry[bidder];
559
+ const spec = adapter?.getSpec && adapter.getSpec();
560
+ if (spec && spec[method] && typeof spec[method] === 'function') {
561
+ return [spec, spec[method]]
562
+ }
563
+ }
564
+
565
+ function invokeBidderMethod(bidder, method, spec, fn, ...params) {
557
566
  try {
558
- const adapter = _bidderRegistry[bidder];
559
- const spec = adapter.getSpec();
560
- if (spec && spec[method] && typeof spec[method] === 'function') {
561
- logInfo(`Invoking ${bidder}.${method}`);
562
- config.runWithBidder(bidder, bind.call(spec[method], spec, param));
563
- }
567
+ logInfo(`Invoking ${bidder}.${method}`);
568
+ config.runWithBidder(bidder, fn.bind(spec, ...params));
564
569
  } catch (e) {
565
570
  logWarn(`Error calling ${method} of ${bidder}`);
566
571
  }
567
572
  }
568
573
 
574
+ function tryCallBidderMethod(bidder, method, param) {
575
+ const target = getBidderMethod(bidder, method);
576
+ if (target != null) {
577
+ invokeBidderMethod(bidder, method, ...target, param);
578
+ }
579
+ }
580
+
569
581
  adapterManager.callTimedOutBidders = function(adUnits, timedOutBidders, cbTimeout) {
570
582
  timedOutBidders = timedOutBidders.map((timedOutBidder) => {
571
583
  // Adding user configured params & timeout to timeout event data
@@ -600,4 +612,41 @@ adapterManager.callBidderError = function(bidder, error, bidderRequest) {
600
612
  tryCallBidderMethod(bidder, 'onBidderError', param);
601
613
  };
602
614
 
615
+ function resolveAlias(alias) {
616
+ const seen = new Set();
617
+ while (_aliasRegistry.hasOwnProperty(alias) && !seen.has(alias)) {
618
+ seen.add(alias);
619
+ alias = _aliasRegistry[alias];
620
+ }
621
+ return alias;
622
+ }
623
+ /**
624
+ * Ask every adapter to delete PII.
625
+ * See https://github.com/prebid/Prebid.js/issues/9081
626
+ */
627
+ adapterManager.callDataDeletionRequest = hook('sync', function (...args) {
628
+ const method = 'onDataDeletionRequest';
629
+ Object.keys(_bidderRegistry)
630
+ .filter((bidder) => !_aliasRegistry.hasOwnProperty(bidder))
631
+ .forEach(bidder => {
632
+ const target = getBidderMethod(bidder, method);
633
+ if (target != null) {
634
+ const bidderRequests = auctionManager.getBidsRequested().filter((br) =>
635
+ resolveAlias(br.bidderCode) === bidder
636
+ );
637
+ invokeBidderMethod(bidder, method, ...target, bidderRequests, ...args);
638
+ }
639
+ });
640
+ Object.entries(_analyticsRegistry).forEach(([name, entry]) => {
641
+ const fn = entry?.adapter?.[method];
642
+ if (typeof fn === 'function') {
643
+ try {
644
+ fn.apply(entry.adapter, args);
645
+ } catch (e) {
646
+ logError(`error calling ${method} of ${name}`, e);
647
+ }
648
+ }
649
+ });
650
+ });
651
+
603
652
  export default adapterManager;
package/src/adloader.js CHANGED
@@ -19,7 +19,8 @@ const _approvedLoadExternalJSList = [
19
19
  'inskin',
20
20
  'hadron',
21
21
  'medianet',
22
- 'improvedigital'
22
+ 'improvedigital',
23
+ 'aaxBlockmeter'
23
24
  ]
24
25
 
25
26
  /**
package/src/auction.js CHANGED
@@ -666,6 +666,7 @@ export const callPrebidCache = hook('async', function(auctionInstance, bidRespon
666
666
  */
667
667
  function addCommonResponseProperties(bidResponse, adUnitCode, {index = auctionManager.index} = {}) {
668
668
  const bidderRequest = index.getBidderRequest(bidResponse);
669
+ const adUnit = index.getAdUnit(bidResponse);
669
670
  const start = (bidderRequest && bidderRequest.start) || bidResponse.requestTimestamp;
670
671
 
671
672
  Object.assign(bidResponse, {
@@ -676,6 +677,10 @@ function addCommonResponseProperties(bidResponse, adUnitCode, {index = auctionMa
676
677
  adUnitCode
677
678
  });
678
679
 
680
+ if (adUnit?.ttlBuffer != null) {
681
+ bidResponse.ttlBuffer = adUnit.ttlBuffer;
682
+ }
683
+
679
684
  bidResponse.timeToRespond = bidResponse.responseTimestamp - bidResponse.requestTimestamp;
680
685
  }
681
686
 
package/src/events.js CHANGED
@@ -133,6 +133,10 @@ const _public = (function () {
133
133
  return _handlers;
134
134
  };
135
135
 
136
+ _public.addEvents = function (events) {
137
+ allEvents = allEvents.concat(events);
138
+ }
139
+
136
140
  /**
137
141
  * This method can return a copy of all the events fired
138
142
  * @return {Array} array of events fired
@@ -152,4 +156,4 @@ const _public = (function () {
152
156
 
153
157
  utils._setEventEmitter(_public.emit.bind(_public));
154
158
 
155
- export const {on, off, get, getEvents, emit} = _public;
159
+ export const {on, off, get, getEvents, emit, addEvents} = _public;
@@ -0,0 +1,35 @@
1
+ export const PROCESSOR_TYPES = ['request', 'imp', 'bidResponse', 'response'];
2
+ export const PROCESSOR_DIALECTS = ['default', 'pbs'];
3
+ export const [REQUEST, IMP, BID_RESPONSE, RESPONSE] = PROCESSOR_TYPES;
4
+ export const [DEFAULT, PBS] = PROCESSOR_DIALECTS;
5
+
6
+ const types = new Set(PROCESSOR_TYPES);
7
+
8
+ export function processorRegistry() {
9
+ const processors = {};
10
+
11
+ return {
12
+ registerOrtbProcessor({type, name, fn, priority = 0, dialects = [DEFAULT]}) {
13
+ if (!types.has(type)) {
14
+ throw new Error(`ORTB processor type must be one of: ${PROCESSOR_TYPES.join(', ')}`)
15
+ }
16
+ dialects.forEach(dialect => {
17
+ if (!processors.hasOwnProperty(dialect)) {
18
+ processors[dialect] = {};
19
+ }
20
+ if (!processors[dialect].hasOwnProperty(type)) {
21
+ processors[dialect][type] = {};
22
+ }
23
+ processors[dialect][type][name] = {
24
+ priority,
25
+ fn
26
+ }
27
+ })
28
+ },
29
+ getProcessors(dialect) {
30
+ return processors[dialect] || {};
31
+ }
32
+ }
33
+ }
34
+
35
+ export const {registerOrtbProcessor, getProcessors} = processorRegistry();
package/src/prebid.js CHANGED
@@ -485,86 +485,99 @@ $$PREBID_GLOBAL$$.renderAd = hook('async', function (doc, id, options) {
485
485
  logInfo('Invoking $$PREBID_GLOBAL$$.renderAd', arguments);
486
486
  logMessage('Calling renderAd with adId :' + id);
487
487
 
488
- if (doc && id) {
489
- try {
490
- // lookup ad by ad Id
491
- const bid = auctionManager.findBidByAdId(id);
492
-
493
- if (bid) {
494
- let shouldRender = true;
495
- if (bid && bid.status === CONSTANTS.BID_STATUS.RENDERED) {
496
- logWarn(`Ad id ${bid.adId} has been rendered before`);
497
- events.emit(STALE_RENDER, bid);
498
- if (deepAccess(config.getConfig('auctionOptions'), 'suppressStaleRender')) {
499
- shouldRender = false;
500
- }
501
- }
488
+ if (!id) {
489
+ const message = `Error trying to write ad Id :${id} to the page. Missing adId`;
490
+ emitAdRenderFail({ reason: MISSING_DOC_OR_ADID, message, id });
491
+ return;
492
+ }
502
493
 
503
- if (shouldRender) {
504
- // replace macros according to openRTB with price paid = bid.cpm
505
- bid.ad = replaceAuctionPrice(bid.ad, bid.originalCpm || bid.cpm);
506
- bid.adUrl = replaceAuctionPrice(bid.adUrl, bid.originalCpm || bid.cpm);
507
- // replacing clickthrough if submitted
508
- if (options && options.clickThrough) {
509
- const {clickThrough} = options;
510
- bid.ad = replaceClickThrough(bid.ad, clickThrough);
511
- bid.adUrl = replaceClickThrough(bid.adUrl, clickThrough);
512
- }
513
-
514
- // save winning bids
515
- auctionManager.addWinningBid(bid);
516
-
517
- // emit 'bid won' event here
518
- events.emit(BID_WON, bid);
519
-
520
- const {height, width, ad, mediaType, adUrl, renderer} = bid;
521
-
522
- const creativeComment = document.createComment(`Creative ${bid.creativeId} served by ${bid.bidder} Prebid.js Header Bidding`);
523
- insertElement(creativeComment, doc, 'html');
524
-
525
- if (isRendererRequired(renderer)) {
526
- executeRenderer(renderer, bid, doc);
527
- reinjectNodeIfRemoved(creativeComment, doc, 'html');
528
- emitAdRenderSucceeded({ doc, bid, id });
529
- } else if ((doc === document && !inIframe()) || mediaType === 'video') {
530
- const message = `Error trying to write ad. Ad render call ad id ${id} was prevented from writing to the main document.`;
531
- emitAdRenderFail({reason: PREVENT_WRITING_ON_MAIN_DOCUMENT, message, bid, id});
532
- } else if (ad) {
533
- doc.write(ad);
534
- doc.close();
535
- setRenderSize(doc, width, height);
536
- reinjectNodeIfRemoved(creativeComment, doc, 'html');
537
- callBurl(bid);
538
- emitAdRenderSucceeded({ doc, bid, id });
539
- } else if (adUrl) {
540
- const iframe = createInvisibleIframe();
541
- iframe.height = height;
542
- iframe.width = width;
543
- iframe.style.display = 'inline';
544
- iframe.style.overflow = 'hidden';
545
- iframe.src = adUrl;
546
-
547
- insertElement(iframe, doc, 'body');
548
- setRenderSize(doc, width, height);
549
- reinjectNodeIfRemoved(creativeComment, doc, 'html');
550
- callBurl(bid);
551
- emitAdRenderSucceeded({ doc, bid, id });
552
- } else {
553
- const message = `Error trying to write ad. No ad for bid response id: ${id}`;
554
- emitAdRenderFail({reason: NO_AD, message, bid, id});
555
- }
556
- }
557
- } else {
558
- const message = `Error trying to write ad. Cannot find ad by given id : ${id}`;
559
- emitAdRenderFail({ reason: CANNOT_FIND_AD, message, id });
494
+ try {
495
+ // lookup ad by ad Id
496
+ const bid = auctionManager.findBidByAdId(id);
497
+ if (!bid) {
498
+ const message = `Error trying to write ad. Cannot find ad by given id : ${id}`;
499
+ emitAdRenderFail({ reason: CANNOT_FIND_AD, message, id });
500
+ return;
501
+ }
502
+
503
+ if (bid.status === CONSTANTS.BID_STATUS.RENDERED) {
504
+ logWarn(`Ad id ${bid.adId} has been rendered before`);
505
+ events.emit(STALE_RENDER, bid);
506
+ if (deepAccess(config.getConfig('auctionOptions'), 'suppressStaleRender')) {
507
+ return;
560
508
  }
561
- } catch (e) {
562
- const message = `Error trying to write ad Id :${id} to the page:${e.message}`;
563
- emitAdRenderFail({ reason: EXCEPTION, message, id });
564
509
  }
565
- } else {
566
- const message = `Error trying to write ad Id :${id} to the page. Missing document or adId`;
567
- emitAdRenderFail({ reason: MISSING_DOC_OR_ADID, message, id });
510
+
511
+ // replace macros according to openRTB with price paid = bid.cpm
512
+ bid.ad = replaceAuctionPrice(bid.ad, bid.originalCpm || bid.cpm);
513
+ bid.adUrl = replaceAuctionPrice(bid.adUrl, bid.originalCpm || bid.cpm);
514
+ // replacing clickthrough if submitted
515
+ if (options && options.clickThrough) {
516
+ const {clickThrough} = options;
517
+ bid.ad = replaceClickThrough(bid.ad, clickThrough);
518
+ bid.adUrl = replaceClickThrough(bid.adUrl, clickThrough);
519
+ }
520
+
521
+ // save winning bids
522
+ auctionManager.addWinningBid(bid);
523
+
524
+ // emit 'bid won' event here
525
+ events.emit(BID_WON, bid);
526
+
527
+ const {height, width, ad, mediaType, adUrl, renderer} = bid;
528
+
529
+ // video module
530
+ const adUnitCode = bid.adUnitCode;
531
+ const adUnit = $$PREBID_GLOBAL$$.adUnits.filter(adUnit => adUnit.code === adUnitCode);
532
+ const videoModule = $$PREBID_GLOBAL$$.videoModule;
533
+ if (adUnit.video && videoModule) {
534
+ videoModule.renderBid(adUnit.video.divId, bid);
535
+ return;
536
+ }
537
+
538
+ if (!doc) {
539
+ const message = `Error trying to write ad Id :${id} to the page. Missing document`;
540
+ emitAdRenderFail({ reason: MISSING_DOC_OR_ADID, message, id });
541
+ return;
542
+ }
543
+
544
+ const creativeComment = document.createComment(`Creative ${bid.creativeId} served by ${bid.bidder} Prebid.js Header Bidding`);
545
+ insertElement(creativeComment, doc, 'html');
546
+
547
+ if (isRendererRequired(renderer)) {
548
+ executeRenderer(renderer, bid, doc);
549
+ reinjectNodeIfRemoved(creativeComment, doc, 'html');
550
+ emitAdRenderSucceeded({ doc, bid, id });
551
+ } else if ((doc === document && !inIframe()) || mediaType === 'video') {
552
+ const message = `Error trying to write ad. Ad render call ad id ${id} was prevented from writing to the main document.`;
553
+ emitAdRenderFail({reason: PREVENT_WRITING_ON_MAIN_DOCUMENT, message, bid, id});
554
+ } else if (ad) {
555
+ doc.write(ad);
556
+ doc.close();
557
+ setRenderSize(doc, width, height);
558
+ reinjectNodeIfRemoved(creativeComment, doc, 'html');
559
+ callBurl(bid);
560
+ emitAdRenderSucceeded({ doc, bid, id });
561
+ } else if (adUrl) {
562
+ const iframe = createInvisibleIframe();
563
+ iframe.height = height;
564
+ iframe.width = width;
565
+ iframe.style.display = 'inline';
566
+ iframe.style.overflow = 'hidden';
567
+ iframe.src = adUrl;
568
+
569
+ insertElement(iframe, doc, 'body');
570
+ setRenderSize(doc, width, height);
571
+ reinjectNodeIfRemoved(creativeComment, doc, 'html');
572
+ callBurl(bid);
573
+ emitAdRenderSucceeded({ doc, bid, id });
574
+ } else {
575
+ const message = `Error trying to write ad. No ad for bid response id: ${id}`;
576
+ emitAdRenderFail({reason: NO_AD, message, bid, id});
577
+ }
578
+ } catch (e) {
579
+ const message = `Error trying to write ad Id :${id} to the page:${e.message}`;
580
+ emitAdRenderFail({ reason: EXCEPTION, message, id });
568
581
  }
569
582
  });
570
583
 
@@ -609,7 +622,7 @@ $$PREBID_GLOBAL$$.removeAdUnit = function (adUnitCode) {
609
622
  * @alias module:pbjs.requestBids
610
623
  */
611
624
  $$PREBID_GLOBAL$$.requestBids = (function() {
612
- const delegate = hook('async', function ({ bidsBackHandler, timeout, adUnits, adUnitCodes, labels, auctionId, ortb2, metrics } = {}) {
625
+ const delegate = hook('sync', function ({ bidsBackHandler, timeout, adUnits, adUnitCodes, labels, auctionId, ttlBuffer, ortb2, metrics } = {}) {
613
626
  events.emit(REQUEST_BIDS);
614
627
  const cbTimeout = timeout || config.getConfig('bidderTimeout');
615
628
  logInfo('Invoking $$PREBID_GLOBAL$$.requestBids', arguments);
@@ -617,7 +630,7 @@ $$PREBID_GLOBAL$$.requestBids = (function() {
617
630
  global: mergeDeep({}, config.getAnyConfig('ortb2') || {}, ortb2 || {}),
618
631
  bidder: Object.fromEntries(Object.entries(config.getBidderConfig()).map(([bidder, cfg]) => [bidder, cfg.ortb2]).filter(([_, ortb2]) => ortb2 != null))
619
632
  }
620
- return startAuction({bidsBackHandler, timeout: cbTimeout, adUnits, adUnitCodes, labels, auctionId, ortb2Fragments, metrics});
633
+ return startAuction({bidsBackHandler, timeout: cbTimeout, adUnits, adUnitCodes, labels, auctionId, ttlBuffer, ortb2Fragments, metrics});
621
634
  }, 'requestBids');
622
635
 
623
636
  return wrapHook(delegate, function requestBids(req = {}) {
@@ -633,7 +646,7 @@ $$PREBID_GLOBAL$$.requestBids = (function() {
633
646
  });
634
647
  })();
635
648
 
636
- export const startAuction = hook('async', function ({ bidsBackHandler, timeout: cbTimeout, adUnits, adUnitCodes, labels, auctionId, ortb2Fragments, metrics } = {}) {
649
+ export const startAuction = hook('sync', function ({ bidsBackHandler, timeout: cbTimeout, adUnits, ttlBuffer, adUnitCodes, labels, auctionId, ortb2Fragments, metrics } = {}) {
637
650
  const s2sBidders = getS2SBidderSet(config.getConfig('s2sConfig') || []);
638
651
  adUnits = useMetrics(metrics).measureTime('requestBids.validate', () => checkAdUnitSetup(adUnits));
639
652
 
@@ -645,77 +658,85 @@ export const startAuction = hook('async', function ({ bidsBackHandler, timeout:
645
658
  adUnitCodes = adUnits && adUnits.map(unit => unit.code);
646
659
  }
647
660
 
648
- /*
649
- * for a given adunit which supports a set of mediaTypes
650
- * and a given bidder which supports a set of mediaTypes
651
- * a bidder is eligible to participate on the adunit
652
- * if it supports at least one of the mediaTypes on the adunit
653
- */
654
- adUnits.forEach(adUnit => {
655
- // get the adunit's mediaTypes, defaulting to banner if mediaTypes isn't present
656
- const adUnitMediaTypes = Object.keys(adUnit.mediaTypes || { 'banner': 'banner' });
657
-
658
- // get the bidder's mediaTypes
659
- const allBidders = adUnit.bids.map(bid => bid.bidder);
660
- const bidderRegistry = adapterManager.bidderRegistry;
661
-
662
- const bidders = allBidders.filter(bidder => !s2sBidders.has(bidder));
663
-
664
- const tid = adUnit.ortb2Imp?.ext?.tid || generateUUID();
665
- adUnit.transactionId = tid;
666
- // Populate ortb2Imp.ext.tid with transactionId. Specifying a transaction ID per item in the ortb impression array, lets multiple transaction IDs be transmitted in a single bid request.
667
- deepSetValue(adUnit, 'ortb2Imp.ext.tid', tid);
668
-
669
- bidders.forEach(bidder => {
670
- const adapter = bidderRegistry[bidder];
671
- const spec = adapter && adapter.getSpec && adapter.getSpec();
672
- // banner is default if not specified in spec
673
- const bidderMediaTypes = (spec && spec.supportedMediaTypes) || ['banner'];
674
-
675
- // check if the bidder's mediaTypes are not in the adUnit's mediaTypes
676
- const bidderEligible = adUnitMediaTypes.some(type => includes(bidderMediaTypes, type));
677
- if (!bidderEligible) {
678
- // drop the bidder from the ad unit if it's not compatible
679
- logWarn(unsupportedBidderMessage(adUnit, bidder));
680
- adUnit.bids = adUnit.bids.filter(bid => bid.bidder !== bidder);
681
- } else {
682
- adunitCounter.incrementBidderRequestsCounter(adUnit.code, bidder);
661
+ return new Promise((resolve) => {
662
+ function auctionDone(bids, timedOut, auctionId) {
663
+ if (typeof bidsBackHandler === 'function') {
664
+ try {
665
+ bidsBackHandler(bids, timedOut, auctionId);
666
+ } catch (e) {
667
+ logError('Error executing bidsBackHandler', null, e);
668
+ }
683
669
  }
670
+ resolve({bids, timedOut, auctionId});
671
+ }
672
+
673
+ /*
674
+ * for a given adunit which supports a set of mediaTypes
675
+ * and a given bidder which supports a set of mediaTypes
676
+ * a bidder is eligible to participate on the adunit
677
+ * if it supports at least one of the mediaTypes on the adunit
678
+ */
679
+ adUnits.forEach(adUnit => {
680
+ // get the adunit's mediaTypes, defaulting to banner if mediaTypes isn't present
681
+ const adUnitMediaTypes = Object.keys(adUnit.mediaTypes || { 'banner': 'banner' });
682
+
683
+ // get the bidder's mediaTypes
684
+ const allBidders = adUnit.bids.map(bid => bid.bidder);
685
+ const bidderRegistry = adapterManager.bidderRegistry;
686
+
687
+ const bidders = allBidders.filter(bidder => !s2sBidders.has(bidder));
688
+
689
+ const tid = adUnit.ortb2Imp?.ext?.tid || generateUUID();
690
+ adUnit.transactionId = tid;
691
+ if (ttlBuffer != null && !adUnit.hasOwnProperty('ttlBuffer')) {
692
+ adUnit.ttlBuffer = ttlBuffer;
693
+ }
694
+ // Populate ortb2Imp.ext.tid with transactionId. Specifying a transaction ID per item in the ortb impression array, lets multiple transaction IDs be transmitted in a single bid request.
695
+ deepSetValue(adUnit, 'ortb2Imp.ext.tid', tid);
696
+
697
+ bidders.forEach(bidder => {
698
+ const adapter = bidderRegistry[bidder];
699
+ const spec = adapter && adapter.getSpec && adapter.getSpec();
700
+ // banner is default if not specified in spec
701
+ const bidderMediaTypes = (spec && spec.supportedMediaTypes) || ['banner'];
702
+
703
+ // check if the bidder's mediaTypes are not in the adUnit's mediaTypes
704
+ const bidderEligible = adUnitMediaTypes.some(type => includes(bidderMediaTypes, type));
705
+ if (!bidderEligible) {
706
+ // drop the bidder from the ad unit if it's not compatible
707
+ logWarn(unsupportedBidderMessage(adUnit, bidder));
708
+ adUnit.bids = adUnit.bids.filter(bid => bid.bidder !== bidder);
709
+ } else {
710
+ adunitCounter.incrementBidderRequestsCounter(adUnit.code, bidder);
711
+ }
712
+ });
713
+ adunitCounter.incrementRequestsCounter(adUnit.code);
684
714
  });
685
- adunitCounter.incrementRequestsCounter(adUnit.code);
686
- });
687
715
 
688
- if (!adUnits || adUnits.length === 0) {
689
- logMessage('No adUnits configured. No bids requested.');
690
- if (typeof bidsBackHandler === 'function') {
691
- // executeCallback, this will only be called in case of first request
692
- try {
693
- bidsBackHandler();
694
- } catch (e) {
695
- logError('Error executing bidsBackHandler', null, e);
716
+ if (!adUnits || adUnits.length === 0) {
717
+ logMessage('No adUnits configured. No bids requested.');
718
+ auctionDone();
719
+ } else {
720
+ const auction = auctionManager.createAuction({
721
+ adUnits,
722
+ adUnitCodes,
723
+ callback: auctionDone,
724
+ cbTimeout,
725
+ labels,
726
+ auctionId,
727
+ ortb2Fragments,
728
+ metrics,
729
+ });
730
+
731
+ let adUnitsLen = adUnits.length;
732
+ if (adUnitsLen > 15) {
733
+ logInfo(`Current auction ${auction.getAuctionId()} contains ${adUnitsLen} adUnits.`, adUnits);
696
734
  }
697
- }
698
- return;
699
- }
700
735
 
701
- const auction = auctionManager.createAuction({
702
- adUnits,
703
- adUnitCodes,
704
- callback: bidsBackHandler,
705
- cbTimeout,
706
- labels,
707
- auctionId,
708
- ortb2Fragments,
709
- metrics,
736
+ adUnitCodes.forEach(code => targeting.setLatestAuctionForAdUnit(code, auction.getAuctionId()));
737
+ auction.callBids();
738
+ }
710
739
  });
711
-
712
- let adUnitsLen = adUnits.length;
713
- if (adUnitsLen > 15) {
714
- logInfo(`Current auction ${auction.getAuctionId()} contains ${adUnitsLen} adUnits.`, adUnits);
715
- }
716
-
717
- adUnitCodes.forEach(code => targeting.setLatestAuctionForAdUnit(code, auction.getAuctionId()));
718
- auction.callBids();
719
740
  }, 'startAuction');
720
741
 
721
742
  export function executeCallbacks(fn, reqBidsConfigObj) {
package/src/targeting.js CHANGED
@@ -28,7 +28,15 @@ import CONSTANTS from './constants.json';
28
28
  var pbTargetingKeys = [];
29
29
 
30
30
  const MAX_DFP_KEYLENGTH = 20;
31
- const TTL_BUFFER = 1000;
31
+ let DEFAULT_TTL_BUFFER = 1;
32
+
33
+ config.getConfig('ttlBuffer', (cfg) => {
34
+ if (typeof cfg.ttlBuffer === 'number') {
35
+ DEFAULT_TTL_BUFFER = cfg.ttlBuffer;
36
+ } else {
37
+ logError('Invalid value for ttlBuffer', cfg.ttlBuffer);
38
+ }
39
+ })
32
40
 
33
41
  const CFG_ALLOW_TARGETING_KEYS = `targetingControls.allowTargetingKeys`;
34
42
  const CFG_ADD_TARGETING_KEYS = `targetingControls.addTargetingKeys`;
@@ -39,7 +47,7 @@ export const TARGETING_KEYS = Object.keys(CONSTANTS.TARGETING_KEYS).map(
39
47
  );
40
48
 
41
49
  // return unexpired bids
42
- const isBidNotExpired = (bid) => (bid.responseTimestamp + bid.ttl * 1000 - TTL_BUFFER) > timestamp();
50
+ const isBidNotExpired = (bid) => (bid.responseTimestamp + (bid.ttl - (bid.hasOwnProperty('ttlBuffer') ? bid.ttlBuffer : DEFAULT_TTL_BUFFER)) * 1000) > timestamp();
43
51
 
44
52
  // return bids whose status is not set. Winning bids can only have a status of `rendered`.
45
53
  const isUnusedBid = (bid) => bid && ((bid.status && !includes([CONSTANTS.BID_STATUS.RENDERED], bid.status)) || !bid.status);
@@ -0,0 +1,16 @@
1
+ import {getGlobal} from '../prebidGlobal.js';
2
+
3
+ /**
4
+ * "best effort" wrapper around currency conversion; always returns an amount that may or may not be correct.
5
+ */
6
+ export function beConvertCurrency(amount, from, to) {
7
+ if (from === to) return amount;
8
+ let result = amount;
9
+ if (typeof getGlobal().convertCurrency === 'function') {
10
+ try {
11
+ result = getGlobal().convertCurrency(amount, from, to);
12
+ } catch (e) {
13
+ }
14
+ }
15
+ return result;
16
+ }
package/src/utils.js CHANGED
@@ -1377,6 +1377,27 @@ export function safeJSONParse(data) {
1377
1377
  } catch (e) {}
1378
1378
  }
1379
1379
 
1380
+ /**
1381
+ * Returns a memoized version of `fn`.
1382
+ *
1383
+ * @param fn
1384
+ * @param key cache key generator, invoked with the same arguments passed to `fn`.
1385
+ * By default, the first argument is used as key.
1386
+ * @return {function(): any}
1387
+ */
1388
+ export function memoize(fn, key = function (arg) { return arg; }) {
1389
+ const cache = new Map();
1390
+ const memoized = function () {
1391
+ const cacheKey = key.apply(this, arguments);
1392
+ if (!cache.has(cacheKey)) {
1393
+ cache.set(cacheKey, fn.apply(this, arguments));
1394
+ }
1395
+ return cache.get(cacheKey);
1396
+ }
1397
+ memoized.clear = cache.clear.bind(cache);
1398
+ return memoized;
1399
+ }
1400
+
1380
1401
  /**
1381
1402
  * Sets dataset attributes on a script
1382
1403
  * @param {Script} script
@@ -955,6 +955,12 @@ describe('auctionmanager.js', function () {
955
955
  const addedBid = find(auction.getBidsReceived(), bid => bid.adUnitCode == ADUNIT_CODE);
956
956
  assert.equal(addedBid.renderer.url, 'renderer.js');
957
957
  });
958
+
959
+ it('sets bidResponse.ttlBuffer from adUnit.ttlBuffer', () => {
960
+ adUnits[0].ttlBuffer = 0;
961
+ auction.callBids();
962
+ expect(auction.getBidsReceived()[0].ttlBuffer).to.eql(0);
963
+ });
958
964
  });
959
965
 
960
966
  describe('when auction timeout is 20', function () {