prebid.js 9.52.0 → 9.53.2
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/.circleci/config.yml +27 -4
- package/creative/crossDomain.js +4 -2
- 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/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/chromeAiRtdProvider.js +1 -0
- 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 -2
- 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/fanAdapter.js +1 -1
- package/dist/feedadBidAdapter.js +1 -1
- package/dist/finativeBidAdapter.js +1 -1
- package/dist/freewheel-sspBidAdapter.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/jixieIdSystem.js +1 -0
- 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 -173
- 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/optidigitalBidAdapter.js +1 -1
- package/dist/orbidderBidAdapter.js +1 -1
- package/dist/ortb2.5Translator.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/ozoneBidAdapter.js +1 -1
- package/dist/pixfutureBidAdapter.js +1 -1
- package/dist/prebidServerBidAdapter.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/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/relevatehealthBidAdapter.js +1 -1
- package/dist/retailspotBidAdapter.js +1 -1
- package/dist/rhythmoneBidAdapter.js +1 -1
- package/dist/riseUtils.js +1 -1
- package/dist/rubiconBidAdapter.js +1 -1
- package/dist/seedingAllianceBidAdapter.js +1 -1
- package/dist/seedtagBidAdapter.js +1 -1
- 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/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/gulpfile.js +12 -6
- package/integrationExamples/chromeai/japanese.html +224 -0
- package/integrationExamples/gpt/x-domain/creative.html +1 -1
- package/karma.conf.maker.js +7 -7
- package/karmaRunner.js +3 -3
- package/libraries/liveIntentId/shared.js +16 -0
- package/modules/.submodules.json +1 -0
- package/modules/aniviewBidAdapter.js +32 -23
- package/modules/chromeAiRtdProvider.js +421 -0
- package/modules/chromeAiRtdProvider.md +230 -0
- package/modules/fanAdapter.js +318 -124
- package/modules/ixBidAdapter.js +5 -0
- package/modules/jixieIdSystem.js +186 -0
- package/modules/ozoneBidAdapter.js +214 -336
- package/modules/prebidServerBidAdapter/index.js +59 -35
- package/modules/pubmaticRtdProvider.js +418 -4
- package/modules/pubmaticRtdProvider.md +12 -2
- package/modules/relevatehealthBidAdapter.js +20 -130
- package/modules/relevatehealthBidAdapter.md +1 -2
- package/modules/sovrnBidAdapter.js +4 -4
- package/modules/teadsBidAdapter.js +5 -0
- package/modules/ttdBidAdapter.js +5 -4
- package/modules/userId/index.js +30 -31
- package/package.json +5 -4
- package/src/adapterManager.js +3 -0
- package/test/spec/libraries/cmUtils_spec.js +17 -12
- package/test/spec/modules/aniviewBidAdapter_spec.js +15 -2
- package/test/spec/modules/chromeAiRtdProvider_spec.js +393 -0
- package/test/spec/modules/dgkeywordRtdProvider_spec.js +5 -2
- package/test/spec/modules/euidIdSystem_spec.js +9 -3
- package/test/spec/modules/fanAdapter_spec.js +264 -268
- package/test/spec/modules/id5IdSystem_spec.js +57 -101
- package/test/spec/modules/identityLinkIdSystem_spec.js +1 -0
- package/test/spec/modules/idxIdSystem_spec.js +2 -75
- package/test/spec/modules/instreamTracking_spec.js +15 -18
- package/test/spec/modules/ixBidAdapter_spec.js +26 -0
- package/test/spec/modules/jixieIdSystem_spec.js +303 -0
- package/test/spec/modules/liveIntentExternalIdSystem_spec.js +5 -0
- package/test/spec/modules/liveIntentIdMinimalSystem_spec.js +5 -0
- package/test/spec/modules/liveIntentIdSystem_spec.js +38 -0
- package/test/spec/modules/lmpIdSystem_spec.js +2 -81
- package/test/spec/modules/ozoneBidAdapter_spec.js +511 -658
- package/test/spec/modules/prebidServerBidAdapter_spec.js +72 -2
- package/test/spec/modules/pubmaticBidAdapter_spec.js +411 -126
- package/test/spec/modules/pubmaticRtdProvider_spec.js +946 -2
- package/test/spec/modules/raynRtdProvider_spec.js +18 -22
- package/test/spec/modules/relevatehealthBidAdapter_spec.js +9 -39
- package/test/spec/modules/sharedIdSystem_spec.js +3 -3
- package/test/spec/modules/sovrnBidAdapter_spec.js +71 -3
- package/test/spec/modules/teadsBidAdapter_spec.js +9 -4
- package/test/spec/modules/ttdBidAdapter_spec.js +24 -2
- package/test/spec/modules/uid2IdSystem_helpers.js +5 -2
- package/test/spec/modules/userId_spec.js +142 -387
- package/test/spec/modules/yieldoneAnalyticsAdapter_spec.js +13 -12
- package/test/spec/modules/zeotapIdPlusIdSystem_spec.js +3 -69
- package/wdio.shared.conf.js +2 -2
- package/CLAUDE.md +0 -1
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import Adapter from '../../src/adapter.js';
|
|
2
2
|
import {
|
|
3
|
+
compressDataWithGZip,
|
|
4
|
+
debugTurnedOn,
|
|
3
5
|
deepClone,
|
|
4
6
|
flatten,
|
|
5
7
|
generateUUID,
|
|
8
|
+
getParameterByName,
|
|
6
9
|
insertUserSyncIframe,
|
|
10
|
+
isGzipCompressionSupported,
|
|
7
11
|
isNumber,
|
|
8
12
|
isPlainObject,
|
|
9
13
|
isStr,
|
|
@@ -14,7 +18,7 @@ import {
|
|
|
14
18
|
triggerPixel,
|
|
15
19
|
uniques,
|
|
16
20
|
} from '../../src/utils.js';
|
|
17
|
-
import {EVENTS, REJECTION_REASON, S2S} from '../../src/constants.js';
|
|
21
|
+
import {DEBUG_MODE, EVENTS, REJECTION_REASON, S2S} from '../../src/constants.js';
|
|
18
22
|
import adapterManager, {s2sActivityParams} from '../../src/adapterManager.js';
|
|
19
23
|
import {config} from '../../src/config.js';
|
|
20
24
|
import {addPaapiConfig, isValid} from '../../src/adapters/bidderFactory.js';
|
|
@@ -66,6 +70,7 @@ let _s2sConfigs;
|
|
|
66
70
|
* @property {number} [maxBids=1]
|
|
67
71
|
* @property {AdapterOptions} [adapterOptions] adds arguments to resulting OpenRTB payload to Prebid Server
|
|
68
72
|
* @property {Object} [syncUrlModifier]
|
|
73
|
+
* @property {boolean} [filterBidderlessCalls=false] filter out ad units without bidders or storedrequest before sending to PBS
|
|
69
74
|
*/
|
|
70
75
|
|
|
71
76
|
/**
|
|
@@ -97,7 +102,8 @@ export const s2sDefaultConfig = {
|
|
|
97
102
|
{event: 1, methods: [1, 2]}
|
|
98
103
|
],
|
|
99
104
|
},
|
|
100
|
-
maxTimeout: 1500
|
|
105
|
+
maxTimeout: 1500,
|
|
106
|
+
filterBidderlessCalls: false
|
|
101
107
|
};
|
|
102
108
|
|
|
103
109
|
config.setDefaults({
|
|
@@ -511,43 +517,61 @@ export const processPBSRequest = hook('async', function (s2sBidRequest, bidReque
|
|
|
511
517
|
events.emit(EVENTS.BEFORE_PBS_HTTP, requestData)
|
|
512
518
|
logInfo('BidRequest: ' + requestData);
|
|
513
519
|
if (request && requestData.requestJson && requestData.endpointUrl) {
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
paapi
|
|
520
|
+
const callAjax = (payload, endpointUrl) => {
|
|
521
|
+
const networkDone = s2sBidRequest.metrics.startTiming('net');
|
|
522
|
+
ajax(
|
|
523
|
+
endpointUrl,
|
|
524
|
+
{
|
|
525
|
+
success: function (response) {
|
|
526
|
+
networkDone();
|
|
527
|
+
let result;
|
|
528
|
+
try {
|
|
529
|
+
result = JSON.parse(response);
|
|
530
|
+
const {bids, paapi} = s2sBidRequest.metrics.measureTime('interpretResponse', () => interpretPBSResponse(result, request));
|
|
531
|
+
bids.forEach(onBid);
|
|
532
|
+
if (paapi) {
|
|
533
|
+
paapi.forEach(onFledge);
|
|
534
|
+
}
|
|
535
|
+
} catch (error) {
|
|
536
|
+
logError(error);
|
|
527
537
|
}
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
}
|
|
535
|
-
|
|
538
|
+
if (!result || (result.status && result.status.includes('Error'))) {
|
|
539
|
+
logError('error parsing response: ', result ? result.status : 'not valid JSON');
|
|
540
|
+
onResponse(false, requestedBidders);
|
|
541
|
+
} else {
|
|
542
|
+
onResponse(true, requestedBidders, result);
|
|
543
|
+
}
|
|
544
|
+
},
|
|
545
|
+
error: function () {
|
|
546
|
+
networkDone();
|
|
547
|
+
onError.apply(this, arguments);
|
|
536
548
|
}
|
|
537
549
|
},
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
550
|
+
payload,
|
|
551
|
+
{
|
|
552
|
+
contentType: 'text/plain',
|
|
553
|
+
withCredentials: true,
|
|
554
|
+
browsingTopics: isActivityAllowed(ACTIVITY_TRANSMIT_UFPD, s2sActivityParams(s2sBidRequest.s2sConfig)),
|
|
555
|
+
customHeaders: requestData.customHeaders
|
|
541
556
|
}
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
557
|
+
);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
const enableGZipCompression = s2sBidRequest.s2sConfig.endpointCompression && !requestData.customHeaders['Content-Encoding'];
|
|
561
|
+
const debugMode = getParameterByName(DEBUG_MODE).toUpperCase() === 'TRUE' || debugTurnedOn();
|
|
562
|
+
if (enableGZipCompression && debugMode) {
|
|
563
|
+
logWarn('Skipping GZIP compression for PBS as debug mode is enabled');
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
if (enableGZipCompression && !debugMode && isGzipCompressionSupported()) {
|
|
567
|
+
compressDataWithGZip(requestData.requestJson).then(compressedPayload => {
|
|
568
|
+
const url = new URL(requestData.endpointUrl);
|
|
569
|
+
url.searchParams.set('gzip', '1');
|
|
570
|
+
callAjax(compressedPayload, url.href);
|
|
571
|
+
});
|
|
572
|
+
} else {
|
|
573
|
+
callAjax(requestData.requestJson, requestData.endpointUrl);
|
|
574
|
+
}
|
|
551
575
|
} else {
|
|
552
576
|
logError('PBS request not made. Check endpoints.');
|
|
553
577
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { submodule } from '../src/hook.js';
|
|
2
|
-
import { logError, isStr, isPlainObject, isEmpty, isFn, mergeDeep } from '../src/utils.js';
|
|
2
|
+
import { logError, logInfo, isStr, isPlainObject, isEmpty, isFn, mergeDeep } from '../src/utils.js';
|
|
3
3
|
import { config as conf } from '../src/config.js';
|
|
4
4
|
import { getDeviceType as fetchDeviceType, getOS } from '../libraries/userAgentUtils/index.js';
|
|
5
5
|
import { getLowEntropySUA } from '../src/fpd/sua.js';
|
|
6
|
+
import { getGlobal } from '../src/prebidGlobal.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* @typedef {import('../modules/rtdModule/index.js').RtdSubmodule} RtdSubmodule
|
|
@@ -14,7 +15,7 @@ import { getLowEntropySUA } from '../src/fpd/sua.js';
|
|
|
14
15
|
*/
|
|
15
16
|
import { continueAuction } from './priceFloors.js'; // eslint-disable-line prebid/validate-imports
|
|
16
17
|
|
|
17
|
-
const CONSTANTS = Object.freeze({
|
|
18
|
+
export const CONSTANTS = Object.freeze({
|
|
18
19
|
SUBMODULE_NAME: 'pubmatic',
|
|
19
20
|
REAL_TIME_MODULE: 'realTimeData',
|
|
20
21
|
LOG_PRE_FIX: 'PubMatic-Rtd-Provider: ',
|
|
@@ -33,6 +34,21 @@ const CONSTANTS = Object.freeze({
|
|
|
33
34
|
BASEURL: 'https://ads.pubmatic.com/AdServer/js/pwt',
|
|
34
35
|
FLOORS: 'floors.json',
|
|
35
36
|
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)
|
|
36
52
|
}
|
|
37
53
|
});
|
|
38
54
|
|
|
@@ -65,6 +81,14 @@ export let configMerged;
|
|
|
65
81
|
// configMerged is a reference to the function that can resolve configMergedPromise whenever we want
|
|
66
82
|
let configMergedPromise = new Promise((resolve) => { configMerged = resolve; });
|
|
67
83
|
export let _country;
|
|
84
|
+
// Store multipliers from floors.json, will use default values from CONSTANTS if not available
|
|
85
|
+
export let _multipliers = null;
|
|
86
|
+
|
|
87
|
+
// Use a private variable for profile configs
|
|
88
|
+
let _profileConfigs;
|
|
89
|
+
// Export getter and setter functions for _profileConfigs
|
|
90
|
+
export const getProfileConfigs = () => _profileConfigs;
|
|
91
|
+
export const setProfileConfigs = (configs) => { _profileConfigs = configs; };
|
|
68
92
|
|
|
69
93
|
// Waits for a given promise to resolve within a timeout
|
|
70
94
|
export function withTimeout(promise, ms) {
|
|
@@ -104,6 +128,303 @@ export const getBrowserType = () => {
|
|
|
104
128
|
return browserIndex.toString();
|
|
105
129
|
}
|
|
106
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 [];
|
|
139
|
+
|
|
140
|
+
// If bidsRejected is an array
|
|
141
|
+
if (Array.isArray(auction.bidsRejected)) {
|
|
142
|
+
return auction.bidsRejected.filter(bid => bid.adUnitCode === code);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// If bidsRejected is an object mapping bidders to their rejected bids
|
|
146
|
+
if (typeof auction.bidsRejected === 'object') {
|
|
147
|
+
return Object.values(auction.bidsRejected)
|
|
148
|
+
.filter(Array.isArray)
|
|
149
|
+
.flatMap(bidderBids => bidderBids.filter(bid => bid.adUnitCode === code));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return [];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Find a rejected bid due to price floor
|
|
156
|
+
function findRejectedFloorBid(rejectedBids) {
|
|
157
|
+
return rejectedBids.find(bid => {
|
|
158
|
+
const errorMessage = bid.statusMessage || bid.status || '';
|
|
159
|
+
return errorMessage.includes('price floor') ||
|
|
160
|
+
(bid.floorData?.floorValue && bid.cpm < bid.floorData.floorValue);
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Find the winning or highest bid for an ad unit
|
|
165
|
+
function findWinningBid(adUnitCode) {
|
|
166
|
+
try {
|
|
167
|
+
const pbjs = getGlobal();
|
|
168
|
+
if (!pbjs?.getHighestCpmBids) return null;
|
|
169
|
+
|
|
170
|
+
const highestCpmBids = pbjs.getHighestCpmBids(adUnitCode);
|
|
171
|
+
if (!highestCpmBids?.length) {
|
|
172
|
+
logInfo(CONSTANTS.LOG_PRE_FIX, `No highest CPM bids found for ad unit: ${adUnitCode}`);
|
|
173
|
+
return null;
|
|
174
|
+
}
|
|
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 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
|
+
|
|
209
|
+
// Find floor value from bidder requests
|
|
210
|
+
function findFloorValueFromBidderRequests(auction, code) {
|
|
211
|
+
if (!auction?.bidderRequests?.length) return 0;
|
|
212
|
+
|
|
213
|
+
// Find all bids in bidder requests for this ad unit
|
|
214
|
+
const bidsFromRequests = auction.bidderRequests
|
|
215
|
+
.flatMap(request => request.bids || [])
|
|
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
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
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
|
+
return {
|
|
387
|
+
scenario: 'nobid',
|
|
388
|
+
bidStatus: CONSTANTS.BID_STATUS.NOBID,
|
|
389
|
+
baseValue,
|
|
390
|
+
multiplierKey: 'NOBID',
|
|
391
|
+
logMessage: `No bids for ad unit: ${code}, Floor value: ${baseValue}`
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
// Determine which scenario applies based on bid conditions
|
|
396
|
+
function determineScenario(winningBid, rejectedFloorBid, bidsForAdUnit, auction, code) {
|
|
397
|
+
if (winningBid) {
|
|
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
|
+
|
|
107
428
|
// Getter Functions
|
|
108
429
|
export const getOs = () => getOS().toString();
|
|
109
430
|
export const getDeviceType = () => fetchDeviceType().toString();
|
|
@@ -181,7 +502,30 @@ export const fetchData = async (publisherId, profileId, type) => {
|
|
|
181
502
|
_country = cc ? cc.split(',')?.map(code => code.trim())[0] : undefined;
|
|
182
503
|
}
|
|
183
504
|
|
|
184
|
-
|
|
505
|
+
const data = await response.json();
|
|
506
|
+
|
|
507
|
+
// Extract multipliers from floors.json if available
|
|
508
|
+
if (type === "FLOORS" && data && data.multiplier) {
|
|
509
|
+
// Map of source keys to destination keys
|
|
510
|
+
const multiplierKeys = {
|
|
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;
|
|
185
529
|
} catch (error) {
|
|
186
530
|
logError(`${CONSTANTS.LOG_PRE_FIX} Error while fetching ${type}: ${error}`);
|
|
187
531
|
}
|
|
@@ -224,6 +568,9 @@ const init = (config, _userConsent) => {
|
|
|
224
568
|
const remainingTime = Math.max(maxWaitTime - elapsedTime, 0);
|
|
225
569
|
const floorsData = await withTimeout(_fetchFloorRulesPromise, remainingTime);
|
|
226
570
|
|
|
571
|
+
// Store the profile configs globally
|
|
572
|
+
setProfileConfigs(profileConfigs);
|
|
573
|
+
|
|
227
574
|
const floorsConfig = getFloorsConfig(floorsData, profileConfigs);
|
|
228
575
|
floorsConfig && conf?.setConfig(floorsConfig);
|
|
229
576
|
configMerged();
|
|
@@ -266,7 +613,73 @@ const getBidRequestData = (reqBidsConfigObj, callback) => {
|
|
|
266
613
|
});
|
|
267
614
|
}
|
|
268
615
|
|
|
269
|
-
/**
|
|
616
|
+
/**
|
|
617
|
+
* Returns targeting data for ad units
|
|
618
|
+
* @param {string[]} adUnitCodes - Ad unit codes
|
|
619
|
+
* @param {Object} config - Module configuration
|
|
620
|
+
* @param {Object} userConsent - User consent data
|
|
621
|
+
* @param {Object} auction - Auction object
|
|
622
|
+
* @return {Object} - Targeting data for ad units
|
|
623
|
+
*/
|
|
624
|
+
export const getTargetingData = (adUnitCodes, config, userConsent, auction) => {
|
|
625
|
+
// Access the profile configs stored globally
|
|
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;
|
|
681
|
+
};
|
|
682
|
+
|
|
270
683
|
export const pubmaticSubmodule = {
|
|
271
684
|
/**
|
|
272
685
|
* used to link submodule with realTimeData
|
|
@@ -275,6 +688,7 @@ export const pubmaticSubmodule = {
|
|
|
275
688
|
name: CONSTANTS.SUBMODULE_NAME,
|
|
276
689
|
init,
|
|
277
690
|
getBidRequestData,
|
|
691
|
+
getTargetingData
|
|
278
692
|
};
|
|
279
693
|
|
|
280
694
|
export const registerSubModule = () => {
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
## Description
|
|
8
8
|
|
|
9
|
-
The PubMatic RTD module
|
|
9
|
+
The PubMatic RTD module provides dynamic yield optimization by fetching real-time pricing floor data and generating targeting data for ad server integration and reporting. The module integrates with Prebid's Price Floors system as per [Dynamic Floor Data Provider](https://docs.prebid.org/dev-docs/modules/floors.html#floor-data-provider-interface) guidelines.
|
|
10
10
|
|
|
11
11
|
## Usage
|
|
12
12
|
|
|
@@ -66,7 +66,17 @@ pbjs.setConfig({
|
|
|
66
66
|
| params.publisherId | String | Publisher ID | |
|
|
67
67
|
| params.profileId | String | Profile ID | |
|
|
68
68
|
|
|
69
|
+
## Targeting Keys
|
|
70
|
+
|
|
71
|
+
The module sets the following targeting keys for ad server integration and reporting:
|
|
72
|
+
|
|
73
|
+
| Key | Description | Values |
|
|
74
|
+
| :-- | :---------- | :----- |
|
|
75
|
+
| pm_ym_flrs | Whether RTD floor was applied to the auction | 0 (not applied)/1 (applied) |
|
|
76
|
+
| pm_ym_flrv | Floor value after applying dynamic multipliers | Decimal value (e.g., "1.25") |
|
|
77
|
+
| pm_ym_bid_s | Bid outcome status | 0 (no bid), 1 (won), 2 (floored) |
|
|
78
|
+
|
|
69
79
|
|
|
70
80
|
## What Should Change in the Bid Request?
|
|
71
81
|
|
|
72
|
-
|
|
82
|
+
The RTD module applies dynamic floor configuration through the Price Floors module, which affects floor values in bid requests. Additionally, the module generates targeting data that is made available to the ad server.
|