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.
- package/dist/33acrossAnalyticsAdapter.js +1 -1
- package/dist/33acrossBidAdapter.js +1 -1
- package/dist/33acrossIdSystem.js +1 -1
- package/dist/BTBidAdapter.js +1 -1
- package/dist/adagioAnalyticsAdapter.js +1 -1
- package/dist/adagioBidAdapter.js +1 -1
- package/dist/adagioUtils.js +1 -1
- package/dist/addefendBidAdapter.js +1 -1
- package/dist/adgenerationBidAdapter.js +1 -1
- package/dist/adlooxRtdProvider.js +1 -1
- package/dist/adqueryBidAdapter.js +1 -1
- package/dist/adrelevantisBidAdapter.js +1 -1
- package/dist/adstirBidAdapter.js +1 -1
- package/dist/adtrgtmeBidAdapter.js +1 -1
- package/dist/adxcgAnalyticsAdapter.js +1 -1
- package/dist/adxcgBidAdapter.js +1 -1
- package/dist/adyoulikeBidAdapter.js +1 -1
- package/dist/agmaAnalyticsAdapter.js +1 -1
- package/dist/ajaBidAdapter.js +1 -1
- package/dist/amxBidAdapter.js +1 -1
- package/dist/amxIdSystem.js +1 -1
- package/dist/aniviewBidAdapter.js +1 -1
- package/dist/appierAnalyticsAdapter.js +1 -1
- package/dist/appnexusBidAdapter.js +1 -1
- package/dist/asoBidAdapter.js +1 -1
- package/dist/axonixBidAdapter.js +1 -1
- package/dist/beopBidAdapter.js +1 -1
- package/dist/bidderTimeoutUtils.js +1 -0
- package/dist/bidglassBidAdapter.js +1 -1
- package/dist/big-richmediaBidAdapter.js +1 -1
- package/dist/bitmediaBidAdapter.js +1 -1
- package/dist/bridBidAdapter.js +1 -1
- package/dist/bridgeuppBidAdapter.js +1 -1
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- package/dist/carodaBidAdapter.js +1 -1
- package/dist/chtnwBidAdapter.js +1 -1
- package/dist/chunk-core.js +1 -1
- package/dist/concertBidAdapter.js +1 -1
- package/dist/connectadBidAdapter.js +1 -1
- package/dist/consumableBidAdapter.js +1 -1
- package/dist/contxtfulBidAdapter.js +1 -1
- package/dist/conversantAnalyticsAdapter.js +1 -1
- package/dist/conversantBidAdapter.js +1 -1
- package/dist/craftBidAdapter.js +1 -1
- package/dist/criteoBidAdapter.js +1 -1
- package/dist/cwireBidAdapter.js +1 -1
- package/dist/dailymotionBidAdapter.js +1 -1
- package/dist/dependencies.json +10 -1
- package/dist/dspxBidAdapter.js +1 -1
- package/dist/dxkultureBidAdapter.js +1 -1
- package/dist/eplanningBidAdapter.js +1 -1
- package/dist/equativBidAdapter.js +1 -1
- package/dist/eskimiBidAdapter.js +1 -1
- package/dist/euidIdSystem.js +1 -1
- package/dist/exadsBidAdapter.js +1 -1
- package/dist/excoBidAdapter.js +1 -1
- package/dist/feedadBidAdapter.js +1 -1
- package/dist/finativeBidAdapter.js +1 -1
- package/dist/freewheel-sspBidAdapter.js +1 -1
- package/dist/fwsspBidAdapter.js +1 -1
- package/dist/gmosspBidAdapter.js +1 -1
- package/dist/greenbidsAnalyticsAdapter.js +1 -1
- package/dist/greenbidsBidAdapter.js +1 -1
- package/dist/greenbidsRtdProvider.js +1 -1
- package/dist/gridBidAdapter.js +1 -1
- package/dist/gumgumBidAdapter.js +1 -1
- package/dist/h12mediaBidAdapter.js +1 -1
- package/dist/hypelabBidAdapter.js +1 -1
- package/dist/id5AnalyticsAdapter.js +1 -1
- package/dist/id5IdSystem.js +1 -1
- package/dist/imdsBidAdapter.js +1 -1
- package/dist/improvedigitalBidAdapter.js +1 -1
- package/dist/inmobiBidAdapter.js +1 -1
- package/dist/insticatorBidAdapter.js +1 -1
- package/dist/intentIqAnalyticsAdapter.js +1 -1
- package/dist/ixBidAdapter.js +1 -1
- package/dist/jixieBidAdapter.js +1 -1
- package/dist/justpremiumBidAdapter.js +1 -1
- package/dist/kargoBidAdapter.js +1 -1
- package/dist/kimberliteBidAdapter.js +1 -1
- package/dist/konduitAnalyticsAdapter.js +1 -1
- package/dist/kueezBidAdapter.js +1 -1
- package/dist/lassoBidAdapter.js +1 -1
- package/dist/lifestreetBidAdapter.js +1 -1
- package/dist/liveIntentId.js +1 -1
- package/dist/logicadBidAdapter.js +1 -1
- package/dist/loglyliftBidAdapter.js +1 -1
- package/dist/luceadBidAdapter.js +1 -1
- package/dist/mabidderBidAdapter.js +1 -1
- package/dist/madsenseBidAdapter.js +1 -1
- package/dist/magniteAnalyticsAdapter.js +1 -1
- package/dist/malltvAnalyticsAdapter.js +1 -1
- package/dist/marsmediaBidAdapter.js +1 -1
- package/dist/mediafuseBidAdapter.js +1 -1
- package/dist/medianetBidAdapter.js +1 -1
- package/dist/medianetUtils.js +1 -1
- package/dist/mediasquareBidAdapter.js +1 -1
- package/dist/mgidBidAdapter.js +1 -1
- package/dist/missenaBidAdapter.js +1 -1
- package/dist/mobilefuseBidAdapter.js +1 -1
- package/dist/nextMillenniumBidAdapter.js +1 -1
- package/dist/nexx360Utils.js +1 -1
- package/dist/nobidAnalyticsAdapter.js +1 -1
- package/dist/nobidBidAdapter.js +1 -1
- package/dist/nodalsAiRtdProvider.js +1 -1
- package/dist/not-for-prod/prebid.js +175 -172
- package/dist/objectGuard.js +1 -1
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/openxBidAdapter.js +1 -1
- package/dist/optableRtdProvider.js +1 -1
- package/dist/optidigitalBidAdapter.js +1 -1
- package/dist/orbidderBidAdapter.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/pixfutureBidAdapter.js +1 -1
- package/dist/publinkIdSystem.js +1 -1
- package/dist/pubmaticAnalyticsAdapter.js +1 -1
- package/dist/pubmaticBidAdapter.js +1 -1
- package/dist/pubmaticRtdProvider.js +1 -1
- package/dist/pubmaticUtils.js +1 -0
- package/dist/pubwiseAnalyticsAdapter.js +1 -1
- package/dist/pubxaiAnalyticsAdapter.js +1 -1
- package/dist/pxyzBidAdapter.js +1 -1
- package/dist/quantcastBidAdapter.js +1 -1
- package/dist/readpeakBidAdapter.js +1 -1
- package/dist/relaidoBidAdapter.js +1 -1
- package/dist/retailspotBidAdapter.js +1 -1
- package/dist/rhythmoneBidAdapter.js +1 -1
- package/dist/riseUtils.js +1 -1
- package/dist/rtdModule.js +1 -1
- package/dist/rubiconBidAdapter.js +1 -1
- package/dist/seedingAllianceBidAdapter.js +1 -1
- package/dist/seedtagBidAdapter.js +1 -1
- package/dist/sevioBidAdapter.js +1 -0
- package/dist/sharethroughAnalyticsAdapter.js +1 -1
- package/dist/sharethroughBidAdapter.js +1 -1
- package/dist/showheroes-bsBidAdapter.js +1 -1
- package/dist/smaatoBidAdapter.js +1 -1
- package/dist/smartadserverBidAdapter.js +1 -1
- package/dist/smartxBidAdapter.js +1 -1
- package/dist/smilewantedBidAdapter.js +1 -1
- package/dist/snigelBidAdapter.js +1 -1
- package/dist/sonobiBidAdapter.js +1 -1
- package/dist/sovrnBidAdapter.js +1 -1
- package/dist/sparteoBidAdapter.js +1 -1
- package/dist/sspBCBidAdapter.js +1 -1
- package/dist/stvBidAdapter.js +1 -1
- package/dist/sublimeBidAdapter.js +1 -1
- package/dist/taboolaBidAdapter.js +1 -1
- package/dist/tappxBidAdapter.js +1 -1
- package/dist/targetVideoBidAdapter.js +1 -1
- package/dist/teadsBidAdapter.js +1 -1
- package/dist/terceptAnalyticsAdapter.js +1 -1
- package/dist/themoneytizerBidAdapter.js +1 -1
- package/dist/timeoutRtdProvider.js +1 -1
- package/dist/trionBidAdapter.js +1 -1
- package/dist/tripleliftBidAdapter.js +1 -1
- package/dist/ttdBidAdapter.js +1 -1
- package/dist/ucfunnelAnalyticsAdapter.js +1 -1
- package/dist/uid2IdSystem.js +1 -1
- package/dist/underdogmediaBidAdapter.js +1 -1
- package/dist/undertoneBidAdapter.js +1 -1
- package/dist/unrulyBidAdapter.js +1 -1
- package/dist/vidazooUtils.js +1 -1
- package/dist/videobyteBidAdapter.js +1 -1
- package/dist/visxBidAdapter.js +1 -1
- package/dist/vuukleBidAdapter.js +1 -1
- package/dist/widespaceBidAdapter.js +1 -1
- package/dist/winrBidAdapter.js +1 -1
- package/dist/yahooAdsBidAdapter.js +1 -1
- package/dist/yandexBidAdapter.js +1 -1
- package/dist/yieldmoBidAdapter.js +1 -1
- package/dist/yieldoneAnalyticsAdapter.js +1 -1
- package/integrationExamples/gpt/pubmaticRtdProvider_Example.html +161 -0
- package/libraries/bidderTimeoutUtils/bidderTimeoutUtils.js +119 -0
- package/libraries/objectGuard/objectGuard.js +36 -15
- package/libraries/pubmaticUtils/plugins/dynamicTimeout.js +209 -0
- package/libraries/pubmaticUtils/plugins/floorProvider.js +168 -0
- package/libraries/pubmaticUtils/plugins/pluginManager.js +106 -0
- package/libraries/pubmaticUtils/plugins/unifiedPricingRule.js +375 -0
- package/libraries/pubmaticUtils/pubmaticUtils.js +76 -0
- package/modules/fwsspBidAdapter.js +134 -69
- package/modules/fwsspBidAdapter.md +121 -26
- package/modules/optableRtdProvider.js +33 -12
- package/modules/pubmaticAnalyticsAdapter.js +5 -1
- package/modules/pubmaticRtdProvider.js +105 -565
- package/modules/rtdModule/index.js +23 -2
- package/modules/sevioBidAdapter.js +413 -0
- package/modules/sevioBidAdapter.md +29 -0
- package/modules/sparteoBidAdapter.js +122 -10
- package/modules/timeoutRtdProvider.js +2 -105
- package/package.json +1 -1
- package/test/spec/activities/objectGuard_spec.js +49 -16
- package/test/spec/libraries/bidderTimeoutUtils/bidderTimeoutUtils_spec.js +213 -0
- package/test/spec/libraries/pubmaticUtils/plugins/dynamicTimeout_spec.js +746 -0
- package/test/spec/libraries/pubmaticUtils/plugins/floorProvider_spec.js +184 -0
- package/test/spec/libraries/pubmaticUtils/plugins/pluginManager_spec.js +489 -0
- package/test/spec/libraries/pubmaticUtils/plugins/unifiedPricingRule_spec.js +359 -0
- package/test/spec/libraries/pubmaticUtils/pubmaticUtils_spec.js +236 -0
- package/test/spec/modules/fwsspBidAdapter_spec.js +513 -78
- package/test/spec/modules/optableRtdProvider_spec.js +55 -5
- package/test/spec/modules/pubmaticRtdProvider_spec.js +252 -1183
- package/test/spec/modules/realTimeDataModule_spec.js +58 -8
- package/test/spec/modules/sevioBidAdapter_spec.js +513 -0
- package/test/spec/modules/sparteoBidAdapter_spec.js +528 -43
- 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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
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 ((
|
|
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
|
+
};
|