prebid.js 9.53.2 → 9.53.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (229) hide show
  1. package/dist/33acrossAnalyticsAdapter.js +1 -1
  2. package/dist/33acrossBidAdapter.js +1 -1
  3. package/dist/33acrossIdSystem.js +1 -1
  4. package/dist/BTBidAdapter.js +1 -1
  5. package/dist/adagioAnalyticsAdapter.js +1 -1
  6. package/dist/adagioBidAdapter.js +1 -1
  7. package/dist/adagioRtdProvider.js +1 -1
  8. package/dist/adagioUtils.js +1 -1
  9. package/dist/addefendBidAdapter.js +1 -1
  10. package/dist/adgenerationBidAdapter.js +1 -1
  11. package/dist/adlooxRtdProvider.js +1 -1
  12. package/dist/adqueryBidAdapter.js +1 -1
  13. package/dist/adrelevantisBidAdapter.js +1 -1
  14. package/dist/adstirBidAdapter.js +1 -1
  15. package/dist/adtrgtmeBidAdapter.js +1 -1
  16. package/dist/adxcgAnalyticsAdapter.js +1 -1
  17. package/dist/adxcgBidAdapter.js +1 -1
  18. package/dist/adyoulikeBidAdapter.js +1 -1
  19. package/dist/agmaAnalyticsAdapter.js +1 -1
  20. package/dist/ajaBidAdapter.js +1 -1
  21. package/dist/amxBidAdapter.js +1 -1
  22. package/dist/amxIdSystem.js +1 -1
  23. package/dist/aniviewBidAdapter.js +1 -1
  24. package/dist/appierAnalyticsAdapter.js +1 -1
  25. package/dist/appnexusBidAdapter.js +1 -1
  26. package/dist/asoBidAdapter.js +1 -1
  27. package/dist/axonixBidAdapter.js +1 -1
  28. package/dist/beopBidAdapter.js +1 -1
  29. package/dist/bidderTimeoutUtils.js +1 -0
  30. package/dist/bidglassBidAdapter.js +1 -1
  31. package/dist/big-richmediaBidAdapter.js +1 -1
  32. package/dist/bitmediaBidAdapter.js +1 -1
  33. package/dist/bridBidAdapter.js +1 -1
  34. package/dist/bridgeuppBidAdapter.js +1 -1
  35. package/dist/bridgewellBidAdapter.js +1 -1
  36. package/dist/brightMountainMediaBidAdapter.js +1 -1
  37. package/dist/carodaBidAdapter.js +1 -1
  38. package/dist/chtnwBidAdapter.js +1 -1
  39. package/dist/chunk-core.js +1 -1
  40. package/dist/concertBidAdapter.js +1 -1
  41. package/dist/connectadBidAdapter.js +1 -1
  42. package/dist/consumableBidAdapter.js +1 -1
  43. package/dist/contxtfulBidAdapter.js +1 -1
  44. package/dist/conversantAnalyticsAdapter.js +1 -1
  45. package/dist/conversantBidAdapter.js +1 -1
  46. package/dist/craftBidAdapter.js +1 -1
  47. package/dist/criteoBidAdapter.js +1 -1
  48. package/dist/cwireBidAdapter.js +1 -1
  49. package/dist/dailymotionBidAdapter.js +1 -1
  50. package/dist/debugging-standalone.js +1 -1
  51. package/dist/dependencies.json +10 -1
  52. package/dist/dspxBidAdapter.js +1 -1
  53. package/dist/dxkultureBidAdapter.js +1 -1
  54. package/dist/eplanningBidAdapter.js +1 -1
  55. package/dist/equativBidAdapter.js +1 -1
  56. package/dist/eskimiBidAdapter.js +1 -1
  57. package/dist/euidIdSystem.js +1 -1
  58. package/dist/exadsBidAdapter.js +1 -1
  59. package/dist/excoBidAdapter.js +1 -1
  60. package/dist/feedadBidAdapter.js +1 -1
  61. package/dist/finativeBidAdapter.js +1 -1
  62. package/dist/freewheel-sspBidAdapter.js +1 -1
  63. package/dist/fwsspBidAdapter.js +1 -1
  64. package/dist/gmosspBidAdapter.js +1 -1
  65. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  66. package/dist/greenbidsBidAdapter.js +1 -1
  67. package/dist/greenbidsRtdProvider.js +1 -1
  68. package/dist/gridBidAdapter.js +1 -1
  69. package/dist/gumgumBidAdapter.js +1 -1
  70. package/dist/h12mediaBidAdapter.js +1 -1
  71. package/dist/hypelabBidAdapter.js +1 -1
  72. package/dist/id5AnalyticsAdapter.js +1 -1
  73. package/dist/id5IdSystem.js +1 -1
  74. package/dist/imdsBidAdapter.js +1 -1
  75. package/dist/improvedigitalBidAdapter.js +1 -1
  76. package/dist/inmobiBidAdapter.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/liveIntentId.js +1 -1
  89. package/dist/logicadBidAdapter.js +1 -1
  90. package/dist/loglyliftBidAdapter.js +1 -1
  91. package/dist/luceadBidAdapter.js +1 -1
  92. package/dist/mabidderBidAdapter.js +1 -1
  93. package/dist/madsenseBidAdapter.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/medianetBidAdapter.js +1 -1
  99. package/dist/medianetUtils.js +1 -1
  100. package/dist/mediasquareBidAdapter.js +1 -1
  101. package/dist/mgidBidAdapter.js +1 -1
  102. package/dist/missenaBidAdapter.js +1 -1
  103. package/dist/mobilefuseBidAdapter.js +1 -1
  104. package/dist/nextMillenniumBidAdapter.js +1 -1
  105. package/dist/nexx360Utils.js +1 -1
  106. package/dist/nobidAnalyticsAdapter.js +1 -1
  107. package/dist/nobidBidAdapter.js +1 -1
  108. package/dist/nodalsAiRtdProvider.js +1 -1
  109. package/dist/not-for-prod/prebid.js +178 -175
  110. package/dist/objectGuard.js +1 -1
  111. package/dist/oguryBidAdapter.js +1 -1
  112. package/dist/onetagBidAdapter.js +1 -1
  113. package/dist/ooloAnalyticsAdapter.js +1 -1
  114. package/dist/openxBidAdapter.js +1 -1
  115. package/dist/optableRtdProvider.js +1 -1
  116. package/dist/optidigitalBidAdapter.js +1 -1
  117. package/dist/orbidderBidAdapter.js +1 -1
  118. package/dist/outbrainBidAdapter.js +1 -1
  119. package/dist/pixfutureBidAdapter.js +1 -1
  120. package/dist/publinkIdSystem.js +1 -1
  121. package/dist/pubmaticAnalyticsAdapter.js +1 -1
  122. package/dist/pubmaticBidAdapter.js +1 -1
  123. package/dist/pubmaticIdSystem.js +1 -1
  124. package/dist/pubmaticRtdProvider.js +1 -1
  125. package/dist/pubmaticUtils.js +1 -0
  126. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  127. package/dist/pubxaiAnalyticsAdapter.js +1 -1
  128. package/dist/pxyzBidAdapter.js +1 -1
  129. package/dist/quantcastBidAdapter.js +1 -1
  130. package/dist/readpeakBidAdapter.js +1 -1
  131. package/dist/relaidoBidAdapter.js +1 -1
  132. package/dist/retailspotBidAdapter.js +1 -1
  133. package/dist/rhythmoneBidAdapter.js +1 -1
  134. package/dist/riseUtils.js +1 -1
  135. package/dist/rtdModule.js +1 -1
  136. package/dist/rubiconBidAdapter.js +1 -1
  137. package/dist/seedingAllianceBidAdapter.js +1 -1
  138. package/dist/seedtagBidAdapter.js +1 -1
  139. package/dist/sevioBidAdapter.js +1 -0
  140. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  141. package/dist/sharethroughBidAdapter.js +1 -1
  142. package/dist/showheroes-bsBidAdapter.js +1 -1
  143. package/dist/smaatoBidAdapter.js +1 -1
  144. package/dist/smartadserverBidAdapter.js +1 -1
  145. package/dist/smartxBidAdapter.js +1 -1
  146. package/dist/smilewantedBidAdapter.js +1 -1
  147. package/dist/snigelBidAdapter.js +1 -1
  148. package/dist/sonobiBidAdapter.js +1 -1
  149. package/dist/sovrnBidAdapter.js +1 -1
  150. package/dist/sparteoBidAdapter.js +1 -1
  151. package/dist/sspBCBidAdapter.js +1 -1
  152. package/dist/stvBidAdapter.js +1 -1
  153. package/dist/sublimeBidAdapter.js +1 -1
  154. package/dist/taboolaBidAdapter.js +1 -1
  155. package/dist/tappxBidAdapter.js +1 -1
  156. package/dist/targetVideoBidAdapter.js +1 -1
  157. package/dist/teadsBidAdapter.js +1 -1
  158. package/dist/terceptAnalyticsAdapter.js +1 -1
  159. package/dist/themoneytizerBidAdapter.js +1 -1
  160. package/dist/timeoutRtdProvider.js +1 -1
  161. package/dist/trionBidAdapter.js +1 -1
  162. package/dist/tripleliftBidAdapter.js +1 -1
  163. package/dist/ttdBidAdapter.js +1 -1
  164. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  165. package/dist/uid2IdSystem.js +1 -1
  166. package/dist/underdogmediaBidAdapter.js +1 -1
  167. package/dist/undertoneBidAdapter.js +1 -1
  168. package/dist/unrulyBidAdapter.js +1 -1
  169. package/dist/userId.js +1 -1
  170. package/dist/vidazooUtils.js +1 -1
  171. package/dist/videobyteBidAdapter.js +1 -1
  172. package/dist/visxBidAdapter.js +1 -1
  173. package/dist/vuukleBidAdapter.js +1 -1
  174. package/dist/widespaceBidAdapter.js +1 -1
  175. package/dist/winrBidAdapter.js +1 -1
  176. package/dist/yahooAdsBidAdapter.js +1 -1
  177. package/dist/yandexBidAdapter.js +1 -1
  178. package/dist/yieldmoBidAdapter.js +1 -1
  179. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  180. package/integrationExamples/gpt/pubmaticRtdProvider_Example.html +161 -0
  181. package/libraries/bidderTimeoutUtils/bidderTimeoutUtils.js +119 -0
  182. package/libraries/objectGuard/objectGuard.js +170 -48
  183. package/libraries/objectGuard/ortbGuard.js +33 -43
  184. package/libraries/pubmaticUtils/plugins/dynamicTimeout.js +209 -0
  185. package/libraries/pubmaticUtils/plugins/floorProvider.js +168 -0
  186. package/libraries/pubmaticUtils/plugins/pluginManager.js +106 -0
  187. package/libraries/pubmaticUtils/plugins/unifiedPricingRule.js +375 -0
  188. package/libraries/pubmaticUtils/pubmaticUtils.js +76 -0
  189. package/modules/adagioAnalyticsAdapter.js +6 -1
  190. package/modules/adagioBidAdapter.js +12 -5
  191. package/modules/adagioRtdProvider.js +41 -35
  192. package/modules/fwsspBidAdapter.js +134 -69
  193. package/modules/fwsspBidAdapter.md +121 -26
  194. package/modules/optableRtdProvider.js +33 -12
  195. package/modules/pubmaticAnalyticsAdapter.js +315 -587
  196. package/modules/pubmaticBidAdapter.js +71 -8
  197. package/modules/pubmaticIdSystem.js +4 -4
  198. package/modules/pubmaticRtdProvider.js +105 -613
  199. package/modules/rtdModule/index.js +23 -6
  200. package/modules/sevioBidAdapter.js +413 -0
  201. package/modules/sevioBidAdapter.md +29 -0
  202. package/modules/sparteoBidAdapter.js +122 -10
  203. package/modules/timeoutRtdProvider.js +2 -105
  204. package/modules/ttdBidAdapter.js +0 -5
  205. package/modules/userId/eids.js +1 -1
  206. package/modules/userId/index.js +32 -1
  207. package/package.json +1 -1
  208. package/src/auction.js +3 -0
  209. package/test/spec/activities/objectGuard_spec.js +189 -32
  210. package/test/spec/activities/ortbGuard_spec.js +10 -15
  211. package/test/spec/libraries/bidderTimeoutUtils/bidderTimeoutUtils_spec.js +213 -0
  212. package/test/spec/libraries/pubmaticUtils/plugins/dynamicTimeout_spec.js +746 -0
  213. package/test/spec/libraries/pubmaticUtils/plugins/floorProvider_spec.js +184 -0
  214. package/test/spec/libraries/pubmaticUtils/plugins/pluginManager_spec.js +489 -0
  215. package/test/spec/libraries/pubmaticUtils/plugins/unifiedPricingRule_spec.js +359 -0
  216. package/test/spec/libraries/pubmaticUtils/pubmaticUtils_spec.js +236 -0
  217. package/test/spec/modules/adagioAnalyticsAdapter_spec.js +94 -24
  218. package/test/spec/modules/adagioRtdProvider_spec.js +17 -17
  219. package/test/spec/modules/fwsspBidAdapter_spec.js +513 -78
  220. package/test/spec/modules/optableRtdProvider_spec.js +55 -5
  221. package/test/spec/modules/pubmaticAnalyticsAdapter_spec.js +634 -916
  222. package/test/spec/modules/pubmaticBidAdapter_spec.js +260 -1
  223. package/test/spec/modules/pubmaticRtdProvider_spec.js +252 -1505
  224. package/test/spec/modules/realTimeDataModule_spec.js +58 -8
  225. package/test/spec/modules/sevioBidAdapter_spec.js +513 -0
  226. package/test/spec/modules/sparteoBidAdapter_spec.js +528 -43
  227. package/test/spec/modules/timeoutRtdProvider_spec.js +1 -201
  228. package/test/spec/modules/ttdBidAdapter_spec.js +0 -33
  229. package/test/spec/modules/userId_spec.js +115 -1
