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
|
@@ -1,488 +1,103 @@
|
|
|
1
1
|
import { submodule } from '../src/hook.js';
|
|
2
|
-
import { logError,
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
2
|
+
import { logError, isStr, mergeDeep, isPlainObject, isEmpty } from '../src/utils.js';
|
|
3
|
+
|
|
4
|
+
import { PluginManager } from '../libraries/pubmaticUtils/plugins/pluginManager.js';
|
|
5
|
+
import { FloorProvider } from '../libraries/pubmaticUtils/plugins/floorProvider.js';
|
|
6
|
+
import { UnifiedPricingRule } from '../libraries/pubmaticUtils/plugins/unifiedPricingRule.js';
|
|
7
|
+
import { DynamicTimeout } from '../libraries/pubmaticUtils/plugins/dynamicTimeout.js';
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* @typedef {import('
|
|
10
|
+
* @typedef {import('./rtdModule/index.js').RtdSubmodule} RtdSubmodule
|
|
11
11
|
*/
|
|
12
|
-
|
|
13
12
|
/**
|
|
14
13
|
* This RTD module has a dependency on the priceFloors module.
|
|
15
14
|
* We utilize the continueAuction function from the priceFloors module to incorporate price floors data into the current auction.
|
|
16
15
|
*/
|
|
17
|
-
import { continueAuction } from './priceFloors.js'; // eslint-disable-line prebid/validate-imports
|
|
18
16
|
|
|
19
17
|
export const CONSTANTS = Object.freeze({
|
|
20
18
|
SUBMODULE_NAME: 'pubmatic',
|
|
21
19
|
REAL_TIME_MODULE: 'realTimeData',
|
|
22
20
|
LOG_PRE_FIX: 'PubMatic-Rtd-Provider: ',
|
|
23
|
-
UTM: 'utm_',
|
|
24
|
-
UTM_VALUES: {
|
|
25
|
-
TRUE: '1',
|
|
26
|
-
FALSE: '0'
|
|
27
|
-
},
|
|
28
|
-
TIME_OF_DAY_VALUES: {
|
|
29
|
-
MORNING: 'morning',
|
|
30
|
-
AFTERNOON: 'afternoon',
|
|
31
|
-
EVENING: 'evening',
|
|
32
|
-
NIGHT: 'night',
|
|
33
|
-
},
|
|
34
21
|
ENDPOINTS: {
|
|
35
22
|
BASEURL: 'https://ads.pubmatic.com/AdServer/js/pwt',
|
|
36
|
-
FLOORS: 'floors.json',
|
|
37
23
|
CONFIGS: 'config.json'
|
|
38
|
-
},
|
|
39
|
-
BID_STATUS: {
|
|
40
|
-
NOBID: 0,
|
|
41
|
-
WON: 1,
|
|
42
|
-
FLOORED: 2
|
|
43
|
-
},
|
|
44
|
-
MULTIPLIERS: {
|
|
45
|
-
WIN: 1.0,
|
|
46
|
-
FLOORED: 0.8,
|
|
47
|
-
NOBID: 1.2
|
|
48
|
-
},
|
|
49
|
-
TARGETING_KEYS: {
|
|
50
|
-
PM_YM_FLRS: 'pm_ym_flrs', // Whether RTD floor was applied
|
|
51
|
-
PM_YM_FLRV: 'pm_ym_flrv', // Final floor value (after applying multiplier)
|
|
52
|
-
PM_YM_BID_S: 'pm_ym_bid_s' // Bid status (0: No bid, 1: Won, 2: Floored)
|
|
53
24
|
}
|
|
54
25
|
});
|
|
55
26
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
{ regex: /(opera|opr)(?:.+version\/|[\/ ]+)([\w\.]+)/i, id: 3 }, // Opera
|
|
60
|
-
{ regex: /(?:ms|\()(ie) ([\w\.]+)|(?:trident\/[\w\.]+)/i, id: 4 }, // Internet Explorer
|
|
61
|
-
{ regex: /fxios\/([-\w\.]+)/i, id: 5 }, // Firefox for iOS
|
|
62
|
-
{ regex: /((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i, id: 6 }, // Facebook In-App Browser
|
|
63
|
-
{ regex: / wv\).+(chrome)\/([\w\.]+)/i, id: 7 }, // Chrome WebView
|
|
64
|
-
{ regex: /droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i, id: 8 }, // Android Browser
|
|
65
|
-
{ regex: /(chrome|crios)(?:\/v?([\w\.]+))?\b/i, id: 9 }, // Chrome
|
|
66
|
-
{ regex: /version\/([\w\.\,]+) .*mobile\/\w+ (safari)/i, id: 10 }, // Safari Mobile
|
|
67
|
-
{ regex: /version\/([\w(\.|\,)]+) .*(mobile ?safari|safari)/i, id: 11 }, // Safari
|
|
68
|
-
{ regex: /(firefox)\/([\w\.]+)/i, id: 12 } // Firefox
|
|
69
|
-
];
|
|
70
|
-
|
|
71
|
-
export const defaultValueTemplate = {
|
|
72
|
-
currency: 'USD',
|
|
73
|
-
skipRate: 0,
|
|
74
|
-
schema: {
|
|
75
|
-
fields: ['mediaType', 'size']
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
let initTime;
|
|
80
|
-
let _fetchFloorRulesPromise = null; let _fetchConfigPromise = null;
|
|
81
|
-
export let configMerged;
|
|
82
|
-
// configMerged is a reference to the function that can resolve configMergedPromise whenever we want
|
|
83
|
-
let configMergedPromise = new Promise((resolve) => { configMerged = resolve; });
|
|
84
|
-
export let _country;
|
|
85
|
-
// Store multipliers from floors.json, will use default values from CONSTANTS if not available
|
|
86
|
-
export let _multipliers = null;
|
|
87
|
-
|
|
88
|
-
// Use a private variable for profile configs
|
|
89
|
-
let _profileConfigs;
|
|
90
|
-
// Export getter and setter functions for _profileConfigs
|
|
91
|
-
export const getProfileConfigs = () => _profileConfigs;
|
|
92
|
-
export const setProfileConfigs = (configs) => { _profileConfigs = configs; };
|
|
93
|
-
|
|
94
|
-
// Waits for a given promise to resolve within a timeout
|
|
95
|
-
export function withTimeout(promise, ms) {
|
|
96
|
-
let timeout;
|
|
97
|
-
const timeoutPromise = new Promise((resolve) => {
|
|
98
|
-
timeout = setTimeout(() => resolve(undefined), ms);
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
return Promise.race([promise.finally(() => clearTimeout(timeout)), timeoutPromise]);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Utility Functions
|
|
105
|
-
export const getCurrentTimeOfDay = () => {
|
|
106
|
-
const currentHour = new Date().getHours();
|
|
107
|
-
|
|
108
|
-
return currentHour < 5 ? CONSTANTS.TIME_OF_DAY_VALUES.NIGHT
|
|
109
|
-
: currentHour < 12 ? CONSTANTS.TIME_OF_DAY_VALUES.MORNING
|
|
110
|
-
: currentHour < 17 ? CONSTANTS.TIME_OF_DAY_VALUES.AFTERNOON
|
|
111
|
-
: currentHour < 19 ? CONSTANTS.TIME_OF_DAY_VALUES.EVENING
|
|
112
|
-
: CONSTANTS.TIME_OF_DAY_VALUES.NIGHT;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export const getBrowserType = () => {
|
|
116
|
-
const brandName = getLowEntropySUA()?.browsers
|
|
117
|
-
?.map(b => b.brand.toLowerCase())
|
|
118
|
-
.join(' ') || '';
|
|
119
|
-
const browserMatch = brandName ? BROWSER_REGEX_MAP.find(({ regex }) => regex.test(brandName)) : -1;
|
|
120
|
-
|
|
121
|
-
if (browserMatch?.id) return browserMatch.id.toString();
|
|
122
|
-
|
|
123
|
-
const userAgent = navigator?.userAgent;
|
|
124
|
-
let browserIndex = userAgent == null ? -1 : 0;
|
|
125
|
-
|
|
126
|
-
if (userAgent) {
|
|
127
|
-
browserIndex = BROWSER_REGEX_MAP.find(({ regex }) => regex.test(userAgent))?.id || 0;
|
|
128
|
-
}
|
|
129
|
-
return browserIndex.toString();
|
|
130
|
-
}
|
|
27
|
+
let _ymConfigPromise;
|
|
28
|
+
export const getYmConfigPromise = () => _ymConfigPromise;
|
|
29
|
+
export const setYmConfigPromise = (promise) => { _ymConfigPromise = promise; };
|
|
131
30
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
}
|
|
31
|
+
export function ConfigJsonManager() {
|
|
32
|
+
let _ymConfig = {};
|
|
33
|
+
const getYMConfig = () => _ymConfig;
|
|
34
|
+
const setYMConfig = (config) => { _ymConfig = config; }
|
|
35
|
+
let country;
|
|
136
36
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Fetch configuration from the server
|
|
39
|
+
* @param {string} publisherId - Publisher ID
|
|
40
|
+
* @param {string} profileId - Profile ID
|
|
41
|
+
* @returns {Promise<Object>} - Promise resolving to the config object
|
|
42
|
+
*/
|
|
43
|
+
async function fetchConfig(publisherId, profileId) {
|
|
44
|
+
try {
|
|
45
|
+
const url = `${CONSTANTS.ENDPOINTS.BASEURL}/${publisherId}/${profileId}/${CONSTANTS.ENDPOINTS.CONFIGS}`;
|
|
46
|
+
const response = await fetch(url);
|
|
140
47
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
logError(`${CONSTANTS.LOG_PRE_FIX} Error while fetching config: Not ok`);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
145
52
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
.filter(Array.isArray)
|
|
150
|
-
.flatMap(bidderBids => bidderBids.filter(bid => bid.adUnitCode === code));
|
|
151
|
-
}
|
|
53
|
+
// Extract country code if available
|
|
54
|
+
const cc = response.headers?.get('country_code');
|
|
55
|
+
country = cc ? cc.split(',')?.map(code => code.trim())[0] : "IN";
|
|
152
56
|
|
|
153
|
-
|
|
154
|
-
|
|
57
|
+
// Parse the JSON response
|
|
58
|
+
const ymConfigs = await response.json();
|
|
155
59
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
(bid.floorData?.floorValue && bid.cpm < bid.floorData.floorValue);
|
|
161
|
-
});
|
|
162
|
-
}
|
|
60
|
+
if (!isPlainObject(ymConfigs) || isEmpty(ymConfigs)) {
|
|
61
|
+
logError(`${CONSTANTS.LOG_PRE_FIX} profileConfigs is not an object or is empty`);
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
163
64
|
|
|
164
|
-
//
|
|
165
|
-
|
|
166
|
-
try {
|
|
167
|
-
const pbjs = getGlobal();
|
|
168
|
-
if (!pbjs?.getHighestCpmBids) return null;
|
|
65
|
+
// Store the configuration
|
|
66
|
+
setYMConfig(ymConfigs);
|
|
169
67
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
68
|
+
return true;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
logError(`${CONSTANTS.LOG_PRE_FIX} Error while fetching config: ${error}`);
|
|
173
71
|
return null;
|
|
174
72
|
}
|
|
175
|
-
|
|
176
|
-
const highestCpmBid = highestCpmBids[0];
|
|
177
|
-
logInfo(CONSTANTS.LOG_PRE_FIX, `Found highest CPM bid using pbjs.getHighestCpmBids() for ad unit: ${adUnitCode}, CPM: ${highestCpmBid.cpm}`);
|
|
178
|
-
return highestCpmBid;
|
|
179
|
-
} catch (error) {
|
|
180
|
-
logError(CONSTANTS.LOG_PRE_FIX, `Error finding highest CPM bid: ${error}`);
|
|
181
|
-
return null;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
// Find floor value from bidder requests
|
|
186
|
-
function findFloorValueFromBidderRequests(auction, code) {
|
|
187
|
-
if (!auction?.bidderRequests?.length) return 0;
|
|
188
|
-
|
|
189
|
-
// Find all bids in bidder requests for this ad unit
|
|
190
|
-
const bidsFromRequests = auction.bidderRequests
|
|
191
|
-
.flatMap(request => request.bids || [])
|
|
192
|
-
.filter(bid => bid.adUnitCode === code);
|
|
193
|
-
|
|
194
|
-
if (!bidsFromRequests.length) {
|
|
195
|
-
logInfo(CONSTANTS.LOG_PRE_FIX, `No bids found for ad unit: ${code}`);
|
|
196
|
-
return 0;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const bidWithGetFloor = bidsFromRequests.find(bid => bid.getFloor);
|
|
200
|
-
if (!bidWithGetFloor) {
|
|
201
|
-
logInfo(CONSTANTS.LOG_PRE_FIX, `No bid with getFloor method found for ad unit: ${code}`);
|
|
202
|
-
return 0;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Helper function to extract sizes with their media types from a source object
|
|
206
|
-
const extractSizes = (source) => {
|
|
207
|
-
if (!source) return null;
|
|
208
|
-
|
|
209
|
-
const result = [];
|
|
210
|
-
|
|
211
|
-
// Extract banner sizes
|
|
212
|
-
if (source.mediaTypes?.banner?.sizes) {
|
|
213
|
-
source.mediaTypes.banner.sizes.forEach(size => {
|
|
214
|
-
result.push({
|
|
215
|
-
size,
|
|
216
|
-
mediaType: 'banner'
|
|
217
|
-
});
|
|
218
|
-
});
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// Extract video sizes
|
|
222
|
-
if (source.mediaTypes?.video?.playerSize) {
|
|
223
|
-
const playerSize = source.mediaTypes.video.playerSize;
|
|
224
|
-
// Handle both formats: [[w, h]] and [w, h]
|
|
225
|
-
const videoSizes = Array.isArray(playerSize[0]) ? playerSize : [playerSize];
|
|
226
|
-
|
|
227
|
-
videoSizes.forEach(size => {
|
|
228
|
-
result.push({
|
|
229
|
-
size,
|
|
230
|
-
mediaType: 'video'
|
|
231
|
-
});
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// Use general sizes as fallback if no specific media types found
|
|
236
|
-
if (result.length === 0 && source.sizes) {
|
|
237
|
-
source.sizes.forEach(size => {
|
|
238
|
-
result.push({
|
|
239
|
-
size,
|
|
240
|
-
mediaType: 'banner' // Default to banner for general sizes
|
|
241
|
-
});
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
return result.length > 0 ? result : null;
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
// Try to get sizes from different sources in order of preference
|
|
249
|
-
const adUnit = auction.adUnits?.find(unit => unit.code === code);
|
|
250
|
-
let sizes = extractSizes(adUnit) || extractSizes(bidWithGetFloor);
|
|
251
|
-
|
|
252
|
-
// Handle fallback to wildcard size if no sizes found
|
|
253
|
-
if (!sizes) {
|
|
254
|
-
sizes = [{ size: ['*', '*'], mediaType: 'banner' }];
|
|
255
|
-
logInfo(CONSTANTS.LOG_PRE_FIX, `No sizes found, using wildcard size for ad unit: ${code}`);
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Try to get floor values for each size
|
|
259
|
-
let minFloor = -1;
|
|
260
|
-
|
|
261
|
-
for (const sizeObj of sizes) {
|
|
262
|
-
// Extract size and mediaType from the object
|
|
263
|
-
const { size, mediaType } = sizeObj;
|
|
264
|
-
|
|
265
|
-
// Call getFloor with the appropriate media type
|
|
266
|
-
const floorInfo = bidWithGetFloor.getFloor({
|
|
267
|
-
currency: 'USD', // Default currency
|
|
268
|
-
mediaType: mediaType, // Use the media type we extracted
|
|
269
|
-
size: size
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
if (floorInfo?.floor && !isNaN(parseFloat(floorInfo.floor))) {
|
|
273
|
-
const floorValue = parseFloat(floorInfo.floor);
|
|
274
|
-
logInfo(CONSTANTS.LOG_PRE_FIX, `Floor value for ${mediaType} size ${size}: ${floorValue}`);
|
|
275
|
-
|
|
276
|
-
// Update minimum floor value
|
|
277
|
-
minFloor = minFloor === -1 ? floorValue : Math.min(minFloor, floorValue);
|
|
278
|
-
}
|
|
279
73
|
}
|
|
280
74
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// Select multiplier based on priority order: floors.json → config.json → default
|
|
291
|
-
function selectMultiplier(multiplierKey, profileConfigs) {
|
|
292
|
-
// Define sources in priority order
|
|
293
|
-
const multiplierSources = [
|
|
294
|
-
{
|
|
295
|
-
name: 'config.json',
|
|
296
|
-
getValue: () => {
|
|
297
|
-
const configPath = profileConfigs?.plugins?.dynamicFloors?.pmTargetingKeys?.multiplier;
|
|
298
|
-
const lowerKey = multiplierKey.toLowerCase();
|
|
299
|
-
return configPath && lowerKey in configPath ? configPath[lowerKey] : null;
|
|
300
|
-
}
|
|
301
|
-
},
|
|
302
|
-
{
|
|
303
|
-
name: 'floor.json',
|
|
304
|
-
getValue: () => _multipliers && multiplierKey in _multipliers ? _multipliers[multiplierKey] : null
|
|
305
|
-
},
|
|
306
|
-
{
|
|
307
|
-
name: 'default',
|
|
308
|
-
getValue: () => CONSTANTS.MULTIPLIERS[multiplierKey]
|
|
309
|
-
}
|
|
310
|
-
];
|
|
311
|
-
|
|
312
|
-
// Find the first source with a non-null value
|
|
313
|
-
for (const source of multiplierSources) {
|
|
314
|
-
const value = source.getValue();
|
|
315
|
-
if (value != null) {
|
|
316
|
-
return { value, source: source.name };
|
|
317
|
-
}
|
|
75
|
+
/**
|
|
76
|
+
* Get configuration by name
|
|
77
|
+
* @param {string} name - Plugin name
|
|
78
|
+
* @returns {Object} - Plugin configuration
|
|
79
|
+
*/
|
|
80
|
+
const getConfigByName = (name) => {
|
|
81
|
+
return getYMConfig()?.plugins?.[name];
|
|
318
82
|
}
|
|
319
83
|
|
|
320
|
-
// Fallback (shouldn't happen due to default source)
|
|
321
|
-
return { value: CONSTANTS.MULTIPLIERS[multiplierKey], source: 'default' };
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Identify winning bid scenario and return scenario data
|
|
325
|
-
function handleWinningBidScenario(winningBid, code) {
|
|
326
|
-
return {
|
|
327
|
-
scenario: 'winning',
|
|
328
|
-
bidStatus: CONSTANTS.BID_STATUS.WON,
|
|
329
|
-
baseValue: winningBid.cpm,
|
|
330
|
-
multiplierKey: 'WIN',
|
|
331
|
-
logMessage: `Bid won for ad unit: ${code}, CPM: ${winningBid.cpm}`
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// Identify rejected floor bid scenario and return scenario data
|
|
336
|
-
function handleRejectedFloorBidScenario(rejectedFloorBid, code) {
|
|
337
|
-
const baseValue = rejectedFloorBid.floorData?.floorValue || 0;
|
|
338
|
-
return {
|
|
339
|
-
scenario: 'rejected',
|
|
340
|
-
bidStatus: CONSTANTS.BID_STATUS.FLOORED,
|
|
341
|
-
baseValue,
|
|
342
|
-
multiplierKey: 'FLOORED',
|
|
343
|
-
logMessage: `Bid rejected due to price floor for ad unit: ${code}, Floor value: ${baseValue}, Bid CPM: ${rejectedFloorBid.cpm}`
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// Identify no bid scenario and return scenario data
|
|
348
|
-
function handleNoBidScenario(auction, code) {
|
|
349
|
-
const baseValue = findFloorValueFromBidderRequests(auction, code);
|
|
350
84
|
return {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
85
|
+
fetchConfig,
|
|
86
|
+
getYMConfig,
|
|
87
|
+
setYMConfig,
|
|
88
|
+
getConfigByName,
|
|
89
|
+
get country() { return country; }
|
|
356
90
|
};
|
|
357
91
|
}
|
|
358
92
|
|
|
359
|
-
//
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
: rejectedFloorBid ? handleRejectedFloorBidScenario(rejectedFloorBid, code)
|
|
363
|
-
: handleNoBidScenario(auction, code);
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
// Main function that determines bid status and calculates values
|
|
367
|
-
function determineBidStatusAndValues(winningBid, rejectedFloorBid, bidsForAdUnit, auction, code) {
|
|
368
|
-
const profileConfigs = getProfileConfigs();
|
|
369
|
-
|
|
370
|
-
// Determine the scenario based on bid conditions
|
|
371
|
-
const { bidStatus, baseValue, multiplierKey, logMessage } =
|
|
372
|
-
determineScenario(winningBid, rejectedFloorBid, bidsForAdUnit, auction, code);
|
|
373
|
-
|
|
374
|
-
// Select the appropriate multiplier
|
|
375
|
-
const { value: multiplier, source } = selectMultiplier(multiplierKey, profileConfigs);
|
|
376
|
-
logInfo(CONSTANTS.LOG_PRE_FIX, logMessage + ` (Using ${source} multiplier: ${multiplier})`);
|
|
377
|
-
|
|
378
|
-
return { bidStatus, baseValue, multiplier };
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
// Getter Functions
|
|
382
|
-
export const getOs = () => getOS().toString();
|
|
383
|
-
export const getDeviceType = () => fetchDeviceType().toString();
|
|
384
|
-
export const getCountry = () => _country;
|
|
385
|
-
export const getBidder = (request) => request?.bidder;
|
|
386
|
-
export const getUtm = () => {
|
|
387
|
-
const url = new URL(window.location?.href);
|
|
388
|
-
const urlParams = new URLSearchParams(url?.search);
|
|
389
|
-
return urlParams && urlParams.toString().includes(CONSTANTS.UTM) ? CONSTANTS.UTM_VALUES.TRUE : CONSTANTS.UTM_VALUES.FALSE;
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
export const getFloorsConfig = (floorsData, profileConfigs) => {
|
|
393
|
-
if (!isPlainObject(profileConfigs) || isEmpty(profileConfigs)) {
|
|
394
|
-
logError(`${CONSTANTS.LOG_PRE_FIX} profileConfigs is not an object or is empty`);
|
|
395
|
-
return undefined;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// Floor configs from adunit / setconfig
|
|
399
|
-
const defaultFloorConfig = conf.getConfig('floors') ?? {};
|
|
400
|
-
if (defaultFloorConfig?.endpoint) {
|
|
401
|
-
delete defaultFloorConfig.endpoint;
|
|
402
|
-
}
|
|
403
|
-
// Plugin data from profile
|
|
404
|
-
const dynamicFloors = profileConfigs?.plugins?.dynamicFloors;
|
|
405
|
-
|
|
406
|
-
// If plugin disabled or config not present, return undefined
|
|
407
|
-
if (!dynamicFloors?.enabled || !dynamicFloors?.config) {
|
|
408
|
-
return undefined;
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
let config = { ...dynamicFloors.config };
|
|
412
|
-
|
|
413
|
-
// default values provided by publisher on profile
|
|
414
|
-
const defaultValues = config.defaultValues ?? {};
|
|
415
|
-
// If floorsData is not present, use default values
|
|
416
|
-
const finalFloorsData = floorsData ?? { ...defaultValueTemplate, values: { ...defaultValues } };
|
|
417
|
-
|
|
418
|
-
delete config.defaultValues;
|
|
419
|
-
// If skiprate is provided in configs, overwrite the value in finalFloorsData
|
|
420
|
-
(config.skipRate !== undefined) && (finalFloorsData.skipRate = config.skipRate);
|
|
421
|
-
|
|
422
|
-
// merge default configs from page, configs
|
|
423
|
-
return {
|
|
424
|
-
floors: {
|
|
425
|
-
...defaultFloorConfig,
|
|
426
|
-
...config,
|
|
427
|
-
data: finalFloorsData,
|
|
428
|
-
additionalSchemaFields: {
|
|
429
|
-
deviceType: getDeviceType,
|
|
430
|
-
timeOfDay: getCurrentTimeOfDay,
|
|
431
|
-
browser: getBrowserType,
|
|
432
|
-
os: getOs,
|
|
433
|
-
utm: getUtm,
|
|
434
|
-
country: getCountry,
|
|
435
|
-
bidder: getBidder,
|
|
436
|
-
},
|
|
437
|
-
},
|
|
438
|
-
};
|
|
439
|
-
};
|
|
440
|
-
|
|
441
|
-
export const fetchData = async (publisherId, profileId, type) => {
|
|
442
|
-
try {
|
|
443
|
-
const endpoint = CONSTANTS.ENDPOINTS[type];
|
|
444
|
-
const baseURL = (type == 'FLOORS') ? `${CONSTANTS.ENDPOINTS.BASEURL}/floors` : CONSTANTS.ENDPOINTS.BASEURL;
|
|
445
|
-
const url = `${baseURL}/${publisherId}/${profileId}/${endpoint}`;
|
|
446
|
-
const response = await fetch(url);
|
|
447
|
-
|
|
448
|
-
if (!response.ok) {
|
|
449
|
-
logError(`${CONSTANTS.LOG_PRE_FIX} Error while fetching ${type}: Not ok`);
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
if (type === "FLOORS") {
|
|
454
|
-
const cc = response.headers?.get('country_code');
|
|
455
|
-
_country = cc ? cc.split(',')?.map(code => code.trim())[0] : undefined;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
const data = await response.json();
|
|
93
|
+
// Create core components
|
|
94
|
+
export const pluginManager = PluginManager();
|
|
95
|
+
export const configJsonManager = ConfigJsonManager();
|
|
459
96
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
'win': 'WIN',
|
|
465
|
-
'floored': 'FLOORED',
|
|
466
|
-
'nobid': 'NOBID'
|
|
467
|
-
};
|
|
468
|
-
|
|
469
|
-
// Initialize _multipliers and only add keys that exist in data.multiplier
|
|
470
|
-
_multipliers = Object.entries(multiplierKeys)
|
|
471
|
-
.reduce((acc, [srcKey, destKey]) => {
|
|
472
|
-
if (srcKey in data.multiplier) {
|
|
473
|
-
acc[destKey] = data.multiplier[srcKey];
|
|
474
|
-
}
|
|
475
|
-
return acc;
|
|
476
|
-
}, {});
|
|
477
|
-
|
|
478
|
-
logInfo(CONSTANTS.LOG_PRE_FIX, `Using multipliers from floors.json: ${JSON.stringify(_multipliers)}`);
|
|
479
|
-
}
|
|
480
|
-
|
|
481
|
-
return data;
|
|
482
|
-
} catch (error) {
|
|
483
|
-
logError(`${CONSTANTS.LOG_PRE_FIX} Error while fetching ${type}: ${error}`);
|
|
484
|
-
}
|
|
485
|
-
};
|
|
97
|
+
// Register plugins
|
|
98
|
+
pluginManager.register('dynamicFloors', FloorProvider);
|
|
99
|
+
pluginManager.register('unifiedPricingRule', UnifiedPricingRule);
|
|
100
|
+
pluginManager.register('dynamicTimeout', DynamicTimeout);
|
|
486
101
|
|
|
487
102
|
/**
|
|
488
103
|
* Initialize the Pubmatic RTD Module.
|
|
@@ -491,44 +106,28 @@ export const fetchData = async (publisherId, profileId, type) => {
|
|
|
491
106
|
* @returns {boolean}
|
|
492
107
|
*/
|
|
493
108
|
const init = (config, _userConsent) => {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
if (!isFn(continueAuction)) {
|
|
508
|
-
logError(`${CONSTANTS.LOG_PRE_FIX} continueAuction is not a function. Please ensure to add priceFloors module.`);
|
|
509
|
-
return false;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
_fetchFloorRulesPromise = fetchData(publisherId, profileId, "FLOORS");
|
|
513
|
-
_fetchConfigPromise = fetchData(publisherId, profileId, "CONFIGS");
|
|
514
|
-
|
|
515
|
-
_fetchConfigPromise.then(async (profileConfigs) => {
|
|
516
|
-
const auctionDelay = conf?.getConfig('realTimeData')?.auctionDelay || 300;
|
|
517
|
-
const maxWaitTime = 0.8 * auctionDelay;
|
|
518
|
-
|
|
519
|
-
const elapsedTime = Date.now() - initTime;
|
|
520
|
-
const remainingTime = Math.max(maxWaitTime - elapsedTime, 0);
|
|
521
|
-
const floorsData = await withTimeout(_fetchFloorRulesPromise, remainingTime);
|
|
522
|
-
|
|
523
|
-
// Store the profile configs globally
|
|
524
|
-
setProfileConfigs(profileConfigs);
|
|
109
|
+
const { publisherId, profileId } = config?.params || {};
|
|
110
|
+
|
|
111
|
+
if (!publisherId || !isStr(publisherId) || !profileId || !isStr(profileId)) {
|
|
112
|
+
logError(
|
|
113
|
+
`${CONSTANTS.LOG_PRE_FIX} ${!publisherId ? 'Missing publisher Id.'
|
|
114
|
+
: !isStr(publisherId) ? 'Publisher Id should be a string.'
|
|
115
|
+
: !profileId ? 'Missing profile Id.'
|
|
116
|
+
: 'Profile Id should be a string.'
|
|
117
|
+
}`
|
|
118
|
+
);
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
525
121
|
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
122
|
+
// Fetch configuration and initialize plugins
|
|
123
|
+
_ymConfigPromise = configJsonManager.fetchConfig(publisherId, profileId)
|
|
124
|
+
.then(success => {
|
|
125
|
+
if (!success) {
|
|
126
|
+
return Promise.reject(new Error('Failed to fetch configuration'));
|
|
127
|
+
}
|
|
128
|
+
return pluginManager.initialize(configJsonManager);
|
|
529
129
|
});
|
|
530
|
-
|
|
531
|
-
return true;
|
|
130
|
+
return true;
|
|
532
131
|
};
|
|
533
132
|
|
|
534
133
|
/**
|
|
@@ -536,34 +135,30 @@ const init = (config, _userConsent) => {
|
|
|
536
135
|
* @param {function} callback
|
|
537
136
|
*/
|
|
538
137
|
const getBidRequestData = (reqBidsConfigObj, callback) => {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
if (_country) {
|
|
549
|
-
const ortb2 = {
|
|
550
|
-
user: {
|
|
551
|
-
ext: {
|
|
552
|
-
ctr: _country,
|
|
553
|
-
}
|
|
554
|
-
}
|
|
138
|
+
_ymConfigPromise.then(() => {
|
|
139
|
+
pluginManager.executeHook('processBidRequest', reqBidsConfigObj);
|
|
140
|
+
// Apply country information if available
|
|
141
|
+
const country = configJsonManager.country;
|
|
142
|
+
if (country) {
|
|
143
|
+
const ortb2 = {
|
|
144
|
+
user: {
|
|
145
|
+
ext: {
|
|
146
|
+
ctr: country,
|
|
555
147
|
}
|
|
556
|
-
|
|
557
|
-
mergeDeep(reqBidsConfigObj.ortb2Fragments.bidder, {
|
|
558
|
-
[CONSTANTS.SUBMODULE_NAME]: ortb2
|
|
559
|
-
});
|
|
560
148
|
}
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
mergeDeep(reqBidsConfigObj.ortb2Fragments.bidder, {
|
|
152
|
+
[CONSTANTS.SUBMODULE_NAME]: ortb2
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
callback();
|
|
157
|
+
}).catch(error => {
|
|
158
|
+
logError(CONSTANTS.LOG_PRE_FIX, error);
|
|
159
|
+
callback();
|
|
160
|
+
});
|
|
161
|
+
};
|
|
567
162
|
|
|
568
163
|
/**
|
|
569
164
|
* Returns targeting data for ad units
|
|
@@ -574,62 +169,7 @@ const getBidRequestData = (reqBidsConfigObj, callback) => {
|
|
|
574
169
|
* @return {Object} - Targeting data for ad units
|
|
575
170
|
*/
|
|
576
171
|
export const getTargetingData = (adUnitCodes, config, userConsent, auction) => {
|
|
577
|
-
|
|
578
|
-
const profileConfigs = getProfileConfigs();
|
|
579
|
-
|
|
580
|
-
// Return empty object if profileConfigs is undefined or pmTargetingKeys.enabled is explicitly set to false
|
|
581
|
-
if (!profileConfigs || profileConfigs?.plugins?.dynamicFloors?.pmTargetingKeys?.enabled === false) {
|
|
582
|
-
logInfo(`${CONSTANTS.LOG_PRE_FIX} pmTargetingKeys is disabled or profileConfigs is undefined`);
|
|
583
|
-
return {};
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
// Helper to check if RTD floor is applied to a bid
|
|
587
|
-
const isRtdFloorApplied = bid => bid.floorData?.floorProvider === "PM" && !bid.floorData.skipped;
|
|
588
|
-
|
|
589
|
-
// Check if any bid has RTD floor applied
|
|
590
|
-
const hasRtdFloorAppliedBid =
|
|
591
|
-
auction?.adUnits?.some(adUnit => adUnit.bids?.some(isRtdFloorApplied)) ||
|
|
592
|
-
auction?.bidsReceived?.some(isRtdFloorApplied);
|
|
593
|
-
|
|
594
|
-
// Only log when RTD floor is applied
|
|
595
|
-
if (hasRtdFloorAppliedBid) {
|
|
596
|
-
logInfo(CONSTANTS.LOG_PRE_FIX, 'Setting targeting via getTargetingData:');
|
|
597
|
-
}
|
|
598
|
-
|
|
599
|
-
// Process each ad unit code
|
|
600
|
-
const targeting = {};
|
|
601
|
-
|
|
602
|
-
adUnitCodes.forEach(code => {
|
|
603
|
-
targeting[code] = {};
|
|
604
|
-
|
|
605
|
-
// For non-RTD floor applied cases, only set pm_ym_flrs to 0
|
|
606
|
-
if (!hasRtdFloorAppliedBid) {
|
|
607
|
-
targeting[code][CONSTANTS.TARGETING_KEYS.PM_YM_FLRS] = 0;
|
|
608
|
-
return;
|
|
609
|
-
}
|
|
610
|
-
|
|
611
|
-
// Find bids and determine status for RTD floor applied cases
|
|
612
|
-
const bidsForAdUnit = findBidsForAdUnit(auction, code);
|
|
613
|
-
const rejectedBidsForAdUnit = findRejectedBidsForAdUnit(auction, code);
|
|
614
|
-
const rejectedFloorBid = findRejectedFloorBid(rejectedBidsForAdUnit);
|
|
615
|
-
const winningBid = findWinningBid(code);
|
|
616
|
-
|
|
617
|
-
// Determine bid status and values
|
|
618
|
-
const { bidStatus, baseValue, multiplier } = determineBidStatusAndValues(
|
|
619
|
-
winningBid,
|
|
620
|
-
rejectedFloorBid,
|
|
621
|
-
bidsForAdUnit,
|
|
622
|
-
auction,
|
|
623
|
-
code
|
|
624
|
-
);
|
|
625
|
-
|
|
626
|
-
// Set all targeting keys
|
|
627
|
-
targeting[code][CONSTANTS.TARGETING_KEYS.PM_YM_FLRS] = 1;
|
|
628
|
-
targeting[code][CONSTANTS.TARGETING_KEYS.PM_YM_FLRV] = (baseValue * multiplier).toFixed(2);
|
|
629
|
-
targeting[code][CONSTANTS.TARGETING_KEYS.PM_YM_BID_S] = bidStatus;
|
|
630
|
-
});
|
|
631
|
-
|
|
632
|
-
return targeting;
|
|
172
|
+
return pluginManager.executeHook('getTargeting', adUnitCodes, config, userConsent, auction);
|
|
633
173
|
};
|
|
634
174
|
|
|
635
175
|
export const pubmaticSubmodule = {
|