prebid.js 9.53.3 → 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 (208) 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/adagioUtils.js +1 -1
  8. package/dist/addefendBidAdapter.js +1 -1
  9. package/dist/adgenerationBidAdapter.js +1 -1
  10. package/dist/adlooxRtdProvider.js +1 -1
  11. package/dist/adqueryBidAdapter.js +1 -1
  12. package/dist/adrelevantisBidAdapter.js +1 -1
  13. package/dist/adstirBidAdapter.js +1 -1
  14. package/dist/adtrgtmeBidAdapter.js +1 -1
  15. package/dist/adxcgAnalyticsAdapter.js +1 -1
  16. package/dist/adxcgBidAdapter.js +1 -1
  17. package/dist/adyoulikeBidAdapter.js +1 -1
  18. package/dist/agmaAnalyticsAdapter.js +1 -1
  19. package/dist/ajaBidAdapter.js +1 -1
  20. package/dist/amxBidAdapter.js +1 -1
  21. package/dist/amxIdSystem.js +1 -1
  22. package/dist/aniviewBidAdapter.js +1 -1
  23. package/dist/appierAnalyticsAdapter.js +1 -1
  24. package/dist/appnexusBidAdapter.js +1 -1
  25. package/dist/asoBidAdapter.js +1 -1
  26. package/dist/axonixBidAdapter.js +1 -1
  27. package/dist/beopBidAdapter.js +1 -1
  28. package/dist/bidderTimeoutUtils.js +1 -0
  29. package/dist/bidglassBidAdapter.js +1 -1
  30. package/dist/big-richmediaBidAdapter.js +1 -1
  31. package/dist/bitmediaBidAdapter.js +1 -1
  32. package/dist/bridBidAdapter.js +1 -1
  33. package/dist/bridgeuppBidAdapter.js +1 -1
  34. package/dist/bridgewellBidAdapter.js +1 -1
  35. package/dist/brightMountainMediaBidAdapter.js +1 -1
  36. package/dist/carodaBidAdapter.js +1 -1
  37. package/dist/chtnwBidAdapter.js +1 -1
  38. package/dist/chunk-core.js +1 -1
  39. package/dist/concertBidAdapter.js +1 -1
  40. package/dist/connectadBidAdapter.js +1 -1
  41. package/dist/consumableBidAdapter.js +1 -1
  42. package/dist/contxtfulBidAdapter.js +1 -1
  43. package/dist/conversantAnalyticsAdapter.js +1 -1
  44. package/dist/conversantBidAdapter.js +1 -1
  45. package/dist/craftBidAdapter.js +1 -1
  46. package/dist/criteoBidAdapter.js +1 -1
  47. package/dist/cwireBidAdapter.js +1 -1
  48. package/dist/dailymotionBidAdapter.js +1 -1
  49. package/dist/dependencies.json +10 -1
  50. package/dist/dspxBidAdapter.js +1 -1
  51. package/dist/dxkultureBidAdapter.js +1 -1
  52. package/dist/eplanningBidAdapter.js +1 -1
  53. package/dist/equativBidAdapter.js +1 -1
  54. package/dist/eskimiBidAdapter.js +1 -1
  55. package/dist/euidIdSystem.js +1 -1
  56. package/dist/exadsBidAdapter.js +1 -1
  57. package/dist/excoBidAdapter.js +1 -1
  58. package/dist/feedadBidAdapter.js +1 -1
  59. package/dist/finativeBidAdapter.js +1 -1
  60. package/dist/freewheel-sspBidAdapter.js +1 -1
  61. package/dist/fwsspBidAdapter.js +1 -1
  62. package/dist/gmosspBidAdapter.js +1 -1
  63. package/dist/greenbidsAnalyticsAdapter.js +1 -1
  64. package/dist/greenbidsBidAdapter.js +1 -1
  65. package/dist/greenbidsRtdProvider.js +1 -1
  66. package/dist/gridBidAdapter.js +1 -1
  67. package/dist/gumgumBidAdapter.js +1 -1
  68. package/dist/h12mediaBidAdapter.js +1 -1
  69. package/dist/hypelabBidAdapter.js +1 -1
  70. package/dist/id5AnalyticsAdapter.js +1 -1
  71. package/dist/id5IdSystem.js +1 -1
  72. package/dist/imdsBidAdapter.js +1 -1
  73. package/dist/improvedigitalBidAdapter.js +1 -1
  74. package/dist/inmobiBidAdapter.js +1 -1
  75. package/dist/insticatorBidAdapter.js +1 -1
  76. package/dist/intentIqAnalyticsAdapter.js +1 -1
  77. package/dist/ixBidAdapter.js +1 -1
  78. package/dist/jixieBidAdapter.js +1 -1
  79. package/dist/justpremiumBidAdapter.js +1 -1
  80. package/dist/kargoBidAdapter.js +1 -1
  81. package/dist/kimberliteBidAdapter.js +1 -1
  82. package/dist/konduitAnalyticsAdapter.js +1 -1
  83. package/dist/kueezBidAdapter.js +1 -1
  84. package/dist/lassoBidAdapter.js +1 -1
  85. package/dist/lifestreetBidAdapter.js +1 -1
  86. package/dist/liveIntentId.js +1 -1
  87. package/dist/logicadBidAdapter.js +1 -1
  88. package/dist/loglyliftBidAdapter.js +1 -1
  89. package/dist/luceadBidAdapter.js +1 -1
  90. package/dist/mabidderBidAdapter.js +1 -1
  91. package/dist/madsenseBidAdapter.js +1 -1
  92. package/dist/magniteAnalyticsAdapter.js +1 -1
  93. package/dist/malltvAnalyticsAdapter.js +1 -1
  94. package/dist/marsmediaBidAdapter.js +1 -1
  95. package/dist/mediafuseBidAdapter.js +1 -1
  96. package/dist/medianetBidAdapter.js +1 -1
  97. package/dist/medianetUtils.js +1 -1
  98. package/dist/mediasquareBidAdapter.js +1 -1
  99. package/dist/mgidBidAdapter.js +1 -1
  100. package/dist/missenaBidAdapter.js +1 -1
  101. package/dist/mobilefuseBidAdapter.js +1 -1
  102. package/dist/nextMillenniumBidAdapter.js +1 -1
  103. package/dist/nexx360Utils.js +1 -1
  104. package/dist/nobidAnalyticsAdapter.js +1 -1
  105. package/dist/nobidBidAdapter.js +1 -1
  106. package/dist/nodalsAiRtdProvider.js +1 -1
  107. package/dist/not-for-prod/prebid.js +175 -172
  108. package/dist/objectGuard.js +1 -1
  109. package/dist/oguryBidAdapter.js +1 -1
  110. package/dist/onetagBidAdapter.js +1 -1
  111. package/dist/ooloAnalyticsAdapter.js +1 -1
  112. package/dist/openxBidAdapter.js +1 -1
  113. package/dist/optableRtdProvider.js +1 -1
  114. package/dist/optidigitalBidAdapter.js +1 -1
  115. package/dist/orbidderBidAdapter.js +1 -1
  116. package/dist/outbrainBidAdapter.js +1 -1
  117. package/dist/pixfutureBidAdapter.js +1 -1
  118. package/dist/publinkIdSystem.js +1 -1
  119. package/dist/pubmaticAnalyticsAdapter.js +1 -1
  120. package/dist/pubmaticBidAdapter.js +1 -1
  121. package/dist/pubmaticRtdProvider.js +1 -1
  122. package/dist/pubmaticUtils.js +1 -0
  123. package/dist/pubwiseAnalyticsAdapter.js +1 -1
  124. package/dist/pubxaiAnalyticsAdapter.js +1 -1
  125. package/dist/pxyzBidAdapter.js +1 -1
  126. package/dist/quantcastBidAdapter.js +1 -1
  127. package/dist/readpeakBidAdapter.js +1 -1
  128. package/dist/relaidoBidAdapter.js +1 -1
  129. package/dist/retailspotBidAdapter.js +1 -1
  130. package/dist/rhythmoneBidAdapter.js +1 -1
  131. package/dist/riseUtils.js +1 -1
  132. package/dist/rtdModule.js +1 -1
  133. package/dist/rubiconBidAdapter.js +1 -1
  134. package/dist/seedingAllianceBidAdapter.js +1 -1
  135. package/dist/seedtagBidAdapter.js +1 -1
  136. package/dist/sevioBidAdapter.js +1 -0
  137. package/dist/sharethroughAnalyticsAdapter.js +1 -1
  138. package/dist/sharethroughBidAdapter.js +1 -1
  139. package/dist/showheroes-bsBidAdapter.js +1 -1
  140. package/dist/smaatoBidAdapter.js +1 -1
  141. package/dist/smartadserverBidAdapter.js +1 -1
  142. package/dist/smartxBidAdapter.js +1 -1
  143. package/dist/smilewantedBidAdapter.js +1 -1
  144. package/dist/snigelBidAdapter.js +1 -1
  145. package/dist/sonobiBidAdapter.js +1 -1
  146. package/dist/sovrnBidAdapter.js +1 -1
  147. package/dist/sparteoBidAdapter.js +1 -1
  148. package/dist/sspBCBidAdapter.js +1 -1
  149. package/dist/stvBidAdapter.js +1 -1
  150. package/dist/sublimeBidAdapter.js +1 -1
  151. package/dist/taboolaBidAdapter.js +1 -1
  152. package/dist/tappxBidAdapter.js +1 -1
  153. package/dist/targetVideoBidAdapter.js +1 -1
  154. package/dist/teadsBidAdapter.js +1 -1
  155. package/dist/terceptAnalyticsAdapter.js +1 -1
  156. package/dist/themoneytizerBidAdapter.js +1 -1
  157. package/dist/timeoutRtdProvider.js +1 -1
  158. package/dist/trionBidAdapter.js +1 -1
  159. package/dist/tripleliftBidAdapter.js +1 -1
  160. package/dist/ttdBidAdapter.js +1 -1
  161. package/dist/ucfunnelAnalyticsAdapter.js +1 -1
  162. package/dist/uid2IdSystem.js +1 -1
  163. package/dist/underdogmediaBidAdapter.js +1 -1
  164. package/dist/undertoneBidAdapter.js +1 -1
  165. package/dist/unrulyBidAdapter.js +1 -1
  166. package/dist/vidazooUtils.js +1 -1
  167. package/dist/videobyteBidAdapter.js +1 -1
  168. package/dist/visxBidAdapter.js +1 -1
  169. package/dist/vuukleBidAdapter.js +1 -1
  170. package/dist/widespaceBidAdapter.js +1 -1
  171. package/dist/winrBidAdapter.js +1 -1
  172. package/dist/yahooAdsBidAdapter.js +1 -1
  173. package/dist/yandexBidAdapter.js +1 -1
  174. package/dist/yieldmoBidAdapter.js +1 -1
  175. package/dist/yieldoneAnalyticsAdapter.js +1 -1
  176. package/integrationExamples/gpt/pubmaticRtdProvider_Example.html +161 -0
  177. package/libraries/bidderTimeoutUtils/bidderTimeoutUtils.js +119 -0
  178. package/libraries/objectGuard/objectGuard.js +36 -15
  179. package/libraries/pubmaticUtils/plugins/dynamicTimeout.js +209 -0
  180. package/libraries/pubmaticUtils/plugins/floorProvider.js +168 -0
  181. package/libraries/pubmaticUtils/plugins/pluginManager.js +106 -0
  182. package/libraries/pubmaticUtils/plugins/unifiedPricingRule.js +375 -0
  183. package/libraries/pubmaticUtils/pubmaticUtils.js +76 -0
  184. package/modules/fwsspBidAdapter.js +134 -69
  185. package/modules/fwsspBidAdapter.md +121 -26
  186. package/modules/optableRtdProvider.js +33 -12
  187. package/modules/pubmaticAnalyticsAdapter.js +5 -1
  188. package/modules/pubmaticRtdProvider.js +105 -565
  189. package/modules/rtdModule/index.js +23 -2
  190. package/modules/sevioBidAdapter.js +413 -0
  191. package/modules/sevioBidAdapter.md +29 -0
  192. package/modules/sparteoBidAdapter.js +122 -10
  193. package/modules/timeoutRtdProvider.js +2 -105
  194. package/package.json +1 -1
  195. package/test/spec/activities/objectGuard_spec.js +49 -16
  196. package/test/spec/libraries/bidderTimeoutUtils/bidderTimeoutUtils_spec.js +213 -0
  197. package/test/spec/libraries/pubmaticUtils/plugins/dynamicTimeout_spec.js +746 -0
  198. package/test/spec/libraries/pubmaticUtils/plugins/floorProvider_spec.js +184 -0
  199. package/test/spec/libraries/pubmaticUtils/plugins/pluginManager_spec.js +489 -0
  200. package/test/spec/libraries/pubmaticUtils/plugins/unifiedPricingRule_spec.js +359 -0
  201. package/test/spec/libraries/pubmaticUtils/pubmaticUtils_spec.js +236 -0
  202. package/test/spec/modules/fwsspBidAdapter_spec.js +513 -78
  203. package/test/spec/modules/optableRtdProvider_spec.js +55 -5
  204. package/test/spec/modules/pubmaticRtdProvider_spec.js +252 -1183
  205. package/test/spec/modules/realTimeDataModule_spec.js +58 -8
  206. package/test/spec/modules/sevioBidAdapter_spec.js +513 -0
  207. package/test/spec/modules/sparteoBidAdapter_spec.js +528 -43
  208. package/test/spec/modules/timeoutRtdProvider_spec.js +1 -201
