prebid.js 9.7.0 → 9.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 (255) hide show
  1. package/.github/codeql/codeql-config.yml +3 -0
  2. package/.github/codeql/queries/deviceMemory.ql +14 -0
  3. package/.github/codeql/queries/hardwareConcurrency.ql +14 -0
  4. package/.github/codeql/queries/prebid.qll +36 -0
  5. package/.github/codeql/queries/qlpack.yml +8 -0
  6. package/.github/workflows/jscpd.yml +1 -1
  7. package/dist/33acrossAnalyticsAdapter.js +1 -1
  8. package/dist/33acrossBidAdapter.js +1 -1
  9. package/dist/33acrossIdSystem.js +1 -1
  10. package/dist/BTBidAdapter.js +1 -1
  11. package/dist/adagioAnalyticsAdapter.js +1 -1
  12. package/dist/adagioBidAdapter.js +1 -1
  13. package/dist/adagioUtils.js +1 -1
  14. package/dist/addefendBidAdapter.js +1 -1
  15. package/dist/adgenerationBidAdapter.js +1 -1
  16. package/dist/adlooxRtdProvider.js +1 -1
  17. package/dist/admixerBidAdapter.js +1 -1
  18. package/dist/adqueryBidAdapter.js +1 -1
  19. package/dist/adrelevantisBidAdapter.js +1 -1
  20. package/dist/adstirBidAdapter.js +1 -1
  21. package/dist/adtrgtmeBidAdapter.js +1 -1
  22. package/dist/adxcgAnalyticsAdapter.js +1 -1
  23. package/dist/adxcgBidAdapter.js +1 -1
  24. package/dist/adyoulikeBidAdapter.js +1 -1
  25. package/dist/agmaAnalyticsAdapter.js +1 -1
  26. package/dist/ajaBidAdapter.js +1 -1
  27. package/dist/amxBidAdapter.js +1 -1
  28. package/dist/amxIdSystem.js +1 -1
  29. package/dist/appierAnalyticsAdapter.js +1 -1
  30. package/dist/appnexusBidAdapter.js +1 -1
  31. package/dist/asoBidAdapter.js +1 -1
  32. package/dist/axonixBidAdapter.js +1 -1
  33. package/dist/bidglassBidAdapter.js +1 -1
  34. package/dist/big-richmediaBidAdapter.js +1 -1
  35. package/dist/bridBidAdapter.js +1 -1
  36. package/dist/bridgewellBidAdapter.js +1 -1
  37. package/dist/brightMountainMediaBidAdapter.js +1 -1
  38. package/dist/carodaBidAdapter.js +1 -1
  39. package/dist/ccxBidAdapter.js +1 -1
  40. package/dist/chtnwBidAdapter.js +1 -1
  41. package/dist/chunk-core.js +1 -1
  42. package/dist/concertBidAdapter.js +1 -1
  43. package/dist/connectadBidAdapter.js +1 -1
  44. package/dist/consumableBidAdapter.js +1 -1
  45. package/dist/contxtfulRtdProvider.js +1 -1
  46. package/dist/conversantAnalyticsAdapter.js +1 -1
  47. package/dist/conversantBidAdapter.js +1 -1
  48. package/dist/craftBidAdapter.js +1 -1
  49. package/dist/criteoBidAdapter.js +1 -1
  50. package/dist/cwireBidAdapter.js +1 -1
  51. package/dist/dailymotionBidAdapter.js +1 -1
  52. package/dist/dependencies.json +19 -4
  53. package/dist/discoveryBidAdapter.js +1 -1
  54. package/dist/docereeAdManagerBidAdapter.js +1 -1
  55. package/dist/dspxBidAdapter.js +1 -1
  56. package/dist/dxkultureBidAdapter.js +1 -1
  57. package/dist/eclickadsBidAdapter.js +1 -0
  58. package/dist/eightPodAnalyticsAdapter.js +1 -1
  59. package/dist/eplanningBidAdapter.js +1 -1
  60. package/dist/euidIdSystem.js +1 -1
  61. package/dist/exadsBidAdapter.js +1 -1
  62. package/dist/feedadBidAdapter.js +1 -1
  63. package/dist/finativeBidAdapter.js +1 -1
  64. package/dist/freewheel-sspBidAdapter.js +1 -1
  65. package/dist/gmosspBidAdapter.js +1 -1
  66. package/dist/goldbachBidAdapter.js +1 -1
  67. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  68. package/dist/greenbidsRtdProvider.js +1 -1
  69. package/dist/gridBidAdapter.js +1 -1
  70. package/dist/gumgumBidAdapter.js +1 -1
  71. package/dist/h12mediaBidAdapter.js +1 -1
  72. package/dist/hypelabBidAdapter.js +1 -1
  73. package/dist/id5AnalyticsAdapter.js +1 -1
  74. package/dist/id5IdSystem.js +1 -1
  75. package/dist/imdsBidAdapter.js +1 -1
  76. package/dist/improvedigitalBidAdapter.js +1 -1
  77. package/dist/insticatorBidAdapter.js +1 -1
  78. package/dist/intentIqAnalyticsAdapter.js +1 -1
  79. package/dist/ixBidAdapter.js +1 -1
  80. package/dist/jixieBidAdapter.js +1 -1
  81. package/dist/justpremiumBidAdapter.js +1 -1
  82. package/dist/kargoBidAdapter.js +1 -1
  83. package/dist/kimberliteBidAdapter.js +1 -1
  84. package/dist/konduitAnalyticsAdapter.js +1 -1
  85. package/dist/kueezBidAdapter.js +1 -1
  86. package/dist/lassoBidAdapter.js +1 -1
  87. package/dist/lifestreetBidAdapter.js +1 -1
  88. package/dist/limelightDigitalBidAdapter.js +1 -1
  89. package/dist/liveIntentIdSystem.js +1 -1
  90. package/dist/logicadBidAdapter.js +1 -1
  91. package/dist/loglyliftBidAdapter.js +1 -1
  92. package/dist/luceadBidAdapter.js +1 -1
  93. package/dist/mabidderBidAdapter.js +1 -1
  94. package/dist/magniteAnalyticsAdapter.js +1 -1
  95. package/dist/malltvAnalyticsAdapter.js +1 -1
  96. package/dist/marsmediaBidAdapter.js +1 -1
  97. package/dist/mediafuseBidAdapter.js +1 -1
  98. package/dist/mediagoBidAdapter.js +1 -1
  99. package/dist/medianetAnalyticsAdapter.js +1 -1
  100. package/dist/medianetBidAdapter.js +1 -1
  101. package/dist/mediasquareBidAdapter.js +1 -1
  102. package/dist/mgidBidAdapter.js +1 -1
  103. package/dist/mgidUtils.js +1 -0
  104. package/dist/mgidXBidAdapter.js +1 -1
  105. package/dist/missenaBidAdapter.js +1 -1
  106. package/dist/mobianRtdProvider.js +1 -1
  107. package/dist/naveggIdSystem.js +1 -1
  108. package/dist/navigatorData.js +1 -0
  109. package/dist/nexx360BidAdapter.js +1 -1
  110. package/dist/nobidAnalyticsAdapter.js +1 -1
  111. package/dist/nobidBidAdapter.js +1 -1
  112. package/dist/not-for-prod/prebid.js +174 -169
  113. package/dist/oguryBidAdapter.js +1 -1
  114. package/dist/omsBidAdapter.js +1 -1
  115. package/dist/onetagBidAdapter.js +1 -1
  116. package/dist/ooloAnalyticsAdapter.js +1 -1
  117. package/dist/openxBidAdapter.js +1 -1
  118. package/dist/optidigitalBidAdapter.js +1 -1
  119. package/dist/orbidderBidAdapter.js +1 -1
  120. package/dist/outbrainBidAdapter.js +1 -1
  121. package/dist/pixfutureBidAdapter.js +1 -1
  122. package/dist/pstudioBidAdapter.js +1 -1
  123. package/dist/publinkIdSystem.js +1 -1
  124. package/dist/pubmaticAnalyticsAdapter.js +1 -1
  125. package/dist/pubmaticBidAdapter.js +1 -1
  126. package/dist/pubriseBidAdapter.js +1 -0
  127. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  128. package/dist/pubxaiAnalyticsAdapter.js +1 -1
  129. package/dist/pubxaiRtdProvider.js +1 -1
  130. package/dist/pxyzBidAdapter.js +1 -1
  131. package/dist/quantcastBidAdapter.js +1 -1
  132. package/dist/readpeakBidAdapter.js +1 -1
  133. package/dist/redtramBidAdapter.js +1 -1
  134. package/dist/relaidoBidAdapter.js +1 -1
  135. package/dist/retailspotBidAdapter.js +1 -1
  136. package/dist/rhythmoneBidAdapter.js +1 -1
  137. package/dist/richaudienceBidAdapter.js +1 -1
  138. package/dist/riseUtils.js +1 -1
  139. package/dist/rubiconBidAdapter.js +1 -1
  140. package/dist/seedingAllianceBidAdapter.js +1 -1
  141. package/dist/seedtagBidAdapter.js +1 -1
  142. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  143. package/dist/sharethroughBidAdapter.js +1 -1
  144. package/dist/smaatoBidAdapter.js +1 -1
  145. package/dist/smartadserverBidAdapter.js +1 -1
  146. package/dist/smarthubBidAdapter.js +1 -1
  147. package/dist/smartxBidAdapter.js +1 -1
  148. package/dist/smilewantedBidAdapter.js +1 -1
  149. package/dist/snigelBidAdapter.js +1 -1
  150. package/dist/sonobiBidAdapter.js +1 -1
  151. package/dist/sovrnBidAdapter.js +1 -1
  152. package/dist/sspBCBidAdapter.js +1 -1
  153. package/dist/stvBidAdapter.js +1 -1
  154. package/dist/sublimeBidAdapter.js +1 -1
  155. package/dist/taboolaBidAdapter.js +1 -1
  156. package/dist/tappxBidAdapter.js +1 -1
  157. package/dist/targetVideoAdServerVideo.js +1 -0
  158. package/dist/targetVideoBidAdapter.js +1 -1
  159. package/dist/teadsBidAdapter.js +1 -1
  160. package/dist/teqblazeUtils.js +1 -1
  161. package/dist/terceptAnalyticsAdapter.js +1 -1
  162. package/dist/themoneytizerBidAdapter.js +1 -1
  163. package/dist/trionBidAdapter.js +1 -1
  164. package/dist/tripleliftBidAdapter.js +1 -1
  165. package/dist/ttdBidAdapter.js +1 -1
  166. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  167. package/dist/uid2IdSystem.js +1 -1
  168. package/dist/underdogmediaBidAdapter.js +1 -1
  169. package/dist/undertoneBidAdapter.js +1 -1
  170. package/dist/unrulyBidAdapter.js +1 -1
  171. package/dist/userId.js +1 -1
  172. package/dist/vidazooUtils.js +1 -1
  173. package/dist/videobyteBidAdapter.js +1 -1
  174. package/dist/visxBidAdapter.js +1 -1
  175. package/dist/vuukleBidAdapter.js +1 -1
  176. package/dist/widespaceBidAdapter.js +1 -1
  177. package/dist/winrBidAdapter.js +1 -1
  178. package/dist/yahooAdsBidAdapter.js +1 -1
  179. package/dist/yieldmoBidAdapter.js +1 -1
  180. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  181. package/libraries/mgidUtils/mgidUtils.js +73 -0
  182. package/{src/fpd/navigator.js → libraries/navigatorData/navigatorData.js} +1 -1
  183. package/libraries/riseUtils/index.js +1 -1
  184. package/libraries/teqblazeUtils/bidderUtils.js +1 -1
  185. package/modules/admixerBidAdapter.js +12 -5
  186. package/modules/appnexusBidAdapter.js +1 -1
  187. package/modules/ccxBidAdapter.js +6 -2
  188. package/modules/contxtfulRtdProvider.js +15 -12
  189. package/modules/cwireBidAdapter.js +13 -9
  190. package/modules/cwireBidAdapter.md +29 -10
  191. package/modules/dailymotionBidAdapter.js +1 -1
  192. package/modules/dailymotionBidAdapter.md +11 -7
  193. package/modules/discoveryBidAdapter.js +1 -3
  194. package/modules/docereeAdManagerBidAdapter.js +14 -8
  195. package/modules/eclickadsBidAdapter.js +80 -0
  196. package/modules/eclickadsBidAdapter.md +55 -0
  197. package/modules/eightPodAnalyticsAdapter.js +13 -1
  198. package/modules/gumgumBidAdapter.js +6 -2
  199. package/modules/ixBidAdapter.js +0 -1
  200. package/modules/limelightDigitalBidAdapter.js +1 -1
  201. package/modules/mediagoBidAdapter.js +2 -4
  202. package/modules/mgidBidAdapter.js +30 -109
  203. package/modules/mgidXBidAdapter.js +2 -66
  204. package/modules/mobianRtdProvider.js +12 -8
  205. package/modules/naveggIdSystem.js +62 -58
  206. package/modules/naveggIdSystem.md +8 -0
  207. package/modules/oguryBidAdapter.js +5 -2
  208. package/modules/omsBidAdapter.js +1 -1
  209. package/modules/openxBidAdapter.js +1 -6
  210. package/modules/pstudioBidAdapter.js +5 -8
  211. package/modules/pstudioBidAdapter.md +6 -4
  212. package/modules/pubriseBidAdapter.js +19 -0
  213. package/modules/pubriseBidAdapter.md +79 -0
  214. package/modules/pubxaiAnalyticsAdapter.js +9 -4
  215. package/modules/pubxaiRtdProvider.js +38 -18
  216. package/modules/pubxaiRtdProvider.md +2 -2
  217. package/modules/redtramBidAdapter.js +2 -6
  218. package/modules/richaudienceBidAdapter.js +8 -1
  219. package/modules/rubiconBidAdapter.js +3 -3
  220. package/modules/smarthubBidAdapter.js +2 -0
  221. package/modules/targetVideoAdServerVideo.js +96 -0
  222. package/modules/targetVideoAdServerVideo.md +26 -0
  223. package/modules/teadsBidAdapter.js +4 -3
  224. package/modules/undertoneBidAdapter.js +1 -19
  225. package/modules/userId/index.js +1 -1
  226. package/package.json +1 -1
  227. package/src/adRendering.js +3 -0
  228. package/src/adapterManager.js +4 -0
  229. package/src/utils/focusTimeout.js +17 -6
  230. package/src/utils/ttlCollection.js +1 -1
  231. package/src/utils.js +28 -0
  232. package/test/spec/modules/admixerBidAdapter_spec.js +2 -2
  233. package/test/spec/modules/ccxBidAdapter_spec.js +81 -0
  234. package/test/spec/modules/contxtfulRtdProvider_spec.js +19 -19
  235. package/test/spec/modules/dailymotionBidAdapter_spec.js +12 -12
  236. package/test/spec/modules/discoveryBidAdapter_spec.js +1 -47
  237. package/test/spec/modules/docereeAdManagerBidAdapter_spec.js +87 -9
  238. package/test/spec/modules/eclickadsBidAdapter_spec.js +214 -0
  239. package/test/spec/modules/ixBidAdapter_spec.js +8 -1
  240. package/test/spec/modules/mobianRtdProvider_spec.js +32 -15
  241. package/test/spec/modules/naveggIdSystem_spec.js +141 -31
  242. package/test/spec/modules/oguryBidAdapter_spec.js +50 -4
  243. package/test/spec/modules/openxBidAdapter_spec.js +16 -49
  244. package/test/spec/modules/pstudioBidAdapter_spec.js +5 -5
  245. package/test/spec/modules/pubriseBidAdapter_spec.js +514 -0
  246. package/test/spec/modules/pubxaiAnalyticsAdapter_spec.js +9 -4
  247. package/test/spec/modules/pubxaiRtdProvider_spec.js +37 -5
  248. package/test/spec/modules/richaudienceBidAdapter_spec.js +62 -0
  249. package/test/spec/modules/rubiconBidAdapter_spec.js +10 -0
  250. package/test/spec/modules/targetVideoAdServerVideo_spec.js +179 -0
  251. package/test/spec/modules/trafficgateBidAdapter_spec.js +1 -1
  252. package/test/spec/ortbConverter/userId_spec.js +23 -2
  253. package/test/spec/unit/adRendering_spec.js +27 -1
  254. package/test/spec/unit/core/adapterManager_spec.js +10 -0
  255. package/test/spec/unit/utils/focusTimeout_spec.js +33 -6
