@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.
Files changed (132) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +149 -0
  3. package/lib/ads/a9.js +190 -0
  4. package/lib/ads/adPipeline.js +159 -0
  5. package/lib/ads/adService.js +251 -0
  6. package/lib/ads/adUnitPath.js +37 -0
  7. package/lib/ads/auctions/adRequestThrottling.js +22 -0
  8. package/lib/ads/auctions/biddersDisabling.js +90 -0
  9. package/lib/ads/auctions/frequencyCapping.js +189 -0
  10. package/lib/ads/auctions/interstitialContext.js +92 -0
  11. package/lib/ads/auctions/previousBidCpms.js +33 -0
  12. package/lib/ads/auctions/resume.js +3 -0
  13. package/lib/ads/bridge/bridge.js +62 -0
  14. package/lib/ads/consent.js +63 -0
  15. package/lib/ads/eventService.js +44 -0
  16. package/lib/ads/globalAuctionContext.js +98 -0
  17. package/lib/ads/googleAdManager.js +380 -0
  18. package/lib/ads/keyValues.js +1 -0
  19. package/lib/ads/labelConfigService.js +42 -0
  20. package/lib/ads/modules/ad-reload/adVisibilityService.js +158 -0
  21. package/lib/ads/modules/ad-reload/index.js +163 -0
  22. package/lib/ads/modules/ad-reload/userActivityService.js +70 -0
  23. package/lib/ads/modules/adex/adex-mapping.js +77 -0
  24. package/lib/ads/modules/adex/adexUtiq.js +15 -0
  25. package/lib/ads/modules/adex/index.js +142 -0
  26. package/lib/ads/modules/adex/sendAdvertisingId.js +20 -0
  27. package/lib/ads/modules/blocklist-url/index.js +118 -0
  28. package/lib/ads/modules/cleanup/index.js +93 -0
  29. package/lib/ads/modules/confiant/index.js +47 -0
  30. package/lib/ads/modules/emetriq/index.js +154 -0
  31. package/lib/ads/modules/emetriq/trackInApp.js +34 -0
  32. package/lib/ads/modules/emetriq/trackLoginEvent.js +59 -0
  33. package/lib/ads/modules/generic-skin/index.js +150 -0
  34. package/lib/ads/modules/identitylink/index.js +58 -0
  35. package/lib/ads/modules/interstitial/index.js +38 -0
  36. package/lib/ads/modules/interstitial/interstitialAd.js +111 -0
  37. package/lib/ads/modules/lazy-load/index.js +191 -0
  38. package/lib/ads/modules/lazy-load/selectInfiniteSlot.js +11 -0
  39. package/lib/ads/modules/prebid-first-party-data/index.js +115 -0
  40. package/lib/ads/modules/pubstack/index.js +59 -0
  41. package/lib/ads/modules/sticky-footer-ad/desktopFloorAd.js +63 -0
  42. package/lib/ads/modules/sticky-footer-ad/index.js +43 -0
  43. package/lib/ads/modules/sticky-footer-ad/mobileSticky.js +93 -0
  44. package/lib/ads/modules/sticky-footer-ad-v2/footerStickyAd.js +118 -0
  45. package/lib/ads/modules/sticky-footer-ad-v2/index.js +43 -0
  46. package/lib/ads/modules/sticky-header-ad/fadeOutCallback.js +25 -0
  47. package/lib/ads/modules/sticky-header-ad/index.js +103 -0
  48. package/lib/ads/modules/sticky-header-ad/renderResult.js +24 -0
  49. package/lib/ads/modules/utiq/index.js +79 -0
  50. package/lib/ads/modules/yield-optimization/dynamicFloorPrice.js +86 -0
  51. package/lib/ads/modules/yield-optimization/index.js +57 -0
  52. package/lib/ads/modules/yield-optimization/isYieldOptimizationConfigDynamic.js +6 -0
  53. package/lib/ads/modules/yield-optimization/yieldOptimizationService.js +169 -0
  54. package/lib/ads/modules/zeotap/index.js +111 -0
  55. package/lib/ads/moli.js +645 -0
  56. package/lib/ads/moliGlobal.js +11 -0
  57. package/lib/ads/prebid-outstream.js +13 -0
  58. package/lib/ads/prebid.js +406 -0
  59. package/lib/ads/sizeConfigService.js +49 -0
  60. package/lib/ads/spa.js +32 -0
  61. package/lib/bundle/adReload.js +2 -0
  62. package/lib/bundle/adex.js +2 -0
  63. package/lib/bundle/blocklistUrls.js +2 -0
  64. package/lib/bundle/cleanup.js +2 -0
  65. package/lib/bundle/confiant.js +2 -0
  66. package/lib/bundle/configureFromEndpoint.js +40 -0
  67. package/lib/bundle/emetriq.js +2 -0
  68. package/lib/bundle/identityLink.js +2 -0
  69. package/lib/bundle/init.js +2 -0
  70. package/lib/bundle/interstitialModule.js +2 -0
  71. package/lib/bundle/lazyLoad.js +2 -0
  72. package/lib/bundle/prebidFirstPartyData.js +2 -0
  73. package/lib/bundle/pubstack.js +2 -0
  74. package/lib/bundle/skin.js +2 -0
  75. package/lib/bundle/stickyFooterAd.js +2 -0
  76. package/lib/bundle/stickyFooterAds2.js +2 -0
  77. package/lib/bundle/stickyHeaderAd.js +2 -0
  78. package/lib/bundle/utiq.js +2 -0
  79. package/lib/bundle/yieldOptimization.js +2 -0
  80. package/lib/bundle/zeotap.js +2 -0
  81. package/lib/console/components/adSlotConfig.js +225 -0
  82. package/lib/console/components/consentConfig.js +138 -0
  83. package/lib/console/components/globalConfig.js +634 -0
  84. package/lib/console/components/labelConfigDebug.js +19 -0
  85. package/lib/console/components/sizeConfigDebug.js +34 -0
  86. package/lib/console/components/tag.js +4 -0
  87. package/lib/console/debug.js +38 -0
  88. package/lib/console/util/array.js +1 -0
  89. package/lib/console/util/calculateAdDensity.js +36 -0
  90. package/lib/console/util/debounce.js +12 -0
  91. package/lib/console/util/debugLogger.js +6 -0
  92. package/lib/console/util/extractPositionFromPath.js +8 -0
  93. package/lib/console/util/prebid.js +3 -0
  94. package/lib/console/util/stringUtils.js +23 -0
  95. package/lib/console/util/themingService.js +31 -0
  96. package/lib/console/util/windowResizeService.js +22 -0
  97. package/lib/console/validations/adReloadValidations.js +47 -0
  98. package/lib/console/validations/bucketValidations.js +78 -0
  99. package/lib/console/validations/sizesConfigValidations.js +97 -0
  100. package/lib/gen/packageJson.js +3 -0
  101. package/lib/index.js +3 -0
  102. package/lib/types/apstag.js +1 -0
  103. package/lib/types/dom.js +1 -0
  104. package/lib/types/emetriq.js +1 -0
  105. package/lib/types/googletag.js +1 -0
  106. package/lib/types/identitylink.js +1 -0
  107. package/lib/types/module.js +1 -0
  108. package/lib/types/moliConfig.js +1 -0
  109. package/lib/types/moliRuntime.js +1 -0
  110. package/lib/types/prebidjs.js +45 -0
  111. package/lib/types/supplyChainObject.js +1 -0
  112. package/lib/types/tcfapi.js +48 -0
  113. package/lib/util/addNewInfiniteSlotToConfig.js +11 -0
  114. package/lib/util/arrayUtils.js +9 -0
  115. package/lib/util/assetLoaderService.js +91 -0
  116. package/lib/util/browserStorageKeys.js +7 -0
  117. package/lib/util/debugDelay.js +12 -0
  118. package/lib/util/domready.js +15 -0
  119. package/lib/util/environmentOverride.js +16 -0
  120. package/lib/util/extractAdTagVersion.js +16 -0
  121. package/lib/util/extractTopPrivateDomainFromHostname.js +17 -0
  122. package/lib/util/localStorage.js +26 -0
  123. package/lib/util/logging.js +106 -0
  124. package/lib/util/objectUtils.js +29 -0
  125. package/lib/util/query.js +40 -0
  126. package/lib/util/queryParameters.js +5 -0
  127. package/lib/util/resolveOverrides.js +21 -0
  128. package/lib/util/resolveStoredRequestIdInOrtb2Object.js +12 -0
  129. package/lib/util/sizes.js +3 -0
  130. package/lib/util/test-slots.js +150 -0
  131. package/lib/util/uuid.js +10 -0
  132. package/package.json +127 -0
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { Tag } from './tag';
3
+ import { classList } from '../util/stringUtils';
4
+ export const LabelConfigDebug = ({ labelSizeConfig }) => {
5
+ return (React.createElement("div", null, labelSizeConfig.map((labelSizeConfigEntry, idx) => {
6
+ const mediaQueryMatches = window.matchMedia(labelSizeConfigEntry.mediaQuery).matches;
7
+ return (React.createElement("div", { key: idx, className: "MoliDebug-sidebarSection MoliDebug-sidebarSection--noBorder" },
8
+ "Entry ",
9
+ React.createElement("strong", null,
10
+ "#",
11
+ idx + 1),
12
+ React.createElement("div", { className: "MoliDebug-tagContainer" },
13
+ React.createElement("span", { className: "MoliDebug-tagLabel" }, "Media query"),
14
+ React.createElement("div", { className: classList('MoliDebug-tag', [mediaQueryMatches, 'MoliDebug-tag--green'], [!mediaQueryMatches, 'MoliDebug-tag--red']), title: `Media query ${mediaQueryMatches ? 'matches' : "doesn't match"}` }, labelSizeConfigEntry.mediaQuery)),
15
+ React.createElement("div", { className: "MoliDebug-tagContainer" },
16
+ React.createElement("span", { className: "MoliDebug-tagLabel" }, "Supported labels"),
17
+ labelSizeConfigEntry.labelsSupported.map(label => (React.createElement(Tag, { key: label }, label))))));
18
+ })));
19
+ };
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import { Tag } from './tag';
3
+ import { classList } from '../util/stringUtils';
4
+ export const SizeConfigDebug = ({ sizeConfig, supportedLabels }) => {
5
+ return (React.createElement("div", null, sizeConfig.map((sizeConfigEntry, idx) => {
6
+ const mediaQueryMatches = window.matchMedia(sizeConfigEntry.mediaQuery).matches;
7
+ return (React.createElement("div", { key: idx, className: "MoliDebug-sidebarSection MoliDebug-sidebarSection--noBorder" },
8
+ "Entry ",
9
+ React.createElement("strong", null,
10
+ "#",
11
+ idx + 1),
12
+ React.createElement("div", { className: "MoliDebug-tagContainer" },
13
+ React.createElement("span", { className: "MoliDebug-tagLabel" }, "Media query"),
14
+ React.createElement("div", { className: classList('MoliDebug-tag', [mediaQueryMatches, 'MoliDebug-tag--green'], [!mediaQueryMatches, 'MoliDebug-tag--red']), title: `Media query ${mediaQueryMatches ? 'matches' : "doesn't match"}` }, sizeConfigEntry.mediaQuery)),
15
+ sizeConfigEntry.labelAll && (React.createElement("div", { className: "MoliDebug-tagContainer" },
16
+ React.createElement("span", { className: "MoliDebug-tagLabel" }, "Label All"),
17
+ sizeConfigEntry.labelAll.map(label => {
18
+ const labelMatches = supportedLabels.includes(label);
19
+ return (React.createElement("div", { key: label, className: classList('MoliDebug-tag', [labelMatches, 'MoliDebug-tag--green'], [!labelMatches, 'MoliDebug-tag--red']), title: `Labels ${labelMatches ? 'match' : "don't match"}` }, label));
20
+ }))),
21
+ sizeConfigEntry.labelNone && (React.createElement("div", { className: "MoliDebug-tagContainer" },
22
+ React.createElement("span", { className: "MoliDebug-tagLabel" }, "Label None"),
23
+ sizeConfigEntry.labelNone.map(label => {
24
+ const labelMatches = supportedLabels.includes(label);
25
+ return (React.createElement("div", { key: label, className: classList('MoliDebug-tag', [!labelMatches, 'MoliDebug-tag--green'], [labelMatches, 'MoliDebug-tag--red']), title: `Labels ${labelMatches ? 'match' : "don't match"}` }, label));
26
+ }))),
27
+ React.createElement("div", { className: "MoliDebug-tagContainer" },
28
+ React.createElement("span", { className: "MoliDebug-tagLabel" }, "Supported slot sizes"),
29
+ sizeConfigEntry.sizesSupported.map((slotSize) => {
30
+ const sizeString = slotSize === 'fluid' ? slotSize : `${slotSize[0]}x${slotSize[1]}`;
31
+ return React.createElement(Tag, { key: sizeString }, sizeString);
32
+ }))));
33
+ })));
34
+ };
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ import { classList } from '../util/stringUtils';
3
+ export const Tag = ({ children, variant, title, spacing }) => (React.createElement("div", { className: classList('MoliDebug-tag', [!!variant, `MoliDebug-tag--${variant}`], [!!spacing, `MoliDebug-tag--${spacing}Spacing`]), title: title }, children));
4
+ export const TagLabel = ({ children }) => (React.createElement("span", { className: "MoliDebug-tagLabel" }, children));
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ import { createRoot } from 'react-dom/client';
3
+ import { GlobalConfig } from './components/globalConfig';
4
+ import { AdSlotConfig } from './components/adSlotConfig';
5
+ import './debug.pcss';
6
+ import { ThemingService } from './util/themingService';
7
+ import { WindowResizeService } from './util/windowResizeService';
8
+ import { createLabelConfigService } from '../ads/labelConfigService';
9
+ const moliConfig = window.moli.getConfig();
10
+ if (moliConfig) {
11
+ const extraLabels = (moliConfig.targeting && moliConfig.targeting.labels) ?? [];
12
+ extraLabels.push(...window.moli.getRuntimeConfig().labels);
13
+ const labelConfigService = createLabelConfigService(moliConfig.labelSizeConfig || [], extraLabels, window);
14
+ const themingService = new ThemingService();
15
+ let container = document.createElement('div');
16
+ container.classList.add('moli-console-container');
17
+ const shadowRoot = container.attachShadow({ mode: 'open' });
18
+ const globalConfigComponent = (React.createElement(GlobalConfig, { config: moliConfig, runtimeConfig: window.moli.getRuntimeConfig(), modules: window.moli.getConfig()?.modules || {}, labelConfigService: labelConfigService, windowResizeService: new WindowResizeService(), themingService: themingService }));
19
+ window.document.body.append(container);
20
+ const root = createRoot(shadowRoot);
21
+ root.render(globalConfigComponent);
22
+ setTimeout(() => {
23
+ const globalConfigComponentRoot = shadowRoot.getElementById('moli-console-global-config');
24
+ themingService.setRootElement(globalConfigComponentRoot);
25
+ themingService.applyTheme();
26
+ themingService.enableSystemThemeListener();
27
+ }, 200);
28
+ moliConfig.slots.forEach(slot => {
29
+ const slotDomElement = document.getElementById(slot.domId);
30
+ if (slotDomElement && labelConfigService.filterSlot(slot)) {
31
+ const slotConfigRoot = createRoot(slotDomElement);
32
+ slotConfigRoot.render(React.createElement(AdSlotConfig, { labelConfigService: labelConfigService, slot: slot, parentElement: slotDomElement }));
33
+ }
34
+ });
35
+ }
36
+ else {
37
+ window.alert('No moli config found. The console cannot be displayed');
38
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,36 @@
1
+ export function calculateAdDensity(contentSelector, adSelectorOverride) {
2
+ const adSelector = adSelectorOverride ?? 'div[id^="google_ads_iframe_"]';
3
+ const contentNode = document.querySelector(contentSelector);
4
+ if (!contentNode) {
5
+ console.warn('Content node not found');
6
+ return { totalAdDensity: 0, totalAdArea: 0, adAreaPerSlot: [] };
7
+ }
8
+ const adNodes = Array.from(document.querySelectorAll(adSelector));
9
+ if (adNodes.length === 0) {
10
+ return { totalAdDensity: 0, totalAdArea: 0, adAreaPerSlot: [] };
11
+ }
12
+ let logMessages = [];
13
+ const adAreaPerSlot = [];
14
+ let totalAdArea = 0;
15
+ adNodes.forEach(ad => {
16
+ const rect = ad.getBoundingClientRect();
17
+ const width = Math.max(0, rect.width);
18
+ const height = Math.max(0, rect.height);
19
+ const area = width * height;
20
+ totalAdArea += area;
21
+ if (area > 0) {
22
+ adAreaPerSlot.push({ adSlot: ad.id, adArea: area });
23
+ logMessages.push(`Ad #${ad.id}: width=${width}px, height=${height}px, area=${area}px²`);
24
+ }
25
+ });
26
+ const contentRect = contentNode.getBoundingClientRect();
27
+ const pageArea = Math.max(0, contentRect.width) * Math.max(0, contentRect.height);
28
+ if (pageArea === 0) {
29
+ console.warn('Content area is zero');
30
+ return { totalAdDensity: 0, totalAdArea: 0, adAreaPerSlot: [] };
31
+ }
32
+ const totalAdDensity = (totalAdArea / pageArea) * 100;
33
+ logMessages.push(`Total ad area: ${totalAdArea}px², Page area: ${pageArea}px², Ad density: ${totalAdDensity.toFixed(2)}%`);
34
+ console.log(logMessages.join('\n'));
35
+ return { totalAdDensity, totalAdArea, adAreaPerSlot };
36
+ }
@@ -0,0 +1,12 @@
1
+ export const debounce = (callback, wait) => {
2
+ let timeout;
3
+ return function (...args) {
4
+ if (timeout) {
5
+ window.clearTimeout(timeout);
6
+ }
7
+ timeout = window.setTimeout(function () {
8
+ timeout = undefined;
9
+ callback(...args);
10
+ }, wait);
11
+ };
12
+ };
@@ -0,0 +1,6 @@
1
+ export const debugLogger = {
2
+ debug: console.debug,
3
+ info: console.info,
4
+ warn: console.warn,
5
+ error: console.error
6
+ };
@@ -0,0 +1,8 @@
1
+ export const extractPositionFromPath = (adPath) => {
2
+ if (!adPath) {
3
+ return undefined;
4
+ }
5
+ return adPath
6
+ .replace(/^google_ads_iframe_\//, '')
7
+ .replace(/_\d+__container__$/, '');
8
+ };
@@ -0,0 +1,3 @@
1
+ export const extractPrebidAdSlotConfigs = (prebid) => {
2
+ return Array.isArray(prebid) ? prebid : [prebid];
3
+ };
@@ -0,0 +1,23 @@
1
+ export function classList(...classNames) {
2
+ let result = '';
3
+ for (const i in classNames) {
4
+ if (!classNames.hasOwnProperty(i)) {
5
+ continue;
6
+ }
7
+ const className = classNames[i];
8
+ if (typeof className === 'string') {
9
+ result += `${className} `;
10
+ }
11
+ else {
12
+ if (className[0]) {
13
+ result += `${className[1]} `;
14
+ }
15
+ }
16
+ }
17
+ return result.trim();
18
+ }
19
+ export function firstUpper(target) {
20
+ return target && target.length > 0
21
+ ? target[0].toUpperCase() + target.slice(1, target.length)
22
+ : '';
23
+ }
@@ -0,0 +1,31 @@
1
+ export const allThemes = ['light', 'dark'];
2
+ export class ThemingService {
3
+ constructor(rootElement) {
4
+ this.rootElement = rootElement;
5
+ this.setRootElement = (rootElement) => {
6
+ this.rootElement = rootElement;
7
+ };
8
+ this.currentTheme = () => (this.rootElement?.classList.contains('dark') ? 'dark' : 'light');
9
+ this.applyTheme = (themeConfig = 'system') => {
10
+ const theme = themeConfig === 'system' ? ThemingService.currentSystemTheme() : themeConfig;
11
+ this.updateThemeCssClass(theme);
12
+ };
13
+ this.enableSystemThemeListener = () => window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => {
14
+ if (e.matches) {
15
+ this.applyTheme('dark');
16
+ }
17
+ else {
18
+ this.applyTheme('light');
19
+ }
20
+ });
21
+ this.updateThemeCssClass = (theme) => {
22
+ if (theme !== 'light') {
23
+ this.rootElement?.classList.add(theme);
24
+ }
25
+ else {
26
+ this.rootElement?.classList.remove('dark');
27
+ }
28
+ };
29
+ }
30
+ }
31
+ ThemingService.currentSystemTheme = () => window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
@@ -0,0 +1,22 @@
1
+ import { debounce } from './debounce';
2
+ const RESIZE_LISTENER_INTERVAL = 200;
3
+ export class WindowResizeService {
4
+ constructor() {
5
+ this.resizeListeners = new Set();
6
+ window.addEventListener('resize', debounce(this.emitEvent(), RESIZE_LISTENER_INTERVAL));
7
+ }
8
+ register(observer) {
9
+ this.resizeListeners.add(observer);
10
+ }
11
+ unregister(observer) {
12
+ this.resizeListeners.delete(observer);
13
+ }
14
+ emitEvent() {
15
+ return (event) => {
16
+ this.resizeListeners.forEach(observer => {
17
+ observer.listener(event);
18
+ });
19
+ };
20
+ }
21
+ }
22
+ export default new WindowResizeService();
@@ -0,0 +1,47 @@
1
+ import { extractPrebidAdSlotConfigs } from '../util/prebid';
2
+ import { prebidjs } from '../../types/prebidjs';
3
+ import { isNotNull } from '../../util/arrayUtils';
4
+ const isWallpaperSlot = (slot, prebidConfigs) => {
5
+ const isFloorAd = slot.adUnitPath.includes('floor');
6
+ const hasWallpaperInAdUnitPath = slot.adUnitPath.includes('wallpaper');
7
+ const wallpaperSizes = new Set(['1x1', '1x2']);
8
+ const hasOnlyWallpaperSizes = slot.sizes
9
+ .map(size => (size === 'fluid' ? null : size.join('x')))
10
+ .filter(isNotNull)
11
+ .every(size => wallpaperSizes.has(size));
12
+ const skinBidder = new Set([
13
+ prebidjs.GumGum,
14
+ prebidjs.DSPX,
15
+ prebidjs.Visx,
16
+ prebidjs.ImproveDigital
17
+ ]);
18
+ const hasOnlySkinBidders = prebidConfigs.every(prebidConfig => prebidConfig.adUnit.bids.length > 0 &&
19
+ prebidConfig.adUnit.bids.every(bid => skinBidder.has(bid.bidder ?? bid.module)));
20
+ return hasWallpaperInAdUnitPath || hasOnlySkinBidders || (hasOnlyWallpaperSizes && !isFloorAd);
21
+ };
22
+ export const checkAdReloadConfig = (messages, modules, slots, labels) => {
23
+ const adReloadConfig = modules?.adReload;
24
+ if (!adReloadConfig) {
25
+ return;
26
+ }
27
+ slots.forEach(slot => {
28
+ if (!slot.prebid) {
29
+ return;
30
+ }
31
+ const prebidConfigs = extractPrebidAdSlotConfigs(slot.prebid);
32
+ if (isWallpaperSlot(slot, prebidConfigs) &&
33
+ !adReloadConfig.excludeAdSlotDomIds.includes(slot.domId)) {
34
+ messages.push({
35
+ kind: 'error',
36
+ text: `Slot ${slot.domId} is a wallpaper ad unit and must be excluded from the ad reload`
37
+ });
38
+ }
39
+ const isOutstreamSlot = prebidConfigs.some(prebid => prebid.adUnit.mediaTypes.video);
40
+ if (isOutstreamSlot && !adReloadConfig.excludeAdSlotDomIds.includes(slot.domId)) {
41
+ messages.push({
42
+ kind: 'error',
43
+ text: `Slot ${slot.domId} is an outstream ad unit and must be excluded from the ad reload`
44
+ });
45
+ }
46
+ });
47
+ };
@@ -0,0 +1,78 @@
1
+ import React from 'react';
2
+ import { isNotNull } from '../../util/arrayUtils';
3
+ export const checkBucketConfig = (messages, bucket, slots) => {
4
+ const hasBucket = slots.some(slot => !!slot.behaviour.bucket);
5
+ const slotsWithoutBucket = slots.filter(slot => !slot.behaviour.bucket);
6
+ if (!hasBucket && bucket.enabled) {
7
+ messages.push({
8
+ kind: 'error',
9
+ text: 'Buckets are enabled in the config, but there are no ad units that have a bucket defined!'
10
+ });
11
+ }
12
+ if (slotsWithoutBucket) {
13
+ messages.push({
14
+ kind: 'warning',
15
+ text: formatMissingBucketsMsg(slotsWithoutBucket)
16
+ });
17
+ }
18
+ if (hasBucket && !bucket.enabled) {
19
+ messages.push({
20
+ kind: 'error',
21
+ text: 'Buckets are configured for ad slots, but buckets are disabled in the config!'
22
+ });
23
+ }
24
+ else if (!bucket.enabled) {
25
+ messages.push({
26
+ kind: 'optimization',
27
+ text: 'Buckets are disabled!'
28
+ });
29
+ }
30
+ };
31
+ export const checkSkinConfig = (messages, modules, slots) => {
32
+ const skinModuleConfig = modules?.skin;
33
+ if (skinModuleConfig) {
34
+ skinModuleConfig.configs.forEach(conf => {
35
+ const skinAdSlotDomId = conf.skinAdSlotDomId;
36
+ const blockedAdSlotDomIds = conf.blockedAdSlotDomIds;
37
+ const bucketName = (bucket) => {
38
+ return typeof bucket === 'string' ? bucket : bucket?.desktop;
39
+ };
40
+ const skinAdSlotBucket = slots.find(slot => slot.domId === skinAdSlotDomId)?.behaviour.bucket;
41
+ const blockedAdBuckets = blockedAdSlotDomIds
42
+ .map(slotId => slots.find(slot => slot.domId === slotId)?.behaviour.bucket)
43
+ .map(bucketName)
44
+ .filter(isNotNull);
45
+ if (skinAdSlotBucket) {
46
+ const areAllInTheSameBucket = new Set([...blockedAdBuckets, skinAdSlotBucket]).size === 1;
47
+ if (!areAllInTheSameBucket) {
48
+ messages.push({
49
+ kind: 'error',
50
+ text: formatSkinConfigMsg({
51
+ id: skinAdSlotDomId,
52
+ bucket: bucketName(skinAdSlotBucket) ?? 'default'
53
+ }, blockedAdSlotDomIds, blockedAdBuckets)
54
+ });
55
+ }
56
+ }
57
+ });
58
+ }
59
+ };
60
+ const formatSkinConfigMsg = (skinAdSlot, blockedAdSlotsIds, blockedAdSlotsBuckets) => {
61
+ return (React.createElement("div", null,
62
+ "The SkinAdSlot ",
63
+ React.createElement("strong", null, skinAdSlot.id),
64
+ " in the bucket",
65
+ ' ',
66
+ React.createElement("strong", null, skinAdSlot.bucket),
67
+ " is not in the same bucket with the BlockedAdSlots:",
68
+ React.createElement("ul", null, blockedAdSlotsIds.map((id, index) => {
69
+ return React.createElement("li", { key: index }, `${id}: ${blockedAdSlotsBuckets[index]}`);
70
+ }))));
71
+ };
72
+ const formatMissingBucketsMsg = (slots) => {
73
+ return (React.createElement("div", null,
74
+ `The following slots might require defined buckets:`,
75
+ React.createElement("ul", null, slots.map((slot, index) => {
76
+ return React.createElement("li", { key: index }, slot.domId);
77
+ }))));
78
+ };
@@ -0,0 +1,97 @@
1
+ import React from 'react';
2
+ import { extractPrebidAdSlotConfigs } from '../util/prebid';
3
+ import { flatten } from '../../util/arrayUtils';
4
+ export const checkSizesConfig = (messages, slots, labels) => {
5
+ const missingSizesInSlots = [];
6
+ slots.map(slot => {
7
+ const supportedSizesAsString = flatten(slot.sizeConfig.map(sizeConfigEntry => sizeConfigEntry.sizesSupported.map(dfpSlotSize => dfpSlotSize === 'fluid' ? dfpSlotSize : dfpSlotSize.join('x'))));
8
+ const supportedSizesSet = new Set(supportedSizesAsString);
9
+ const sizesInSlot = slot.sizes.map(size => (size === 'fluid' ? size : size.join('x')));
10
+ const sizesInSlotSet = new Set(sizesInSlot);
11
+ const unsupportedSizes = sizesInSlot.filter(size => !supportedSizesSet.has(size));
12
+ missingSizesInSlots.push({ slotId: slot.domId, unsupportedSizes: unsupportedSizes });
13
+ const unusedSupportedSizes = supportedSizesAsString.filter(size => !sizesInSlotSet.has(size));
14
+ const existingSlot = missingSizesInSlots.find(missingSize => missingSize.slotId === slot.domId);
15
+ if (existingSlot) {
16
+ existingSlot.unusedSupportedSizes = unusedSupportedSizes;
17
+ }
18
+ else {
19
+ missingSizesInSlots.push({
20
+ slotId: slot.domId,
21
+ unusedSupportedSizes: unusedSupportedSizes
22
+ });
23
+ }
24
+ if (slot.prebid) {
25
+ const missingBannerSizes = [];
26
+ const bannerSizes = extractPrebidAdSlotConfigs(slot.prebid).map(prebid => prebid.adUnit?.mediaTypes.banner?.sizes);
27
+ bannerSizes.map(bannerSize => {
28
+ bannerSize?.map(value => {
29
+ const bannerSizeString = value.join('x');
30
+ if (!sizesInSlotSet.has(bannerSizeString)) {
31
+ missingBannerSizes.push(bannerSizeString);
32
+ }
33
+ });
34
+ });
35
+ const existingSlot = missingSizesInSlots.find(missingSize => missingSize.slotId === slot.domId);
36
+ if (existingSlot) {
37
+ existingSlot.bannerSizes = missingBannerSizes;
38
+ }
39
+ else {
40
+ missingSizesInSlots.push({
41
+ slotId: slot.domId,
42
+ bannerSizes: missingBannerSizes
43
+ });
44
+ }
45
+ }
46
+ });
47
+ if (missingSizesInSlots.some(ms => ms.unsupportedSizes?.some(s => s.length) ||
48
+ ms.bannerSizes?.some(s => s.length) ||
49
+ ms.unusedSupportedSizes?.some(s => s.length))) {
50
+ messages.push({
51
+ kind: 'error',
52
+ text: formatSizesConfigMsg(missingSizesInSlots)
53
+ });
54
+ }
55
+ };
56
+ const formatSizesConfigMsg = (missingSizes) => {
57
+ const formatTableRow = (sizes) => {
58
+ if (!sizes) {
59
+ return;
60
+ }
61
+ return sizes.map((size, index) => {
62
+ if (sizes.length === 1) {
63
+ return size !== 'fluid' ? `[${size}]` : size;
64
+ }
65
+ else if (index === 0) {
66
+ return size !== 'fluid' ? `[${size}],` : 'fluid,';
67
+ }
68
+ else if (index === sizes.length - 1) {
69
+ return size !== 'fluid' ? ` [${size}]` : size;
70
+ }
71
+ else {
72
+ return size !== 'fluid' ? ` [${size}],` : ' fluid,';
73
+ }
74
+ });
75
+ };
76
+ return (React.createElement("div", null,
77
+ "The following slots have sizes that need to be supported/defined:",
78
+ React.createElement("table", { className: 'size-valid-table' },
79
+ React.createElement("thead", null,
80
+ React.createElement("tr", null,
81
+ React.createElement("th", null, "Slot ID"),
82
+ React.createElement("th", null, "Unsupported sizes"),
83
+ React.createElement("th", null, "Undefined banned sizes"),
84
+ React.createElement("th", null, "Unused supported sizes"))),
85
+ React.createElement("tbody", null, missingSizes.map((row, index) => {
86
+ if (!row.unsupportedSizes?.length &&
87
+ !row.bannerSizes?.length &&
88
+ !row.unusedSupportedSizes?.length) {
89
+ return null;
90
+ }
91
+ return (React.createElement("tr", { key: index },
92
+ React.createElement("td", null, row.slotId),
93
+ React.createElement("td", null, formatTableRow(row.unsupportedSizes)),
94
+ React.createElement("td", null, formatTableRow(row.bannerSizes)),
95
+ React.createElement("td", null, formatTableRow(row.unusedSupportedSizes))));
96
+ })))));
97
+ };
@@ -0,0 +1,3 @@
1
+ export const packageJson = {
2
+ version: '5.5.4'
3
+ };
package/lib/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from './ads/moliGlobal';
2
+ export * from './ads/prebid-outstream';
3
+ export * from './util/extractAdTagVersion';
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,45 @@
1
+ export var prebidjs;
2
+ (function (prebidjs) {
3
+ prebidjs.Adagio = 'adagio';
4
+ prebidjs.AdaptMx = 'amx';
5
+ prebidjs.Adform = 'adf';
6
+ prebidjs.AdUp = 'aduptech';
7
+ prebidjs.Criteo = 'criteo';
8
+ prebidjs.CWire = 'cwire';
9
+ prebidjs.ConnectAd = 'connectad';
10
+ prebidjs.AppNexusAst = 'appnexusAst';
11
+ prebidjs.AppNexus = 'appnexus';
12
+ prebidjs.GumGum = 'gumgum';
13
+ prebidjs.ImproveDigital = 'improvedigital';
14
+ prebidjs.IndexExchange = 'ix';
15
+ prebidjs.InMobi = 'inmobi';
16
+ prebidjs.Invibes = 'invibes';
17
+ prebidjs.NanoInteractive = 'nanointeractive';
18
+ prebidjs.NextMillennium = 'nextMillennium';
19
+ prebidjs.PubMatic = 'pubmatic';
20
+ prebidjs.Ogury = 'ogury';
21
+ prebidjs.OneTag = 'onetag';
22
+ prebidjs.OpenX = 'openx';
23
+ prebidjs.SmartAdServer = 'smartadserver';
24
+ prebidjs.Smartx = 'smartx';
25
+ prebidjs.SmileWanted = 'smilewanted';
26
+ prebidjs.Unruly = 'unruly';
27
+ prebidjs.Taboola = 'taboola';
28
+ prebidjs.Teads = 'teads';
29
+ prebidjs.TheTradeDesk = 'ttd';
30
+ prebidjs.Triplelift = 'triplelift';
31
+ prebidjs.Yieldlab = 'yieldlab';
32
+ prebidjs.Seedtag = 'seedtag';
33
+ prebidjs.Spotx = 'spotx';
34
+ prebidjs.ShowHeroes = 'showheroesBs';
35
+ prebidjs.StroeerCore = 'stroeerCore';
36
+ prebidjs.StailaMedia = 'stailamedia';
37
+ prebidjs.Xaxis = 'xhb';
38
+ prebidjs.DSPX = 'dspx';
39
+ prebidjs.RichAudience = 'ra';
40
+ prebidjs.Rubicon = 'rubicon';
41
+ prebidjs.Recognified = 'rads';
42
+ prebidjs.Visx = 'visx';
43
+ prebidjs.Vlyby = 'vlyby';
44
+ prebidjs.Orbidder = 'orbidder';
45
+ })(prebidjs || (prebidjs = {}));
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,48 @@
1
+ export var tcfapi;
2
+ (function (tcfapi) {
3
+ let responses;
4
+ (function (responses) {
5
+ let TCPurpose;
6
+ (function (TCPurpose) {
7
+ TCPurpose[TCPurpose["STORE_INFORMATION_ON_DEVICE"] = 1] = "STORE_INFORMATION_ON_DEVICE";
8
+ TCPurpose[TCPurpose["SELECT_BASIC_ADS"] = 2] = "SELECT_BASIC_ADS";
9
+ TCPurpose[TCPurpose["CREATE_PERSONALISED_ADS_PROFILE"] = 3] = "CREATE_PERSONALISED_ADS_PROFILE";
10
+ TCPurpose[TCPurpose["SELECT_PERSONALISED_ADS"] = 4] = "SELECT_PERSONALISED_ADS";
11
+ TCPurpose[TCPurpose["CREATE_PERSONALISED_CONTENT_PROFILE"] = 5] = "CREATE_PERSONALISED_CONTENT_PROFILE";
12
+ TCPurpose[TCPurpose["SELECT_PERSONALISED_CONTENT"] = 6] = "SELECT_PERSONALISED_CONTENT";
13
+ TCPurpose[TCPurpose["MEASURE_AD_PERFORMANCE"] = 7] = "MEASURE_AD_PERFORMANCE";
14
+ TCPurpose[TCPurpose["MEASURE_CONTENT_PERFORMANCE"] = 8] = "MEASURE_CONTENT_PERFORMANCE";
15
+ TCPurpose[TCPurpose["APPLY_MARKET_RESEARCH"] = 9] = "APPLY_MARKET_RESEARCH";
16
+ TCPurpose[TCPurpose["DEVELOP_IMPROVE_PRODUCTS"] = 10] = "DEVELOP_IMPROVE_PRODUCTS";
17
+ TCPurpose[TCPurpose["USE_LIMITED_DATA_TO_SElECT_CONTENT"] = 11] = "USE_LIMITED_DATA_TO_SElECT_CONTENT";
18
+ })(TCPurpose = responses.TCPurpose || (responses.TCPurpose = {}));
19
+ let RestrictionType;
20
+ (function (RestrictionType) {
21
+ RestrictionType[RestrictionType["NOT_ALLOWED"] = 0] = "NOT_ALLOWED";
22
+ RestrictionType[RestrictionType["REQUIRE_CONSENT"] = 1] = "REQUIRE_CONSENT";
23
+ RestrictionType[RestrictionType["REQUIRE_LI"] = 2] = "REQUIRE_LI";
24
+ })(RestrictionType = responses.RestrictionType || (responses.RestrictionType = {}));
25
+ })(responses = tcfapi.responses || (tcfapi.responses = {}));
26
+ let status;
27
+ (function (status) {
28
+ let DisplayStatus;
29
+ (function (DisplayStatus) {
30
+ DisplayStatus["VISIBLE"] = "visible";
31
+ DisplayStatus["HIDDEN"] = "hidden";
32
+ DisplayStatus["DISABLED"] = "disabled";
33
+ })(DisplayStatus = status.DisplayStatus || (status.DisplayStatus = {}));
34
+ let CmpStatus;
35
+ (function (CmpStatus) {
36
+ CmpStatus["STUB"] = "stub";
37
+ CmpStatus["LOADING"] = "loading";
38
+ CmpStatus["LOADED"] = "loaded";
39
+ CmpStatus["ERROR"] = "error";
40
+ })(CmpStatus = status.CmpStatus || (status.CmpStatus = {}));
41
+ let EventStatus;
42
+ (function (EventStatus) {
43
+ EventStatus["TC_LOADED"] = "tcloaded";
44
+ EventStatus["CMP_UI_SHOWN"] = "cmpuishown";
45
+ EventStatus["USER_ACTION_COMPLETE"] = "useractioncomplete";
46
+ })(EventStatus = status.EventStatus || (status.EventStatus = {}));
47
+ })(status = tcfapi.status || (tcfapi.status = {}));
48
+ })(tcfapi || (tcfapi = {}));
@@ -0,0 +1,11 @@
1
+ export const addNewInfiniteSlotToConfig = (config, idOfConfiguredSlot, artificialIdOfNewSlot, logger) => {
2
+ const configuredInfiniteAdSlot = config.slots.find(configSlot => configSlot.domId === idOfConfiguredSlot);
3
+ if (configuredInfiniteAdSlot) {
4
+ const newAdSlot = { ...configuredInfiniteAdSlot, domId: artificialIdOfNewSlot };
5
+ return { ...config, slots: [...config.slots, newAdSlot] };
6
+ }
7
+ else {
8
+ logger.error('MoliGlobal', `no infinite ad slot configured!`, config);
9
+ return config;
10
+ }
11
+ };
@@ -0,0 +1,9 @@
1
+ export function flatten(arr) {
2
+ return arr.reduce((acc, val) => acc.concat(val), []);
3
+ }
4
+ export function uniquePrimitiveFilter(elm, position, arr) {
5
+ return arr.indexOf(elm) === position;
6
+ }
7
+ export function isNotNull(elem) {
8
+ return elem !== null && elem !== undefined;
9
+ }