@@ -7,11 +7,7 @@ import {
7
7
  ORTB_UFPD_PATHS
8
8
  } from '../../src/activities/redactor.js';
9
9
  import {objectGuard, writeProtectRule} from './objectGuard.js';
10
- import {mergeDeep} from '../../src/utils.js';
11
-
12
- /**
13
- * @typedef {import('./objectGuard.js').ObjectGuard} ObjectGuard
14
- */
10
+ import {logError} from '../../src/utils.js';
15
11
 
16
12
  function ortb2EnrichRules(isAllowed = isActivityAllowed) {
17
13
  return [
@@ -32,20 +28,10 @@ export function ortb2GuardFactory(isAllowed = isActivityAllowed) {
32
28
  return objectGuard(ortb2TransmitRules(isAllowed).concat(ortb2EnrichRules(isAllowed)));
33
29
  }
34
30
 
35
- /**
36
- *
37
- *
38
- * @typedef {Function} ortb2Guard
39
- * @param {{}} ortb2 ORTB object to guard
40
- * @param {{}} params activity params to use for activity checks
41
- * @returns {ObjectGuard}
42
- */
43
-
44
31
  /*
45
32
  * Get a guard for an ORTB object. Read access is restricted in the same way it'd be redacted (see activites/redactor.js);
46
33
  * and writes are checked against the enrich* activites.
47
34
  *
48
- * @type ortb2Guard
49
35
  */
50
36
  export const ortb2Guard = ortb2GuardFactory();
51
37
 
@@ -53,40 +39,44 @@ export function ortb2FragmentsGuardFactory(guardOrtb2 = ortb2Guard) {
53
39
  return function guardOrtb2Fragments(fragments, params) {
54
40
  fragments.global = fragments.global || {};
55
41
  fragments.bidder = fragments.bidder || {};
56
- const bidders = new Set(Object.keys(fragments.bidder));
57
- const verifiers = [];
58
-
59
- function makeGuard(ortb2) {
60
- const guard = guardOrtb2(ortb2, params);
61
- verifiers.push(guard.verify);
62
- return guard.obj;
63
- }
64
-
65
- const obj = {
66
- global: makeGuard(fragments.global),
67
- bidder: Object.fromEntries(Object.entries(fragments.bidder).map(([bidder, ortb2]) => [bidder, makeGuard(ortb2)]))
42
+ const guard = {
43
+ global: guardOrtb2(fragments.global, params),
44
+ bidder: new Proxy(fragments.bidder, {
45
+ get(target, prop, receiver) {
46
+ let bidderData = Reflect.get(target, prop, receiver);
47
+ if (bidderData != null) {
48
+ bidderData = guardOrtb2(bidderData, params)
49
+ }
50
+ return bidderData;
51
+ },
52
+ set(target, prop, newValue, receiver) {
53
+ if (newValue == null || typeof newValue !== 'object') {
54
+ logError(`ortb2Fragments.bidder[bidderCode] must be an object`);
55
+ }
56
+ let bidderData = Reflect.get(target, prop, receiver);
57
+ if (bidderData == null) {
58
+ bidderData = target[prop] = {};
59
+ }
60
+ bidderData = guardOrtb2(bidderData, params);
61
+ Object.entries(newValue).forEach(([prop, value]) => {
62
+ bidderData[prop] = value;
63
+ })
64
+ return true;
65
+ }
66
+ })
68
67
  };
69
68
 
70
- return {
71
- obj,
72
- verify() {
73
- Object.entries(obj.bidder)
74
- .filter(([bidder]) => !bidders.has(bidder))
75
- .forEach(([bidder, ortb2]) => {
76
- const repl = {};
77
- const guard = guardOrtb2(repl, params);
78
- mergeDeep(guard.obj, ortb2);
79
- guard.verify();
80
- fragments.bidder[bidder] = repl;
81
- })
82
- verifiers.forEach(fn => fn());
83
- }
84
- }
69
+ return Object.defineProperties(
70
+ {},
71
+ Object.fromEntries(
72
+ // disallow overwriting of the top level `global` / `bidder`
73
+ Object.entries(guard).map(([prop, obj]) => [prop, {get: () => obj}])
74
+ )
75
+ )
85
76
  }
86
77
  }
87
78
 
88
79
  /**
89
80
  * Get a guard for an ortb2Fragments object.
90
- * @type {function(*, *): ObjectGuard}
91
81
  */
92
82
  export const guardOrtb2Fragments = ortb2FragmentsGuardFactory();
@@ -0,0 +1,209 @@
1
+ import { logInfo } from '../../../src/utils.js';
2
+ import { getGlobal } from '../../../src/prebidGlobal.js';
3
+ import { bidderTimeoutFunctions } from '../../bidderTimeoutUtils/bidderTimeoutUtils.js';
4
+ import { shouldThrottle } from '../pubmaticUtils.js';
5
+
6
+ let _dynamicTimeoutConfig = null;
7
+ export const getDynamicTimeoutConfig = () => _dynamicTimeoutConfig;
8
+ export const setDynamicTimeoutConfig = (config) => { _dynamicTimeoutConfig = config; }
9
+
10
+ export const CONSTANTS = Object.freeze({
11
+ LOG_PRE_FIX: 'PubMatic-Dynamic-Timeout: ',
12
+ INCLUDES_VIDEOS: 'includesVideo',
13
+ NUM_AD_UNITS: 'numAdUnits',
14
+ DEVICE_TYPE: 'deviceType',
15
+ CONNECTION_SPEED: 'connectionSpeed',
16
+ DEFAULT_SKIP_RATE: 50,
17
+ DEFAULT_THRESHOLD_TIMEOUT: 500
18
+ });
19
+
20
+ export const RULES_PERCENTAGE = {
21
+ [CONSTANTS.INCLUDES_VIDEOS]: {
22
+ "true": 20, // 20% of bidderTimeout
23
+ "false": 5 // 5% of bidderTimeout
24
+ },
25
+ [CONSTANTS.NUM_AD_UNITS]: {
26
+ "1-5": 10, // 10% of bidderTimeout
27
+ "6-10": 20, // 20% of bidderTimeout
28
+ "11-15": 30 // 30% of bidderTimeout
29
+ },
30
+ [CONSTANTS.DEVICE_TYPE]: {
31
+ "2": 5, // 5% of bidderTimeout
32
+ "4": 10, // 10% of bidderTimeout
33
+ "5": 20 // 20% of bidderTimeout
34
+ },
35
+ [CONSTANTS.CONNECTION_SPEED]: {
36
+ "slow": 20, // 20% of bidderTimeout
37
+ "medium": 10, // 10% of bidderTimeout
38
+ "fast": 5, // 5% of bidderTimeout
39
+ "unknown": 1 // 1% of bidderTimeout
40
+ }
41
+ };
42
+
43
+ /**
44
+ * Initialize the dynamic timeout plugin
45
+ * @param {Object} pluginName - Plugin name
46
+ * @param {Object} configJsonManager - Configuration JSON manager object
47
+ * @returns {Promise<boolean>} - Promise resolving to initialization status
48
+ */
49
+ export async function init(pluginName, configJsonManager) {
50
+ const config = configJsonManager.getConfigByName(pluginName);
51
+ if (!config) {
52
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Dynamic Timeout configuration not found`);
53
+ return false;
54
+ }
55
+ // Set the Dynamic Timeout config
56
+ setDynamicTimeoutConfig(config);
57
+
58
+ if (!getDynamicTimeoutConfig()?.enabled) {
59
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Dynamic Timeout configuration is disabled`);
60
+ return false;
61
+ }
62
+ return true;
63
+ }
64
+
65
+ /**
66
+ * Process bid request by applying dynamic timeout adjustments
67
+ * @param {Object} reqBidsConfigObj - Bid request config object
68
+ * @returns {Object} - Updated bid request config object with adjusted timeout
69
+ */
70
+ export function processBidRequest(reqBidsConfigObj) {
71
+ // Cache config to avoid multiple calls
72
+ const timeoutConfig = getDynamicTimeoutConfig();
73
+
74
+ // Check if request should be throttled based on skipRate
75
+ const skipRate = (timeoutConfig?.config?.skipRate !== undefined && timeoutConfig?.config?.skipRate !== null) ? timeoutConfig?.config?.skipRate : CONSTANTS.DEFAULT_SKIP_RATE;
76
+ if (shouldThrottle(skipRate)) {
77
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Dynamic timeout is skipped (skipRate: ${skipRate}%)`);
78
+ return reqBidsConfigObj;
79
+ }
80
+
81
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Dynamic timeout is applying...`);
82
+
83
+ // Get ad units and bidder timeout
84
+ const adUnits = reqBidsConfigObj.adUnits || getGlobal().adUnits;
85
+ const bidderTimeout = getBidderTimeout(reqBidsConfigObj);
86
+
87
+ // Calculate and apply additional timeout
88
+ const rules = getRules(bidderTimeout);
89
+ const additionalTimeout = bidderTimeoutFunctions.calculateTimeoutModifier(adUnits, rules);
90
+
91
+ reqBidsConfigObj.timeout = getFinalTimeout(bidderTimeout, additionalTimeout);
92
+
93
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Timeout adjusted from ${bidderTimeout}ms to ${reqBidsConfigObj.timeout}ms (added ${additionalTimeout}ms)`);
94
+ return reqBidsConfigObj;
95
+ }
96
+
97
+ /**
98
+ * Get targeting data
99
+ * @param {Array} adUnitCodes - Ad unit codes
100
+ * @param {Object} config - Module configuration
101
+ * @param {Object} userConsent - User consent data
102
+ * @param {Object} auction - Auction object
103
+ * @returns {Object} - Targeting data
104
+ */
105
+ export function getTargeting(adUnitCodes, config, userConsent, auction) {
106
+ // Implementation for targeting data, if not applied then do nothing
107
+ }
108
+
109
+ // Export the dynamic timeout functions
110
+ export const DynamicTimeout = {
111
+ init,
112
+ processBidRequest,
113
+ getTargeting
114
+ };
115
+
116
+ // Helper Functions
117
+
118
+ export const getFinalTimeout = (bidderTimeout, additionalTimeout) => {
119
+ // Calculate the final timeout by adding bidder timeout and additional timeout
120
+ const calculatedTimeout = parseInt(bidderTimeout) + parseInt(additionalTimeout);
121
+ const thresholdTimeout = getDynamicTimeoutConfig()?.config?.thresholdTimeout || CONSTANTS.DEFAULT_THRESHOLD_TIMEOUT;
122
+
123
+ // Handle cases where the calculated timeout might be negative or below threshold
124
+ if (calculatedTimeout < thresholdTimeout) {
125
+ // Log warning for negative or very low timeouts
126
+ if (calculatedTimeout < 0) {
127
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Warning: Negative timeout calculated (${calculatedTimeout}ms), using threshold (${thresholdTimeout}ms)`);
128
+ } else if (calculatedTimeout < thresholdTimeout) {
129
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Calculated timeout (${calculatedTimeout}ms) below threshold, using threshold (${thresholdTimeout}ms)`);
130
+ }
131
+ return thresholdTimeout;
132
+ }
133
+
134
+ return calculatedTimeout;
135
+ }
136
+
137
+ export const getBidderTimeout = (reqBidsConfigObj) => {
138
+ return getDynamicTimeoutConfig()?.config?.bidderTimeout
139
+ ? getDynamicTimeoutConfig()?.config?.bidderTimeout
140
+ : reqBidsConfigObj?.timeout || getGlobal()?.getConfig('bidderTimeout');
141
+ }
142
+
143
+ /**
144
+ * Get rules based on percentage values and bidderTimeout
145
+ * @param {number} bidderTimeout - Bidder timeout in milliseconds
146
+ * @returns {Object} - Rules with calculated millisecond values
147
+ */
148
+ export const getRules = (bidderTimeout) => {
149
+ const timeoutConfig = getDynamicTimeoutConfig();
150
+
151
+ // In milliseconds - If timeout rules provided by publishers are available then return it
152
+ if (timeoutConfig?.config?.timeoutRules && Object.keys(timeoutConfig.config.timeoutRules).length > 0) {
153
+ return timeoutConfig.config.timeoutRules;
154
+ }
155
+ // In milliseconds - Check for rules in priority order, If ML model rules are available then return it
156
+ if (timeoutConfig?.data && Object.keys(timeoutConfig.data).length > 0) {
157
+ return timeoutConfig.data;
158
+ }
159
+ // In Percentage - If no rules are available then create rules from the default defined - values are in percentages
160
+ return createDynamicRules(RULES_PERCENTAGE, bidderTimeout);
161
+ }
162
+
163
+ /**
164
+ * Creates dynamic rules based on percentage values and bidder timeout
165
+ * @param {Object} percentageRules - Rules with percentage values
166
+ * @param {number} bidderTimeout - Bidder timeout in milliseconds
167
+ * @return {Object} - Rules with calculated millisecond values
168
+ */
169
+ export const createDynamicRules = (percentageRules, bidderTimeout) => {
170
+ // Return empty object if required parameters are missing or invalid
171
+ if (!percentageRules || typeof percentageRules !== 'object') {
172
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Invalid percentage rules provided to createDynamicRules`);
173
+ return {};
174
+ }
175
+
176
+ // Handle negative or zero bidderTimeout gracefully
177
+ if (!bidderTimeout || typeof bidderTimeout !== 'number' || bidderTimeout <= 0) {
178
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Invalid bidderTimeout (${bidderTimeout}ms) provided to createDynamicRules`);
179
+ return {};
180
+ }
181
+
182
+ // Create a new rules object with millisecond values
183
+ return Object.entries(percentageRules).reduce((dynamicRules, [category, rules]) => {
184
+ // Skip if rules is not an object
185
+ if (!rules || typeof rules !== 'object') {
186
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Skipping invalid rule category: ${category}`);
187
+ return dynamicRules;
188
+ }
189
+
190
+ // Initialize category in the dynamic rules
191
+ dynamicRules[category] = {};
192
+
193
+ // Convert each percentage value to milliseconds
194
+ Object.entries(rules).forEach(([key, percentValue]) => {
195
+ // Ensure percentage value is a number and not zero
196
+ if (typeof percentValue === 'number' && percentValue !== 0) {
197
+ const calculatedTimeout = Math.floor(bidderTimeout * (percentValue / 100));
198
+ dynamicRules[category][key] = calculatedTimeout;
199
+
200
+ // Log warning for negative calculated timeouts
201
+ if (calculatedTimeout < 0) {
202
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Warning: Negative timeout calculated for ${category}.${key}: ${calculatedTimeout}ms`);
203
+ }
204
+ }
205
+ });
206
+
207
+ return dynamicRules;
208
+ }, {});
209
+ };
@@ -0,0 +1,168 @@
1
+ // plugins/floorProvider.js
2
+ import { logInfo, logError, isFn, logMessage, isEmpty } from '../../../src/utils.js';
3
+ import { getDeviceType as fetchDeviceType, getOS } from '../../userAgentUtils/index.js';
4
+ import { getBrowserType, getCurrentTimeOfDay, getUtmValue } from '../pubmaticUtils.js';
5
+ import { config as conf } from '../../../src/config.js';
6
+
7
+ /**
8
+ * This RTD module has a dependency on the priceFloors module.
9
+ * We utilize the continueAuction function from the priceFloors module to incorporate price floors data into the current auction.
10
+ */
11
+ import { continueAuction } from '../../../modules/priceFloors.js'; // eslint-disable-line prebid/validate-imports
12
+
13
+ let _floorConfig = null;
14
+ export const getFloorConfig = () => _floorConfig;
15
+ export const setFloorsConfig = (config) => { _floorConfig = config; }
16
+
17
+ let _configJsonManager = null;
18
+ export const getConfigJsonManager = () => _configJsonManager;
19
+ export const setConfigJsonManager = (configJsonManager) => { _configJsonManager = configJsonManager; }
20
+
21
+ export const CONSTANTS = Object.freeze({
22
+ LOG_PRE_FIX: 'PubMatic-Floor-Provider: '
23
+ });
24
+
25
+ /**
26
+ * Initialize the floor provider
27
+ * @param {Object} pluginName - Plugin name
28
+ * @param {Object} configJsonManager - Configuration JSON manager object
29
+ * @returns {Promise<boolean>} - Promise resolving to initialization status
30
+ */
31
+ export async function init(pluginName, configJsonManager) {
32
+ // Process floor-specific configuration
33
+ const config = configJsonManager.getConfigByName(pluginName);
34
+ if (!config) {
35
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Floor configuration not found`);
36
+ return false;
37
+ }
38
+ setFloorsConfig(config);
39
+
40
+ if (!getFloorConfig()?.enabled) {
41
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Floor configuration is disabled`);
42
+ return false;
43
+ }
44
+
45
+ if (!isFn(continueAuction)) {
46
+ logError(`${CONSTANTS.LOG_PRE_FIX} continueAuction is not a function. Please ensure to add priceFloors module.`);
47
+ return false;
48
+ }
49
+
50
+ setConfigJsonManager(configJsonManager);
51
+ try {
52
+ conf.setConfig(prepareFloorsConfig());
53
+ logMessage(`${CONSTANTS.LOG_PRE_FIX} dynamicFloors config set successfully`);
54
+ } catch (error) {
55
+ logError(`${CONSTANTS.LOG_PRE_FIX} Error setting dynamicFloors config: ${error}`);
56
+ }
57
+
58
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Floor configuration loaded`);
59
+
60
+ return true;
61
+ }
62
+
63
+ /**
64
+ * Process bid request
65
+ * @param {Object} reqBidsConfigObj - Bid request config object
66
+ * @returns {Object} - Updated bid request config object
67
+ */
68
+ export function processBidRequest(reqBidsConfigObj) {
69
+ try {
70
+ const hookConfig = {
71
+ reqBidsConfigObj,
72
+ context: null, // Removed 'this' as it's not applicable in function-based implementation
73
+ nextFn: () => true,
74
+ haveExited: false,
75
+ timer: null
76
+ };
77
+
78
+ // Apply floor configuration
79
+ continueAuction(hookConfig);
80
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Applied floor configuration to auction`);
81
+
82
+ return reqBidsConfigObj;
83
+ } catch (error) {
84
+ logError(`${CONSTANTS.LOG_PRE_FIX} Error applying floor configuration: ${error}`);
85
+ return reqBidsConfigObj;
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Get targeting data
91
+ * @param {Array} adUnitCodes - Ad unit codes
92
+ * @param {Object} config - Module configuration
93
+ * @param {Object} userConsent - User consent data
94
+ * @param {Object} auction - Auction object
95
+ * @returns {Object} - Targeting data
96
+ */
97
+ export function getTargeting(adUnitCodes, config, userConsent, auction) {
98
+ // Implementation for targeting data, if not applied then do nothing
99
+ }
100
+
101
+ // Export the floor provider functions
102
+ export const FloorProvider = {
103
+ init,
104
+ processBidRequest,
105
+ getTargeting
106
+ };
107
+
108
+ // Helper Functions
109
+
110
+ export const defaultValueTemplate = {
111
+ currency: 'USD',
112
+ skipRate: 0,
113
+ schema: {
114
+ fields: ['mediaType', 'size']
115
+ }
116
+ };
117
+
118
+ // Getter Functions
119
+ export const getTimeOfDay = () => getCurrentTimeOfDay();
120
+ export const getBrowser = () => getBrowserType();
121
+ export const getOs = () => getOS().toString();
122
+ export const getDeviceType = () => fetchDeviceType().toString();
123
+ export const getCountry = () => getConfigJsonManager().country;
124
+ export const getBidder = (request) => request?.bidder;
125
+ export const getUtm = () => getUtmValue();
126
+
127
+ export const prepareFloorsConfig = () => {
128
+ if (!getFloorConfig()?.enabled || !getFloorConfig()?.config) {
129
+ return undefined;
130
+ }
131
+
132
+ // Floor configs from adunit / setconfig
133
+ const defaultFloorConfig = conf.getConfig('floors') ?? {};
134
+ if (defaultFloorConfig?.endpoint) {
135
+ delete defaultFloorConfig.endpoint;
136
+ }
137
+
138
+ let ymUiConfig = { ...getFloorConfig().config };
139
+
140
+ // default values provided by publisher on YM UI
141
+ const defaultValues = ymUiConfig.defaultValues ?? {};
142
+ // If floorsData is not present or is an empty object, use default values
143
+ const ymFloorsData = isEmpty(getFloorConfig().data)
144
+ ? { ...defaultValueTemplate, values: { ...defaultValues } }
145
+ : getFloorConfig().data;
146
+
147
+ delete ymUiConfig.defaultValues;
148
+ // If skiprate is provided in configs, overwrite the value in ymFloorsData
149
+ (ymUiConfig.skipRate !== undefined) && (ymFloorsData.skipRate = ymUiConfig.skipRate);
150
+
151
+ // merge default configs from page, configs
152
+ return {
153
+ floors: {
154
+ ...defaultFloorConfig,
155
+ ...ymUiConfig,
156
+ data: ymFloorsData,
157
+ additionalSchemaFields: {
158
+ deviceType: getDeviceType,
159
+ timeOfDay: getTimeOfDay,
160
+ browser: getBrowser,
161
+ os: getOs,
162
+ utm: getUtm,
163
+ country: getCountry,
164
+ bidder: getBidder,
165
+ },
166
+ },
167
+ };
168
+ };
@@ -0,0 +1,106 @@
1
+ import { logInfo, logWarn, logError } from "../../../src/utils.js";
2
+
3
+ // pluginManager.js
4
+ export const plugins = new Map();
5
+ export const CONSTANTS = Object.freeze({
6
+ LOG_PRE_FIX: 'PubMatic-Plugin-Manager: '
7
+ });
8
+
9
+ /**
10
+ * Initialize the plugin manager with constants
11
+ * @returns {Object} - Plugin manager functions
12
+ */
13
+ export const PluginManager = () => ({
14
+ register,
15
+ initialize,
16
+ executeHook
17
+ });
18
+
19
+ /**
20
+ * Register a plugin with the plugin manager
21
+ * @param {string} name - Plugin name
22
+ * @param {Object} plugin - Plugin object
23
+ * @returns {Object} - Plugin manager functions
24
+ */
25
+ const register = (name, plugin) => {
26
+ if (plugins.has(name)) {
27
+ logWarn(`${CONSTANTS.LOG_PRE_FIX} Plugin ${name} already registered`);
28
+ return;
29
+ }
30
+ plugins.set(name, plugin);
31
+ };
32
+
33
+ /**
34
+ * Unregister a plugin from the plugin manager
35
+ * @param {string} name - Plugin name
36
+ * @returns {Object} - Plugin manager functions
37
+ */
38
+ const unregister = (name) => {
39
+ if (plugins.has(name)) {
40
+ logInfo(`${CONSTANTS.LOG_PRE_FIX} Unregistering plugin ${name}`);
41
+ plugins.delete(name);
42
+ }
43
+ };
44
+
45
+ /**
46
+ * Initialize all registered plugins with their specific config
47
+ * @param {Object} configJsonManager - Configuration JSON manager object
48
+ * @returns {Promise} - Promise resolving when all plugins are initialized
49
+ */
50
+ const initialize = async (configJsonManager) => {
51
+ const initPromises = [];
52
+
53
+ // Initialize each plugin with its specific config
54
+ for (const [name, plugin] of plugins.entries()) {
55
+ if (plugin.init) {
56
+ const initialized = await plugin.init(name, configJsonManager);
57
+ if (!initialized) {
58
+ unregister(name);
59
+ }
60
+ initPromises.push(initialized);
61
+ }
62
+ }
63
+
64
+ return Promise.all(initPromises);
65
+ };
66
+
67
+ /**
68
+ * Execute a hook on all registered plugins synchronously
69
+ * @param {string} hookName - Name of the hook to execute
70
+ * @param {...any} args - Arguments to pass to the hook
71
+ * @returns {Object} - Object containing merged results from all plugins
72
+ */
73
+ const executeHook = (hookName, ...args) => {
74
+ // Cache results to avoid repeated processing
75
+ const results = {};
76
+
77
+ try {
78
+ // Get all plugins that have the specified hook method
79
+ const pluginsWithHook = Array.from(plugins.entries())
80
+ .filter(([_, plugin]) => typeof plugin[hookName] === 'function');
81
+
82
+ // Process each plugin synchronously
83
+ for (const [name, plugin] of pluginsWithHook) {
84
+ try {
85
+ // Call the plugin's hook method synchronously
86
+ const result = plugin[hookName](...args);
87
+
88
+ // Skip null/undefined results
89
+ if (result === null || result === undefined) {
90
+ continue;
91
+ }
92
+
93
+ // If result is an object, merge it
94
+ if (typeof result === 'object') {
95
+ Object.assign(results, result);
96
+ }
97
+ } catch (error) {
98
+ logError(`${CONSTANTS.LOG_PRE_FIX} Error executing hook ${hookName} in plugin ${name}: ${error.message}`);
99
+ }
100
+ }
101
+ } catch (error) {
102
+ logError(`${CONSTANTS.LOG_PRE_FIX} Error in executeHookSync: ${error.message}`);
103
+ }
104
+
105
+ return results;
106
+ };