@@ -0,0 +1,96 @@
1
+ import { registerVideoSupport } from '../src/adServerManager.js';
2
+ import { targeting } from '../src/targeting.js';
3
+ import { buildUrl, isEmpty, isPlainObject, logError, parseUrl } from '../src/utils.js';
4
+
5
+ /**
6
+ * Merge all the bid data and publisher-supplied options into a single URL, and then return it.
7
+ * @param {Object} options - The options object.
8
+ * @param {Object} options.params - params property.
9
+ * @param {string} options.params.iu - Required iu property.
10
+ * @param {Object} options.adUnit - adUnit property.
11
+ * @param {Object} [options.bid] - Optional bid property.
12
+ * @returns {string|undefined} The generated URL (if neither bid nor adUnit property is provided the generated string is undefined).
13
+ */
14
+ export function buildVideoUrl(options) {
15
+ if (!options.params || !options.params?.iu) {
16
+ logError('buildVideoUrl: Missing required properties.');
17
+ return;
18
+ }
19
+
20
+ if (!isPlainObject(options.adUnit) && !isPlainObject(options.bid)) {
21
+ logError('buildVideoUrl: Requires either \'adUnit\' or \'bid\' options value');
22
+ return;
23
+ }
24
+
25
+ const isURL = /^(https?:\/\/)/i;
26
+ const defaultParameters = {
27
+ autoplay: '[autoplay]',
28
+ mute: '[vpmute]',
29
+ page_url: '[page_url]',
30
+ cachebuster: '[timestamp]',
31
+ consent: '[consent]',
32
+ }
33
+
34
+ const adUnit = options.adUnit;
35
+ const bid = options.bid || targeting.getWinningBids(adUnit.code)[0];
36
+ const allTargetingData = getAllTargetingData(options);
37
+ const custParams = options.params.cust_params;
38
+ let iu = options.params.iu;
39
+
40
+ if (isURL.test(iu)) {
41
+ const urlComponents = parseUrl(iu, {noDecodeWholeURL: true});
42
+
43
+ for (const [key, value] of Object.entries({...allTargetingData, ...bid.adserverTargeting, ...defaultParameters})) {
44
+ if (!urlComponents.search.hasOwnProperty(key)) {
45
+ urlComponents.search[key] = value;
46
+ }
47
+ }
48
+
49
+ if (urlComponents.search.cust_params) {
50
+ for (const [key, value] of Object.entries(custParams)) {
51
+ if (!urlComponents.search.cust_params.includes(key)) {
52
+ urlComponents.search.cust_params += '%26' + key + '%3D' + value;
53
+ }
54
+ }
55
+ }
56
+
57
+ if (!isEmpty(custParams) && !urlComponents.search.cust_params) {
58
+ urlComponents.search.cust_params = Object.entries(custParams).map(([key, value]) => key + '%3D' + value).join('%26');
59
+ }
60
+
61
+ return buildUrl(urlComponents);
62
+ }
63
+
64
+ const search = {
65
+ iu,
66
+ ...defaultParameters,
67
+ ...allTargetingData,
68
+ ...bid.adserverTargeting,
69
+ };
70
+
71
+ if (!isEmpty(custParams)) {
72
+ search.cust_params = Object.entries(custParams).map(([key, value]) => key + '%3D' + value).join('%26');
73
+ }
74
+
75
+ return buildUrl({
76
+ protocol: 'https',
77
+ host: 'vid.tvserve.io',
78
+ pathname: '/ads/bid',
79
+ search
80
+ });
81
+ }
82
+
83
+ function getAllTargetingData(options) {
84
+ let allTargetingData = {};
85
+ const adUnit = options && options.adUnit;
86
+ if (adUnit) {
87
+ let allTargeting = targeting.getAllTargeting(adUnit.code);
88
+ allTargetingData = allTargeting ? allTargeting[adUnit.code] : {};
89
+ }
90
+
91
+ return allTargetingData;
92
+ }
93
+
94
+ registerVideoSupport('targetVideo', {
95
+ buildVideoUrl,
96
+ });
@@ -0,0 +1,26 @@
1
+ # Overview
2
+
3
+ ```
4
+ Module Name: Target Video Ad Server Video
5
+ Module Type: Ad Server Video
6
+ Maintainer: danijel.ristic@target-video.com
7
+ ```
8
+
9
+ # Description
10
+
11
+ Ad Server Video for target-video.com. Contact danijel.ristic@target-video.com for information.
12
+
13
+ # Integration
14
+
15
+ The helper function takes the form:
16
+
17
+ pbjs.adServers.targetVideo.buildVideoUrl(options)
18
+
19
+ Where:
20
+
21
+ * **`options`:** configuration object:
22
+ * **`params`:**
23
+ * **`iu`:** required property used to construct valid VAST tag URL
24
+ * **`adUnit`:** ad unit that is being filled
25
+ * **`bid` [optional]:** if you override the hardcoded `pbjs.adServers.dfp.buildVideoUrl(...)` logic that picks the first bid you *must* pass in the `bid` object you select
26
+ * **`url`:** VAST tag URL, similar to the value returned by `pbjs.adServers.dfp.buildVideoUrl(...)`
@@ -2,6 +2,7 @@ import {getValue, logError, deepAccess, parseSizesInput, isArray, getBidIdParame
2
2
  import {registerBidder} from '../src/adapters/bidderFactory.js';
3
3
  import {getStorageManager} from '../src/storageManager.js';
4
4
  import {isAutoplayEnabled} from '../libraries/autoplayDetection/autoplay.js';
5
+ import {getDM, getHC, getHLen} from '../libraries/navigatorData/navigatorData.js';
5
6
 
6
7
  /**
7
8
  * @typedef {import('../src/adapters/bidderFactory.js').BidRequest} BidRequest
@@ -65,11 +66,11 @@ export const spec = {
65
66
  deviceHeight: screen.height,
66
67
  devicePixelRatio: topWindow.devicePixelRatio,
67
68
  screenOrientation: screen.orientation?.type,
68
- historyLength: topWindow.history?.length,
69
+ historyLength: getHLen(),
69
70
  viewportHeight: topWindow.visualViewport?.height,
70
71
  viewportWidth: topWindow.visualViewport?.width,
71
- hardwareConcurrency: topWindow.navigator?.hardwareConcurrency,
72
- deviceMemory: topWindow.navigator?.deviceMemory,
72
+ hardwareConcurrency: getHC(),
73
+ deviceMemory: getDM(),
73
74
  hb_version: '$prebid.version$',
74
75
  ...getSharedViewerIdParameters(validBidRequests),
75
76
  ...getFirstPartyTeadsIdParameter(validBidRequests)
@@ -2,7 +2,7 @@
2
2
  * Adapter to send bids to Undertone
3
3
  */
4
4
 
5
- import {deepAccess, parseUrl} from '../src/utils.js';
5
+ import {deepAccess, parseUrl, extractDomainFromHost} from '../src/utils.js';
6
6
  import {registerBidder} from '../src/adapters/bidderFactory.js';
7
7
  import {BANNER, VIDEO} from '../src/mediaTypes.js';
8
8
 
@@ -26,24 +26,6 @@ function getBidFloor(bidRequest, mediaType) {
26
26
  return (floor && floor.currency === 'USD' && floor.floor) || 0;
27
27
  }
28
28
 
29
- function extractDomainFromHost(pageHost) {
30
- let domain = null;
31
- try {
32
- let domains = /[-\w]+\.([-\w]+|[-\w]{3,}|[-\w]{1,3}\.[-\w]{2})$/i.exec(pageHost);
33
- if (domains != null && domains.length > 0) {
34
- domain = domains[0];
35
- for (let i = 1; i < domains.length; i++) {
36
- if (domains[i].length > domain.length) {
37
- domain = domains[i];
38
- }
39
- }
40
- }
41
- } catch (e) {
42
- domain = null;
43
- }
44
- return domain;
45
- }
46
-
47
29
  function getGdprQueryParams(gdprConsent) {
48
30
  if (!gdprConsent) {
49
31
  return null;
@@ -1196,7 +1196,7 @@ module('userId', attachIdSystem, { postInstallAllowed: true });
1196
1196
  export function setOrtbUserExtEids(ortbRequest, bidderRequest, context) {
1197
1197
  const eids = deepAccess(context, 'bidRequests.0.userIdAsEids');
1198
1198
  if (eids && Object.keys(eids).length > 0) {
1199
- deepSetValue(ortbRequest, 'user.ext.eids', eids);
1199
+ deepSetValue(ortbRequest, 'user.ext.eids', eids.concat(ortbRequest.user?.ext?.eids || []));
1200
1200
  }
1201
1201
  }
1202
1202
  registerOrtbProcessor({type: REQUEST, name: 'userExtEids', fn: setOrtbUserExtEids});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "prebid.js",
3
- "version": "9.7.0",
3
+ "version": "9.9.0",
4
4
  "description": "Header Bidding Management Library",
5
5
  "main": "src/prebid.public.js",
6
6
  "exports": {
@@ -18,6 +18,7 @@ import {getCreativeRenderer} from './creativeRenderers.js';
18
18
  import {hook} from './hook.js';
19
19
  import {fireNativeTrackers} from './native.js';
20
20
  import {GreedyPromise} from './utils/promise.js';
21
+ import adapterManager from './adapterManager.js';
21
22
 
22
23
  const { AD_RENDER_FAILED, AD_RENDER_SUCCEEDED, STALE_RENDER, BID_WON } = EVENTS;
23
24
  const { EXCEPTION } = AD_RENDER_FAILED_REASON;
@@ -68,6 +69,8 @@ export function emitAdRenderSucceeded({ doc, bid, id }) {
68
69
  if (bid) data.bid = bid;
69
70
  if (id) data.adId = id;
70
71
 
72
+ adapterManager.callAdRenderSucceededBidder(bid.adapterCode || bid.bidder, bid);
73
+
71
74
  events.emit(AD_RENDER_SUCCEEDED, data);
72
75
  }
73
76
 
@@ -688,6 +688,10 @@ adapterManager.callBidderError = function(bidder, error, bidderRequest) {
688
688
  tryCallBidderMethod(bidder, 'onBidderError', param);
689
689
  };
690
690
 
691
+ adapterManager.callAdRenderSucceededBidder = function (bidder, bid) {
692
+ tryCallBidderMethod(bidder, 'onAdRenderSucceeded', bid);
693
+ }
694
+
691
695
  function resolveAlias(alias) {
692
696
  const seen = new Set();
693
697
  while (_aliasRegistry.hasOwnProperty(alias) && !seen.has(alias)) {
@@ -1,16 +1,27 @@
1
- let outOfFocusStart;
1
+ let outOfFocusStart = null; // enforce null otherwise it could be undefined and the callback wouldn't execute
2
2
  let timeOutOfFocus = 0;
3
3
  let suspendedTimeouts = [];
4
4
 
5
- document.addEventListener('visibilitychange', () => {
5
+ function trackTimeOutOfFocus() {
6
6
  if (document.hidden) {
7
7
  outOfFocusStart = Date.now()
8
8
  } else {
9
- timeOutOfFocus += Date.now() - outOfFocusStart
10
- suspendedTimeouts.forEach(({ callback, startTime, setTimerId }) => setTimerId(setFocusTimeout(callback, timeOutOfFocus - startTime)()))
9
+ timeOutOfFocus += Date.now() - (outOfFocusStart ?? 0); // when the page is loaded in hidden state outOfFocusStart is undefined, which results in timeoutOffset being NaN
11
10
  outOfFocusStart = null;
11
+ suspendedTimeouts.forEach(({ callback, startTime, setTimerId }) => setTimerId(setFocusTimeout(callback, timeOutOfFocus - startTime)()));
12
+ suspendedTimeouts = [];
12
13
  }
13
- });
14
+ }
15
+
16
+ document.addEventListener('visibilitychange', trackTimeOutOfFocus);
17
+
18
+ export function reset() {
19
+ outOfFocusStart = null;
20
+ timeOutOfFocus = 0;
21
+ suspendedTimeouts = [];
22
+ document.removeEventListener('visibilitychange', trackTimeOutOfFocus);
23
+ document.addEventListener('visibilitychange', trackTimeOutOfFocus);
24
+ }
14
25
 
15
26
  /**
16
27
  * Wraps native setTimeout function in order to count time only when page is focused
@@ -19,7 +30,7 @@ document.addEventListener('visibilitychange', () => {
19
30
  * @param {number} [milliseconds] - Minimum duration (in milliseconds) that the callback will be executed after
20
31
  * @returns {function(*): (number)} - Getter function for current timer id
21
32
  */
22
- export default function setFocusTimeout(callback, milliseconds) {
33
+ export function setFocusTimeout(callback, milliseconds) {
23
34
  const startTime = timeOutOfFocus;
24
35
  let timerId = setTimeout(() => {
25
36
  if (timeOutOfFocus === startTime && outOfFocusStart == null) {
@@ -1,6 +1,6 @@
1
1
  import {GreedyPromise} from './promise.js';
2
2
  import {binarySearch, logError, timestamp} from '../utils.js';
3
- import setFocusTimeout from './focusTimeout.js';
3
+ import {setFocusTimeout} from './focusTimeout.js';
4
4
 
5
5
  /**
6
6
  * Create a set-like collection that automatically forgets items after a certain time.
package/src/utils.js CHANGED
@@ -1258,3 +1258,31 @@ export function setOnAny(collection, key) {
1258
1258
  }
1259
1259
  return undefined;
1260
1260
  }
1261
+
1262
+ export function extractDomainFromHost(pageHost) {
1263
+ let domain = null;
1264
+ try {
1265
+ let domains = /[-\w]+\.([-\w]+|[-\w]{3,}|[-\w]{1,3}\.[-\w]{2})$/i.exec(pageHost);
1266
+ if (domains != null && domains.length > 0) {
1267
+ domain = domains[0];
1268
+ for (let i = 1; i < domains.length; i++) {
1269
+ if (domains[i].length > domain.length) {
1270
+ domain = domains[i];
1271
+ }
1272
+ }
1273
+ }
1274
+ } catch (e) {
1275
+ domain = null;
1276
+ }
1277
+ return domain;
1278
+ }
1279
+
1280
+ export function triggerNurlWithCpm(bid, cpm) {
1281
+ if (isStr(bid.nurl) && bid.nurl !== '') {
1282
+ bid.nurl = bid.nurl.replace(
1283
+ /\${AUCTION_PRICE}/,
1284
+ cpm
1285
+ );
1286
+ triggerPixel(bid.nurl);
1287
+ }
1288
+ }
@@ -226,12 +226,12 @@ describe('AdmixerAdapter', function () {
226
226
  },
227
227
  };
228
228
  it('gets floor', function () {
229
- bidderRequest.getFloor = () => {
229
+ validRequest[0].getFloor = () => {
230
230
  return { floor: 0.6 };
231
231
  };
232
232
  const request = spec.buildRequests(validRequest, bidderRequest);
233
233
  const payload = request.data;
234
- expect(payload.bidFloor).to.deep.equal(0.6);
234
+ expect(payload.imps[0].bidFloor).to.deep.equal(0.6);
235
235
  });
236
236
  });
237
237
 
@@ -1,4 +1,5 @@
1
1
  import { expect } from 'chai';
2
+ import {syncAddFPDToBidderRequest} from '../../helpers/fpd';
2
3
  import { spec } from 'modules/ccxBidAdapter.js';
3
4
  import * as utils from 'src/utils.js';
4
5
 
@@ -39,6 +40,7 @@ describe('ccxAdapter', function () {
39
40
  transactionId: 'aefddd38-cfa0-48ab-8bdd-325de4bab5f9'
40
41
  }
41
42
  ];
43
+
42
44
  describe('isBidRequestValid', function () {
43
45
  it('Valid bid requests', function () {
44
46
  expect(spec.isBidRequestValid(bids[0])).to.be.true;
@@ -75,6 +77,7 @@ describe('ccxAdapter', function () {
75
77
  expect(spec.isBidRequestValid(bidsClone[0])).to.be.true;
76
78
  });
77
79
  });
80
+
78
81
  describe('buildRequests', function () {
79
82
  it('No valid bids', function () {
80
83
  expect(spec.buildRequests([])).to.be.undefined;
@@ -173,6 +176,7 @@ describe('ccxAdapter', function () {
173
176
 
174
177
  expect(data.imp).to.deep.have.same.members(imps);
175
178
  });
179
+
176
180
  it('Valid bid request - sizes old style', function () {
177
181
  let bidsClone = utils.deepClone(bids);
178
182
  delete (bidsClone[0].mediaTypes);
@@ -218,6 +222,7 @@ describe('ccxAdapter', function () {
218
222
 
219
223
  expect(data.imp).to.deep.have.same.members(imps);
220
224
  });
225
+
221
226
  it('Valid bid request - sizes old style - no media type', function () {
222
227
  let bidsClone = utils.deepClone(bids);
223
228
  delete (bidsClone[0].mediaTypes);
@@ -385,6 +390,7 @@ describe('ccxAdapter', function () {
385
390
  expect(spec.interpretResponse({})).to.be.empty;
386
391
  });
387
392
  });
393
+
388
394
  describe('getUserSyncs', function () {
389
395
  it('Valid syncs - all', function () {
390
396
  let syncOptions = {
@@ -434,6 +440,7 @@ describe('ccxAdapter', function () {
434
440
  expect(spec.getUserSyncs(syncOptions, [{body: response}])).to.be.empty;
435
441
  });
436
442
  });
443
+
437
444
  describe('mediaTypesVideoParams', function () {
438
445
  it('Valid video mediaTypes', function () {
439
446
  let bids = [
@@ -488,4 +495,78 @@ describe('ccxAdapter', function () {
488
495
  expect(data.imp).to.deep.have.same.members(imps);
489
496
  });
490
497
  });
498
+
499
+ describe('FLEDGE', function () {
500
+ it('should properly build a request when FLEDGE is enabled', function () {
501
+ let bidderRequest = {
502
+ paapi: {
503
+ enabled: true
504
+ }
505
+ };
506
+ let bids = [
507
+ {
508
+ adUnitCode: 'banner',
509
+ auctionId: '0b9de793-8eda-481e-a548-aaaaaaaaaaa1',
510
+ bidId: '2e56e1af51ccc1',
511
+ bidder: 'ccx',
512
+ bidderRequestId: '17e7b9f58accc1',
513
+ mediaTypes: {
514
+ banner: {
515
+ sizes: [[300, 250]]
516
+ }
517
+ },
518
+ params: {
519
+ placementId: 609
520
+ },
521
+ sizes: [[300, 250]],
522
+ transactionId: 'befddd38-cfa0-48ab-8bdd-bbbbbbbbbbb1',
523
+ ortb2Imp: {
524
+ ext: {
525
+ ae: 1
526
+ }
527
+ }
528
+ }
529
+ ];
530
+
531
+ let ortbRequest = spec.buildRequests(bids, syncAddFPDToBidderRequest(bidderRequest));
532
+ let data = JSON.parse(ortbRequest.data);
533
+ expect(data.imp[0].ext.ae).to.equal(1);
534
+ });
535
+
536
+ it('should properly build a request when FLEDGE is disabled', function () {
537
+ let bidderRequest = {
538
+ paapi: {
539
+ enabled: false
540
+ }
541
+ };
542
+ let bids = [
543
+ {
544
+ adUnitCode: 'banner',
545
+ auctionId: '0b9de793-8eda-481e-a548-aaaaaaaaaaa2',
546
+ bidId: '2e56e1af51ccc2',
547
+ bidder: 'ccx',
548
+ bidderRequestId: '17e7b9f58accc2',
549
+ mediaTypes: {
550
+ banner: {
551
+ sizes: [[300, 250]]
552
+ }
553
+ },
554
+ params: {
555
+ placementId: 610
556
+ },
557
+ sizes: [[300, 250]],
558
+ transactionId: 'befddd38-cfa0-48ab-8bdd-bbbbbbbbbbb2',
559
+ ortb2Imp: {
560
+ ext: {
561
+ ae: 1
562
+ }
563
+ }
564
+ }
565
+ ];
566
+
567
+ let ortbRequest = spec.buildRequests(bids, syncAddFPDToBidderRequest(bidderRequest));
568
+ let data = JSON.parse(ortbRequest.data);
569
+ expect(data.imp[0].ext.ae).to.be.undefined;
570
+ });
571
+ });
491
572
  });
@@ -17,7 +17,7 @@ const RX_CONNECTOR_MOCK = {
17
17
  };
18
18
 
19
19
  const TIMEOUT = 10;
20
- const RX_CONNECTOR_IS_READY_EVENT = new CustomEvent('rxConnectorIsReady', { detail: RX_CONNECTOR_MOCK });
20
+ const RX_CONNECTOR_IS_READY_EVENT = new CustomEvent('rxConnectorIsReady', { detail: {[CUSTOMER]: RX_CONNECTOR_MOCK}, bubbles: true });
21
21
 
22
22
  function writeToStorage(requester, timeDiff) {
23
23
  let rx = RX_FROM_SESSION_STORAGE;
@@ -157,30 +157,30 @@ describe('contxtfulRtdProvider', function () {
157
157
  });
158
158
 
159
159
  describe('init', function () {
160
- it('gets the RX API returned by an external script', (done) => {
160
+ it('uses the RX API to get receptivity', (done) => {
161
161
  let config = buildInitConfig(VERSION, CUSTOMER);
162
162
  contxtfulSubmodule.init(config);
163
- loadExternalScriptTag.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
163
+ window.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
164
164
 
165
165
  setTimeout(() => {
166
166
  contxtfulSubmodule.getTargetingData(['ad-slot'], config);
167
- expect(RX_CONNECTOR_MOCK.fetchConfig.callCount, 'fetchConfig').to.be.equal(1);
168
- expect(RX_CONNECTOR_MOCK.rxApiBuilder.callCount, 'rxApiBuilder').to.be.equal(1);
167
+ expect(RX_API_MOCK.receptivity.callCount, 'receptivity 42').to.be.equal(1);
168
+ expect(RX_API_MOCK.receptivity.firstCall.returnValue, 'receptivity').to.be.equal(RX_FROM_API);
169
169
  done();
170
170
  }, TIMEOUT);
171
171
  });
172
172
  });
173
173
 
174
174
  describe('init', function () {
175
- it('uses the RX API to get receptivity', (done) => {
175
+ it('gets the RX API returned by an external script', (done) => {
176
176
  let config = buildInitConfig(VERSION, CUSTOMER);
177
177
  contxtfulSubmodule.init(config);
178
- loadExternalScriptTag.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
178
+ window.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
179
179
 
180
180
  setTimeout(() => {
181
181
  contxtfulSubmodule.getTargetingData(['ad-slot'], config);
182
- expect(RX_API_MOCK.receptivity.callCount, 'receptivity 42').to.be.equal(1);
183
- expect(RX_API_MOCK.receptivity.firstCall.returnValue, 'receptivity').to.be.equal(RX_FROM_API);
182
+ expect(RX_CONNECTOR_MOCK.fetchConfig.callCount, 'fetchConfig').at.least(1);
183
+ expect(RX_CONNECTOR_MOCK.rxApiBuilder.callCount, 'rxApiBuilder').at.least(1);
184
184
  done();
185
185
  }, TIMEOUT);
186
186
  });
@@ -245,7 +245,7 @@ describe('contxtfulRtdProvider', function () {
245
245
  it('adds receptivity to the ad units using the RX API', function (done) {
246
246
  let config = buildInitConfig(VERSION, CUSTOMER);
247
247
  contxtfulSubmodule.init(config);
248
- loadExternalScriptTag.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
248
+ window.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
249
249
 
250
250
  setTimeout(() => {
251
251
  let targetingData = contxtfulSubmodule.getTargetingData(adUnits, config);
@@ -278,7 +278,7 @@ describe('contxtfulRtdProvider', function () {
278
278
  let config = buildInitConfig(VERSION, CUSTOMER);
279
279
  config.params.adServerTargeting = false;
280
280
  contxtfulSubmodule.init(config);
281
- loadExternalScriptTag.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
281
+ window.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
282
282
 
283
283
  setTimeout(() => {
284
284
  let _ = contxtfulSubmodule.getTargetingData(adUnits, config);
@@ -291,7 +291,7 @@ describe('contxtfulRtdProvider', function () {
291
291
  let config = buildInitConfig(VERSION, CUSTOMER);
292
292
  config.params.adServerTargeting = false;
293
293
  contxtfulSubmodule.init(config);
294
- loadExternalScriptTag.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
294
+ window.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
295
295
 
296
296
  setTimeout(() => {
297
297
  let targetingData = contxtfulSubmodule.getTargetingData(adUnits, config);
@@ -375,7 +375,7 @@ describe('contxtfulRtdProvider', function () {
375
375
  describe('getBidRequestData', function () {
376
376
  it('calls once the onDone callback', function (done) {
377
377
  contxtfulSubmodule.init(buildInitConfig(VERSION, CUSTOMER));
378
- loadExternalScriptTag.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
378
+ window.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
379
379
 
380
380
  let reqBidsConfigObj = {
381
381
  ortb2Fragments: {
@@ -397,7 +397,7 @@ describe('contxtfulRtdProvider', function () {
397
397
  it('does not write receptivity to the global OpenRTB 2 fragment', function (done) {
398
398
  let config = buildInitConfig(VERSION, CUSTOMER);
399
399
  contxtfulSubmodule.init(config);
400
- loadExternalScriptTag.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
400
+ window.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
401
401
 
402
402
  let reqBidsConfigObj = {
403
403
  ortb2Fragments: {
@@ -419,7 +419,7 @@ describe('contxtfulRtdProvider', function () {
419
419
  it('writes receptivity to the configured bidder OpenRTB 2 fragments', function (done) {
420
420
  let config = buildInitConfig(VERSION, CUSTOMER);
421
421
  contxtfulSubmodule.init(config);
422
- loadExternalScriptTag.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
422
+ window.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
423
423
 
424
424
  let reqBidsConfigObj = {
425
425
  ortb2Fragments: {
@@ -505,7 +505,7 @@ describe('contxtfulRtdProvider', function () {
505
505
  it('uses the RX API', function (done) {
506
506
  let config = buildInitConfig(VERSION, CUSTOMER);
507
507
  contxtfulSubmodule.init(config);
508
- loadExternalScriptTag.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
508
+ window.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
509
509
 
510
510
  let reqBidsConfigObj = {
511
511
  ortb2Fragments: {
@@ -515,8 +515,8 @@ describe('contxtfulRtdProvider', function () {
515
515
  };
516
516
 
517
517
  setTimeout(() => {
518
- expect(RX_CONNECTOR_MOCK.fetchConfig.callCount).to.equal(1);
519
- expect(RX_CONNECTOR_MOCK.rxApiBuilder.callCount).to.equal(1);
518
+ expect(RX_CONNECTOR_MOCK.fetchConfig.callCount).at.least(1);
519
+ expect(RX_CONNECTOR_MOCK.rxApiBuilder.callCount).at.least(1);
520
520
  const onDoneSpy = sinon.spy();
521
521
  contxtfulSubmodule.getBidRequestData(reqBidsConfigObj, onDoneSpy, config);
522
522
  expect(onDoneSpy.callCount).to.equal(1);
@@ -530,7 +530,7 @@ describe('contxtfulRtdProvider', function () {
530
530
  it('adds receptivity to the reqBidsConfigObj', function (done) {
531
531
  let config = buildInitConfig(VERSION, CUSTOMER);
532
532
  contxtfulSubmodule.init(config);
533
- loadExternalScriptTag.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
533
+ window.dispatchEvent(RX_CONNECTOR_IS_READY_EVENT);
534
534
 
535
535
  let reqBidsConfigObj = {
536
536
  ortb2Fragments: {