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