prebid.js 7.14.0 → 7.16.0
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 +3 -0
- package/dist/1plusXRtdProvider.js +1 -1
- package/dist/33acrossBidAdapter.js +1 -1
- package/dist/adagioBidAdapter.js +1 -1
- package/dist/adbookpspBidAdapter.js +1 -1
- package/dist/adfBidAdapter.js +1 -1
- package/dist/adgenerationBidAdapter.js +1 -1
- package/dist/adkernelAdnBidAdapter.js +1 -1
- package/dist/adkernelBidAdapter.js +1 -1
- package/dist/adlooxAdServerVideo.js +1 -1
- package/dist/adlooxRtdProvider.js +1 -1
- package/dist/adrelevantisBidAdapter.js +1 -1
- package/dist/adtrgtmeBidAdapter.js +1 -1
- package/dist/adtrueBidAdapter.js +1 -1
- package/dist/adxcgBidAdapter.js +1 -1
- package/dist/airgridRtdProvider.js +1 -1
- package/dist/ajaBidAdapter.js +1 -1
- package/dist/amxBidAdapter.js +1 -1
- package/dist/amxIdSystem.js +1 -1
- package/dist/aolBidAdapter.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/beachfrontBidAdapter.js +1 -1
- package/dist/bidglassBidAdapter.js +1 -1
- package/dist/big-richmediaBidAdapter.js +1 -1
- package/dist/bizzclickBidAdapter.js +1 -1
- package/dist/bliinkBidAdapter.js +1 -1
- package/dist/bluebillywigBidAdapter.js +1 -1
- package/dist/brandmetricsRtdProvider.js +1 -1
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- package/dist/brightcomBidAdapter.js +1 -1
- package/dist/browsiRtdProvider.js +1 -1
- package/dist/categoryTranslation.js +1 -1
- package/dist/concertBidAdapter.js +1 -1
- package/dist/connectadBidAdapter.js +1 -1
- package/dist/consentManagement.js +1 -1
- package/dist/consentManagementUsp.js +1 -1
- package/dist/consumableBidAdapter.js +1 -1
- package/dist/conversantBidAdapter.js +1 -1
- package/dist/cpmstarBidAdapter.js +1 -1
- package/dist/craftBidAdapter.js +1 -1
- package/dist/criteoBidAdapter.js +1 -1
- package/dist/currency.js +1 -1
- package/dist/dataControllerModule.js +1 -1
- package/dist/dchain.js +1 -1
- package/dist/deepintentBidAdapter.js +1 -1
- package/dist/dependencies.json +3 -0
- package/dist/dgkeywordRtdProvider.js +1 -1
- package/dist/dianomiBidAdapter.js +1 -1
- package/dist/distroscaleBidAdapter.js +1 -1
- package/dist/dspxBidAdapter.js +1 -1
- package/dist/eplanningBidAdapter.js +1 -1
- package/dist/etargetBidAdapter.js +1 -1
- package/dist/feedadBidAdapter.js +1 -1
- package/dist/finativeBidAdapter.js +1 -1
- package/dist/fpdModule.js +1 -1
- package/dist/gamoshiBidAdapter.js +1 -1
- package/dist/glimpseBidAdapter.js +1 -1
- package/dist/gmosspBidAdapter.js +1 -1
- package/dist/goldbachBidAdapter.js +1 -1
- package/dist/gothamadsBidAdapter.js +1 -1
- package/dist/gridBidAdapter.js +1 -1
- package/dist/gridNMBidAdapter.js +1 -1
- package/dist/gumgumBidAdapter.js +1 -1
- package/dist/h12mediaBidAdapter.js +1 -1
- package/dist/iasRtdProvider.js +1 -1
- package/dist/id5IdSystem.js +1 -1
- package/dist/imRtdProvider.js +1 -1
- package/dist/impactifyBidAdapter.js +1 -1
- package/dist/improvedigitalBidAdapter.js +1 -1
- package/dist/inmarBidAdapter.js +1 -1
- package/dist/insticatorBidAdapter.js +1 -1
- package/dist/ixBidAdapter.js +1 -1
- package/dist/justpremiumBidAdapter.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/liveIntentAnalyticsAdapter.js +1 -0
- package/dist/liveyieldAnalyticsAdapter.js +1 -1
- package/dist/logicadBidAdapter.js +1 -1
- package/dist/loglyliftBidAdapter.js +1 -1
- package/dist/luponmediaBidAdapter.js +1 -1
- package/dist/malltvAnalyticsAdapter.js +1 -1
- package/dist/marsmediaBidAdapter.js +1 -1
- package/dist/mass.js +1 -1
- package/dist/mediafuseBidAdapter.js +1 -1
- package/dist/mediakeysBidAdapter.js +1 -1
- package/dist/mediasniperBidAdapter.js +1 -1
- package/dist/mediasquareBidAdapter.js +1 -1
- package/dist/mgidBidAdapter.js +1 -1
- package/dist/minutemediaBidAdapter.js +1 -1
- package/dist/multibid.js +1 -1
- package/dist/naveggIdSystem.js +1 -1
- package/dist/newspassidBidAdapter.js +1 -1
- package/dist/nextMillenniumBidAdapter.js +1 -1
- package/dist/not-for-prod/prebid.js +172 -171
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/oneKeyRtdProvider.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/openxBidAdapter.js +1 -1
- package/dist/openxOrtbBidAdapter.js +1 -1
- package/dist/operaadsBidAdapter.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/ozoneBidAdapter.js +1 -1
- package/dist/parrableIdSystem.js +1 -1
- package/dist/permutiveRtdProvider.js +1 -1
- package/dist/pixfutureBidAdapter.js +1 -1
- package/dist/prebid-core.js +2 -2
- package/dist/prebidServerBidAdapter.js +1 -1
- package/dist/priceFloors.js +1 -1
- package/dist/pubCommonId.js +1 -1
- package/dist/pubgeniusBidAdapter.js +1 -1
- package/dist/publinkIdSystem.js +1 -1
- package/dist/pubmaticBidAdapter.js +1 -1
- package/dist/pubwiseAnalyticsAdapter.js +1 -1
- package/dist/pubwiseBidAdapter.js +1 -1
- package/dist/pubxBidAdapter.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/rhythmoneBidAdapter.js +1 -1
- package/dist/riseBidAdapter.js +1 -1
- package/dist/rtdModule.js +1 -1
- package/dist/rubiconAnalyticsAdapter.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/shinezBidAdapter.js +1 -1
- package/dist/sirdataRtdProvider.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/sonobiBidAdapter.js +1 -1
- package/dist/sovrnAnalyticsAdapter.js +1 -1
- package/dist/sovrnBidAdapter.js +1 -1
- package/dist/spotxBidAdapter.js +1 -1
- package/dist/sspBCBidAdapter.js +1 -1
- package/dist/stroeerCoreBidAdapter.js +1 -1
- package/dist/sublimeBidAdapter.js +1 -1
- package/dist/synacormediaBidAdapter.js +1 -1
- package/dist/targetVideoBidAdapter.js +1 -1
- package/dist/teadsBidAdapter.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/ucfunnelBidAdapter.js +1 -1
- package/dist/underdogmediaBidAdapter.js +1 -1
- package/dist/undertoneBidAdapter.js +1 -1
- package/dist/userId.js +1 -1
- package/dist/vidazooBidAdapter.js +1 -1
- package/dist/videobyteBidAdapter.js +1 -1
- package/dist/viewability.js +1 -1
- package/dist/visxBidAdapter.js +1 -1
- package/dist/vuukleBidAdapter.js +1 -1
- package/dist/weboramaRtdProvider.js +1 -1
- package/dist/widespaceBidAdapter.js +1 -1
- package/dist/winrBidAdapter.js +1 -1
- package/dist/yahoosspBidAdapter.js +1 -1
- package/dist/yieldliftBidAdapter.js +1 -1
- package/dist/yieldmoBidAdapter.js +1 -1
- package/dist/yieldoneAnalyticsAdapter.js +1 -1
- package/dist/zeta_global_sspBidAdapter.js +1 -1
- package/modules/amxBidAdapter.js +98 -78
- package/modules/appnexusBidAdapter.js +73 -12
- package/modules/categoryTranslation.js +9 -8
- package/modules/consentManagement.js +4 -2
- package/modules/consentManagementUsp.js +17 -14
- package/modules/cpmstarBidAdapter.js +2 -1
- package/modules/currency.js +4 -3
- package/modules/dataControllerModule/index.js +4 -3
- package/modules/dchain.js +3 -2
- package/modules/dianomiBidAdapter.js +17 -14
- package/modules/dianomiBidAdapter.md +1 -1
- package/modules/feedadBidAdapter.js +40 -8
- package/modules/fpdModule/index.js +3 -2
- package/modules/iasRtdProvider.js +17 -3
- package/modules/ixBidAdapter.js +2 -5
- package/modules/liveIntentAnalyticsAdapter.js +148 -0
- package/modules/liveIntentAnalyticsAdapter.md +22 -0
- package/modules/mass.js +5 -3
- package/modules/multibid/index.js +4 -2
- package/modules/naveggIdSystem.js +53 -22
- package/modules/nextMillenniumBidAdapter.js +168 -55
- package/modules/openxOrtbBidAdapter.js +1 -1
- package/modules/prebidServerBidAdapter/index.js +18 -4
- package/modules/priceFloors.js +5 -4
- package/modules/pubCommonId.js +3 -2
- package/modules/rtdModule/index.js +3 -2
- package/modules/sharethroughBidAdapter.js +8 -6
- package/modules/spotxBidAdapter.js +1 -0
- package/modules/stroeerCoreBidAdapter.js +129 -92
- package/modules/stroeerCoreBidAdapter.md +52 -14
- package/modules/teadsBidAdapter.js +32 -10
- package/modules/ucfunnelBidAdapter.js +9 -10
- package/modules/userId/index.js +73 -48
- package/modules/viewability.js +2 -170
- package/package.json +3 -3
- package/src/adapterManager.js +21 -13
- package/src/adapters/bidderFactory.js +28 -6
- package/src/auction.js +17 -4
- package/src/auctionManager.js +5 -0
- package/src/constants.json +2 -0
- package/src/native.js +5 -2
- package/src/prebid.js +52 -23
- package/src/secureCreatives.js +1 -1
- package/src/utils/perfMetrics.js +386 -0
- package/src/utils.js +1 -1
- package/test/helpers/testing-utils.js +4 -3
- package/test/spec/modules/adriverIdSystem_spec.js +7 -3
- package/test/spec/modules/amxBidAdapter_spec.js +250 -192
- package/test/spec/modules/appnexusBidAdapter_spec.js +61 -6
- package/test/spec/modules/consentManagementUsp_spec.js +6 -2
- package/test/spec/modules/dianomiBidAdapter_spec.js +326 -6
- package/test/spec/modules/feedadBidAdapter_spec.js +147 -11
- package/test/spec/modules/iasRtdProvider_spec.js +3 -1
- package/test/spec/modules/ixBidAdapter_spec.js +0 -64
- package/test/spec/modules/liveIntentAnalyticsAdapter_spec.js +297 -0
- package/test/spec/modules/nextMillenniumBidAdapter_spec.js +103 -1
- package/test/spec/modules/openxOrtbBidAdapter_spec.js +31 -0
- package/test/spec/modules/sharethroughBidAdapter_spec.js +23 -2
- package/test/spec/modules/spotxBidAdapter_spec.js +6 -0
- package/test/spec/modules/stroeerCoreBidAdapter_spec.js +315 -33
- package/test/spec/modules/teadsBidAdapter_spec.js +65 -11
- package/test/spec/modules/ucfunnelBidAdapter_spec.js +24 -10
- package/test/spec/native_spec.js +11 -0
- package/test/spec/unit/utils/perfMetrics_spec.js +394 -0
- package/wdio.conf.js +1 -0
- package/modules/viewability.md +0 -87
- package/test/spec/modules/viewability_spec.js +0 -280
package/modules/userId/index.js
CHANGED
|
@@ -154,6 +154,7 @@ import {
|
|
|
154
154
|
import {getPPID as coreGetPPID} from '../../src/adserver.js';
|
|
155
155
|
import {defer, GreedyPromise} from '../../src/utils/promise.js';
|
|
156
156
|
import {hasPurpose1Consent} from '../../src/utils/gpdr.js';
|
|
157
|
+
import {newMetrics, timedAuctionHook, useMetrics} from '../../src/utils/perfMetrics.js';
|
|
157
158
|
|
|
158
159
|
const MODULE_NAME = 'User ID';
|
|
159
160
|
const COOKIE = 'cookie';
|
|
@@ -196,6 +197,20 @@ let ppidSource;
|
|
|
196
197
|
|
|
197
198
|
let configListener;
|
|
198
199
|
|
|
200
|
+
const uidMetrics = (() => {
|
|
201
|
+
let metrics;
|
|
202
|
+
return () => {
|
|
203
|
+
if (metrics == null) {
|
|
204
|
+
metrics = newMetrics();
|
|
205
|
+
}
|
|
206
|
+
return metrics;
|
|
207
|
+
}
|
|
208
|
+
})();
|
|
209
|
+
|
|
210
|
+
function submoduleMetrics(moduleName) {
|
|
211
|
+
return uidMetrics().fork().renameWith(n => [`userId.mod.${n}`, `userId.mods.${moduleName}.${n}`])
|
|
212
|
+
}
|
|
213
|
+
|
|
199
214
|
/** @param {Submodule[]} submodules */
|
|
200
215
|
export function setSubmoduleRegistry(submodules) {
|
|
201
216
|
submoduleRegistry = submodules;
|
|
@@ -395,14 +410,13 @@ export function findRootDomain(fullDomain = window.location.hostname) {
|
|
|
395
410
|
* @param {function} cb - callback for after processing is done.
|
|
396
411
|
*/
|
|
397
412
|
function processSubmoduleCallbacks(submodules, cb) {
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
}, submodules.length);
|
|
404
|
-
}
|
|
413
|
+
cb = uidMetrics().fork().startTiming('userId.callbacks.total').stopBefore(cb);
|
|
414
|
+
const done = delayExecution(() => {
|
|
415
|
+
clearTimeout(timeoutID);
|
|
416
|
+
cb();
|
|
417
|
+
}, submodules.length);
|
|
405
418
|
submodules.forEach(function (submodule) {
|
|
419
|
+
const moduleDone = submoduleMetrics(submodule.submodule.name).startTiming('callback').stopBefore(done);
|
|
406
420
|
function callbackCompleted(idObj) {
|
|
407
421
|
// if valid, id data should be saved to cookie/html storage
|
|
408
422
|
if (idObj) {
|
|
@@ -414,13 +428,13 @@ function processSubmoduleCallbacks(submodules, cb) {
|
|
|
414
428
|
} else {
|
|
415
429
|
logInfo(`${MODULE_NAME}: ${submodule.submodule.name} - request id responded with an empty value`);
|
|
416
430
|
}
|
|
417
|
-
|
|
431
|
+
moduleDone();
|
|
418
432
|
}
|
|
419
433
|
try {
|
|
420
434
|
submodule.callback(callbackCompleted);
|
|
421
435
|
} catch (e) {
|
|
422
436
|
logError(`Error in userID module '${submodule.submodule.name}':`, e);
|
|
423
|
-
|
|
437
|
+
moduleDone();
|
|
424
438
|
}
|
|
425
439
|
// clear callback, this prop is used to test if all submodule callbacks are complete below
|
|
426
440
|
submodule.callback = undefined;
|
|
@@ -508,13 +522,16 @@ function idSystemInitializer({delay = GreedyPromise.timeout} = {}) {
|
|
|
508
522
|
const startCallbacks = defer();
|
|
509
523
|
let cancel;
|
|
510
524
|
let initialized = false;
|
|
525
|
+
let initMetrics;
|
|
511
526
|
|
|
512
527
|
function cancelAndTry(promise) {
|
|
528
|
+
initMetrics = uidMetrics().fork();
|
|
513
529
|
if (cancel != null) {
|
|
514
530
|
cancel.reject(INIT_CANCELED);
|
|
515
531
|
}
|
|
516
532
|
cancel = defer();
|
|
517
|
-
return GreedyPromise.race([promise, cancel.promise])
|
|
533
|
+
return GreedyPromise.race([promise, cancel.promise])
|
|
534
|
+
.finally(initMetrics.startTiming('userId.total'))
|
|
518
535
|
}
|
|
519
536
|
|
|
520
537
|
// grab a reference to global vars so that the promise chains remain isolated;
|
|
@@ -532,13 +549,17 @@ function idSystemInitializer({delay = GreedyPromise.timeout} = {}) {
|
|
|
532
549
|
}
|
|
533
550
|
}
|
|
534
551
|
|
|
552
|
+
function timeGdpr() {
|
|
553
|
+
return gdprDataHandler.promise.finally(initMetrics.startTiming('userId.init.gdpr'));
|
|
554
|
+
}
|
|
555
|
+
|
|
535
556
|
let done = cancelAndTry(
|
|
536
557
|
GreedyPromise.all([hooksReady, startInit.promise])
|
|
537
|
-
.then(
|
|
558
|
+
.then(timeGdpr)
|
|
538
559
|
.then(checkRefs((consentData) => {
|
|
539
560
|
initSubmodules(initModules, allModules, consentData);
|
|
540
561
|
}))
|
|
541
|
-
.then(() => startCallbacks.promise)
|
|
562
|
+
.then(() => startCallbacks.promise.finally(initMetrics.startTiming('userId.callbacks.pending')))
|
|
542
563
|
.then(checkRefs(() => {
|
|
543
564
|
const modWithCb = initModules.filter(item => isFn(item.callback));
|
|
544
565
|
if (modWithCb.length) {
|
|
@@ -570,7 +591,7 @@ function idSystemInitializer({delay = GreedyPromise.timeout} = {}) {
|
|
|
570
591
|
done = cancelAndTry(
|
|
571
592
|
done
|
|
572
593
|
.catch(() => null)
|
|
573
|
-
.then(
|
|
594
|
+
.then(timeGdpr) // fetch again in case a refresh was forced before this was resolved
|
|
574
595
|
.then(checkRefs((consentData) => {
|
|
575
596
|
const cbModules = initSubmodules(
|
|
576
597
|
initModules,
|
|
@@ -614,7 +635,7 @@ function getPPID() {
|
|
|
614
635
|
* @param {Object} reqBidsConfigObj required; This is the same param that's used in pbjs.requestBids.
|
|
615
636
|
* @param {function} fn required; The next function in the chain, used by hook.js
|
|
616
637
|
*/
|
|
617
|
-
export function requestBidsHook(fn, reqBidsConfigObj, {delay = GreedyPromise.timeout, getIds = getUserIdsAsync} = {}) {
|
|
638
|
+
export const requestBidsHook = timedAuctionHook('userId', function requestBidsHook(fn, reqBidsConfigObj, {delay = GreedyPromise.timeout, getIds = getUserIdsAsync} = {}) {
|
|
618
639
|
GreedyPromise.race([
|
|
619
640
|
getIds().catch(() => null),
|
|
620
641
|
delay(auctionDelay)
|
|
@@ -633,11 +654,11 @@ export function requestBidsHook(fn, reqBidsConfigObj, {delay = GreedyPromise.tim
|
|
|
633
654
|
});
|
|
634
655
|
}
|
|
635
656
|
}
|
|
636
|
-
|
|
657
|
+
uidMetrics().join(useMetrics(reqBidsConfigObj.metrics), {propagate: false, includeGroups: true});
|
|
637
658
|
// calling fn allows prebid to continue processing
|
|
638
659
|
fn.call(this, reqBidsConfigObj);
|
|
639
660
|
});
|
|
640
|
-
}
|
|
661
|
+
});
|
|
641
662
|
|
|
642
663
|
/**
|
|
643
664
|
* This function will be exposed in global-name-space so that userIds stored by Prebid UserId module can be used by external codes as well.
|
|
@@ -835,43 +856,47 @@ function populateSubmoduleId(submodule, consentData, storedConsentData, forceRef
|
|
|
835
856
|
}
|
|
836
857
|
|
|
837
858
|
function initSubmodules(dest, submodules, consentData, forceRefresh = false) {
|
|
838
|
-
|
|
859
|
+
return uidMetrics().fork().measureTime('userId.init.modules', function () {
|
|
860
|
+
if (!submodules.length) return []; // to simplify log messages from here on
|
|
839
861
|
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
if (!submodules.length) {
|
|
846
|
-
logWarn(`${MODULE_NAME} - no ID module is configured for one of the available storage types:`, Array.from(storageTypes));
|
|
847
|
-
return [];
|
|
848
|
-
}
|
|
862
|
+
// filter out submodules whose storage type is not enabled
|
|
863
|
+
// this needs to be done here (after consent data has loaded) so that enforcement may disable storage globally
|
|
864
|
+
const storageTypes = getActiveStorageTypes();
|
|
865
|
+
submodules = submodules.filter((submod) => !submod.config.storage || storageTypes.has(submod.config.storage.type));
|
|
849
866
|
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
return [];
|
|
855
|
-
}
|
|
867
|
+
if (!submodules.length) {
|
|
868
|
+
logWarn(`${MODULE_NAME} - no ID module is configured for one of the available storage types:`, Array.from(storageTypes));
|
|
869
|
+
return [];
|
|
870
|
+
}
|
|
856
871
|
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
872
|
+
// another consent check, this time each module is checked for consent with its own gvlid
|
|
873
|
+
let { userIdModules, hasValidated } = validateGdprEnforcement(submodules, consentData);
|
|
874
|
+
if (!hasValidated && !hasPurpose1Consent(consentData)) {
|
|
875
|
+
logWarn(`${MODULE_NAME} - gdpr permission not valid for local storage or cookies, exit module`);
|
|
876
|
+
return [];
|
|
877
|
+
}
|
|
860
878
|
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
879
|
+
// we always want the latest consentData stored, even if we don't execute any submodules
|
|
880
|
+
const storedConsentData = getStoredConsentData();
|
|
881
|
+
setStoredConsentData(consentData);
|
|
882
|
+
|
|
883
|
+
const initialized = userIdModules.reduce((carry, submodule) => {
|
|
884
|
+
return submoduleMetrics(submodule.submodule.name).measureTime('init', () => {
|
|
885
|
+
try {
|
|
886
|
+
populateSubmoduleId(submodule, consentData, storedConsentData, forceRefresh);
|
|
887
|
+
carry.push(submodule);
|
|
888
|
+
} catch (e) {
|
|
889
|
+
logError(`Error in userID module '${submodule.submodule.name}':`, e);
|
|
890
|
+
}
|
|
891
|
+
return carry;
|
|
892
|
+
})
|
|
893
|
+
}, []);
|
|
894
|
+
if (initialized.length) {
|
|
895
|
+
setPrebidServerEidPermissions(initialized);
|
|
867
896
|
}
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
setPrebidServerEidPermissions(initialized);
|
|
872
|
-
}
|
|
873
|
-
initialized.forEach(updateInitializedSubmodules.bind(null, dest));
|
|
874
|
-
return initialized;
|
|
897
|
+
initialized.forEach(updateInitializedSubmodules.bind(null, dest));
|
|
898
|
+
return initialized;
|
|
899
|
+
})
|
|
875
900
|
}
|
|
876
901
|
|
|
877
902
|
function updateInitializedSubmodules(dest, submodule) {
|
package/modules/viewability.js
CHANGED
|
@@ -1,177 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {getGlobal} from '../src/prebidGlobal.js';
|
|
3
|
-
import {find} from '../src/polyfill.js';
|
|
1
|
+
import {logWarn} from '../src/utils.js';
|
|
4
2
|
|
|
5
3
|
export const MODULE_NAME = 'viewability';
|
|
6
4
|
|
|
7
5
|
export function init() {
|
|
8
|
-
(
|
|
9
|
-
startMeasurement: startMeasurement,
|
|
10
|
-
stopMeasurement: stopMeasurement,
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
listenMessagesFromCreative();
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const observers = new Map();
|
|
17
|
-
|
|
18
|
-
function isValid(vid, element, tracker, criteria) {
|
|
19
|
-
if (!element) {
|
|
20
|
-
logWarn(`${MODULE_NAME}: no html element provided`);
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
let validTracker = tracker &&
|
|
25
|
-
((tracker.method === 'img' && isStr(tracker.value)) ||
|
|
26
|
-
(tracker.method === 'js' && isStr(tracker.value)) ||
|
|
27
|
-
(tracker.method === 'callback' && isFn(tracker.value)));
|
|
28
|
-
|
|
29
|
-
if (!validTracker) {
|
|
30
|
-
logWarn(`${MODULE_NAME}: invalid tracker`, tracker);
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (!criteria || !criteria.inViewThreshold || !criteria.timeInView) {
|
|
35
|
-
logWarn(`${MODULE_NAME}: missing criteria`, criteria);
|
|
36
|
-
return false;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
if (!vid || observers.has(vid)) {
|
|
40
|
-
logWarn(`${MODULE_NAME}: must provide an unregistered vid`, vid);
|
|
41
|
-
return false;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return true;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function stopObserving(observer, vid, element) {
|
|
48
|
-
observer.unobserve(element);
|
|
49
|
-
observers.get(vid).done = true;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
function fireViewabilityTracker(element, tracker) {
|
|
53
|
-
switch (tracker.method) {
|
|
54
|
-
case 'img':
|
|
55
|
-
triggerPixel(tracker.value, () => {
|
|
56
|
-
logInfo(`${MODULE_NAME}: viewability pixel fired`, tracker.value);
|
|
57
|
-
});
|
|
58
|
-
break;
|
|
59
|
-
case 'js':
|
|
60
|
-
insertHtmlIntoIframe(`<script src="${tracker.value}"></script>`);
|
|
61
|
-
break;
|
|
62
|
-
case 'callback':
|
|
63
|
-
tracker.value(element);
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function viewabilityCriteriaMet(observer, vid, element, tracker) {
|
|
69
|
-
stopObserving(observer, vid, element);
|
|
70
|
-
fireViewabilityTracker(element, tracker);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* Start measuring viewability of an element
|
|
75
|
-
* @typedef {{ method: string='img','js','callback', value: string|function }} ViewabilityTracker { method: 'img', value: 'http://my.tracker/123' }
|
|
76
|
-
* @typedef {{ inViewThreshold: number, timeInView: number }} ViewabilityCriteria { inViewThreshold: 0.5, timeInView: 1000 }
|
|
77
|
-
* @param {string} vid unique viewability identifier
|
|
78
|
-
* @param {HTMLElement} element
|
|
79
|
-
* @param {ViewabilityTracker} tracker
|
|
80
|
-
* @param {ViewabilityCriteria} criteria
|
|
81
|
-
*/
|
|
82
|
-
export function startMeasurement(vid, element, tracker, criteria) {
|
|
83
|
-
if (!isValid(vid, element, tracker, criteria)) {
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const options = {
|
|
88
|
-
root: null,
|
|
89
|
-
rootMargin: '0px',
|
|
90
|
-
threshold: criteria.inViewThreshold,
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
let observer;
|
|
94
|
-
let viewable = false;
|
|
95
|
-
let stateChange = (entries) => {
|
|
96
|
-
viewable = entries[0].isIntersecting;
|
|
97
|
-
|
|
98
|
-
if (viewable) {
|
|
99
|
-
observers.get(vid).timeoutId = window.setTimeout(() => {
|
|
100
|
-
viewabilityCriteriaMet(observer, vid, element, tracker);
|
|
101
|
-
}, criteria.timeInView);
|
|
102
|
-
} else if (observers.get(vid).timeoutId) {
|
|
103
|
-
window.clearTimeout(observers.get(vid).timeoutId);
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
observer = new IntersectionObserver(stateChange, options);
|
|
108
|
-
observers.set(vid, {
|
|
109
|
-
observer: observer,
|
|
110
|
-
element: element,
|
|
111
|
-
timeoutId: null,
|
|
112
|
-
done: false,
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
observer.observe(element);
|
|
116
|
-
|
|
117
|
-
logInfo(`${MODULE_NAME}: startMeasurement called with:`, arguments);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Stop measuring viewability of an element
|
|
122
|
-
* @param {string} vid unique viewability identifier
|
|
123
|
-
*/
|
|
124
|
-
export function stopMeasurement(vid) {
|
|
125
|
-
if (!vid || !observers.has(vid)) {
|
|
126
|
-
logWarn(`${MODULE_NAME}: must provide a registered vid`, vid);
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
observers.get(vid).observer.unobserve(observers.get(vid).element);
|
|
131
|
-
if (observers.get(vid).timeoutId) {
|
|
132
|
-
window.clearTimeout(observers.get(vid).timeoutId);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// allow the observer under this vid to be created again
|
|
136
|
-
if (!observers.get(vid).done) {
|
|
137
|
-
observers.delete(vid);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function listenMessagesFromCreative() {
|
|
142
|
-
window.addEventListener('message', receiveMessage, false);
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
/**
|
|
146
|
-
* Recieve messages from creatives
|
|
147
|
-
* @param {MessageEvent} evt
|
|
148
|
-
*/
|
|
149
|
-
export function receiveMessage(evt) {
|
|
150
|
-
var key = evt.message ? 'message' : 'data';
|
|
151
|
-
var data = {};
|
|
152
|
-
try {
|
|
153
|
-
data = JSON.parse(evt[key]);
|
|
154
|
-
} catch (e) {
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
if (!data || data.message !== 'Prebid Viewability') {
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
switch (data.action) {
|
|
163
|
-
case 'startMeasurement':
|
|
164
|
-
let element = data.elementId && document.getElementById(data.elementId);
|
|
165
|
-
if (!element) {
|
|
166
|
-
element = find(document.getElementsByTagName('IFRAME'), iframe => (iframe.contentWindow || iframe.contentDocument.defaultView) == evt.source);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
startMeasurement(data.vid, element, data.tracker, data.criteria);
|
|
170
|
-
break;
|
|
171
|
-
case 'stopMeasurement':
|
|
172
|
-
stopMeasurement(data.vid);
|
|
173
|
-
break;
|
|
174
|
-
}
|
|
6
|
+
logWarn('Viewability module should not be used. See https://github.com/prebid/Prebid.js/issues/8928');
|
|
175
7
|
}
|
|
176
8
|
|
|
177
9
|
init();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "prebid.js",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.16.0",
|
|
4
4
|
"description": "Header Bidding Management Library",
|
|
5
5
|
"main": "src/prebid.js",
|
|
6
6
|
"scripts": {
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"gulp-clean": "^0.3.2",
|
|
68
68
|
"gulp-concat": "^2.6.0",
|
|
69
69
|
"gulp-connect": "^5.7.0",
|
|
70
|
-
"gulp-eslint": "^
|
|
70
|
+
"gulp-eslint": "^6.0.0",
|
|
71
71
|
"gulp-if": "^3.0.0",
|
|
72
72
|
"gulp-js-escape": "^1.0.1",
|
|
73
73
|
"gulp-replace": "^1.0.0",
|
|
@@ -122,7 +122,7 @@
|
|
|
122
122
|
"criteo-direct-rsa-validate": "^1.1.0",
|
|
123
123
|
"crypto-js": "^3.3.0",
|
|
124
124
|
"dlv": "1.1.3",
|
|
125
|
-
"dset": "
|
|
125
|
+
"dset": "3.1.2",
|
|
126
126
|
"express": "^4.15.4",
|
|
127
127
|
"fun-hooks": "^0.9.9",
|
|
128
128
|
"just-clone": "^1.0.2",
|
package/src/adapterManager.js
CHANGED
|
@@ -17,22 +17,24 @@ import {
|
|
|
17
17
|
logError,
|
|
18
18
|
logInfo,
|
|
19
19
|
logMessage,
|
|
20
|
-
logWarn,
|
|
20
|
+
logWarn,
|
|
21
|
+
mergeDeep,
|
|
21
22
|
shuffle,
|
|
22
23
|
timestamp,
|
|
23
24
|
} from './utils.js';
|
|
24
25
|
import {processAdUnitsForLabels} from './sizeMapping.js';
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import {
|
|
32
|
-
import {
|
|
26
|
+
import {decorateAdUnitsWithNativeParams, nativeAdapters} from './native.js';
|
|
27
|
+
import {newBidder} from './adapters/bidderFactory.js';
|
|
28
|
+
import {ajaxBuilder} from './ajax.js';
|
|
29
|
+
import {config, RANDOM} from './config.js';
|
|
30
|
+
import {hook} from './hook.js';
|
|
31
|
+
import {find, includes} from './polyfill.js';
|
|
32
|
+
import {adunitCounter} from './adUnits.js';
|
|
33
|
+
import {getRefererInfo} from './refererDetection.js';
|
|
33
34
|
import {GdprConsentHandler, UspConsentHandler} from './consentHandler.js';
|
|
34
35
|
import * as events from './events.js';
|
|
35
36
|
import CONSTANTS from './constants.json';
|
|
37
|
+
import {useMetrics} from './utils/perfMetrics.js';
|
|
36
38
|
|
|
37
39
|
export const PARTITIONS = {
|
|
38
40
|
CLIENT: 'client',
|
|
@@ -60,7 +62,7 @@ var _analyticsRegistry = {};
|
|
|
60
62
|
* @property {Array<string>} activeLabels the labels specified as being active by requestBids
|
|
61
63
|
*/
|
|
62
64
|
|
|
63
|
-
function getBids({bidderCode, auctionId, bidderRequestId, adUnits, src}) {
|
|
65
|
+
function getBids({bidderCode, auctionId, bidderRequestId, adUnits, src, metrics}) {
|
|
64
66
|
return adUnits.reduce((result, adUnit) => {
|
|
65
67
|
result.push(adUnit.bids.filter(bid => bid.bidder === bidderCode)
|
|
66
68
|
.reduce((bids, bid) => {
|
|
@@ -92,6 +94,7 @@ function getBids({bidderCode, auctionId, bidderRequestId, adUnits, src}) {
|
|
|
92
94
|
bidderRequestId,
|
|
93
95
|
auctionId,
|
|
94
96
|
src,
|
|
97
|
+
metrics,
|
|
95
98
|
bidRequestsCount: adunitCounter.getRequestsCounter(adUnit.code),
|
|
96
99
|
bidderRequestsCount: adunitCounter.getBidderRequestsCounter(adUnit.code, bid.bidder),
|
|
97
100
|
bidderWinsCount: adunitCounter.getBidderWinsCounter(adUnit.code, bid.bidder),
|
|
@@ -206,7 +209,8 @@ export function _partitionBidders (adUnits, s2sConfigs, {getS2SBidders = getS2SB
|
|
|
206
209
|
|
|
207
210
|
export const partitionBidders = hook('sync', _partitionBidders, 'partitionBidders');
|
|
208
211
|
|
|
209
|
-
adapterManager.makeBidRequests = hook('sync', function (adUnits, auctionStart, auctionId, cbTimeout, labels, ortb2Fragments = {}) {
|
|
212
|
+
adapterManager.makeBidRequests = hook('sync', function (adUnits, auctionStart, auctionId, cbTimeout, labels, ortb2Fragments = {}, auctionMetrics) {
|
|
213
|
+
auctionMetrics = useMetrics(auctionMetrics);
|
|
210
214
|
/**
|
|
211
215
|
* emit and pass adunits for external modification
|
|
212
216
|
* @see {@link https://github.com/prebid/Prebid.js/issues/4149|Issue}
|
|
@@ -244,16 +248,18 @@ adapterManager.makeBidRequests = hook('sync', function (adUnits, auctionStart, a
|
|
|
244
248
|
let uniquePbsTid = generateUUID();
|
|
245
249
|
serverBidders.forEach(bidderCode => {
|
|
246
250
|
const bidderRequestId = getUniqueIdentifierStr();
|
|
251
|
+
const metrics = auctionMetrics.fork();
|
|
247
252
|
const bidderRequest = addOrtb2({
|
|
248
253
|
bidderCode,
|
|
249
254
|
auctionId,
|
|
250
255
|
bidderRequestId,
|
|
251
256
|
uniquePbsTid,
|
|
252
|
-
bids: hookedGetBids({bidderCode, auctionId, bidderRequestId, 'adUnits': deepClone(adUnitsS2SCopy), src: CONSTANTS.S2S.SRC}),
|
|
257
|
+
bids: hookedGetBids({bidderCode, auctionId, bidderRequestId, 'adUnits': deepClone(adUnitsS2SCopy), src: CONSTANTS.S2S.SRC, metrics}),
|
|
253
258
|
auctionStart: auctionStart,
|
|
254
259
|
timeout: s2sConfig.timeout,
|
|
255
260
|
src: CONSTANTS.S2S.SRC,
|
|
256
261
|
refererInfo,
|
|
262
|
+
metrics,
|
|
257
263
|
});
|
|
258
264
|
if (bidderRequest.bids.length !== 0) {
|
|
259
265
|
bidRequests.push(bidderRequest);
|
|
@@ -281,14 +287,16 @@ adapterManager.makeBidRequests = hook('sync', function (adUnits, auctionStart, a
|
|
|
281
287
|
let adUnitsClientCopy = getAdUnitCopyForClientAdapters(adUnits);
|
|
282
288
|
clientBidders.forEach(bidderCode => {
|
|
283
289
|
const bidderRequestId = getUniqueIdentifierStr();
|
|
290
|
+
const metrics = auctionMetrics.fork();
|
|
284
291
|
const bidderRequest = addOrtb2({
|
|
285
292
|
bidderCode,
|
|
286
293
|
auctionId,
|
|
287
294
|
bidderRequestId,
|
|
288
|
-
bids: hookedGetBids({bidderCode, auctionId, bidderRequestId, 'adUnits': deepClone(adUnitsClientCopy), labels, src: 'client'}),
|
|
295
|
+
bids: hookedGetBids({bidderCode, auctionId, bidderRequestId, 'adUnits': deepClone(adUnitsClientCopy), labels, src: 'client', metrics}),
|
|
289
296
|
auctionStart: auctionStart,
|
|
290
297
|
timeout: cbTimeout,
|
|
291
298
|
refererInfo,
|
|
299
|
+
metrics,
|
|
292
300
|
});
|
|
293
301
|
const adapter = _bidderRegistry[bidderCode];
|
|
294
302
|
if (!adapter) {
|
|
@@ -15,6 +15,7 @@ import { getHook, hook } from '../hook.js';
|
|
|
15
15
|
import { getCoreStorageManager } from '../storageManager.js';
|
|
16
16
|
import {auctionManager} from '../auctionManager.js';
|
|
17
17
|
import { bidderSettings } from '../bidderSettings.js';
|
|
18
|
+
import {useMetrics} from '../utils/perfMetrics.js';
|
|
18
19
|
|
|
19
20
|
export const storage = getCoreStorageManager('bidderFactory');
|
|
20
21
|
|
|
@@ -196,8 +197,10 @@ export function newBidder(spec) {
|
|
|
196
197
|
|
|
197
198
|
const adUnitCodesHandled = {};
|
|
198
199
|
function addBidWithCode(adUnitCode, bid) {
|
|
200
|
+
const metrics = useMetrics(bid.metrics);
|
|
201
|
+
metrics.checkpoint('addBidResponse');
|
|
199
202
|
adUnitCodesHandled[adUnitCode] = true;
|
|
200
|
-
if (isValid(adUnitCode, bid)) {
|
|
203
|
+
if (metrics.measureTime('addBidResponse.validate', () => isValid(adUnitCode, bid))) {
|
|
201
204
|
addBidResponse(adUnitCode, bid);
|
|
202
205
|
}
|
|
203
206
|
}
|
|
@@ -213,7 +216,9 @@ export function newBidder(spec) {
|
|
|
213
216
|
});
|
|
214
217
|
}
|
|
215
218
|
|
|
216
|
-
const validBidRequests = bidderRequest
|
|
219
|
+
const validBidRequests = adapterMetrics(bidderRequest)
|
|
220
|
+
.measureTime('validate', () => bidderRequest.bids.filter(filterAndWarn));
|
|
221
|
+
|
|
217
222
|
if (validBidRequests.length === 0) {
|
|
218
223
|
afterAllResponses();
|
|
219
224
|
return;
|
|
@@ -315,7 +320,11 @@ export function newBidder(spec) {
|
|
|
315
320
|
* @param onCompletion {function()} invoked once when all bid requests have been processed
|
|
316
321
|
*/
|
|
317
322
|
export const processBidderRequests = hook('sync', function (spec, bids, bidderRequest, ajax, wrapCallback, {onRequest, onResponse, onFledgeAuctionConfigs, onError, onBid, onCompletion}) {
|
|
318
|
-
|
|
323
|
+
const metrics = adapterMetrics(bidderRequest);
|
|
324
|
+
onCompletion = metrics.startTiming('total').stopBefore(onCompletion);
|
|
325
|
+
|
|
326
|
+
let requests = metrics.measureTime('buildRequests', () => spec.buildRequests(bids, bidderRequest));
|
|
327
|
+
|
|
319
328
|
if (!requests || requests.length === 0) {
|
|
320
329
|
onCompletion();
|
|
321
330
|
return;
|
|
@@ -327,10 +336,16 @@ export const processBidderRequests = hook('sync', function (spec, bids, bidderRe
|
|
|
327
336
|
const requestDone = delayExecution(onCompletion, requests.length);
|
|
328
337
|
|
|
329
338
|
requests.forEach((request) => {
|
|
339
|
+
const requestMetrics = metrics.fork();
|
|
340
|
+
function addBid(bid) {
|
|
341
|
+
if (bid != null) bid.metrics = requestMetrics.fork().renameWith();
|
|
342
|
+
onBid(bid);
|
|
343
|
+
}
|
|
330
344
|
// If the server responds successfully, use the adapter code to unpack the Bids from it.
|
|
331
345
|
// If the adapter code fails, no bids should be added. After all the bids have been added,
|
|
332
346
|
// make sure to call the `requestDone` function so that we're one step closer to calling onCompletion().
|
|
333
347
|
const onSuccess = wrapCallback(function(response, responseObj) {
|
|
348
|
+
networkDone();
|
|
334
349
|
try {
|
|
335
350
|
response = JSON.parse(response);
|
|
336
351
|
} catch (e) { /* response might not be JSON... that's ok. */ }
|
|
@@ -343,7 +358,7 @@ export const processBidderRequests = hook('sync', function (spec, bids, bidderRe
|
|
|
343
358
|
onResponse(response);
|
|
344
359
|
|
|
345
360
|
try {
|
|
346
|
-
response = spec.interpretResponse(response, request);
|
|
361
|
+
response = requestMetrics.measureTime('interpretResponse', () => spec.interpretResponse(response, request));
|
|
347
362
|
} catch (err) {
|
|
348
363
|
logError(`Bidder ${spec.code} failed to interpret the server's response. Continuing without bids`, null, err);
|
|
349
364
|
requestDone();
|
|
@@ -361,9 +376,9 @@ export const processBidderRequests = hook('sync', function (spec, bids, bidderRe
|
|
|
361
376
|
|
|
362
377
|
if (bids) {
|
|
363
378
|
if (isArray(bids)) {
|
|
364
|
-
bids.forEach(
|
|
379
|
+
bids.forEach(addBid);
|
|
365
380
|
} else {
|
|
366
|
-
|
|
381
|
+
addBid(bids);
|
|
367
382
|
}
|
|
368
383
|
}
|
|
369
384
|
requestDone();
|
|
@@ -376,11 +391,14 @@ export const processBidderRequests = hook('sync', function (spec, bids, bidderRe
|
|
|
376
391
|
});
|
|
377
392
|
|
|
378
393
|
const onFailure = wrapCallback(function (errorMessage, error) {
|
|
394
|
+
networkDone();
|
|
379
395
|
onError(errorMessage, error);
|
|
380
396
|
requestDone();
|
|
381
397
|
});
|
|
382
398
|
|
|
383
399
|
onRequest(request);
|
|
400
|
+
|
|
401
|
+
const networkDone = requestMetrics.startTiming('net');
|
|
384
402
|
switch (request.method) {
|
|
385
403
|
case 'GET':
|
|
386
404
|
ajax(
|
|
@@ -588,3 +606,7 @@ export function isValid(adUnitCode, bid, {index = auctionManager.index} = {}) {
|
|
|
588
606
|
|
|
589
607
|
return true;
|
|
590
608
|
}
|
|
609
|
+
|
|
610
|
+
function adapterMetrics(bidderRequest) {
|
|
611
|
+
return useMetrics(bidderRequest.metrics).renameWith(n => [`adapter.client.${n}`, `adapters.client.${bidderRequest.bidderCode}.${n}`])
|
|
612
|
+
}
|