@@ -0,0 +1,161 @@
1
+ <html>
2
+ <head>
3
+ <title>PubMatic RTD Provider Example</title>
4
+ <script async src="../../build/dev/prebid.js"></script>
5
+ <script async src="https://securepubads.g.doubleclick.net/tag/js/gpt.js"></script>
6
+ <script>
7
+ var FAILSAFE_TIMEOUT = 3300;
8
+ var PREBID_TIMEOUT = 1000;
9
+
10
+ var adUnits = [{
11
+ code: 'div-gpt-ad-1460505748561-0',
12
+ mediaTypes: {
13
+ banner: {
14
+ sizes: [[300, 250], [300,600]],
15
+ pos: 7,
16
+ }
17
+ },
18
+ bids: [
19
+ {
20
+ bidder: 'appnexus',
21
+ params: {
22
+ placementId: 13144370
23
+ }
24
+ }, {
25
+ bidder: 'pubmatic',
26
+ params: {
27
+ publisherId: '103207',
28
+ adUnit: 'dcomHomeTop-728x90',
29
+ }
30
+ },
31
+ ]
32
+ }
33
+ ,
34
+ {
35
+ code: 'div-gpt-ad-1460505748561-1',
36
+ mediaTypes: {
37
+ banner: {
38
+ sizes: [[728, 90]],
39
+ }
40
+ },
41
+ bids: [
42
+ {
43
+ bidder: 'appnexus',
44
+ params: {
45
+ placementId: 13144370
46
+ }
47
+ }, {
48
+ bidder: 'pubmatic',
49
+ params: {
50
+ publisherId: '103207',
51
+ adUnit: 'dcomHomeTop-728x90',
52
+ }
53
+ }
54
+ ]
55
+ }
56
+ ];
57
+
58
+ var pbjs = pbjs || {};
59
+ pbjs.que = pbjs.que || [];
60
+
61
+ </script>
62
+
63
+ <script>
64
+ var googletag = googletag || {};
65
+ googletag.cmd = googletag.cmd || [];
66
+ var s1;
67
+ googletag.cmd.push(function () {
68
+ googletag.pubads().disableInitialLoad();
69
+ });
70
+
71
+ pbjs.que.push(function () {
72
+ pbjs.setConfig({
73
+ enableSendAllBids : true,
74
+ enableTIDs: true,
75
+ realTimeData: {
76
+ auctionDelay: 500,
77
+ dataProviders: [
78
+ {
79
+ name: 'pubmatic',
80
+ waitForIt: true,
81
+ params:{
82
+ publisherId: '103207', // please contact PubMatic to get a publisherId for yourself
83
+ profileId: '12', // please contact PubMatic to get a profileId for yourself
84
+ }
85
+ }
86
+ ]
87
+ }
88
+ })
89
+
90
+ pbjs.addAdUnits(adUnits);
91
+ pbjs.enableAnalytics({
92
+ provider: 'pubmatic',
93
+ options: {
94
+ "publisherId": 5890 // please contact PubMatic to get a publisherId for yourself
95
+ }
96
+ });
97
+
98
+ pbjs.requestBids({
99
+ bidsBackHandler: sendAdserverRequest,
100
+ timeout: PREBID_TIMEOUT
101
+ });
102
+
103
+ });
104
+
105
+
106
+ function sendAdserverRequest() {
107
+ if (pbjs.adserverRequestSent) return;
108
+ pbjs.adserverRequestSent = true;
109
+ googletag.cmd.push(function () {
110
+ pbjs.que.push(function () {
111
+ pbjs.setTargetingForGPTAsync();
112
+ googletag.pubads().refresh();
113
+
114
+ });
115
+ });
116
+ }
117
+
118
+ </script>
119
+
120
+ <script>
121
+ googletag.cmd.push(function () {
122
+ s1 = googletag.defineSlot('/19968336/header-bid-tag-0', [[300, 250], [300, 600]], 'div-gpt-ad-1460505748561-0').addService(googletag.pubads());
123
+ s2 = googletag.defineSlot('/19968336/header-bid-tag-1', [[728, 90]], 'div-gpt-ad-1460505748561-1').addService(googletag.pubads());
124
+
125
+ googletag.pubads().enableSingleRequest();
126
+ googletag.enableServices();
127
+ });
128
+
129
+
130
+ function sendAdserverRequest() {
131
+ if (pbjs.adserverRequestSent) return;
132
+ pbjs.adserverRequestSent = true;
133
+ googletag.cmd.push(function () {
134
+ pbjs.que.push(function () {
135
+ pbjs.setTargetingForGPTAsync();
136
+ googletag.pubads().refresh();
137
+
138
+ });
139
+ });
140
+ }
141
+ </script>
142
+ </head>
143
+
144
+ <body>
145
+ <h2>Prebid.js Test</h2>
146
+ <h5>Div-1111</h5>
147
+ <div id='div-gpt-ad-1460505748561-0'>
148
+ <script type='text/javascript'>
149
+ googletag.cmd.push(function () { googletag.display('div-gpt-ad-1460505748561-0'); });
150
+ </script>
151
+ </div>
152
+ <br>
153
+
154
+ <h5>Div 2</h5>
155
+ <div id='div-gpt-ad-1460505748561-1'>
156
+ <script type='text/javascript'>
157
+ googletag.cmd.push(function () { googletag.display('div-gpt-ad-1460505748561-1'); });
158
+ </script>
159
+ </div>
160
+ </body>
161
+ </html>
@@ -0,0 +1,119 @@
1
+ import { logInfo } from '../../src/utils.js';
2
+
3
+ // this allows the stubbing of functions during testing
4
+ export const bidderTimeoutFunctions = {
5
+ getDeviceType,
6
+ checkVideo,
7
+ getConnectionSpeed,
8
+ calculateTimeoutModifier
9
+ };
10
+
11
+ /**
12
+ * Returns an array of a given object's own enumerable string-keyed property [key, value] pairs.
13
+ * @param {Object} obj
14
+ * @return {Array}
15
+ */
16
+ const entries = Object.entries || function (obj) {
17
+ const ownProps = Object.keys(obj);
18
+ let i = ownProps.length;
19
+ let resArray = new Array(i);
20
+ while (i--) { resArray[i] = [ownProps[i], obj[ownProps[i]]]; }
21
+ return resArray;
22
+ };
23
+
24
+ function getDeviceType() {
25
+ const userAgent = window.navigator.userAgent.toLowerCase();
26
+ if ((/ipad|android 3.0|xoom|sch-i800|playbook|tablet|kindle/i.test(userAgent))) {
27
+ return 5; // tablet
28
+ }
29
+ if ((/iphone|ipod|android|blackberry|opera|mini|windows\sce|palm|smartphone|iemobile/i.test(userAgent))) {
30
+ return 4; // mobile
31
+ }
32
+ return 2; // personal computer
33
+ }
34
+
35
+ function checkVideo(adUnits) {
36
+ return adUnits.some((adUnit) => {
37
+ return adUnit.mediaTypes && adUnit.mediaTypes.video;
38
+ });
39
+ }
40
+
41
+ function getConnectionSpeed() {
42
+ const connection = window.navigator.connection || window.navigator.mozConnection || window.navigator.webkitConnection || {}
43
+ const connectionType = connection.type || connection.effectiveType;
44
+
45
+ switch (connectionType) {
46
+ case 'slow-2g':
47
+ case '2g':
48
+ return 'slow';
49
+
50
+ case '3g':
51
+ return 'medium';
52
+
53
+ case 'bluetooth':
54
+ case 'cellular':
55
+ case 'ethernet':
56
+ case 'wifi':
57
+ case 'wimax':
58
+ case '4g':
59
+ return 'fast';
60
+ }
61
+
62
+ return 'unknown';
63
+ }
64
+
65
+ /**
66
+ * Calculate the time to be added to the timeout
67
+ * @param {Array} adUnits
68
+ * @param {Object} rules
69
+ * @return {number}
70
+ */
71
+ function calculateTimeoutModifier(adUnits, rules) {
72
+ if (!rules) {
73
+ return 0;
74
+ }
75
+
76
+ logInfo('Timeout rules', rules);
77
+ let timeoutModifier = 0;
78
+ let toAdd = 0;
79
+
80
+ if (rules.includesVideo) {
81
+ const hasVideo = bidderTimeoutFunctions.checkVideo(adUnits);
82
+ toAdd = rules.includesVideo[hasVideo] || 0;
83
+ logInfo(`Adding ${toAdd} to timeout for includesVideo ${hasVideo}`)
84
+ timeoutModifier += toAdd;
85
+ }
86
+
87
+ if (rules.numAdUnits) {
88
+ const numAdUnits = adUnits.length;
89
+ if (rules.numAdUnits[numAdUnits]) {
90
+ timeoutModifier += rules.numAdUnits[numAdUnits];
91
+ } else {
92
+ for (const [rangeStr, timeoutVal] of entries(rules.numAdUnits)) {
93
+ const [lowerBound, upperBound] = rangeStr.split('-');
94
+ if (parseInt(lowerBound) <= numAdUnits && numAdUnits <= parseInt(upperBound)) {
95
+ logInfo(`Adding ${timeoutVal} to timeout for numAdUnits ${numAdUnits}`)
96
+ timeoutModifier += timeoutVal;
97
+ break;
98
+ }
99
+ }
100
+ }
101
+ }
102
+
103
+ if (rules.deviceType) {
104
+ const deviceType = bidderTimeoutFunctions.getDeviceType();
105
+ toAdd = rules.deviceType[deviceType] || 0;
106
+ logInfo(`Adding ${toAdd} to timeout for deviceType ${deviceType}`)
107
+ timeoutModifier += toAdd;
108
+ }
109
+
110
+ if (rules.connectionSpeed) {
111
+ const connectionSpeed = bidderTimeoutFunctions.getConnectionSpeed();
112
+ toAdd = rules.connectionSpeed[connectionSpeed] || 0;
113
+ logInfo(`Adding ${toAdd} to timeout for connectionSpeed ${connectionSpeed}`)
114
+ timeoutModifier += toAdd;
115
+ }
116
+
117
+ logInfo('timeout Modifier calculated', timeoutModifier);
118
+ return timeoutModifier;
119
+ }
@@ -26,6 +26,10 @@ export function objectGuard(rules) {
26
26
  // build a tree representation of them, where the root is the object itself,
27
27
  // and each node's children are properties of the corresponding (nested) object.
28
28
 
29
+ function invalid() {
30
+ return new Error('incompatible redaction rules');
31
+ }
32
+
29
33
  rules.forEach(rule => {
30
34
  rule.paths.forEach(path => {
31
35
  let node = root;
@@ -36,15 +40,22 @@ export function objectGuard(rules) {
36
40
  node.wpRules = node.wpRules ?? [];
37
41
  node.redactRules = node.redactRules ?? [];
38
42
  });
39
- (rule.wp ? node.wpRules : node.redactRules).push(rule);
40
- if (rule.wp) {
41
- // mark the whole path as write protected, so that write operations
42
- // on parents do not need to walk down the tree
43
- let parent = node;
44
- while (parent && !parent.hasWP) {
45
- parent.hasWP = true;
46
- parent = parent.parent;
43
+ const tag = rule.wp ? 'hasWP' : 'hasRedact';
44
+ const ruleset = rule.wp ? 'wpRules' : 'redactRules';
45
+ // sanity check: do not allow rules of the same type on related paths,
46
+ // e.g. redact both 'user' and 'user.eids'; we don't need and this logic
47
+ // does not handle it
48
+ if (node[tag] && !node[ruleset]?.length) {
49
+ throw invalid();
50
+ }
51
+ node[ruleset].push(rule);
52
+ let parent = node;
53
+ while (parent) {
54
+ parent[tag] = true;
55
+ if (parent !== node && parent[ruleset]?.length) {
56
+ throw invalid();
47
57
  }
58
+ parent = parent.parent;
48
59
  }
49
60
  });
50
61
  });
@@ -128,25 +139,31 @@ export function objectGuard(rules) {
128
139
  return true;
129
140
  }
130
141
 
131
- function mkGuard(obj, tree, final, applies) {
132
- return new Proxy(obj, {
142
+ function mkGuard(obj, tree, final, applies, cache = new WeakMap()) {
143
+ // If this object is already proxied, return the cached proxy
144
+ if (cache.has(obj)) {
145
+ return cache.get(obj);
146
+ }
147
+
148
+ const proxy = new Proxy(obj, {
133
149
  get(target, prop, receiver) {
134
150
  const val = Reflect.get(target, prop, receiver);
135
151
  if (final && val != null && typeof val === 'object') {
136
152
  // a parent property has write protect rules, keep guarding
137
- return mkGuard(val, tree, final, applies)
153
+ return mkGuard(val, tree, final, applies, cache)
138
154
  } else if (tree.children?.hasOwnProperty(prop)) {
139
155
  const {children, hasWP} = tree.children[prop];
140
- if ((children || hasWP) && val != null && typeof val === 'object') {
141
- // some nested properties have rules, return a guard for the branch
142
- return mkGuard(val, tree.children?.[prop] || tree, final || children == null, applies);
143
- } else if (isData(val)) {
156
+ if (isData(val)) {
144
157
  // if this property has redact rules, apply them
145
158
  const rule = getRedactRule(tree.children[prop]);
146
159
  if (rule && rule.check(applies)) {
147
160
  return rule.get(val);
148
161
  }
149
162
  }
163
+ if ((children || hasWP) && val != null && typeof val === 'object') {
164
+ // some nested properties have rules, return a guard for the branch
165
+ return mkGuard(val, tree.children?.[prop] || tree, final || children == null, applies, cache);
166
+ }
150
167
  }
151
168
  return val;
152
169
  },
@@ -183,6 +200,10 @@ export function objectGuard(rules) {
183
200
  return Reflect.deleteProperty(target, prop);
184
201
  }
185
202
  });
203
+
204
+ // Cache the proxy before returning
205
+ cache.set(obj, proxy);
206
+ return proxy;
186
207
  }
187
208
 
188
209
  return function guard(obj, ...args) {
@@ -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
+ };