prebid.js 7.4.0 → 7.7.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 +11 -6
- package/dist/1plusXRtdProvider.js +1 -0
- package/dist/33acrossBidAdapter.js +1 -1
- package/dist/adagioBidAdapter.js +1 -1
- package/dist/adbookpspBidAdapter.js +1 -1
- package/dist/adgenerationBidAdapter.js +1 -1
- package/dist/adnuntiusBidAdapter.js +1 -1
- package/dist/adoceanBidAdapter.js +1 -1
- package/dist/adotBidAdapter.js +1 -1
- package/dist/adrelevantisBidAdapter.js +1 -1
- package/dist/adrinoBidAdapter.js +1 -1
- package/dist/adtelligentBidAdapter.js +1 -1
- package/dist/adxcgBidAdapter.js +1 -1
- package/dist/ajaBidAdapter.js +1 -1
- package/dist/amxBidAdapter.js +1 -1
- package/dist/amxIdSystem.js +1 -1
- package/dist/appierAnalyticsAdapter.js +1 -1
- package/dist/appnexusBidAdapter.js +1 -1
- package/dist/asoBidAdapter.js +1 -1
- package/dist/atsAnalyticsAdapter.js +1 -1
- package/dist/axonixBidAdapter.js +1 -1
- package/dist/bidglassBidAdapter.js +1 -1
- package/dist/big-richmediaBidAdapter.js +1 -1
- package/dist/bliinkBidAdapter.js +1 -1
- package/dist/bridgewellBidAdapter.js +1 -1
- package/dist/brightMountainMediaBidAdapter.js +1 -1
- package/dist/byDataAnalyticsAdapter.js +1 -1
- package/dist/concertBidAdapter.js +1 -1
- package/dist/connectadBidAdapter.js +1 -1
- package/dist/consumableBidAdapter.js +1 -1
- package/dist/conversantBidAdapter.js +1 -1
- package/dist/craftBidAdapter.js +1 -1
- package/dist/criteoBidAdapter.js +1 -1
- package/dist/currency.js +1 -1
- package/dist/dspxBidAdapter.js +1 -1
- package/dist/eplanningBidAdapter.js +1 -1
- package/dist/finativeBidAdapter.js +1 -1
- package/dist/gdprEnforcement.js +1 -1
- package/dist/glimpseBidAdapter.js +1 -1
- package/dist/gmosspBidAdapter.js +1 -1
- package/dist/goldbachBidAdapter.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/hadronIdSystem.js +1 -1
- package/dist/hadronRtdProvider.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/jixieBidAdapter.js +1 -1
- package/dist/justpremiumBidAdapter.js +1 -1
- package/dist/kargoAnalyticsAdapter.js +1 -1
- package/dist/konduitAnalyticsAdapter.js +1 -1
- package/dist/kueezBidAdapter.js +1 -1
- package/dist/lassoBidAdapter.js +1 -1
- package/dist/liveyieldAnalyticsAdapter.js +1 -1
- package/dist/logicadBidAdapter.js +1 -1
- package/dist/loglyliftBidAdapter.js +1 -1
- package/dist/malltvAnalyticsAdapter.js +1 -1
- package/dist/marsmediaBidAdapter.js +1 -1
- package/dist/mediafuseBidAdapter.js +1 -1
- package/dist/mediasquareBidAdapter.js +1 -1
- package/dist/mgidBidAdapter.js +1 -1
- package/dist/minutemediaBidAdapter.js +1 -1
- package/dist/naveggIdSystem.js +1 -1
- package/dist/newspassidBidAdapter.js +1 -0
- package/dist/nextMillenniumBidAdapter.js +1 -1
- package/dist/not-for-prod/prebid.js +131 -128
- package/dist/oguryBidAdapter.js +1 -1
- package/dist/onetagBidAdapter.js +1 -1
- package/dist/ooloAnalyticsAdapter.js +1 -1
- package/dist/outbrainBidAdapter.js +1 -1
- package/dist/parrableIdSystem.js +1 -1
- package/dist/pixfutureBidAdapter.js +1 -1
- package/dist/prebid-core.js +1 -1
- package/dist/prebidServerBidAdapter.js +1 -1
- package/dist/priceFloors.js +1 -1
- package/dist/pubCommonId.js +1 -1
- package/dist/publinkIdSystem.js +1 -1
- package/dist/pubmaticBidAdapter.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/rasBidAdapter.js +1 -0
- 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/rubiconAnalyticsAdapter.js +1 -1
- package/dist/rubiconBidAdapter.js +1 -1
- package/dist/seedingAllianceBidAdapter.js +1 -1
- package/dist/seedtagBidAdapter.js +1 -1
- package/dist/sharedIdSystem.js +1 -1
- package/dist/sharethroughAnalyticsAdapter.js +1 -1
- package/dist/sharethroughBidAdapter.js +1 -1
- package/dist/shinezBidAdapter.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/sspBCBidAdapter.js +1 -1
- package/dist/sublimeBidAdapter.js +1 -1
- package/dist/synacormediaBidAdapter.js +1 -1
- package/dist/taboolaBidAdapter.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/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/visxBidAdapter.js +1 -1
- package/dist/vuukleBidAdapter.js +1 -1
- package/dist/widespaceBidAdapter.js +1 -1
- package/dist/winrBidAdapter.js +1 -1
- package/dist/yahoosspBidAdapter.js +1 -1
- package/dist/yieldmoBidAdapter.js +1 -1
- package/dist/yieldoneAnalyticsAdapter.js +1 -1
- package/integrationExamples/gpt/1plusXRtdProviderExample.html +112 -0
- package/karma.conf.maker.js +3 -1
- package/modules/.submodules.json +2 -1
- package/modules/1plusXRtdProvider.js +251 -0
- package/modules/1plusXRtdProvider.md +65 -0
- package/modules/adgenerationBidAdapter.js +24 -1
- package/modules/adnuntiusBidAdapter.js +26 -8
- package/modules/adoceanBidAdapter.js +10 -3
- package/modules/adotBidAdapter.js +13 -4
- package/modules/adrinoBidAdapter.js +10 -2
- package/modules/adrinoBidAdapter.md +6 -0
- package/modules/adtelligentBidAdapter.js +2 -1
- package/modules/appnexusBidAdapter.js +3 -3
- package/modules/atsAnalyticsAdapter.js +4 -5
- package/modules/big-richmediaBidAdapter.js +3 -3
- package/modules/bliinkBidAdapter.js +120 -193
- package/modules/bliinkBidAdapter.md +2 -5
- package/modules/byDataAnalyticsAdapter.js +172 -74
- package/modules/byDataAnalyticsAdapter.md +5 -6
- package/modules/consumableBidAdapter.js +21 -1
- package/modules/criteoBidAdapter.js +7 -1
- package/modules/currency.js +2 -2
- package/modules/cwireBidAdapter.md +1 -1
- package/modules/eplanningBidAdapter.js +82 -97
- package/modules/gdprEnforcement.js +8 -14
- package/modules/gridNMBidAdapter.js +45 -4
- package/modules/hadronAnalyticsAdapter.md +5 -5
- package/modules/hadronIdSystem.js +18 -5
- package/modules/hadronIdSystem.md +15 -11
- package/modules/hadronRtdProvider.js +14 -1
- package/modules/hadronRtdProvider.md +17 -13
- package/modules/imRtdProvider.js +0 -8
- package/modules/impactifyBidAdapter.js +6 -2
- package/modules/ixBidAdapter.js +133 -23
- package/modules/ixBidAdapter.md +2 -5
- package/modules/jixieBidAdapter.js +10 -10
- package/modules/kargoAnalyticsAdapter.js +88 -6
- package/modules/kargoAnalyticsAdapter.md +33 -0
- package/modules/minutemediaBidAdapter.js +1 -0
- package/modules/naveggIdSystem.js +1 -12
- package/modules/newspassidBidAdapter.js +649 -0
- package/modules/nextMillenniumBidAdapter.js +17 -1
- package/modules/nextMillenniumBidAdapter.md +1 -1
- package/modules/oguryBidAdapter.js +2 -0
- package/modules/onetagBidAdapter.js +44 -7
- package/modules/prebidServerBidAdapter/index.js +7 -0
- package/modules/priceFloors.js +1 -1
- package/modules/pubCommonId.js +1 -2
- package/modules/pubxaiAnalyticsAdapter.js +6 -1
- package/modules/rasBidAdapter.js +149 -0
- package/modules/rasBidAdapter.md +50 -0
- package/modules/rubiconBidAdapter.js +5 -0
- package/modules/seedingAllianceBidAdapter.js +3 -0
- package/modules/seedtagBidAdapter.js +37 -1
- package/modules/sharedIdSystem.js +11 -5
- package/modules/sharethroughBidAdapter.js +9 -24
- package/modules/taboolaBidAdapter.js +1 -1
- package/modules/taboolaBidAdapter.md +3 -3
- package/modules/targetVideoBidAdapter.js +18 -0
- package/modules/userId/index.js +39 -21
- package/package.json +1 -1
- package/src/auction.js +6 -5
- package/src/consentHandler.js +11 -11
- package/src/debugging.js +5 -3
- package/src/hook.js +2 -2
- package/src/storageManager.js +4 -5
- package/src/utils/promise.js +96 -21
- package/src/utils.js +3 -2
- package/test/helpers/consentData.js +2 -1
- package/test/spec/auctionmanager_spec.js +1 -6
- package/test/spec/debugging_spec.js +2 -2
- package/test/spec/modules/1plusXRtdProvider_spec.js +430 -0
- package/test/spec/modules/adgenerationBidAdapter_spec.js +52 -4
- package/test/spec/modules/adnuntiusBidAdapter_spec.js +126 -14
- package/test/spec/modules/adoceanBidAdapter_spec.js +4 -1
- package/test/spec/modules/adotBidAdapter_spec.js +12 -9
- package/test/spec/modules/adrinoBidAdapter_spec.js +22 -0
- package/test/spec/modules/appnexusBidAdapter_spec.js +165 -156
- package/test/spec/modules/bliinkBidAdapter_spec.js +323 -136
- package/test/spec/modules/byDataAnalyticsAdapter_spec.js +74 -24
- package/test/spec/modules/consumableBidAdapter_spec.js +122 -1
- package/test/spec/modules/criteoBidAdapter_spec.js +15 -5
- package/test/spec/modules/eplanningBidAdapter_spec.js +58 -18
- package/test/spec/modules/gdprEnforcement_spec.js +53 -100
- package/test/spec/modules/gridNMBidAdapter_spec.js +32 -0
- package/test/spec/modules/hadronIdSystem_spec.js +2 -2
- package/test/spec/modules/idxIdSystem_spec.js +1 -1
- package/test/spec/modules/imRtdProvider_spec.js +0 -1
- package/test/spec/modules/ixBidAdapter_spec.js +212 -5
- package/test/spec/modules/jixieBidAdapter_spec.js +8 -8
- package/test/spec/modules/kargoAnalyticsAdapter_spec.js +42 -0
- package/test/spec/modules/minutemediaBidAdapter_spec.js +3 -0
- package/test/spec/modules/newspassidBidAdapter_spec.js +1793 -0
- package/test/spec/modules/nextMillenniumBidAdapter_spec.js +20 -0
- package/test/spec/modules/onetagBidAdapter_spec.js +53 -4
- package/test/spec/modules/parrableIdSystem_spec.js +2 -1
- package/test/spec/modules/prebidServerBidAdapter_spec.js +20 -0
- package/test/spec/modules/pubxaiAnalyticsAdapter_spec.js +5 -0
- package/test/spec/modules/rasBidAdapter_spec.js +190 -0
- package/test/spec/modules/rubiconBidAdapter_spec.js +27 -0
- package/test/spec/modules/seedtagBidAdapter_spec.js +29 -0
- package/test/spec/modules/sharethroughBidAdapter_spec.js +4 -4
- package/test/spec/modules/taboolaBidAdapter_spec.js +1 -1
- package/test/spec/modules/targetVideoBidAdapter_spec.js +43 -0
- package/test/spec/modules/userId_spec.js +15 -2
- package/test/spec/unit/pbjs_api_spec.js +1 -5
- package/test/spec/unit/utils/promise_spec.js +283 -38
- package/test/helpers/syncPromise.js +0 -71
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {getWindowSelf, isEmpty, parseSizesInput} from '../src/utils.js';
|
|
1
|
+
import {getWindowSelf, isEmpty, parseSizesInput, isGptPubadsDefined, isSlotMatchingAdUnitCode} from '../src/utils.js';
|
|
2
2
|
import {getGlobal} from '../src/prebidGlobal.js';
|
|
3
3
|
import {registerBidder} from '../src/adapters/bidderFactory.js';
|
|
4
4
|
import {getStorageManager} from '../src/storageManager.js';
|
|
@@ -291,13 +291,25 @@ function getCharset() {
|
|
|
291
291
|
|
|
292
292
|
function waitForElementsPresent(elements) {
|
|
293
293
|
const observer = new MutationObserver(function (mutationList, observer) {
|
|
294
|
+
let index;
|
|
295
|
+
let adView;
|
|
294
296
|
if (mutationList && Array.isArray(mutationList)) {
|
|
295
297
|
mutationList.forEach(mr => {
|
|
296
298
|
if (mr && mr.addedNodes && Array.isArray(mr.addedNodes)) {
|
|
297
299
|
mr.addedNodes.forEach(ad => {
|
|
298
|
-
|
|
300
|
+
index = elements.indexOf(ad.id);
|
|
301
|
+
adView = ad;
|
|
302
|
+
if (index < 0) {
|
|
303
|
+
elements.forEach(code => {
|
|
304
|
+
let div = _getAdSlotHTMLElement(code);
|
|
305
|
+
if (div && div.contains(ad) && div.getBoundingClientRect().width > 0) {
|
|
306
|
+
index = elements.indexOf(div.id);
|
|
307
|
+
adView = div;
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
}
|
|
299
311
|
if (index >= 0) {
|
|
300
|
-
registerViewability(
|
|
312
|
+
registerViewability(adView, elements[index]);
|
|
301
313
|
elements.splice(index, 1);
|
|
302
314
|
if (!elements.length) {
|
|
303
315
|
observer.disconnect();
|
|
@@ -318,19 +330,41 @@ function waitForElementsPresent(elements) {
|
|
|
318
330
|
});
|
|
319
331
|
}
|
|
320
332
|
|
|
321
|
-
function registerViewability(div) {
|
|
333
|
+
function registerViewability(div, name) {
|
|
322
334
|
visibilityHandler({
|
|
323
|
-
name:
|
|
335
|
+
name: name,
|
|
324
336
|
div: div
|
|
325
337
|
});
|
|
326
338
|
}
|
|
327
339
|
|
|
340
|
+
function _mapAdUnitPathToElementId(adUnitCode) {
|
|
341
|
+
if (isGptPubadsDefined()) {
|
|
342
|
+
// eslint-disable-next-line no-undef
|
|
343
|
+
const adSlots = googletag.pubads().getSlots();
|
|
344
|
+
const isMatchingAdSlot = isSlotMatchingAdUnitCode(adUnitCode);
|
|
345
|
+
|
|
346
|
+
for (let i = 0; i < adSlots.length; i++) {
|
|
347
|
+
if (isMatchingAdSlot(adSlots[i])) {
|
|
348
|
+
const id = adSlots[i].getSlotElementId();
|
|
349
|
+
return id;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function _getAdSlotHTMLElement(adUnitCode) {
|
|
358
|
+
return document.getElementById(adUnitCode) ||
|
|
359
|
+
document.getElementById(_mapAdUnitPathToElementId(adUnitCode));
|
|
360
|
+
}
|
|
361
|
+
|
|
328
362
|
function registerViewabilityAllBids(bids) {
|
|
329
363
|
let elementsNotPresent = [];
|
|
330
364
|
bids.forEach(bid => {
|
|
331
|
-
let div =
|
|
365
|
+
let div = _getAdSlotHTMLElement(bid.adUnitCode);
|
|
332
366
|
if (div) {
|
|
333
|
-
registerViewability(div);
|
|
367
|
+
registerViewability(div, bid.adUnitCode);
|
|
334
368
|
} else {
|
|
335
369
|
elementsNotPresent.push(bid.adUnitCode);
|
|
336
370
|
}
|
|
@@ -345,114 +379,65 @@ function getViewabilityTracker() {
|
|
|
345
379
|
let VIEWABILITY_TIME = 1000;
|
|
346
380
|
let VIEWABILITY_MIN_RATIO = 0.5;
|
|
347
381
|
let publicApi;
|
|
348
|
-
let
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
function segmentEndsAfterTheVisibleRange(visibleRangeEnd, p2) {
|
|
359
|
-
return p2 < visibleRangeEnd;
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
function axialVisibilityRatio(visibleRangeEnd, p1, p2) {
|
|
363
|
-
let visibilityRatio = 0;
|
|
364
|
-
if (!segmentIsOutsideTheVisibleRange(visibleRangeEnd, p1, p2)) {
|
|
365
|
-
if (segmentBeginsBeforeTheVisibleRange(p1)) {
|
|
366
|
-
visibilityRatio = p2 / (p2 - p1);
|
|
382
|
+
let observer;
|
|
383
|
+
let visibilityAds = {};
|
|
384
|
+
|
|
385
|
+
function intersectionCallback(entries) {
|
|
386
|
+
entries.forEach(function(entry) {
|
|
387
|
+
var adBox = entry.target;
|
|
388
|
+
if (entry.isIntersecting) {
|
|
389
|
+
if (entry.intersectionRatio >= VIEWABILITY_MIN_RATIO && entry.boundingClientRect && entry.boundingClientRect.height > 0 && entry.boundingClientRect.width > 0) {
|
|
390
|
+
visibilityAds[adBox.id] = true;
|
|
391
|
+
}
|
|
367
392
|
} else {
|
|
368
|
-
|
|
393
|
+
visibilityAds[adBox.id] = false;
|
|
369
394
|
}
|
|
370
|
-
}
|
|
371
|
-
return visibilityRatio;
|
|
372
|
-
}
|
|
373
|
-
|
|
374
|
-
function isNotHiddenByNonFriendlyIframe() {
|
|
375
|
-
try { return (window === window.top) || window.frameElement; } catch (e) {}
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
function defineContext(e) {
|
|
379
|
-
try {
|
|
380
|
-
context = e && window.document.body.contains(e) ? window : (window.top.document.body.contains(e) ? top : undefined);
|
|
381
|
-
} catch (err) {}
|
|
382
|
-
return context;
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
function getContext(e) {
|
|
386
|
-
return context;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
function verticalVisibilityRatio(position) {
|
|
390
|
-
return axialVisibilityRatio(getContext().innerHeight, position.top, position.bottom);
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
function horizontalVisibilityRatio(position) {
|
|
394
|
-
return axialVisibilityRatio(getContext().innerWidth, position.left, position.right);
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
function itIsNotHiddenByBannerAreaPosition(e) {
|
|
398
|
-
let position = e.getBoundingClientRect();
|
|
399
|
-
return (verticalVisibilityRatio(position) * horizontalVisibilityRatio(position)) > VIEWABILITY_MIN_RATIO;
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
function itIsNotHiddenByDisplayStyleCascade(e) {
|
|
403
|
-
return e.offsetHeight > 0 && e.offsetWidth > 0;
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
function itIsNotHiddenByOpacityStyleCascade(e) {
|
|
407
|
-
let s = e.style;
|
|
408
|
-
let p = e.parentNode;
|
|
409
|
-
return !(s && parseFloat(s.opacity) === 0) && (!p || itIsNotHiddenByOpacityStyleCascade(p));
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
function itIsNotHiddenByVisibilityStyleCascade(e) {
|
|
413
|
-
return getContext().getComputedStyle(e).visibility !== 'hidden';
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
function itIsNotHiddenByTabFocus() {
|
|
417
|
-
try { return getContext().top.document.hasFocus(); } catch (e) {}
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
function isDefined(e) {
|
|
421
|
-
return (e !== null) && (typeof e !== 'undefined');
|
|
395
|
+
});
|
|
422
396
|
}
|
|
423
397
|
|
|
424
|
-
function
|
|
425
|
-
return
|
|
398
|
+
function observedElementIsVisible(element) {
|
|
399
|
+
return visibilityAds[element.id] && document.visibilityState && document.visibilityState === 'visible';
|
|
426
400
|
}
|
|
427
401
|
|
|
428
|
-
function
|
|
429
|
-
|
|
402
|
+
function defineObserver() {
|
|
403
|
+
if (!observer) {
|
|
404
|
+
var observerConfig = {
|
|
405
|
+
root: null,
|
|
406
|
+
rootMargin: '0px',
|
|
407
|
+
threshold: [VIEWABILITY_MIN_RATIO]
|
|
408
|
+
};
|
|
409
|
+
observer = new IntersectionObserver(intersectionCallback.bind(this), observerConfig);
|
|
410
|
+
}
|
|
430
411
|
}
|
|
431
|
-
|
|
432
412
|
function processIntervalVisibilityStatus(elapsedVisibleIntervals, element, callback) {
|
|
433
|
-
let visibleIntervals =
|
|
413
|
+
let visibleIntervals = observedElementIsVisible(element) ? (elapsedVisibleIntervals + 1) : 0;
|
|
434
414
|
if (visibleIntervals === TIME_PARTITIONS) {
|
|
415
|
+
stopObserveViewability(element)
|
|
435
416
|
callback();
|
|
436
417
|
} else {
|
|
437
418
|
setTimeout(processIntervalVisibilityStatus.bind(this, visibleIntervals, element, callback), VIEWABILITY_TIME / TIME_PARTITIONS);
|
|
438
419
|
}
|
|
439
420
|
}
|
|
440
421
|
|
|
441
|
-
function
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
422
|
+
function stopObserveViewability(element) {
|
|
423
|
+
delete visibilityAds[element.id];
|
|
424
|
+
observer.unobserve(element);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function observeAds(element) {
|
|
428
|
+
observer.observe(element);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function initAndVerifyVisibility(element, callback) {
|
|
432
|
+
if (element) {
|
|
433
|
+
defineObserver();
|
|
434
|
+
observeAds(element);
|
|
435
|
+
processIntervalVisibilityStatus(0, element, callback);
|
|
436
|
+
}
|
|
451
437
|
}
|
|
452
438
|
|
|
453
439
|
publicApi = {
|
|
454
|
-
|
|
455
|
-
onView: processIntervalVisibilityStatus.bind(this, 0)
|
|
440
|
+
onView: initAndVerifyVisibility.bind(this)
|
|
456
441
|
};
|
|
457
442
|
|
|
458
443
|
return publicApi;
|
|
@@ -18,8 +18,6 @@ const TCF2 = {
|
|
|
18
18
|
'purpose7': { id: 7, name: 'measurement' }
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
const VENDORLESS_MODULE_TYPES = ['fpid-module'];
|
|
22
|
-
|
|
23
21
|
/*
|
|
24
22
|
These rules would be used if `consentManagement.gdpr.rules` is undefined by the publisher.
|
|
25
23
|
*/
|
|
@@ -125,10 +123,9 @@ function getGvlidForAnalyticsAdapter(code) {
|
|
|
125
123
|
* @param {Object} consentData - gdpr consent data
|
|
126
124
|
* @param {string=} currentModule - Bidder code of the current module
|
|
127
125
|
* @param {number=} gvlId - GVL ID for the module
|
|
128
|
-
* @param {string=} moduleType module type
|
|
129
126
|
* @returns {boolean}
|
|
130
127
|
*/
|
|
131
|
-
export function validateRules(rule, consentData, currentModule, gvlId
|
|
128
|
+
export function validateRules(rule, consentData, currentModule, gvlId) {
|
|
132
129
|
const purposeId = TCF2[Object.keys(TCF2).filter(purposeName => TCF2[purposeName].name === rule.purpose)[0]].id;
|
|
133
130
|
|
|
134
131
|
// return 'true' if vendor present in 'vendorExceptions'
|
|
@@ -141,14 +138,12 @@ export function validateRules(rule, consentData, currentModule, gvlId, moduleTyp
|
|
|
141
138
|
const vendorConsent = deepAccess(consentData, `vendorData.vendor.consents.${gvlId}`);
|
|
142
139
|
const liTransparency = deepAccess(consentData, `vendorData.purpose.legitimateInterests.${purposeId}`);
|
|
143
140
|
|
|
144
|
-
const vendorlessModule = includes(VENDORLESS_MODULE_TYPES, moduleType);
|
|
145
|
-
|
|
146
141
|
/*
|
|
147
142
|
Since vendor exceptions have already been handled, the purpose as a whole is allowed if it's not being enforced
|
|
148
143
|
or the user has consented. Similar with vendors.
|
|
149
144
|
*/
|
|
150
145
|
const purposeAllowed = rule.enforcePurpose === false || purposeConsent === true;
|
|
151
|
-
const vendorAllowed = rule.enforceVendor === false || vendorConsent === true
|
|
146
|
+
const vendorAllowed = rule.enforceVendor === false || vendorConsent === true;
|
|
152
147
|
|
|
153
148
|
/*
|
|
154
149
|
Few if any vendors should be declaring Legitimate Interest for Device Access (Purpose 1), but some are claiming
|
|
@@ -167,16 +162,15 @@ export function validateRules(rule, consentData, currentModule, gvlId, moduleTyp
|
|
|
167
162
|
* @param {Function} fn reference to original function (used by hook logic)
|
|
168
163
|
* @param {Number=} gvlid gvlid of the module
|
|
169
164
|
* @param {string=} moduleName name of the module
|
|
170
|
-
* @param {string=} moduleType module type
|
|
171
165
|
*/
|
|
172
|
-
export function deviceAccessHook(fn, gvlid, moduleName,
|
|
166
|
+
export function deviceAccessHook(fn, gvlid, moduleName, result) {
|
|
173
167
|
result = Object.assign({}, {
|
|
174
168
|
hasEnforcementHook: true
|
|
175
169
|
});
|
|
176
170
|
if (!hasDeviceAccess()) {
|
|
177
171
|
logWarn('Device access is disabled by Publisher');
|
|
178
172
|
result.valid = false;
|
|
179
|
-
fn.call(this, gvlid, moduleName,
|
|
173
|
+
fn.call(this, gvlid, moduleName, result);
|
|
180
174
|
} else {
|
|
181
175
|
const consentData = gdprDataHandler.getConsentData();
|
|
182
176
|
if (consentData && consentData.gdprApplies) {
|
|
@@ -188,19 +182,19 @@ export function deviceAccessHook(fn, gvlid, moduleName, moduleType, result) {
|
|
|
188
182
|
gvlid = getGvlid(moduleName) || gvlid;
|
|
189
183
|
}
|
|
190
184
|
const curModule = moduleName || curBidder;
|
|
191
|
-
let isAllowed = validateRules(purpose1Rule, consentData, curModule, gvlid
|
|
185
|
+
let isAllowed = validateRules(purpose1Rule, consentData, curModule, gvlid);
|
|
192
186
|
if (isAllowed) {
|
|
193
187
|
result.valid = true;
|
|
194
|
-
fn.call(this, gvlid, moduleName,
|
|
188
|
+
fn.call(this, gvlid, moduleName, result);
|
|
195
189
|
} else {
|
|
196
190
|
curModule && logWarn(`TCF2 denied device access for ${curModule}`);
|
|
197
191
|
result.valid = false;
|
|
198
192
|
storageBlocked.push(curModule);
|
|
199
|
-
fn.call(this, gvlid, moduleName,
|
|
193
|
+
fn.call(this, gvlid, moduleName, result);
|
|
200
194
|
}
|
|
201
195
|
} else {
|
|
202
196
|
result.valid = true;
|
|
203
|
-
fn.call(this, gvlid, moduleName,
|
|
197
|
+
fn.call(this, gvlid, moduleName, result);
|
|
204
198
|
}
|
|
205
199
|
}
|
|
206
200
|
}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
isStr,
|
|
3
|
+
deepAccess,
|
|
4
|
+
isArray,
|
|
5
|
+
isNumber,
|
|
6
|
+
logError,
|
|
7
|
+
logWarn,
|
|
8
|
+
parseGPTSingleSizeArrayToRtbSize,
|
|
9
|
+
mergeDeep
|
|
10
|
+
} from '../src/utils.js';
|
|
2
11
|
import { registerBidder } from '../src/adapters/bidderFactory.js';
|
|
3
12
|
import { Renderer } from '../src/Renderer.js';
|
|
4
13
|
import { VIDEO } from '../src/mediaTypes.js';
|
|
@@ -153,9 +162,7 @@ export const spec = {
|
|
|
153
162
|
user = {
|
|
154
163
|
data: [{
|
|
155
164
|
name: 'iow_labs_pub_data',
|
|
156
|
-
segment: jwpseg
|
|
157
|
-
return {name: 'jwpseg', value: seg};
|
|
158
|
-
})
|
|
165
|
+
segment: segmentProcessing(jwpseg, 'jwpseg'),
|
|
159
166
|
}]
|
|
160
167
|
};
|
|
161
168
|
}
|
|
@@ -174,9 +181,27 @@ export const spec = {
|
|
|
174
181
|
user.ext = userExt;
|
|
175
182
|
}
|
|
176
183
|
|
|
184
|
+
const ortb2UserData = deepAccess(bidderRequest, 'ortb2.user.data');
|
|
185
|
+
if (ortb2UserData && ortb2UserData.length) {
|
|
186
|
+
if (!user) {
|
|
187
|
+
user = { data: [] };
|
|
188
|
+
}
|
|
189
|
+
user = mergeDeep(user, {
|
|
190
|
+
data: [...ortb2UserData]
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
|
|
177
194
|
if (user) {
|
|
178
195
|
request.user = user;
|
|
179
196
|
}
|
|
197
|
+
const site = deepAccess(bidderRequest, 'ortb2.site');
|
|
198
|
+
if (site) {
|
|
199
|
+
const data = deepAccess(site, 'content.data');
|
|
200
|
+
if (data && data.length) {
|
|
201
|
+
const siteContent = request.site.content || {};
|
|
202
|
+
request.site.content = mergeDeep(siteContent, { data });
|
|
203
|
+
}
|
|
204
|
+
}
|
|
180
205
|
|
|
181
206
|
if (gdprConsent && gdprConsent.gdprApplies) {
|
|
182
207
|
request.regs = {
|
|
@@ -408,4 +433,20 @@ export function getSyncUrl() {
|
|
|
408
433
|
return SYNC_URL;
|
|
409
434
|
}
|
|
410
435
|
|
|
436
|
+
function segmentProcessing(segment, forceSegName) {
|
|
437
|
+
return segment
|
|
438
|
+
.map((seg) => {
|
|
439
|
+
const value = seg && (seg.value || seg.id || seg);
|
|
440
|
+
if (typeof value === 'string' || typeof value === 'number') {
|
|
441
|
+
return {
|
|
442
|
+
value: value.toString(),
|
|
443
|
+
...(forceSegName && { name: forceSegName }),
|
|
444
|
+
...(seg.name && { name: seg.name }),
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
return null;
|
|
448
|
+
})
|
|
449
|
+
.filter((seg) => !!seg);
|
|
450
|
+
}
|
|
451
|
+
|
|
411
452
|
registerBidder(spec);
|
|
@@ -33,7 +33,7 @@ The following configuration parameters are available:
|
|
|
33
33
|
|
|
34
34
|
```javascript
|
|
35
35
|
pbjs.enableAnalytics({
|
|
36
|
-
provider: '
|
|
36
|
+
provider: 'hadronAnalytics',
|
|
37
37
|
options: {
|
|
38
38
|
partnerId: 1234, // change to the Partner ID you got from Audigent
|
|
39
39
|
eventsToTrack: ['auctionEnd','bidWon']
|
|
@@ -41,8 +41,8 @@ pbjs.enableAnalytics({
|
|
|
41
41
|
});
|
|
42
42
|
```
|
|
43
43
|
|
|
44
|
-
| Parameter
|
|
45
|
-
|
|
46
|
-
| provider
|
|
47
|
-
| options.partnerId
|
|
44
|
+
| Parameter | Scope | Type | Description | Example |
|
|
45
|
+
|-----------------------|----------|------------------|---------------------------------------------------------|---------------------------|
|
|
46
|
+
| provider | Required | String | The name of this module: `hadronAnalytics` | `hadronAnalytics` |
|
|
47
|
+
| options.partnerId | Required | Number | This is the Audigent Partner ID obtained from Audigent. | `1234` |
|
|
48
48
|
| options.eventsToTrack | Optional | Array of strings | Overrides the set of tracked events | `['auctionEnd','bidWon']` |
|
|
@@ -12,6 +12,7 @@ import { isFn, isStr, isPlainObject, logError } from '../src/utils.js';
|
|
|
12
12
|
|
|
13
13
|
const MODULE_NAME = 'hadronId';
|
|
14
14
|
const AU_GVLID = 561;
|
|
15
|
+
const DEFAULT_HADRON_URL_ENDPOINT = 'https://id.hadron.ad.gt/api/v1/pbhid';
|
|
15
16
|
|
|
16
17
|
export const storage = getStorageManager({gvlid: AU_GVLID, moduleName: 'hadron'});
|
|
17
18
|
|
|
@@ -29,6 +30,15 @@ function paramOrDefault(param, defaultVal, arg) {
|
|
|
29
30
|
return defaultVal;
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
/**
|
|
34
|
+
* @param {string} url
|
|
35
|
+
* @param {string} params
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
const urlAddParams = (url, params) => {
|
|
39
|
+
return url + (url.indexOf('?') > -1 ? '&' : '?') + params
|
|
40
|
+
}
|
|
41
|
+
|
|
32
42
|
/** @type {Submodule} */
|
|
33
43
|
export const hadronIdSubmodule = {
|
|
34
44
|
/**
|
|
@@ -39,8 +49,8 @@ export const hadronIdSubmodule = {
|
|
|
39
49
|
/**
|
|
40
50
|
* decode the stored id value for passing to bid requests
|
|
41
51
|
* @function
|
|
42
|
-
* @param {
|
|
43
|
-
* @returns {
|
|
52
|
+
* @param {string} value
|
|
53
|
+
* @returns {Object}
|
|
44
54
|
*/
|
|
45
55
|
decode(value) {
|
|
46
56
|
let hadronId = storage.getDataFromLocalStorage('auHadronId');
|
|
@@ -59,9 +69,12 @@ export const hadronIdSubmodule = {
|
|
|
59
69
|
if (!isPlainObject(config.params)) {
|
|
60
70
|
config.params = {};
|
|
61
71
|
}
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
72
|
+
const partnerId = config.params.partnerId | 0;
|
|
73
|
+
|
|
74
|
+
const url = urlAddParams(
|
|
75
|
+
paramOrDefault(config.params.url, DEFAULT_HADRON_URL_ENDPOINT, config.params.urlArg),
|
|
76
|
+
`partner_id=${partnerId}&_it=prebid`
|
|
77
|
+
);
|
|
65
78
|
|
|
66
79
|
const resp = function (callback) {
|
|
67
80
|
let hadronId = storage.getDataFromLocalStorage('auHadronId');
|
|
@@ -11,6 +11,9 @@ pbjs.setConfig({
|
|
|
11
11
|
usersync: {
|
|
12
12
|
userIds: [{
|
|
13
13
|
name: 'hadronId',
|
|
14
|
+
params: {
|
|
15
|
+
partnerId: 1234 // change it to the Partner ID you'll get from Audigent
|
|
16
|
+
},
|
|
14
17
|
storage: {
|
|
15
18
|
name: 'hadronId',
|
|
16
19
|
type: 'html5'
|
|
@@ -22,14 +25,15 @@ pbjs.setConfig({
|
|
|
22
25
|
## Parameter Descriptions for the `usersync` Configuration Section
|
|
23
26
|
The below parameters apply only to the HadronID User ID Module integration.
|
|
24
27
|
|
|
25
|
-
| Param under usersync.userIds[] | Scope
|
|
26
|
-
|
|
27
|
-
| name
|
|
28
|
-
| storage
|
|
29
|
-
| storage.type
|
|
30
|
-
| storage.name
|
|
31
|
-
| storage.expires
|
|
32
|
-
| value
|
|
33
|
-
| params
|
|
34
|
-
| params.
|
|
35
|
-
| params.
|
|
28
|
+
| Param under usersync.userIds[] | Scope | Type | Description | Example |
|
|
29
|
+
|--------------------------------|----------|---------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------|
|
|
30
|
+
| name | Required | String | ID value for the HadronID module - `"hadronId"` | `"hadronId"` |
|
|
31
|
+
| storage | Required | Object | The publisher must specify the local storage in which to store the results of the call to get the user ID. This can be either cookie or HTML5 storage. | |
|
|
32
|
+
| storage.type | Required | String | This is where the results of the user ID will be stored. The recommended method is `localStorage` by specifying `html5`. | `"html5"` |
|
|
33
|
+
| storage.name | Required | String | The name of the cookie or html5 local storage where the user ID will be stored. | `"hadronid"` |
|
|
34
|
+
| storage.expires | Optional | Integer | How long (in days) the user ID information will be stored. | `365` |
|
|
35
|
+
| value | Optional | Object | Used only if the page has a separate mechanism for storing the Hadron ID. The value is an object containing the values to be sent to the adapters. In this scenario, no URL is called and nothing is added to local storage | `{"hadronId": "eb33b0cb-8d35-4722-b9c0-1a31d4064888"}` |
|
|
36
|
+
| params | Optional | Object | Used to store params for the id system |
|
|
37
|
+
| params.partnerId | Required | Number | This is the Audigent Partner ID obtained from Audigent. | `1234` |
|
|
38
|
+
| params.url | Optional | String | Set an alternate GET url for HadronId with this parameter |
|
|
39
|
+
| params.urlArg | Optional | Object | Optional url parameter for params.url |
|
|
@@ -23,6 +23,15 @@ export const HALOID_LOCAL_NAME = 'auHadronId';
|
|
|
23
23
|
export const RTD_LOCAL_NAME = 'auHadronRtd';
|
|
24
24
|
export const storage = getStorageManager({gvlid: AU_GVLID, moduleName: SUBMODULE_NAME});
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* @param {string} url
|
|
28
|
+
* @param {string} params
|
|
29
|
+
* @returns {string}
|
|
30
|
+
*/
|
|
31
|
+
const urlAddParams = (url, params) => {
|
|
32
|
+
return url + (url.indexOf('?') > -1 ? '&' : '?') + params
|
|
33
|
+
}
|
|
34
|
+
|
|
26
35
|
/**
|
|
27
36
|
* Deep set an object unless value present.
|
|
28
37
|
* @param {Object} obj
|
|
@@ -165,8 +174,12 @@ export function getRealTimeData(bidConfig, onDone, rtdConfig, userConsent) {
|
|
|
165
174
|
userIds.hadronId = hadronId;
|
|
166
175
|
getRealTimeDataAsync(bidConfig, onDone, rtdConfig, userConsent, userIds);
|
|
167
176
|
}
|
|
177
|
+
const partnerId = rtdConfig.params.partnerId | 0;
|
|
168
178
|
const hadronIdUrl = rtdConfig.params && rtdConfig.params.hadronIdUrl;
|
|
169
|
-
const scriptUrl =
|
|
179
|
+
const scriptUrl = urlAddParams(
|
|
180
|
+
paramOrDefault(hadronIdUrl, HADRON_ID_DEFAULT_URL, userIds),
|
|
181
|
+
`partner_id=${partnerId}&_it=prebid`
|
|
182
|
+
);
|
|
170
183
|
loadExternalScript(scriptUrl, 'hadron', () => {
|
|
171
184
|
logInfo(LOG_PREFIX, 'hadronIdTag loaded', scriptUrl);
|
|
172
185
|
})
|
|
@@ -44,8 +44,9 @@ pbjs.setConfig(
|
|
|
44
44
|
params: {
|
|
45
45
|
segmentCache: false,
|
|
46
46
|
requestParams: {
|
|
47
|
-
publisherId: 1234
|
|
48
|
-
}
|
|
47
|
+
publisherId: 1234 // deprecated, use partnerId instead
|
|
48
|
+
},
|
|
49
|
+
partnerId: 1234
|
|
49
50
|
}
|
|
50
51
|
}
|
|
51
52
|
]
|
|
@@ -56,15 +57,17 @@ pbjs.setConfig(
|
|
|
56
57
|
|
|
57
58
|
### Parameter Descriptions for the Hadron Configuration Section
|
|
58
59
|
|
|
59
|
-
| Name
|
|
60
|
-
|
|
61
|
-
| name
|
|
62
|
-
| waitForIt
|
|
63
|
-
| params
|
|
64
|
-
| params.
|
|
65
|
-
| params.
|
|
66
|
-
| params.
|
|
67
|
-
| params.
|
|
60
|
+
| Name | Type | Description | Notes |
|
|
61
|
+
|:---------------------------------|:---------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------|
|
|
62
|
+
| name | String | Real time data module name | Always 'hadron' |
|
|
63
|
+
| waitForIt | Boolean | Required to ensure that the auction is delayed until prefetch is complete | Optional. Defaults to false |
|
|
64
|
+
| params | Object | | |
|
|
65
|
+
| params.partnerId | Number | This is the Audigent Partner ID obtained from Audigent. | `1234` |
|
|
66
|
+
| params.handleRtd | Function | A passable RTD handler that allows custom adunit and ortb2 logic to be configured. The function signature is (bidConfig, rtd, rtdConfig, pbConfig) => {}. | Optional |
|
|
67
|
+
| params.segmentCache | Boolean | This parameter tells the Hadron RTD module to attempt reading segments from a local storage cache instead of always requesting them from the Audigent server. | Optional. Defaults to false. |
|
|
68
|
+
| params.requestParams | Object | Publisher partner specific configuration options, such as optional publisher id and other segment query related metadata to be submitted to Audigent's backend with each request. Contact prebid@audigent.com for more information. | Optional |
|
|
69
|
+
| params.requestParams.publisherId | Object | (deprecated) Publisher id and other segment query related metadata to be submitted to Audigent's backend with each request. Contact prebid@audigent.com for more information. | Optional |
|
|
70
|
+
| params.hadronIdUrl | String | Parameter to specify alternate hadronid endpoint url. | Optional |
|
|
68
71
|
|
|
69
72
|
### Publisher Customized RTD Handling
|
|
70
73
|
As indicated above, it is possible to provide your own bid augmentation
|
|
@@ -100,8 +103,9 @@ pbjs.setConfig(
|
|
|
100
103
|
},
|
|
101
104
|
segmentCache: false,
|
|
102
105
|
requestParams: {
|
|
103
|
-
publisherId: 1234
|
|
104
|
-
}
|
|
106
|
+
publisherId: 1234 // deprecated, use partnerId instead
|
|
107
|
+
},
|
|
108
|
+
partnerId: 1234
|
|
105
109
|
}
|
|
106
110
|
}
|
|
107
111
|
]
|
package/modules/imRtdProvider.js
CHANGED
|
@@ -42,14 +42,6 @@ function setImDataInCookie(value) {
|
|
|
42
42
|
*/
|
|
43
43
|
export function getBidderFunction(bidderName) {
|
|
44
44
|
const biddersFunction = {
|
|
45
|
-
ix: function (bid, data) {
|
|
46
|
-
if (data.im_segments && data.im_segments.length) {
|
|
47
|
-
config.setConfig({
|
|
48
|
-
ix: {firstPartyData: {im_segments: data.im_segments}},
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
return bid
|
|
52
|
-
},
|
|
53
45
|
pubmatic: function (bid, data) {
|
|
54
46
|
if (data.im_segments && data.im_segments.length) {
|
|
55
47
|
const dctr = deepAccess(bid, 'params.dctr');
|
|
@@ -37,9 +37,13 @@ const createOpenRtbRequest = (validBidRequests, bidderRequest) => {
|
|
|
37
37
|
source: {tid: bidderRequest.auctionId}
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
+
// Get the url parameters
|
|
41
|
+
const queryString = window.location.search;
|
|
42
|
+
const urlParams = new URLSearchParams(queryString);
|
|
43
|
+
const checkPrebid = urlParams.get('_checkPrebid');
|
|
40
44
|
// Force impactify debugging parameter
|
|
41
|
-
if (
|
|
42
|
-
request.test = Number(
|
|
45
|
+
if (checkPrebid != null) {
|
|
46
|
+
request.test = Number(checkPrebid);
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
// Set Schain in request
|