@highfivve/ad-tag 5.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +149 -0
- package/lib/ads/a9.js +190 -0
- package/lib/ads/adPipeline.js +159 -0
- package/lib/ads/adService.js +251 -0
- package/lib/ads/adUnitPath.js +37 -0
- package/lib/ads/auctions/adRequestThrottling.js +22 -0
- package/lib/ads/auctions/biddersDisabling.js +90 -0
- package/lib/ads/auctions/frequencyCapping.js +189 -0
- package/lib/ads/auctions/interstitialContext.js +92 -0
- package/lib/ads/auctions/previousBidCpms.js +33 -0
- package/lib/ads/auctions/resume.js +3 -0
- package/lib/ads/bridge/bridge.js +62 -0
- package/lib/ads/consent.js +63 -0
- package/lib/ads/eventService.js +44 -0
- package/lib/ads/globalAuctionContext.js +98 -0
- package/lib/ads/googleAdManager.js +380 -0
- package/lib/ads/keyValues.js +1 -0
- package/lib/ads/labelConfigService.js +42 -0
- package/lib/ads/modules/ad-reload/adVisibilityService.js +158 -0
- package/lib/ads/modules/ad-reload/index.js +163 -0
- package/lib/ads/modules/ad-reload/userActivityService.js +70 -0
- package/lib/ads/modules/adex/adex-mapping.js +77 -0
- package/lib/ads/modules/adex/adexUtiq.js +15 -0
- package/lib/ads/modules/adex/index.js +142 -0
- package/lib/ads/modules/adex/sendAdvertisingId.js +20 -0
- package/lib/ads/modules/blocklist-url/index.js +118 -0
- package/lib/ads/modules/cleanup/index.js +93 -0
- package/lib/ads/modules/confiant/index.js +47 -0
- package/lib/ads/modules/emetriq/index.js +154 -0
- package/lib/ads/modules/emetriq/trackInApp.js +34 -0
- package/lib/ads/modules/emetriq/trackLoginEvent.js +59 -0
- package/lib/ads/modules/generic-skin/index.js +150 -0
- package/lib/ads/modules/identitylink/index.js +58 -0
- package/lib/ads/modules/interstitial/index.js +38 -0
- package/lib/ads/modules/interstitial/interstitialAd.js +111 -0
- package/lib/ads/modules/lazy-load/index.js +191 -0
- package/lib/ads/modules/lazy-load/selectInfiniteSlot.js +11 -0
- package/lib/ads/modules/prebid-first-party-data/index.js +115 -0
- package/lib/ads/modules/pubstack/index.js +59 -0
- package/lib/ads/modules/sticky-footer-ad/desktopFloorAd.js +63 -0
- package/lib/ads/modules/sticky-footer-ad/index.js +43 -0
- package/lib/ads/modules/sticky-footer-ad/mobileSticky.js +93 -0
- package/lib/ads/modules/sticky-footer-ad-v2/footerStickyAd.js +118 -0
- package/lib/ads/modules/sticky-footer-ad-v2/index.js +43 -0
- package/lib/ads/modules/sticky-header-ad/fadeOutCallback.js +25 -0
- package/lib/ads/modules/sticky-header-ad/index.js +103 -0
- package/lib/ads/modules/sticky-header-ad/renderResult.js +24 -0
- package/lib/ads/modules/utiq/index.js +79 -0
- package/lib/ads/modules/yield-optimization/dynamicFloorPrice.js +86 -0
- package/lib/ads/modules/yield-optimization/index.js +57 -0
- package/lib/ads/modules/yield-optimization/isYieldOptimizationConfigDynamic.js +6 -0
- package/lib/ads/modules/yield-optimization/yieldOptimizationService.js +169 -0
- package/lib/ads/modules/zeotap/index.js +111 -0
- package/lib/ads/moli.js +645 -0
- package/lib/ads/moliGlobal.js +11 -0
- package/lib/ads/prebid-outstream.js +13 -0
- package/lib/ads/prebid.js +406 -0
- package/lib/ads/sizeConfigService.js +49 -0
- package/lib/ads/spa.js +32 -0
- package/lib/bundle/adReload.js +2 -0
- package/lib/bundle/adex.js +2 -0
- package/lib/bundle/blocklistUrls.js +2 -0
- package/lib/bundle/cleanup.js +2 -0
- package/lib/bundle/confiant.js +2 -0
- package/lib/bundle/configureFromEndpoint.js +40 -0
- package/lib/bundle/emetriq.js +2 -0
- package/lib/bundle/identityLink.js +2 -0
- package/lib/bundle/init.js +2 -0
- package/lib/bundle/interstitialModule.js +2 -0
- package/lib/bundle/lazyLoad.js +2 -0
- package/lib/bundle/prebidFirstPartyData.js +2 -0
- package/lib/bundle/pubstack.js +2 -0
- package/lib/bundle/skin.js +2 -0
- package/lib/bundle/stickyFooterAd.js +2 -0
- package/lib/bundle/stickyFooterAds2.js +2 -0
- package/lib/bundle/stickyHeaderAd.js +2 -0
- package/lib/bundle/utiq.js +2 -0
- package/lib/bundle/yieldOptimization.js +2 -0
- package/lib/bundle/zeotap.js +2 -0
- package/lib/console/components/adSlotConfig.js +225 -0
- package/lib/console/components/consentConfig.js +138 -0
- package/lib/console/components/globalConfig.js +634 -0
- package/lib/console/components/labelConfigDebug.js +19 -0
- package/lib/console/components/sizeConfigDebug.js +34 -0
- package/lib/console/components/tag.js +4 -0
- package/lib/console/debug.js +38 -0
- package/lib/console/util/array.js +1 -0
- package/lib/console/util/calculateAdDensity.js +36 -0
- package/lib/console/util/debounce.js +12 -0
- package/lib/console/util/debugLogger.js +6 -0
- package/lib/console/util/extractPositionFromPath.js +8 -0
- package/lib/console/util/prebid.js +3 -0
- package/lib/console/util/stringUtils.js +23 -0
- package/lib/console/util/themingService.js +31 -0
- package/lib/console/util/windowResizeService.js +22 -0
- package/lib/console/validations/adReloadValidations.js +47 -0
- package/lib/console/validations/bucketValidations.js +78 -0
- package/lib/console/validations/sizesConfigValidations.js +97 -0
- package/lib/gen/packageJson.js +3 -0
- package/lib/index.js +3 -0
- package/lib/types/apstag.js +1 -0
- package/lib/types/dom.js +1 -0
- package/lib/types/emetriq.js +1 -0
- package/lib/types/googletag.js +1 -0
- package/lib/types/identitylink.js +1 -0
- package/lib/types/module.js +1 -0
- package/lib/types/moliConfig.js +1 -0
- package/lib/types/moliRuntime.js +1 -0
- package/lib/types/prebidjs.js +45 -0
- package/lib/types/supplyChainObject.js +1 -0
- package/lib/types/tcfapi.js +48 -0
- package/lib/util/addNewInfiniteSlotToConfig.js +11 -0
- package/lib/util/arrayUtils.js +9 -0
- package/lib/util/assetLoaderService.js +91 -0
- package/lib/util/browserStorageKeys.js +7 -0
- package/lib/util/debugDelay.js +12 -0
- package/lib/util/domready.js +15 -0
- package/lib/util/environmentOverride.js +16 -0
- package/lib/util/extractAdTagVersion.js +16 -0
- package/lib/util/extractTopPrivateDomainFromHostname.js +17 -0
- package/lib/util/localStorage.js +26 -0
- package/lib/util/logging.js +106 -0
- package/lib/util/objectUtils.js +29 -0
- package/lib/util/query.js +40 -0
- package/lib/util/queryParameters.js +5 -0
- package/lib/util/resolveOverrides.js +21 -0
- package/lib/util/resolveStoredRequestIdInOrtb2Object.js +12 -0
- package/lib/util/sizes.js +3 -0
- package/lib/util/test-slots.js +150 -0
- package/lib/util/uuid.js +10 -0
- package/package.json +127 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import domready from '../util/domready';
|
|
2
|
+
export var AssetLoadMethod;
|
|
3
|
+
(function (AssetLoadMethod) {
|
|
4
|
+
AssetLoadMethod[AssetLoadMethod["FETCH"] = 0] = "FETCH";
|
|
5
|
+
AssetLoadMethod[AssetLoadMethod["TAG"] = 1] = "TAG";
|
|
6
|
+
})(AssetLoadMethod || (AssetLoadMethod = {}));
|
|
7
|
+
export class AssetLoaderService {
|
|
8
|
+
constructor(window) {
|
|
9
|
+
this.window = window;
|
|
10
|
+
}
|
|
11
|
+
loadScript(config, parent = this.window.document.head) {
|
|
12
|
+
return this.awaitDomReady().then(() => {
|
|
13
|
+
switch (config.loadMethod) {
|
|
14
|
+
case AssetLoadMethod.FETCH:
|
|
15
|
+
return this.loadAssetViaFetch(config, parent);
|
|
16
|
+
case AssetLoadMethod.TAG:
|
|
17
|
+
return this.loadAssetViaTag(config, parent);
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
loadJson(name, assetUrl) {
|
|
22
|
+
return this.window
|
|
23
|
+
.fetch(assetUrl, {
|
|
24
|
+
method: 'GET',
|
|
25
|
+
mode: 'cors',
|
|
26
|
+
headers: {
|
|
27
|
+
'Content-Type': 'application/json'
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
.then(response => {
|
|
31
|
+
return response.ok
|
|
32
|
+
? response.json()
|
|
33
|
+
: response
|
|
34
|
+
.text()
|
|
35
|
+
.then(errorMessage => Promise.reject(`${response.statusText}: ${errorMessage}`));
|
|
36
|
+
})
|
|
37
|
+
.catch(error => {
|
|
38
|
+
return Promise.reject(error);
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
loadAssetViaFetch(config, parentElement) {
|
|
42
|
+
return this.window
|
|
43
|
+
.fetch(config.assetUrl)
|
|
44
|
+
.then((response) => response.ok ? Promise.resolve(response) : Promise.reject(response))
|
|
45
|
+
.then((response) => response.text())
|
|
46
|
+
.then((body) => this.scriptTagWithBody(body))
|
|
47
|
+
.then((element) => parentElement.appendChild(element));
|
|
48
|
+
}
|
|
49
|
+
scriptTagWithBody(body) {
|
|
50
|
+
const scriptTag = this.window.document.createElement('script');
|
|
51
|
+
scriptTag.type = 'text/javascript';
|
|
52
|
+
scriptTag.async = true;
|
|
53
|
+
scriptTag.text = body;
|
|
54
|
+
return scriptTag;
|
|
55
|
+
}
|
|
56
|
+
loadAssetViaTag(config, parentElement) {
|
|
57
|
+
const tag = this.scriptTag(config);
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
tag.onload = resolve;
|
|
60
|
+
tag.onerror = reject;
|
|
61
|
+
parentElement.appendChild(tag);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
scriptTag(config) {
|
|
65
|
+
const scriptTag = this.window.document.createElement('script');
|
|
66
|
+
if (config.type === 'module') {
|
|
67
|
+
scriptTag.type = 'module';
|
|
68
|
+
}
|
|
69
|
+
else if (config.type === 'nomodule') {
|
|
70
|
+
scriptTag.type = 'text/javascript';
|
|
71
|
+
scriptTag.setAttribute('nomodule', '');
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
if (config.assetUrl.endsWith('mjs')) {
|
|
75
|
+
scriptTag.type = 'module';
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
scriptTag.type = 'text/javascript';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
scriptTag.async = true;
|
|
82
|
+
scriptTag.src = config.assetUrl;
|
|
83
|
+
return scriptTag;
|
|
84
|
+
}
|
|
85
|
+
awaitDomReady() {
|
|
86
|
+
return new Promise((resolve) => {
|
|
87
|
+
domready(this.window, resolve);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export const createAssetLoaderService = (window) => new AssetLoaderService(window);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { BrowserStorageKeys } from './browserStorageKeys';
|
|
2
|
+
import { getBrowserStorageValue, removeBrowserStorageValue, setBrowserStorageValue } from './localStorage';
|
|
3
|
+
export const executeDebugDelay = (window, delay) => delay ? new Promise(resolve => window.setTimeout(resolve, delay)) : Promise.resolve();
|
|
4
|
+
export const getDebugDelayFromLocalStorage = (window) => Number(getBrowserStorageValue(BrowserStorageKeys.debugDelay, window.localStorage)) || undefined;
|
|
5
|
+
export const setDebugDelayToLocalStorage = (window, value) => {
|
|
6
|
+
if (value) {
|
|
7
|
+
setBrowserStorageValue(BrowserStorageKeys.debugDelay, value.toString(), window.localStorage);
|
|
8
|
+
}
|
|
9
|
+
else {
|
|
10
|
+
removeBrowserStorageValue(BrowserStorageKeys.debugDelay, window.localStorage);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export default (window, callback) => {
|
|
2
|
+
let callbacks = [], listener, doc = typeof window.document === 'object' && window.document, hack = doc && doc.documentElement.doScroll, domContentLoaded = 'DOMContentLoaded', loaded = doc && (hack ? /^loaded|^c/ : /^loaded|^i|^c/).test(doc.readyState);
|
|
3
|
+
if (!loaded && doc) {
|
|
4
|
+
doc.addEventListener(domContentLoaded, (listener = () => {
|
|
5
|
+
if (doc) {
|
|
6
|
+
doc.removeEventListener(domContentLoaded, listener);
|
|
7
|
+
loaded = true;
|
|
8
|
+
while ((listener = callbacks.shift())) {
|
|
9
|
+
listener();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
14
|
+
loaded ? setTimeout(callback, 0) : callbacks.push(callback);
|
|
15
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BrowserStorageKeys } from './browserStorageKeys';
|
|
2
|
+
import { removeBrowserStorageValue, setBrowserStorageValue } from './localStorage';
|
|
3
|
+
import { updateQueryString } from './query';
|
|
4
|
+
import { QueryParameters } from './queryParameters';
|
|
5
|
+
import { resolveOverrides } from './resolveOverrides';
|
|
6
|
+
const isEnvironmentString = (environment) => {
|
|
7
|
+
const validValues = ['production', 'test'];
|
|
8
|
+
return !!validValues.find(value => value === environment);
|
|
9
|
+
};
|
|
10
|
+
export const getActiveEnvironmentOverride = (window) => resolveOverrides(window, QueryParameters.moliEnv, BrowserStorageKeys.moliEnv, isEnvironmentString)[0] || undefined;
|
|
11
|
+
export const setEnvironmentOverrideInStorage = (value, storage) => setBrowserStorageValue(BrowserStorageKeys.moliEnv, value, storage);
|
|
12
|
+
export const resetEnvironmentOverrides = (window) => {
|
|
13
|
+
removeBrowserStorageValue(BrowserStorageKeys.moliEnv, window.sessionStorage);
|
|
14
|
+
removeBrowserStorageValue(BrowserStorageKeys.moliEnv, window.localStorage);
|
|
15
|
+
window.location.replace(updateQueryString(QueryParameters.moliEnv, undefined));
|
|
16
|
+
};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const extractAdTagVersion = ({ currentVersion }) => {
|
|
2
|
+
try {
|
|
3
|
+
switch (typeof currentVersion) {
|
|
4
|
+
case 'number':
|
|
5
|
+
return currentVersion.toFixed();
|
|
6
|
+
case 'string':
|
|
7
|
+
const num = Number(currentVersion);
|
|
8
|
+
return Number.isNaN(num) ? undefined : num.toFixed();
|
|
9
|
+
default:
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
catch (e) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export const extractTopPrivateDomainFromHostname = (hostname) => {
|
|
2
|
+
if (hostname) {
|
|
3
|
+
const [tld, sub1, sub2] = hostname.split('.').reverse();
|
|
4
|
+
switch (`${sub1}.${tld}`) {
|
|
5
|
+
case 'co.uk':
|
|
6
|
+
case 'com.br':
|
|
7
|
+
case 'com.mx':
|
|
8
|
+
case 'com.au':
|
|
9
|
+
return `${sub2}.${sub1}.${tld}`;
|
|
10
|
+
default:
|
|
11
|
+
return sub1 ? `${sub1}.${tld}` : tld;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { getDefaultLogger } from './logging';
|
|
2
|
+
export const getBrowserStorageValue = (key, storage = localStorage) => {
|
|
3
|
+
try {
|
|
4
|
+
return storage.getItem(key);
|
|
5
|
+
}
|
|
6
|
+
catch (e) {
|
|
7
|
+
getDefaultLogger().debug(`Could not read value with key ${key} from browser storage`, storage);
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
export const setBrowserStorageValue = (key, value, storage = localStorage) => {
|
|
12
|
+
try {
|
|
13
|
+
storage.setItem(key, value);
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
getDefaultLogger().debug(`Could not set key ${key} with value ${value} to browser storage`, storage);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
export const removeBrowserStorageValue = (key, storage = localStorage) => {
|
|
20
|
+
try {
|
|
21
|
+
storage.removeItem(key);
|
|
22
|
+
}
|
|
23
|
+
catch (e) {
|
|
24
|
+
getDefaultLogger().debug(`Could not remove key ${key} from browser storage`, storage);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { parseQueryString } from './query';
|
|
2
|
+
export function getMoliDebugParameter(window) {
|
|
3
|
+
try {
|
|
4
|
+
const key = 'moliDebug';
|
|
5
|
+
const params = parseQueryString(window.location.search);
|
|
6
|
+
return (!!params.get(key) ||
|
|
7
|
+
!!window.sessionStorage.getItem(key) ||
|
|
8
|
+
!!window.localStorage.getItem(key));
|
|
9
|
+
}
|
|
10
|
+
catch (_) {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function getNoopLogger() {
|
|
15
|
+
const noop = () => {
|
|
16
|
+
return;
|
|
17
|
+
};
|
|
18
|
+
return {
|
|
19
|
+
debug: noop,
|
|
20
|
+
info: noop,
|
|
21
|
+
warn: noop,
|
|
22
|
+
error: console.error
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function getLabelStyle(background) {
|
|
26
|
+
return `background:${background}; color:#FFF; padding:3px; margin:3px; border-radius:5px; line-height: 15px;`;
|
|
27
|
+
}
|
|
28
|
+
function getLogStageLabelStyle(logStage) {
|
|
29
|
+
switch (logStage) {
|
|
30
|
+
case 'debug':
|
|
31
|
+
return getLabelStyle('#49A0CC');
|
|
32
|
+
case 'info':
|
|
33
|
+
return getLabelStyle('#61A172');
|
|
34
|
+
case 'warn':
|
|
35
|
+
return getLabelStyle('#FFC300');
|
|
36
|
+
case 'error':
|
|
37
|
+
return getLabelStyle('#C70039');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function getSourceLabelStyle(source) {
|
|
41
|
+
switch (source) {
|
|
42
|
+
case 'AdPipeline':
|
|
43
|
+
return getLabelStyle('#74ABC6');
|
|
44
|
+
case 'GAM':
|
|
45
|
+
return getLabelStyle('#BA0E5F');
|
|
46
|
+
case 'MoliGlobal':
|
|
47
|
+
return getLabelStyle('#403073');
|
|
48
|
+
case 'Prebid':
|
|
49
|
+
return getLabelStyle('#4357AD');
|
|
50
|
+
case 'AdVisibilityService':
|
|
51
|
+
return getLabelStyle('#d5ba3c');
|
|
52
|
+
case 'UserActivityService':
|
|
53
|
+
return getLabelStyle('#19ad0e');
|
|
54
|
+
case 'Adex DMP':
|
|
55
|
+
return getLabelStyle('#003E74');
|
|
56
|
+
default:
|
|
57
|
+
return getLabelStyle('#052E53');
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
export function getDefaultLogger() {
|
|
61
|
+
return {
|
|
62
|
+
debug(source, message, ...optionalParams) {
|
|
63
|
+
console.debug(`%c[DEBUG]%c${source}%c${message}`, getLogStageLabelStyle('debug'), getSourceLabelStyle(source), '', ...optionalParams);
|
|
64
|
+
},
|
|
65
|
+
info(source, message, ...optionalParams) {
|
|
66
|
+
console.info(`%c[INFO]%c${source}%c${message}`, getLogStageLabelStyle('info'), getSourceLabelStyle(source), '', ...optionalParams);
|
|
67
|
+
},
|
|
68
|
+
warn(source, message, ...optionalParams) {
|
|
69
|
+
console.warn(`%c[WARN]%c${source}%c${message}`, getLogStageLabelStyle('warn'), getSourceLabelStyle(source), '', ...optionalParams);
|
|
70
|
+
},
|
|
71
|
+
error(source, message, ...optionalParams) {
|
|
72
|
+
console.error(`%c[ERROR]%c${source}%c${message}`, getLogStageLabelStyle('error'), getSourceLabelStyle(source), '', ...optionalParams);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export function getLogger(config, window) {
|
|
77
|
+
if (getMoliDebugParameter(window)) {
|
|
78
|
+
return getDefaultLogger();
|
|
79
|
+
}
|
|
80
|
+
else if (config && config.logger) {
|
|
81
|
+
return config.logger;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
return getNoopLogger();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export class ProxyLogger {
|
|
88
|
+
constructor(logger) {
|
|
89
|
+
this.logger = logger;
|
|
90
|
+
this.setLogger = (newLogger) => {
|
|
91
|
+
this.logger = newLogger;
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
debug(message, ...optionalParams) {
|
|
95
|
+
this.logger.debug(message, ...optionalParams);
|
|
96
|
+
}
|
|
97
|
+
error(message, ...optionalParams) {
|
|
98
|
+
this.logger.error(message, ...optionalParams);
|
|
99
|
+
}
|
|
100
|
+
info(message, ...optionalParams) {
|
|
101
|
+
this.logger.info(message, ...optionalParams);
|
|
102
|
+
}
|
|
103
|
+
warn(message, ...optionalParams) {
|
|
104
|
+
this.logger.warn(message, ...optionalParams);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const isPlainObject = (value) => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
2
|
+
export function mergeDeep(target, ...sources) {
|
|
3
|
+
if (!sources.length) {
|
|
4
|
+
return target;
|
|
5
|
+
}
|
|
6
|
+
const source = sources.shift();
|
|
7
|
+
if (isPlainObject(target) && isPlainObject(source)) {
|
|
8
|
+
for (const key in source) {
|
|
9
|
+
if (isPlainObject(source[key])) {
|
|
10
|
+
if (!target[key]) {
|
|
11
|
+
Object.assign(target, { [key]: {} });
|
|
12
|
+
}
|
|
13
|
+
mergeDeep(target[key], source[key]);
|
|
14
|
+
}
|
|
15
|
+
else if (Array.isArray(source[key])) {
|
|
16
|
+
if (!target[key]) {
|
|
17
|
+
Object.assign(target, { [key]: source[key] });
|
|
18
|
+
}
|
|
19
|
+
else if (Array.isArray(target[key])) {
|
|
20
|
+
target[key] = target[key].concat(source[key]);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
Object.assign(target, { [key]: source[key] });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return mergeDeep(target, ...sources);
|
|
29
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const parseQueryParameter = (parameter) => {
|
|
2
|
+
const valueStart = parameter.indexOf('=');
|
|
3
|
+
if (valueStart >= 0) {
|
|
4
|
+
const key = decodeURIComponent(parameter.slice(0, valueStart));
|
|
5
|
+
const value = decodeURIComponent(parameter.slice(valueStart + 1));
|
|
6
|
+
return [key, value];
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
return [decodeURIComponent(parameter), ''];
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
export const parseQueryString = (search) => {
|
|
13
|
+
try {
|
|
14
|
+
const query = search.startsWith('?') ? search.slice(1) : search;
|
|
15
|
+
if (query.length > 0) {
|
|
16
|
+
return new Map(query
|
|
17
|
+
.split('&')
|
|
18
|
+
.filter(s => s.length > 0)
|
|
19
|
+
.map(parseQueryParameter));
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
return new Map();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
catch (e) {
|
|
26
|
+
console.error(e);
|
|
27
|
+
return new Map();
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
export const updateQueryString = (key, value, baseUrl, search) => {
|
|
31
|
+
baseUrl = baseUrl || [location.protocol, '//', location.host, location.pathname].join('');
|
|
32
|
+
search = search || window.location.search;
|
|
33
|
+
const newSearch = Array.from(parseQueryString(search)
|
|
34
|
+
.set(key, value || '')
|
|
35
|
+
.entries())
|
|
36
|
+
.filter(v => v[1] !== '')
|
|
37
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
38
|
+
.join('&');
|
|
39
|
+
return [baseUrl, newSearch ? '?' : '', newSearch].join('');
|
|
40
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { parseQueryString } from './query';
|
|
2
|
+
import { getBrowserStorageValue } from './localStorage';
|
|
3
|
+
import { isNotNull } from './arrayUtils';
|
|
4
|
+
export const resolveOverrides = (window, queryParam, storageKey, predicate = (value) => true) => {
|
|
5
|
+
return [
|
|
6
|
+
{
|
|
7
|
+
source: 'queryParam',
|
|
8
|
+
value: parseQueryString(window.location.search).get(queryParam)
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
source: 'sessionStorage',
|
|
12
|
+
value: getBrowserStorageValue(storageKey, window.sessionStorage)
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
source: 'localStorage',
|
|
16
|
+
value: getBrowserStorageValue(storageKey, window.localStorage)
|
|
17
|
+
}
|
|
18
|
+
]
|
|
19
|
+
.map(({ source, value }) => (!!value && predicate(value) ? { source, value } : undefined))
|
|
20
|
+
.filter(isNotNull);
|
|
21
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export const resolveStoredRequestIdInOrtb2Object = (unresolvedOrtb2, storedRequestWithSolvedId) => {
|
|
2
|
+
return {
|
|
3
|
+
...unresolvedOrtb2,
|
|
4
|
+
ext: {
|
|
5
|
+
...unresolvedOrtb2.ext,
|
|
6
|
+
prebid: {
|
|
7
|
+
...unresolvedOrtb2.ext?.prebid,
|
|
8
|
+
storedrequest: storedRequestWithSolvedId
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
};
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import { SizeConfigService } from '../ads/sizeConfigService';
|
|
2
|
+
import { isNotNull } from './arrayUtils';
|
|
3
|
+
import { BrowserStorageKeys } from './browserStorageKeys';
|
|
4
|
+
import { getBrowserStorageValue, removeBrowserStorageValue, setBrowserStorageValue } from './localStorage';
|
|
5
|
+
const isTestSlotSize = (size) => size === 'hidden' ||
|
|
6
|
+
(Array.isArray(size) &&
|
|
7
|
+
size.length === 2 &&
|
|
8
|
+
typeof size[0] === 'number' &&
|
|
9
|
+
typeof size[1] === 'number');
|
|
10
|
+
const testSlotContainerId = (moliSlotDomId) => `${moliSlotDomId}__container`;
|
|
11
|
+
export const createTestSlots = (context, slots) => {
|
|
12
|
+
const testSlots = createBlankTestSlots(context, slots);
|
|
13
|
+
testSlots.forEach(({ slot, container }) => {
|
|
14
|
+
container.innerHTML = '';
|
|
15
|
+
container.appendChild(testSlotContent(slot));
|
|
16
|
+
});
|
|
17
|
+
return testSlots;
|
|
18
|
+
};
|
|
19
|
+
export const removeTestSlotSizeFromLocalStorage = (slot) => removeBrowserStorageValue(BrowserStorageKeys.testSlotSize(slot.domId));
|
|
20
|
+
const setContent = (adSlotId, content) => {
|
|
21
|
+
const slotToFill = document.getElementById(adSlotId);
|
|
22
|
+
if (slotToFill) {
|
|
23
|
+
slotToFill.innerHTML = content;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const createBlankTestSlots = (context, slots) => {
|
|
27
|
+
slots.forEach(slot => {
|
|
28
|
+
const { moliSlot } = slot;
|
|
29
|
+
const containerId = testSlotContainerId(moliSlot.domId);
|
|
30
|
+
const div = document.createElement('div');
|
|
31
|
+
div.id = containerId;
|
|
32
|
+
const adSlotContainer = document.getElementById(moliSlot.domId);
|
|
33
|
+
if (adSlotContainer) {
|
|
34
|
+
adSlotContainer.setAttribute('data-google-query-id', 'test');
|
|
35
|
+
}
|
|
36
|
+
setContent(moliSlot.domId, div.outerHTML);
|
|
37
|
+
context.logger__.debug('GAM', `Set content for slot: [DomID] ${moliSlot.domId} [AdUnitPath] ${moliSlot.adUnitPath}`);
|
|
38
|
+
});
|
|
39
|
+
return queryTestSlots(slots);
|
|
40
|
+
};
|
|
41
|
+
const queryTestSlots = (slots) => slots
|
|
42
|
+
.map(slot => {
|
|
43
|
+
const container = document.getElementById(testSlotContainerId(slot.moliSlot.domId));
|
|
44
|
+
return container ? { slot, container } : undefined;
|
|
45
|
+
})
|
|
46
|
+
.filter(isNotNull);
|
|
47
|
+
const testSlotContent = (slot) => {
|
|
48
|
+
const sizes = getSizesForSlot(slot);
|
|
49
|
+
const activeSize = pickTestSlotSize(slot.moliSlot, sizes);
|
|
50
|
+
if (activeSize === 'hidden') {
|
|
51
|
+
return document.createElement('div');
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
const content = document.createElement('div');
|
|
55
|
+
const [width, height] = activeSize;
|
|
56
|
+
content.style.cssText = `
|
|
57
|
+
position: relative; display: inline-flex; flex-direction: column; align-items: center; justify-content: center;
|
|
58
|
+
width: ${width}px; height: ${height}px; padding: 6px; border: 2px dotted gray; background-color: #fff;
|
|
59
|
+
background-image: linear-gradient(90deg, transparent 79px, #abced4 79px, #abced4 81px, transparent 81px), linear-gradient(#eee .1em, transparent .1em);
|
|
60
|
+
background-size: 100% 1.2em; box-sizing: border-box;
|
|
61
|
+
`;
|
|
62
|
+
const description = document.createElement('h4');
|
|
63
|
+
description.innerHTML = `<strong>${slot.moliSlot.domId}</strong>`;
|
|
64
|
+
content.appendChild(description);
|
|
65
|
+
const sizeDescription = document.createElement('span');
|
|
66
|
+
sizeDescription.style.color = '#656565';
|
|
67
|
+
const updateSizeDescription = ([width, height]) => (sizeDescription.innerText = `(${width}x${height})`);
|
|
68
|
+
updateSizeDescription([width, height]);
|
|
69
|
+
description.appendChild(sizeDescription);
|
|
70
|
+
const buttonContainer = document.createElement('div');
|
|
71
|
+
buttonContainer.style.cssText = `position: absolute; top: 5px; left: 5px`;
|
|
72
|
+
content.appendChild(buttonContainer);
|
|
73
|
+
const updateSize = (size, button) => {
|
|
74
|
+
if (size === 'hidden') {
|
|
75
|
+
content.style.display = 'none';
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
const [width, height] = size;
|
|
79
|
+
content.style.width = `${width}px`;
|
|
80
|
+
content.style.height = `${height}px`;
|
|
81
|
+
updateSizeDescription(size);
|
|
82
|
+
markButtonAsActive(button);
|
|
83
|
+
}
|
|
84
|
+
saveSizeInLocalStorage(slot.moliSlot, size);
|
|
85
|
+
};
|
|
86
|
+
const defaultButtonBorder = '1px dotted white';
|
|
87
|
+
const activeButtonBorder = '1px solid black';
|
|
88
|
+
const hideButton = document.createElement('button');
|
|
89
|
+
hideButton.innerText = 'hide';
|
|
90
|
+
hideButton.title =
|
|
91
|
+
'Once hidden, it can only be restored using the moli console (or by clearing local storage manually)';
|
|
92
|
+
hideButton.style.cssText = `font-size: 10px; background: #656565; color: white; width: auto important!; border: ${defaultButtonBorder};`;
|
|
93
|
+
hideButton.addEventListener('click', () => updateSize('hidden', hideButton));
|
|
94
|
+
const buttons = [
|
|
95
|
+
...sizes.map(buttonSize => {
|
|
96
|
+
const [width, height] = buttonSize;
|
|
97
|
+
const isActiveSize = equalsSize(activeSize, buttonSize);
|
|
98
|
+
const button = document.createElement('button');
|
|
99
|
+
button.innerText = `${width}x${height}`;
|
|
100
|
+
button.style.cssText = `font-size: 10px; background: #00a4a6; color: white; width: auto important!; border: ${isActiveSize ? activeButtonBorder : defaultButtonBorder};`;
|
|
101
|
+
button.addEventListener('click', () => updateSize(buttonSize, button));
|
|
102
|
+
return button;
|
|
103
|
+
}),
|
|
104
|
+
hideButton
|
|
105
|
+
];
|
|
106
|
+
buttons.forEach(button => buttonContainer.appendChild(button));
|
|
107
|
+
const markButtonAsActive = (button) => {
|
|
108
|
+
buttons.forEach(button => (button.style.border = defaultButtonBorder));
|
|
109
|
+
button.style.border = activeButtonBorder;
|
|
110
|
+
};
|
|
111
|
+
return content;
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
const getSizesForSlot = (slot) => {
|
|
115
|
+
return slot
|
|
116
|
+
.filterSupportedSizes(slot.moliSlot.sizes)
|
|
117
|
+
.filter(SizeConfigService.isFixedSize)
|
|
118
|
+
.filter(([width, height]) => width > 1 && height > 1);
|
|
119
|
+
};
|
|
120
|
+
const pickTestSlotSize = (slot, sizes) => {
|
|
121
|
+
const sizeFromLocalStorage = getSizeFromLocalStorage(slot);
|
|
122
|
+
if (sizeFromLocalStorage &&
|
|
123
|
+
(sizeFromLocalStorage === 'hidden' || includesSize(sizes, sizeFromLocalStorage))) {
|
|
124
|
+
return sizeFromLocalStorage;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
const randomIndex = Math.floor(Math.random() * sizes.length);
|
|
128
|
+
return sizes.length === 0 ? [300, 250] : sizes[randomIndex];
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
const saveSizeInLocalStorage = (slot, size) => setBrowserStorageValue(BrowserStorageKeys.testSlotSize(slot.domId), JSON.stringify(size));
|
|
132
|
+
const getSizeFromLocalStorage = (slot) => {
|
|
133
|
+
const localStorageValue = getBrowserStorageValue(BrowserStorageKeys.testSlotSize(slot.domId));
|
|
134
|
+
if (!localStorageValue) {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
try {
|
|
138
|
+
const size = JSON.parse(localStorageValue);
|
|
139
|
+
return isTestSlotSize(size) ? size : undefined;
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
const equalsSize = (a, b) => {
|
|
146
|
+
const [widthA, heightA] = a;
|
|
147
|
+
const [widthB, heightB] = b;
|
|
148
|
+
return widthA === widthB && heightA === heightB;
|
|
149
|
+
};
|
|
150
|
+
const includesSize = (validSizes, size) => validSizes.some(validSize => equalsSize(validSize, size));
|
package/lib/util/uuid.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const uuidV4 = (window) => {
|
|
2
|
+
if (typeof window.crypto?.randomUUID === 'function') {
|
|
3
|
+
return window.crypto.randomUUID();
|
|
4
|
+
}
|
|
5
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
|
6
|
+
const r = (Math.random() * 16) | 0;
|
|
7
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
8
|
+
return v.toString(16);
|
|
9
|
+
});
|
|
10
|
+
};
|