@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,406 @@
|
|
|
1
|
+
import { LOW_PRIORITY, mkConfigureStep, mkConfigureStepOncePerRequestAdsCycle, mkInitStep, mkPrepareRequestAdsStep, mkRequestBidsStep } from './adPipeline';
|
|
2
|
+
import { SizeConfigService } from './sizeConfigService';
|
|
3
|
+
import { resolveAdUnitPath } from './adUnitPath';
|
|
4
|
+
import { isNotNull, uniquePrimitiveFilter } from '../util/arrayUtils';
|
|
5
|
+
import { resolveStoredRequestIdInOrtb2Object } from '../util/resolveStoredRequestIdInOrtb2Object';
|
|
6
|
+
import { createTestSlots } from '../util/test-slots';
|
|
7
|
+
import { AssetLoadMethod } from '../util/assetLoaderService';
|
|
8
|
+
import { packageJson } from 'ad-tag/gen/packageJson';
|
|
9
|
+
import { prebidOutstreamRenderer } from 'ad-tag/ads/prebid-outstream';
|
|
10
|
+
import { isGamInterstitial } from 'ad-tag/ads/auctions/interstitialContext';
|
|
11
|
+
const prebidTimeout = (context) => {
|
|
12
|
+
return new Promise((_, reject) => {
|
|
13
|
+
context.window__.setTimeout(() => reject('Prebid did not resolve in time. Maybe you forgot to import the prebid distribution in the ad tag'), 5000);
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
const prebidReady = (window) => new Promise(resolve => window.pbjs.que.push(resolve));
|
|
17
|
+
const isPrebidSlotDefinition = (slotDefinition) => {
|
|
18
|
+
return !!slotDefinition.moliSlot.prebid;
|
|
19
|
+
};
|
|
20
|
+
const isAdUnitDefined = (adUnit, window) => {
|
|
21
|
+
if (window.pbjs.adUnits) {
|
|
22
|
+
return window.pbjs.adUnits.some(adUnit2 => adUnit.code === adUnit2.code);
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
};
|
|
26
|
+
const createdAdUnits = (context, prebidConfig, slots) => {
|
|
27
|
+
const prebidAdUnits = slots
|
|
28
|
+
.filter(isPrebidSlotDefinition)
|
|
29
|
+
.map(({ moliSlot, priceRule, filterSupportedSizes }) => {
|
|
30
|
+
const floors = priceRule
|
|
31
|
+
? {
|
|
32
|
+
floors: {
|
|
33
|
+
currency: prebidConfig.config.currency?.adServerCurrency ?? 'EUR',
|
|
34
|
+
schema: {
|
|
35
|
+
delimiter: '|',
|
|
36
|
+
fields: ['mediaType']
|
|
37
|
+
},
|
|
38
|
+
values: {
|
|
39
|
+
'*': priceRule.floorprice
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
: null;
|
|
44
|
+
context.logger__.debug('Prebid', context.requestId__, 'Price Rule', priceRule, moliSlot.domId, floors);
|
|
45
|
+
return extractPrebidAdSlotConfigs(moliSlot.prebid)
|
|
46
|
+
.map(prebidAdSlotConfig => {
|
|
47
|
+
const mediaTypeBanner = prebidAdSlotConfig.adUnit.mediaTypes.banner;
|
|
48
|
+
const mediaTypeVideo = prebidAdSlotConfig.adUnit.mediaTypes.video;
|
|
49
|
+
const mediaTypeNative = prebidAdSlotConfig.adUnit.mediaTypes.native;
|
|
50
|
+
const bannerSizes = mediaTypeBanner
|
|
51
|
+
? filterSupportedSizes(mediaTypeBanner.sizes).filter(SizeConfigService.isFixedSize)
|
|
52
|
+
: [];
|
|
53
|
+
const videoSizes = mediaTypeVideo
|
|
54
|
+
? filterVideoPlayerSizes(mediaTypeVideo.playerSize, filterSupportedSizes)
|
|
55
|
+
: [];
|
|
56
|
+
const bids = prebidAdSlotConfig.adUnit.bids
|
|
57
|
+
.filter((bid) => context.labelConfigService__.filterSlot(bid))
|
|
58
|
+
.filter((bid) => !bid.bidder ||
|
|
59
|
+
(bid.bidder &&
|
|
60
|
+
!context.auction__.isBidderDisabled(moliSlot.domId, bid.bidder) &&
|
|
61
|
+
!context.auction__.isBidderFrequencyCappedOnSlot(moliSlot.domId, bid.bidder)))
|
|
62
|
+
.map(bid => {
|
|
63
|
+
const { labelAny: _, labelAll: __, ...bidCopy } = bid;
|
|
64
|
+
return bidCopy;
|
|
65
|
+
});
|
|
66
|
+
const videoDimensionsWH = videoSizes.length > 0 && !mediaTypeVideo?.w && !mediaTypeVideo?.h
|
|
67
|
+
? {
|
|
68
|
+
w: videoSizes[0][0],
|
|
69
|
+
h: videoSizes[0][1]
|
|
70
|
+
}
|
|
71
|
+
: {};
|
|
72
|
+
const backupVideoRenderer = prebidConfig.backupVideoRenderer;
|
|
73
|
+
const video = mediaTypeVideo
|
|
74
|
+
? {
|
|
75
|
+
video: {
|
|
76
|
+
...mediaTypeVideo,
|
|
77
|
+
playerSize: videoSizes.length === 0 ? undefined : videoSizes,
|
|
78
|
+
...videoDimensionsWH,
|
|
79
|
+
...(backupVideoRenderer
|
|
80
|
+
? { renderer: prebidOutstreamRenderer(moliSlot.domId, backupVideoRenderer.url) }
|
|
81
|
+
: {})
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
: undefined;
|
|
85
|
+
const banner = mediaTypeBanner && bannerSizes.length > 0
|
|
86
|
+
? {
|
|
87
|
+
banner: { ...mediaTypeBanner, sizes: bannerSizes }
|
|
88
|
+
}
|
|
89
|
+
: undefined;
|
|
90
|
+
const native = mediaTypeNative
|
|
91
|
+
? {
|
|
92
|
+
native: { ...mediaTypeNative }
|
|
93
|
+
}
|
|
94
|
+
: undefined;
|
|
95
|
+
const pubstack = {
|
|
96
|
+
...prebidAdSlotConfig.adUnit.pubstack,
|
|
97
|
+
adUnitPath: resolveAdUnitPath(prebidAdSlotConfig.adUnit.pubstack?.adUnitPath || moliSlot.adUnitPath, context.adUnitPathVariables__)
|
|
98
|
+
};
|
|
99
|
+
const storedRequest = prebidAdSlotConfig.adUnit.ortb2Imp?.ext?.prebid?.storedrequest;
|
|
100
|
+
const storedRequestWithSolvedId = storedRequest && storedRequest.id
|
|
101
|
+
? {
|
|
102
|
+
...storedRequest,
|
|
103
|
+
id: resolveAdUnitPath(storedRequest.id, context.adUnitPathVariables__)
|
|
104
|
+
}
|
|
105
|
+
: null;
|
|
106
|
+
return {
|
|
107
|
+
...prebidAdSlotConfig.adUnit,
|
|
108
|
+
...(storedRequest &&
|
|
109
|
+
storedRequestWithSolvedId && {
|
|
110
|
+
ortb2Imp: resolveStoredRequestIdInOrtb2Object(prebidAdSlotConfig.adUnit.ortb2Imp, storedRequestWithSolvedId)
|
|
111
|
+
}),
|
|
112
|
+
code: prebidAdSlotConfig.adUnit.code || moliSlot.domId,
|
|
113
|
+
...(prebidAdSlotConfig.adUnit.pubstack ? { pubstack } : {}),
|
|
114
|
+
mediaTypes: {
|
|
115
|
+
...video,
|
|
116
|
+
...banner,
|
|
117
|
+
...native
|
|
118
|
+
},
|
|
119
|
+
bids: bids,
|
|
120
|
+
...floors
|
|
121
|
+
};
|
|
122
|
+
})
|
|
123
|
+
.filter(adUnit => adUnit.bids.length > 0 &&
|
|
124
|
+
adUnit.mediaTypes &&
|
|
125
|
+
(adUnit.mediaTypes.banner || adUnit.mediaTypes.video || adUnit.mediaTypes.native) &&
|
|
126
|
+
!isAdUnitDefined(adUnit, context.window__));
|
|
127
|
+
});
|
|
128
|
+
return prebidAdUnits.reduce((acc, adUnits) => [...acc, ...adUnits], []);
|
|
129
|
+
};
|
|
130
|
+
export const prebidInit = (assetService) => mkInitStep('prebid-init', context => {
|
|
131
|
+
context.window__.pbjs = context.window__.pbjs || { que: [] };
|
|
132
|
+
const analyticAdapters = context.config__.prebid?.analyticAdapters;
|
|
133
|
+
if (analyticAdapters && analyticAdapters.length > 0) {
|
|
134
|
+
context.window__.pbjs.que.push(() => {
|
|
135
|
+
context.window__.pbjs.enableAnalytics(analyticAdapters);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
if (context.window__.pbjs.libLoaded) {
|
|
139
|
+
return Promise.resolve();
|
|
140
|
+
}
|
|
141
|
+
else if (context.config__.prebid?.distributionUrl) {
|
|
142
|
+
assetService.loadScript({
|
|
143
|
+
name: 'prebid',
|
|
144
|
+
assetUrl: context.config__.prebid.distributionUrl,
|
|
145
|
+
loadMethod: AssetLoadMethod.TAG
|
|
146
|
+
});
|
|
147
|
+
return Promise.resolve();
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
return Promise.race([prebidReady(context.window__), prebidTimeout(context)]);
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
export const prebidRemoveAdUnits = (prebidConfig) => mkConfigureStep('prebid-remove-adunits', (context) => new Promise(resolve => {
|
|
154
|
+
if (prebidConfig.ephemeralAdUnits !== true) {
|
|
155
|
+
context.window__.pbjs = context.window__.pbjs || { que: [] };
|
|
156
|
+
const adUnits = context.window__.pbjs.adUnits;
|
|
157
|
+
if (adUnits) {
|
|
158
|
+
context.window__.pbjs.que.push(() => {
|
|
159
|
+
context.logger__.debug('Prebid', `Destroying prebid adUnits`, adUnits);
|
|
160
|
+
adUnits.forEach(adUnit => context.window__.pbjs.removeAdUnit(adUnit.code));
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
resolve();
|
|
165
|
+
}));
|
|
166
|
+
export const prebidClearAuction = () => {
|
|
167
|
+
return mkConfigureStepOncePerRequestAdsCycle('prebid-clear-auction', (context) => new Promise(resolve => {
|
|
168
|
+
context.window__.pbjs = context.window__.pbjs || { que: [] };
|
|
169
|
+
context.window__.pbjs.que.push(() => {
|
|
170
|
+
context.logger__.debug('Prebid', 'Clearing prebid auctions');
|
|
171
|
+
context.window__.pbjs.clearAllAuctions();
|
|
172
|
+
});
|
|
173
|
+
resolve();
|
|
174
|
+
}));
|
|
175
|
+
};
|
|
176
|
+
export const prebidConfigure = (prebidConfig, schainConfig) => {
|
|
177
|
+
let result;
|
|
178
|
+
const mkSupplyChainConfig = (nodes) => ({
|
|
179
|
+
validation: 'relaxed',
|
|
180
|
+
config: {
|
|
181
|
+
ver: '1.0',
|
|
182
|
+
complete: 1,
|
|
183
|
+
nodes
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
return mkConfigureStep('prebid-configure', (context, _slots) => {
|
|
187
|
+
if (!result) {
|
|
188
|
+
result = new Promise(resolve => {
|
|
189
|
+
if (prebidConfig.bidderSettings) {
|
|
190
|
+
context.window__.pbjs.bidderSettings = prebidConfig.bidderSettings;
|
|
191
|
+
}
|
|
192
|
+
context.window__.pbjs.que.push(() => {
|
|
193
|
+
const s2sConfig = prebidConfig.config.s2sConfig;
|
|
194
|
+
if (s2sConfig) {
|
|
195
|
+
const s2sConfigs = Array.isArray(prebidConfig.config.s2sConfig)
|
|
196
|
+
? prebidConfig.config.s2sConfig
|
|
197
|
+
: [prebidConfig.config.s2sConfig];
|
|
198
|
+
s2sConfigs.forEach(s2sConfigEntry => {
|
|
199
|
+
const h5v = s2sConfigEntry.extPrebid?.analytics?.h5v;
|
|
200
|
+
if (h5v) {
|
|
201
|
+
h5v.configLabel = context.window__.moli.configLabel;
|
|
202
|
+
h5v.moliVersion = packageJson.version;
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
context.window__.pbjs.setConfig({
|
|
207
|
+
...prebidConfig.config,
|
|
208
|
+
...{ schain: mkSupplyChainConfig([schainConfig.supplyChainStartNode]) },
|
|
209
|
+
...{ floors: prebidConfig.config.floors || {} }
|
|
210
|
+
});
|
|
211
|
+
prebidConfig.bidderConfigs?.forEach(({ options, merge }) => {
|
|
212
|
+
context.window__.pbjs.setBidderConfig(options, merge);
|
|
213
|
+
});
|
|
214
|
+
prebidConfig.schain.nodes.forEach(({ bidder, node, appendNode }) => {
|
|
215
|
+
const nodes = [schainConfig.supplyChainStartNode];
|
|
216
|
+
if (appendNode) {
|
|
217
|
+
nodes.push(node);
|
|
218
|
+
}
|
|
219
|
+
context.window__.pbjs.setBidderConfig({ bidders: [bidder], config: { schain: mkSupplyChainConfig(nodes) } }, true);
|
|
220
|
+
});
|
|
221
|
+
if (context.window__.pbjs.registerSignalSources) {
|
|
222
|
+
context.window__.pbjs.registerSignalSources();
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
resolve();
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
return result;
|
|
229
|
+
});
|
|
230
|
+
};
|
|
231
|
+
const extractPrebidAdSlotConfigs = (provider) => {
|
|
232
|
+
return Array.isArray(provider) ? provider : [provider];
|
|
233
|
+
};
|
|
234
|
+
export const prebidPrepareRequestAds = (prebidConfig) => mkPrepareRequestAdsStep('prebid-prepare-adunits', LOW_PRIORITY, (context, slots) => new Promise(resolve => {
|
|
235
|
+
if (prebidConfig.ephemeralAdUnits) {
|
|
236
|
+
resolve();
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
context.window__.pbjs.que.push(() => {
|
|
240
|
+
const adUnits = createdAdUnits(context, prebidConfig, slots);
|
|
241
|
+
adUnits.forEach(adUnit => {
|
|
242
|
+
context.logger__.debug('Prebid', context.requestId__, `Prebid add ad unit: [Code] ${adUnit.code}`, adUnit);
|
|
243
|
+
});
|
|
244
|
+
context.window__.pbjs.addAdUnits(adUnits);
|
|
245
|
+
});
|
|
246
|
+
resolve();
|
|
247
|
+
}
|
|
248
|
+
}));
|
|
249
|
+
export const prebidRequestBids = (prebidConfig, adServer) => mkRequestBidsStep('prebid-request-bids', (context, slots) => {
|
|
250
|
+
const failsafeTimeout = Math.max((prebidConfig.config.bidderTimeout ?? 2000) + 3000, prebidConfig.failsafeTimeout ?? 0);
|
|
251
|
+
const failsafe = new Promise(resolve => context.window__.setTimeout(resolve, failsafeTimeout));
|
|
252
|
+
const auction = new Promise(resolve => {
|
|
253
|
+
const slotsToRefresh = slots.filter(slot => !context.auction__.isSlotThrottled(slot.adSlot) &&
|
|
254
|
+
(!isGamInterstitial(slot.adSlot, context.window__) ||
|
|
255
|
+
context.auction__.interstitialChannel() !== 'gam'));
|
|
256
|
+
const requestObject = prebidConfig.ephemeralAdUnits
|
|
257
|
+
? {
|
|
258
|
+
adUnits: createdAdUnits(context, prebidConfig, slotsToRefresh)
|
|
259
|
+
}
|
|
260
|
+
: {
|
|
261
|
+
adUnitCodes: slotsToRefresh
|
|
262
|
+
.filter(isPrebidSlotDefinition)
|
|
263
|
+
.map(slot => slot.moliSlot.domId)
|
|
264
|
+
};
|
|
265
|
+
const adUnitCodes = requestObject.adUnitCodes ||
|
|
266
|
+
requestObject.adUnits
|
|
267
|
+
?.map(adUnit => adUnit.code)
|
|
268
|
+
.filter(isNotNull)
|
|
269
|
+
.filter(uniquePrimitiveFilter) ||
|
|
270
|
+
[];
|
|
271
|
+
if (adUnitCodes.length === 0) {
|
|
272
|
+
context.logger__.debug('Prebid', 'skip request bids. All slots were filtered.', slotsToRefresh.map(s => s.moliSlot));
|
|
273
|
+
return resolve();
|
|
274
|
+
}
|
|
275
|
+
let adserverRequestSent = false;
|
|
276
|
+
context.logger__.debug('Prebid', `Prebid request bids: \n\t\t\t${adUnitCodes.join('\n\t\t\t')}`);
|
|
277
|
+
const bidsBackHandler = (bidResponses, timedOut, auctionId) => {
|
|
278
|
+
context.logger__.info('Prebid', auctionId, bidResponses, slots.map(s => s.moliSlot.domId));
|
|
279
|
+
try {
|
|
280
|
+
if (adserverRequestSent) {
|
|
281
|
+
context.logger__.warn('Prebid', `ad server request already sent [${context.requestId__}]. AuctionId ${auctionId}`);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (!bidResponses) {
|
|
285
|
+
context.logger__.warn('Prebid', `Undefined bid response map for ad unit codes: ${adUnitCodes.join(', ')}`);
|
|
286
|
+
return resolve();
|
|
287
|
+
}
|
|
288
|
+
adserverRequestSent = true;
|
|
289
|
+
if (adServer === 'gam') {
|
|
290
|
+
context.runtimeConfig__.adPipelineConfig.prebidBidsBackHandler.forEach(handler => handler(context, bidResponses, slots));
|
|
291
|
+
context.window__.pbjs.setTargetingForGPTAsync(adUnitCodes);
|
|
292
|
+
}
|
|
293
|
+
resolve();
|
|
294
|
+
}
|
|
295
|
+
catch (error) {
|
|
296
|
+
context.logger__.error('Prebid', 'DfpService:: could not resolve bidsBackHandler' + JSON.stringify(error));
|
|
297
|
+
resolve();
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
context.window__.pbjs.que.push(() => {
|
|
301
|
+
context.window__.pbjs.requestBids({
|
|
302
|
+
...requestObject,
|
|
303
|
+
auctionId: context.auctionId__,
|
|
304
|
+
timeout: context.bucket__?.timeout,
|
|
305
|
+
bidsBackHandler: bidsBackHandler
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
});
|
|
309
|
+
return Promise.race([failsafe, auction]);
|
|
310
|
+
});
|
|
311
|
+
export const prebidDefineSlots = () => (context, slots) => {
|
|
312
|
+
const slotDefinitions = slots.map(moliSlot => {
|
|
313
|
+
const sizeConfigService = new SizeConfigService(moliSlot.sizeConfig, context.labelConfigService__.getSupportedLabels(), context.window__);
|
|
314
|
+
const filterSupportedSizes = sizeConfigService.filterSupportedSizes;
|
|
315
|
+
if (!(sizeConfigService.filterSlot(moliSlot) &&
|
|
316
|
+
context.labelConfigService__.filterSlot(moliSlot))) {
|
|
317
|
+
return Promise.resolve(null);
|
|
318
|
+
}
|
|
319
|
+
const adSlot = {
|
|
320
|
+
getAdUnitPath: () => moliSlot.adUnitPath
|
|
321
|
+
};
|
|
322
|
+
switch (context.env__) {
|
|
323
|
+
case 'production':
|
|
324
|
+
return Promise.resolve({
|
|
325
|
+
moliSlot,
|
|
326
|
+
adSlot,
|
|
327
|
+
filterSupportedSizes
|
|
328
|
+
});
|
|
329
|
+
case 'test':
|
|
330
|
+
return Promise.resolve({
|
|
331
|
+
moliSlot,
|
|
332
|
+
adSlot,
|
|
333
|
+
filterSupportedSizes
|
|
334
|
+
});
|
|
335
|
+
default:
|
|
336
|
+
return Promise.reject(`invalid environment: ${context.runtimeConfig__.environment}`);
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
return Promise.all(slotDefinitions).then(slots => slots.filter(isNotNull));
|
|
340
|
+
};
|
|
341
|
+
export const prebidRenderAds = () => (context, slots) => {
|
|
342
|
+
return new Promise((resolve, reject) => {
|
|
343
|
+
context.logger__.debug('Prebid', 'start rendering');
|
|
344
|
+
try {
|
|
345
|
+
switch (context.env__) {
|
|
346
|
+
case 'test':
|
|
347
|
+
context.logger__.debug('Prebid', 'Rendering test slots');
|
|
348
|
+
createTestSlots(context, slots);
|
|
349
|
+
break;
|
|
350
|
+
case 'production':
|
|
351
|
+
context.window__.pbjs
|
|
352
|
+
.getHighestCpmBids()
|
|
353
|
+
.filter(bid => bid && bid.adId)
|
|
354
|
+
.forEach(winningBid => {
|
|
355
|
+
const adSlotDiv = context.window__.document.getElementById(winningBid.adUnitCode);
|
|
356
|
+
if (adSlotDiv) {
|
|
357
|
+
const innerDiv = document.createElement('div');
|
|
358
|
+
innerDiv.style.setProperty('border', '0pt none');
|
|
359
|
+
const iframe = document.createElement('iframe');
|
|
360
|
+
iframe.scrolling = 'no';
|
|
361
|
+
iframe.frameBorder = '0';
|
|
362
|
+
iframe.marginHeight = '0';
|
|
363
|
+
iframe.marginHeight = '0';
|
|
364
|
+
iframe.name = `prebid_ads_iframe_${winningBid.adUnitCode}`;
|
|
365
|
+
iframe.title = '3rd party ad content';
|
|
366
|
+
iframe.sandbox.add('allow-forms', 'allow-popups', 'allow-popups-to-escape-sandbox', 'allow-same-origin', 'allow-scripts', 'allow-top-navigation-by-user-activation');
|
|
367
|
+
iframe.setAttribute('aria-label', 'Advertisment');
|
|
368
|
+
iframe.style.setProperty('border', '0');
|
|
369
|
+
iframe.style.setProperty('margin', '0');
|
|
370
|
+
iframe.style.setProperty('overflow', 'hidden');
|
|
371
|
+
innerDiv.appendChild(iframe);
|
|
372
|
+
adSlotDiv.appendChild(innerDiv);
|
|
373
|
+
const iframeDoc = iframe.contentWindow?.document;
|
|
374
|
+
if (iframeDoc) {
|
|
375
|
+
context.window__.pbjs.renderAd(iframeDoc, winningBid.adId);
|
|
376
|
+
const normalizeCss = `/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */button,hr,input{overflow:visible}progress,sub,sup{vertical-align:baseline}[type=checkbox],[type=radio],legend{box-sizing:border-box;padding:0}html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}details,main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:ButtonText dotted 1px}fieldset{padding:.35em .75em .625em}legend{color:inherit;display:table;max-width:100%;white-space:normal}textarea{overflow:auto}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}[hidden],template{display:none}`;
|
|
377
|
+
const iframeStyle = iframeDoc.createElement('style');
|
|
378
|
+
iframeStyle.appendChild(iframeDoc.createTextNode(normalizeCss));
|
|
379
|
+
iframeDoc.head.appendChild(iframeStyle);
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
context.logger__.error('Prebid', `No access to iframe contentWindow for ad unit${winningBid.adUnitCode}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
context.logger__.error('Prebid', `Could not locate ad slot with id ${winningBid.adUnitCode}`);
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
resolve();
|
|
392
|
+
}
|
|
393
|
+
catch (e) {
|
|
394
|
+
reject(e);
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
};
|
|
398
|
+
const filterVideoPlayerSizes = (playerSize, filterSupportedSizes) => {
|
|
399
|
+
const isSinglePlayerSize = (size) => {
|
|
400
|
+
return (!!size && size.length === 2 && typeof size[0] === 'number' && typeof size[1] === 'number');
|
|
401
|
+
};
|
|
402
|
+
if (!playerSize) {
|
|
403
|
+
return [];
|
|
404
|
+
}
|
|
405
|
+
return filterSupportedSizes(isSinglePlayerSize(playerSize) ? [playerSize] : playerSize).filter(SizeConfigService.isFixedSize);
|
|
406
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { flatten, uniquePrimitiveFilter } from '../util/arrayUtils';
|
|
2
|
+
import { isSizeEqual } from '../util/sizes';
|
|
3
|
+
export class SizeConfigService {
|
|
4
|
+
static isFixedSize(size) {
|
|
5
|
+
return size !== 'fluid';
|
|
6
|
+
}
|
|
7
|
+
constructor(sizeConfig, supportedLabels, window) {
|
|
8
|
+
this.sizeConfig = sizeConfig;
|
|
9
|
+
this.supportedLabels = supportedLabels;
|
|
10
|
+
this.window = window;
|
|
11
|
+
this.filterSupportedSizes = (givenSizes) => {
|
|
12
|
+
if (!this.isValid) {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
return this.supportedSizes.length === 0
|
|
16
|
+
? givenSizes
|
|
17
|
+
: givenSizes.filter(givenSize => this.supportedSizes.some(configuredSize => {
|
|
18
|
+
if (configuredSize === 'fluid') {
|
|
19
|
+
return givenSize === 'fluid';
|
|
20
|
+
}
|
|
21
|
+
else if (givenSize === 'fluid') {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
return isSizeEqual(givenSize, configuredSize);
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
};
|
|
29
|
+
this.areLabelsMatching = (conf, supportedLabels) => {
|
|
30
|
+
return ((!conf.labelAll ||
|
|
31
|
+
conf.labelAll.every(label => supportedLabels.some(supportedLabel => supportedLabel === label))) &&
|
|
32
|
+
(!conf.labelNone ||
|
|
33
|
+
!conf.labelNone.some(label => supportedLabels.some(supportedLabel => supportedLabel === label))));
|
|
34
|
+
};
|
|
35
|
+
const supportedSizeConfigs = sizeConfig.length !== 0
|
|
36
|
+
? sizeConfig.filter(conf => window.matchMedia(conf.mediaQuery).matches &&
|
|
37
|
+
this.areLabelsMatching(conf, supportedLabels))
|
|
38
|
+
: [];
|
|
39
|
+
this.isValid =
|
|
40
|
+
sizeConfig.length === 0 || !(sizeConfig.length > 0 && supportedSizeConfigs.length === 0);
|
|
41
|
+
this.supportedSizes = flatten(supportedSizeConfigs.map(conf => conf.sizesSupported))
|
|
42
|
+
.map(size => JSON.stringify(size))
|
|
43
|
+
.filter(uniquePrimitiveFilter)
|
|
44
|
+
.map(sizeAsString => JSON.parse(sizeAsString));
|
|
45
|
+
}
|
|
46
|
+
filterSlot(slot) {
|
|
47
|
+
return (!slot.sizes || slot.sizes.length === 0 || this.filterSupportedSizes(slot.sizes).length > 0);
|
|
48
|
+
}
|
|
49
|
+
}
|
package/lib/ads/spa.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export const allowRefreshAdSlot = (validateLocation, stateHref, currentLocation) => {
|
|
2
|
+
switch (validateLocation) {
|
|
3
|
+
case 'none':
|
|
4
|
+
return true;
|
|
5
|
+
case 'href':
|
|
6
|
+
return currentLocation.href === stateHref;
|
|
7
|
+
case 'path':
|
|
8
|
+
try {
|
|
9
|
+
const url = new URL(stateHref);
|
|
10
|
+
return currentLocation.pathname === url.pathname;
|
|
11
|
+
}
|
|
12
|
+
catch (e) {
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
export const allowRequestAds = (validateLocation, stateHref, currentLocation) => {
|
|
18
|
+
switch (validateLocation) {
|
|
19
|
+
case 'none':
|
|
20
|
+
return true;
|
|
21
|
+
case 'href':
|
|
22
|
+
return currentLocation.href !== stateHref;
|
|
23
|
+
case 'path':
|
|
24
|
+
try {
|
|
25
|
+
const url = new URL(stateHref);
|
|
26
|
+
return currentLocation.pathname !== url.pathname;
|
|
27
|
+
}
|
|
28
|
+
catch (e) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { QueryParameters } from '../util/queryParameters';
|
|
2
|
+
import { resolveOverrides } from '../util/resolveOverrides';
|
|
3
|
+
import { BrowserStorageKeys } from '../util/browserStorageKeys';
|
|
4
|
+
const currentScript = window.document.currentScript ?? document.getElementById('moli-ad-tag');
|
|
5
|
+
const pubCodeOverride = resolveOverrides(window, QueryParameters.moliPubCode, BrowserStorageKeys.moliPubCode)[0]?.value;
|
|
6
|
+
const versionOverride = resolveOverrides(window, QueryParameters.moliVersion, BrowserStorageKeys.moliVersion)[0]?.value;
|
|
7
|
+
if (currentScript) {
|
|
8
|
+
const publisherCode = pubCodeOverride ?? currentScript.getAttribute('data-publisher-code');
|
|
9
|
+
const version = versionOverride ?? currentScript.getAttribute('data-version') ?? 'production';
|
|
10
|
+
const labels = (currentScript.getAttribute('data-labels') ?? '')
|
|
11
|
+
.split(',')
|
|
12
|
+
.map(l => l.trim())
|
|
13
|
+
.filter(l => l.length > 0);
|
|
14
|
+
if (labels.length > 0) {
|
|
15
|
+
window.moli.que.push(moli => {
|
|
16
|
+
moli.beforeRequestAds(() => labels.forEach(label => moli.addLabel(label)));
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
window.moli.configLabel = version;
|
|
20
|
+
const endpoint = currentScript.getAttribute('data-endpoint') ?? 'api.h5v.eu/publishers';
|
|
21
|
+
const fallback = currentScript.getAttribute('data-endpoint-fallback') ?? 'cdn.h5v.eu/publishers';
|
|
22
|
+
if (publisherCode) {
|
|
23
|
+
const path = `/${publisherCode}/configs/${version}/config.json`;
|
|
24
|
+
const url = `//${endpoint}${path}`;
|
|
25
|
+
fetch(url, { mode: 'cors' })
|
|
26
|
+
.then(response => response.json())
|
|
27
|
+
.catch(error => {
|
|
28
|
+
console.error(`Failed to load configuration from ${url}. Using fallback`, error);
|
|
29
|
+
return fetch(`//${fallback}${path}`, { mode: 'cors' });
|
|
30
|
+
})
|
|
31
|
+
.then(config => window.moli.configure(config))
|
|
32
|
+
.catch(error => console.error(`Failed to load configuration from ${url}:`, error));
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
console.error('No publisher code provided for ad tag configuration! Add the `data-publisher-code="yourCode"` attribute to the script tag.');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
console.error('Failed to find the current script tag for the ad tag bundle!');
|
|
40
|
+
}
|