@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
package/lib/ads/moli.js
ADDED
|
@@ -0,0 +1,645 @@
|
|
|
1
|
+
import { parseQueryString } from '../util/query';
|
|
2
|
+
import { AssetLoadMethod, createAssetLoaderService } from '../util/assetLoaderService';
|
|
3
|
+
import { getLogger } from '../util/logging';
|
|
4
|
+
import { addNewInfiniteSlotToConfig } from '../util/addNewInfiniteSlotToConfig';
|
|
5
|
+
import { AdService } from './adService';
|
|
6
|
+
import { createEventService } from './eventService';
|
|
7
|
+
import { getActiveEnvironmentOverride, setEnvironmentOverrideInStorage } from '../util/environmentOverride';
|
|
8
|
+
import { packageJson } from '../gen/packageJson';
|
|
9
|
+
import * as adUnitPath from './adUnitPath';
|
|
10
|
+
import { extractTopPrivateDomainFromHostname } from '../util/extractTopPrivateDomainFromHostname';
|
|
11
|
+
import { createLabelConfigService } from './labelConfigService';
|
|
12
|
+
import { allowRefreshAdSlot, allowRequestAds } from './spa';
|
|
13
|
+
export const createMoliTag = (window) => {
|
|
14
|
+
const assetLoaderService = createAssetLoaderService(window);
|
|
15
|
+
const eventService = createEventService();
|
|
16
|
+
const adService = new AdService(assetLoaderService, eventService, window);
|
|
17
|
+
const moliWindow = window;
|
|
18
|
+
let state = {
|
|
19
|
+
state: 'configurable',
|
|
20
|
+
initialize: false,
|
|
21
|
+
runtimeConfig: newEmptyRuntimeConfig(),
|
|
22
|
+
modules: []
|
|
23
|
+
};
|
|
24
|
+
function setTargeting(key, value) {
|
|
25
|
+
switch (state.state) {
|
|
26
|
+
case 'configurable':
|
|
27
|
+
case 'configured': {
|
|
28
|
+
state.runtimeConfig.keyValues[key] = value;
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
case 'spa-finished':
|
|
32
|
+
case 'spa-requestAds': {
|
|
33
|
+
state.nextRuntimeConfig.keyValues[key] = value;
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
default: {
|
|
37
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', `Setting key-value after configuration: ${key} : ${value}`);
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function addLabel(label) {
|
|
43
|
+
switch (state.state) {
|
|
44
|
+
case 'configurable':
|
|
45
|
+
case 'configured': {
|
|
46
|
+
state.runtimeConfig.labels.push(label);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
case 'spa-requestAds':
|
|
50
|
+
case 'spa-finished': {
|
|
51
|
+
state.nextRuntimeConfig.labels.push(label);
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
default: {
|
|
55
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', `Adding label after configure: ${label}`);
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function setAdUnitPathVariables(variables) {
|
|
61
|
+
switch (state.state) {
|
|
62
|
+
case 'configurable':
|
|
63
|
+
case 'configured': {
|
|
64
|
+
state.runtimeConfig.adUnitPathVariables = variables;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
case 'spa-requestAds':
|
|
68
|
+
case 'spa-finished': {
|
|
69
|
+
state.nextRuntimeConfig.adUnitPathVariables = variables;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
default: {
|
|
73
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', `Setting unit path variables after configuration: ${variables}`);
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function getAdUnitPathVariables() {
|
|
79
|
+
const domain = extractTopPrivateDomainFromHostname(window.location.hostname) || 'unknown';
|
|
80
|
+
switch (state.state) {
|
|
81
|
+
case 'configurable':
|
|
82
|
+
return { ...state.runtimeConfig.adUnitPathVariables, domain: domain, device: 'unknown' };
|
|
83
|
+
case 'configured':
|
|
84
|
+
case 'requestAds':
|
|
85
|
+
case 'spa-requestAds':
|
|
86
|
+
case 'spa-finished':
|
|
87
|
+
case 'finished':
|
|
88
|
+
case 'error':
|
|
89
|
+
const labelService = createLabelConfigService(state.config.labelSizeConfig || [], [], window);
|
|
90
|
+
return {
|
|
91
|
+
...getPageTargeting().adUnitPathVariables,
|
|
92
|
+
domain: state.config.domain || domain,
|
|
93
|
+
device: labelService.getDeviceLabel()
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function resolveAdUnitPath(adUnitPathParam, options) {
|
|
98
|
+
const opts = options || {};
|
|
99
|
+
const removeNetworkChildId = opts.removeNetworkChildId || false;
|
|
100
|
+
const resolvedPath = adUnitPath.resolveAdUnitPath(adUnitPathParam, getAdUnitPathVariables());
|
|
101
|
+
return removeNetworkChildId ? adUnitPath.removeChildId(resolvedPath) : resolvedPath;
|
|
102
|
+
}
|
|
103
|
+
function setLogger(logger) {
|
|
104
|
+
switch (state.state) {
|
|
105
|
+
case 'configurable':
|
|
106
|
+
case 'configured': {
|
|
107
|
+
state.runtimeConfig.logger = logger;
|
|
108
|
+
break;
|
|
109
|
+
}
|
|
110
|
+
default: {
|
|
111
|
+
logger.error('Setting a custom logger is not allowed after configuration');
|
|
112
|
+
break;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function beforeRequestAds(callback) {
|
|
117
|
+
switch (state.state) {
|
|
118
|
+
case 'configurable':
|
|
119
|
+
case 'configured': {
|
|
120
|
+
state.runtimeConfig.hooks.beforeRequestAds.push(callback);
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
default: {
|
|
124
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', 'Trying to add a hook beforeRequestAds. Already configured.', state.config);
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function afterRequestAds(callback) {
|
|
130
|
+
switch (state.state) {
|
|
131
|
+
case 'configurable':
|
|
132
|
+
case 'configured': {
|
|
133
|
+
state.runtimeConfig.hooks.afterRequestAds.push(callback);
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
default: {
|
|
137
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', 'Trying to add a hook afterRequestAds. Already configured.', state.config);
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function getConfig() {
|
|
143
|
+
switch (state.state) {
|
|
144
|
+
case 'configurable': {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
case 'configured': {
|
|
148
|
+
return state.config;
|
|
149
|
+
}
|
|
150
|
+
case 'requestAds': {
|
|
151
|
+
return state.config;
|
|
152
|
+
}
|
|
153
|
+
case 'spa-requestAds':
|
|
154
|
+
case 'spa-finished': {
|
|
155
|
+
return state.config;
|
|
156
|
+
}
|
|
157
|
+
case 'finished': {
|
|
158
|
+
return state.config;
|
|
159
|
+
}
|
|
160
|
+
case 'error': {
|
|
161
|
+
return state.config;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function getRuntimeConfig() {
|
|
166
|
+
return state.runtimeConfig;
|
|
167
|
+
}
|
|
168
|
+
function getPageTargeting() {
|
|
169
|
+
return {
|
|
170
|
+
keyValues: { ...state.config?.targeting?.keyValues, ...state.runtimeConfig.keyValues },
|
|
171
|
+
labels: [...(state.config?.targeting?.labels ?? []), ...state.runtimeConfig.labels],
|
|
172
|
+
adUnitPathVariables: {
|
|
173
|
+
...state.config?.targeting?.adUnitPathVariables,
|
|
174
|
+
...state.runtimeConfig.adUnitPathVariables
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function registerModule(module) {
|
|
179
|
+
switch (state.state) {
|
|
180
|
+
case 'configurable':
|
|
181
|
+
case 'configured': {
|
|
182
|
+
state.modules.push(module);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
default: {
|
|
186
|
+
getLogger(state.runtimeConfig, window).error('Registering a module is only allowed within the ad tag before the ad tag is configured');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
function configure(config) {
|
|
191
|
+
switch (state.state) {
|
|
192
|
+
case 'configurable': {
|
|
193
|
+
const shouldInitialize = state.initialize;
|
|
194
|
+
const envOverride = getActiveEnvironmentOverride(window);
|
|
195
|
+
const modules = state.modules;
|
|
196
|
+
if (envOverride) {
|
|
197
|
+
state.runtimeConfig.environment = envOverride.value;
|
|
198
|
+
}
|
|
199
|
+
if (envOverride?.source === 'queryParam') {
|
|
200
|
+
setEnvironmentOverrideInStorage(envOverride.value, window.sessionStorage);
|
|
201
|
+
}
|
|
202
|
+
const log = getLogger(state.runtimeConfig, window);
|
|
203
|
+
log.debug('MoliGlobal', 'configure modules', config.modules ?? {});
|
|
204
|
+
modules.forEach(module => {
|
|
205
|
+
try {
|
|
206
|
+
module.configure__(config.modules ?? {});
|
|
207
|
+
log.debug('MoliGlobal', `configure ${module.moduleType} module ${module.name}`, module.config__());
|
|
208
|
+
state.runtimeConfig.adPipelineConfig.initSteps.push(...module.initSteps__());
|
|
209
|
+
state.runtimeConfig.adPipelineConfig.configureSteps.push(...module.configureSteps__());
|
|
210
|
+
state.runtimeConfig.adPipelineConfig.prepareRequestAdsSteps.push(...module.prepareRequestAdsSteps__());
|
|
211
|
+
if (module.requestBidsSteps__) {
|
|
212
|
+
state.runtimeConfig.adPipelineConfig.requestBidsSteps.push(...module.requestBidsSteps__());
|
|
213
|
+
}
|
|
214
|
+
if (module.prebidBidsBackHandler__) {
|
|
215
|
+
state.runtimeConfig.adPipelineConfig.prebidBidsBackHandler.push(...module.prebidBidsBackHandler__());
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
catch (e) {
|
|
219
|
+
log.error('MoliGlobal', `failed to configure ${module.moduleType} module ${module.name}`, e);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
state = {
|
|
223
|
+
state: 'configured',
|
|
224
|
+
config: config,
|
|
225
|
+
runtimeConfig: state.runtimeConfig,
|
|
226
|
+
modules: modules
|
|
227
|
+
};
|
|
228
|
+
if (shouldInitialize || config.requestAds === true) {
|
|
229
|
+
return requestAds();
|
|
230
|
+
}
|
|
231
|
+
return Promise.resolve(state);
|
|
232
|
+
}
|
|
233
|
+
case 'configured': {
|
|
234
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', 'Trying to configure moli tag twice. Already configured.', state.config);
|
|
235
|
+
return Promise.resolve(state);
|
|
236
|
+
}
|
|
237
|
+
case 'requestAds': {
|
|
238
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', 'Trying to configure moli tag twice. Already requesting ads.');
|
|
239
|
+
return Promise.resolve(state);
|
|
240
|
+
}
|
|
241
|
+
case 'finished': {
|
|
242
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', 'Trying to configure moli tag twice. Already finished.');
|
|
243
|
+
return Promise.resolve(state);
|
|
244
|
+
}
|
|
245
|
+
case 'error': {
|
|
246
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', 'Trying to configure moli tag twice. Already finished, but with an error.', state.error);
|
|
247
|
+
return Promise.resolve(state);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return Promise.resolve(null);
|
|
251
|
+
}
|
|
252
|
+
function requestAds() {
|
|
253
|
+
switch (state.state) {
|
|
254
|
+
case 'configurable': {
|
|
255
|
+
state.initialize = true;
|
|
256
|
+
return Promise.resolve(state);
|
|
257
|
+
}
|
|
258
|
+
case 'configured': {
|
|
259
|
+
setABtestTargeting();
|
|
260
|
+
addDomainLabel(state.config.domain);
|
|
261
|
+
const { refreshInfiniteSlots } = state.runtimeConfig;
|
|
262
|
+
let config = state.config;
|
|
263
|
+
if (refreshInfiniteSlots.length > 0) {
|
|
264
|
+
refreshInfiniteSlots.forEach(slot => {
|
|
265
|
+
config = addNewInfiniteSlotToConfig(config, slot.idOfConfiguredSlot, slot.artificialDomId, getLogger(state.runtimeConfig, window));
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
const log = getLogger(state.runtimeConfig, window);
|
|
269
|
+
if (state.runtimeConfig.hooks && state.runtimeConfig.hooks.beforeRequestAds) {
|
|
270
|
+
state.runtimeConfig.hooks.beforeRequestAds.forEach(hook => {
|
|
271
|
+
try {
|
|
272
|
+
hook(config, state.runtimeConfig);
|
|
273
|
+
}
|
|
274
|
+
catch (e) {
|
|
275
|
+
log.error('MoliGlobal', 'beforeRequestAds hook failed', e);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
const afterRequestAds = state.runtimeConfig.hooks.afterRequestAds;
|
|
280
|
+
const isSinglePageApp = config.spa?.enabled === true;
|
|
281
|
+
if (isSinglePageApp) {
|
|
282
|
+
const requestAdsRuntimeConfig = state.runtimeConfig;
|
|
283
|
+
const initialized = adService.initialize(config, requestAdsRuntimeConfig);
|
|
284
|
+
state = {
|
|
285
|
+
state: 'spa-requestAds',
|
|
286
|
+
config: config,
|
|
287
|
+
initialized,
|
|
288
|
+
modules: state.modules,
|
|
289
|
+
href: window.location.href,
|
|
290
|
+
runtimeConfig: Object.freeze(newEmptyRuntimeConfig(state.runtimeConfig, { keepTargeting: true })),
|
|
291
|
+
nextRuntimeConfig: newEmptyRuntimeConfig(state.runtimeConfig)
|
|
292
|
+
};
|
|
293
|
+
return initialized
|
|
294
|
+
.then(() => adService.requestAds(config, requestAdsRuntimeConfig))
|
|
295
|
+
.then(() => {
|
|
296
|
+
const validateLocation = config.spa?.validateLocation ?? 'href';
|
|
297
|
+
if (state.state === 'spa-requestAds' &&
|
|
298
|
+
allowRefreshAdSlot(validateLocation, state.href, window.location)) {
|
|
299
|
+
const { config, runtimeConfig } = state;
|
|
300
|
+
if (state.runtimeConfig.refreshSlots.length > 0) {
|
|
301
|
+
adService.refreshAdSlots(runtimeConfig.refreshSlots, config, runtimeConfig);
|
|
302
|
+
}
|
|
303
|
+
if (state.runtimeConfig.refreshBuckets.length > 0) {
|
|
304
|
+
state.runtimeConfig.refreshBuckets.forEach(bucket => {
|
|
305
|
+
adService.refreshBucket(bucket.bucket, config, runtimeConfig, bucket.options);
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
afterRequestAds.forEach(hook => hook('spa-finished'));
|
|
309
|
+
const finishedState = {
|
|
310
|
+
...state,
|
|
311
|
+
state: 'spa-finished',
|
|
312
|
+
nextRuntimeConfig: newEmptyRuntimeConfig(state.runtimeConfig),
|
|
313
|
+
runtimeConfig: newEmptyRuntimeConfig(state.runtimeConfig, { keepTargeting: true })
|
|
314
|
+
};
|
|
315
|
+
state = finishedState;
|
|
316
|
+
return finishedState;
|
|
317
|
+
}
|
|
318
|
+
else if (state.state === 'spa-finished' || state.state === 'spa-requestAds') {
|
|
319
|
+
getLogger(state.runtimeConfig, window).debug('MoliGlobal', 'A previous requestAds() was slower than the following requestAds() call');
|
|
320
|
+
return state;
|
|
321
|
+
}
|
|
322
|
+
else {
|
|
323
|
+
return Promise.reject(`reached invalid state [${state.state}]`);
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
state = {
|
|
329
|
+
state: 'requestAds',
|
|
330
|
+
config: config,
|
|
331
|
+
modules: state.modules,
|
|
332
|
+
runtimeConfig: Object.freeze(state.runtimeConfig)
|
|
333
|
+
};
|
|
334
|
+
return adService
|
|
335
|
+
.initialize(config, state.runtimeConfig)
|
|
336
|
+
.then(config => adService.requestAds(config, state.runtimeConfig))
|
|
337
|
+
.then(() => {
|
|
338
|
+
state = {
|
|
339
|
+
state: 'finished',
|
|
340
|
+
config: config,
|
|
341
|
+
runtimeConfig: state.runtimeConfig,
|
|
342
|
+
modules: state.modules
|
|
343
|
+
};
|
|
344
|
+
afterRequestAds.forEach(hook => hook('finished'));
|
|
345
|
+
return Promise.resolve(state);
|
|
346
|
+
})
|
|
347
|
+
.catch(error => {
|
|
348
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', error);
|
|
349
|
+
state = {
|
|
350
|
+
state: 'error',
|
|
351
|
+
config: config,
|
|
352
|
+
runtimeConfig: state.runtimeConfig,
|
|
353
|
+
error: error,
|
|
354
|
+
modules: state.modules
|
|
355
|
+
};
|
|
356
|
+
afterRequestAds.forEach(hook => hook('error'));
|
|
357
|
+
return Promise.resolve(state);
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
case 'spa-requestAds':
|
|
362
|
+
case 'spa-finished': {
|
|
363
|
+
if (state.state === 'spa-requestAds') {
|
|
364
|
+
getLogger(state.runtimeConfig, window).debug('MoliGlobal', "requestAds is being called while the previous requestAds() hasn't finished yet");
|
|
365
|
+
}
|
|
366
|
+
setABtestTargeting();
|
|
367
|
+
addDomainLabel(state.config.domain);
|
|
368
|
+
const { modules } = state;
|
|
369
|
+
const afterRequestAds = state.nextRuntimeConfig.hooks.afterRequestAds;
|
|
370
|
+
const beforeRequestAds = state.nextRuntimeConfig.hooks.beforeRequestAds;
|
|
371
|
+
const currentState = state;
|
|
372
|
+
beforeRequestAds.forEach(hook => {
|
|
373
|
+
try {
|
|
374
|
+
hook(currentState.config, state.runtimeConfig);
|
|
375
|
+
}
|
|
376
|
+
catch (e) {
|
|
377
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', 'beforeRequestAds hook failed', e);
|
|
378
|
+
}
|
|
379
|
+
});
|
|
380
|
+
const { initialized, href, nextRuntimeConfig } = state;
|
|
381
|
+
state = {
|
|
382
|
+
...currentState,
|
|
383
|
+
state: 'spa-requestAds',
|
|
384
|
+
runtimeConfig: newEmptyRuntimeConfig(state.nextRuntimeConfig, { keepTargeting: true }),
|
|
385
|
+
nextRuntimeConfig: newEmptyRuntimeConfig(state.runtimeConfig)
|
|
386
|
+
};
|
|
387
|
+
return initialized
|
|
388
|
+
.then(config => {
|
|
389
|
+
const validation = config.spa?.validateLocation ?? 'href';
|
|
390
|
+
if (!allowRequestAds(validation, href, window.location)) {
|
|
391
|
+
return Promise.reject(`You are trying to refresh ads on the same page, which is not allowed. Using ${validation} for validation.`);
|
|
392
|
+
}
|
|
393
|
+
return adService.requestAds(config, nextRuntimeConfig).then(() => config);
|
|
394
|
+
})
|
|
395
|
+
.then(config => {
|
|
396
|
+
const runtimeConfig = state.runtimeConfig;
|
|
397
|
+
if (state.runtimeConfig.refreshSlots.length > 0) {
|
|
398
|
+
adService.refreshAdSlots(state.runtimeConfig.refreshSlots, config, state.runtimeConfig);
|
|
399
|
+
}
|
|
400
|
+
if (state.runtimeConfig.refreshBuckets.length > 0) {
|
|
401
|
+
state.runtimeConfig.refreshBuckets.forEach(bucket => {
|
|
402
|
+
adService.refreshBucket(bucket.bucket, config, runtimeConfig, bucket.options);
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
state = {
|
|
406
|
+
state: 'spa-finished',
|
|
407
|
+
config: config,
|
|
408
|
+
initialized,
|
|
409
|
+
modules,
|
|
410
|
+
href: window.location.href,
|
|
411
|
+
runtimeConfig: state.runtimeConfig,
|
|
412
|
+
nextRuntimeConfig: newEmptyRuntimeConfig(state.runtimeConfig)
|
|
413
|
+
};
|
|
414
|
+
afterRequestAds.forEach(hook => hook('spa-finished'));
|
|
415
|
+
return state;
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
case 'requestAds': {
|
|
419
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', 'Trying to requestAds twice. Already requesting ads.');
|
|
420
|
+
return Promise.reject();
|
|
421
|
+
}
|
|
422
|
+
case 'finished': {
|
|
423
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', 'Trying to requestAds twice. Already finished.');
|
|
424
|
+
return Promise.reject();
|
|
425
|
+
}
|
|
426
|
+
case 'error': {
|
|
427
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', 'Trying to requestAds twice. Already finished, but with an error.', state.error);
|
|
428
|
+
return Promise.reject();
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
function refreshAdSlot(domId, options) {
|
|
433
|
+
const domIds = typeof domId === 'string' ? [domId] : domId;
|
|
434
|
+
switch (state.state) {
|
|
435
|
+
case 'configurable':
|
|
436
|
+
case 'configured': {
|
|
437
|
+
state.runtimeConfig.refreshSlots.push(...domIds);
|
|
438
|
+
return Promise.resolve('queued');
|
|
439
|
+
}
|
|
440
|
+
case 'spa-requestAds':
|
|
441
|
+
state.runtimeConfig.refreshSlots.push(...domIds);
|
|
442
|
+
return Promise.resolve('queued');
|
|
443
|
+
case 'spa-finished':
|
|
444
|
+
const validateLocation = state.config.spa?.validateLocation ?? 'href';
|
|
445
|
+
if (allowRefreshAdSlot(validateLocation, state.href, window.location)) {
|
|
446
|
+
return adService
|
|
447
|
+
.refreshAdSlots(domIds, state.config, state.runtimeConfig, options)
|
|
448
|
+
.then(() => 'refreshed');
|
|
449
|
+
}
|
|
450
|
+
else {
|
|
451
|
+
state.nextRuntimeConfig.refreshSlots.push(...domIds);
|
|
452
|
+
return Promise.resolve('queued');
|
|
453
|
+
}
|
|
454
|
+
case 'finished':
|
|
455
|
+
case 'requestAds': {
|
|
456
|
+
return adService
|
|
457
|
+
.refreshAdSlots(domIds, state.config, state.runtimeConfig, options)
|
|
458
|
+
.then(() => 'refreshed');
|
|
459
|
+
}
|
|
460
|
+
default: {
|
|
461
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', `refreshAdSlot is not allowed in state ${state.state}`, state.config);
|
|
462
|
+
return Promise.reject(`not allowed in state ${state.state}`);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
function refreshInfiniteAdSlot(domId, idOfConfiguredSlot) {
|
|
467
|
+
switch (state.state) {
|
|
468
|
+
case 'configurable':
|
|
469
|
+
case 'configured': {
|
|
470
|
+
state.runtimeConfig.refreshInfiniteSlots.push({
|
|
471
|
+
artificialDomId: domId,
|
|
472
|
+
idOfConfiguredSlot: idOfConfiguredSlot
|
|
473
|
+
});
|
|
474
|
+
return Promise.resolve('queued');
|
|
475
|
+
}
|
|
476
|
+
case 'spa-requestAds':
|
|
477
|
+
state.runtimeConfig.refreshInfiniteSlots.push({
|
|
478
|
+
artificialDomId: domId,
|
|
479
|
+
idOfConfiguredSlot: idOfConfiguredSlot
|
|
480
|
+
});
|
|
481
|
+
return Promise.resolve('queued');
|
|
482
|
+
case 'spa-finished':
|
|
483
|
+
const validateLocation = state.config.spa?.validateLocation ?? 'href';
|
|
484
|
+
if (allowRefreshAdSlot(validateLocation, state.href, window.location)) {
|
|
485
|
+
state = {
|
|
486
|
+
...state,
|
|
487
|
+
config: addNewInfiniteSlotToConfig(state.config, idOfConfiguredSlot, domId, getLogger(state.runtimeConfig, window))
|
|
488
|
+
};
|
|
489
|
+
return adService
|
|
490
|
+
.refreshAdSlots([domId], state.config, state.runtimeConfig)
|
|
491
|
+
.then(() => 'refreshed');
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
state.runtimeConfig.refreshInfiniteSlots.push({
|
|
495
|
+
artificialDomId: domId,
|
|
496
|
+
idOfConfiguredSlot: idOfConfiguredSlot
|
|
497
|
+
});
|
|
498
|
+
return Promise.resolve('queued');
|
|
499
|
+
}
|
|
500
|
+
case 'finished':
|
|
501
|
+
case 'requestAds': {
|
|
502
|
+
state = {
|
|
503
|
+
...state,
|
|
504
|
+
config: addNewInfiniteSlotToConfig(state.config, idOfConfiguredSlot, domId, getLogger(state.runtimeConfig, window))
|
|
505
|
+
};
|
|
506
|
+
return adService
|
|
507
|
+
.refreshAdSlots([domId], state.config, state.runtimeConfig)
|
|
508
|
+
.then(() => 'refreshed');
|
|
509
|
+
}
|
|
510
|
+
default: {
|
|
511
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', `refreshInfiniteAdSlot is not allowed in state ${state.state}`, state.config);
|
|
512
|
+
return Promise.reject(`not allowed in state ${state.state}`);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
function refreshBucket(bucket, options) {
|
|
517
|
+
switch (state.state) {
|
|
518
|
+
case 'configurable': {
|
|
519
|
+
state.runtimeConfig.refreshBuckets.push({ bucket, options });
|
|
520
|
+
return Promise.resolve('queued');
|
|
521
|
+
}
|
|
522
|
+
case 'configured': {
|
|
523
|
+
state.runtimeConfig.refreshBuckets.push({ bucket, options });
|
|
524
|
+
return Promise.resolve('queued');
|
|
525
|
+
}
|
|
526
|
+
case 'spa-requestAds': {
|
|
527
|
+
state.runtimeConfig.refreshBuckets.push({ bucket, options });
|
|
528
|
+
return Promise.resolve('queued');
|
|
529
|
+
}
|
|
530
|
+
case 'spa-finished': {
|
|
531
|
+
const validateLocation = state.config.spa?.validateLocation ?? 'href';
|
|
532
|
+
if (allowRefreshAdSlot(validateLocation, state.href, window.location)) {
|
|
533
|
+
return adService
|
|
534
|
+
.refreshBucket(bucket, state.config, state.runtimeConfig, options)
|
|
535
|
+
.then(() => 'refreshed');
|
|
536
|
+
}
|
|
537
|
+
else {
|
|
538
|
+
state.runtimeConfig.refreshBuckets.push({ bucket, options });
|
|
539
|
+
return Promise.resolve('queued');
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
case 'finished':
|
|
543
|
+
case 'requestAds': {
|
|
544
|
+
return adService
|
|
545
|
+
.refreshBucket(bucket, state.config, state.runtimeConfig, options)
|
|
546
|
+
.then(() => 'refreshed');
|
|
547
|
+
}
|
|
548
|
+
default: {
|
|
549
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', `refreshAdSlot is not allowed in state ${state.state}`, state.config);
|
|
550
|
+
return Promise.reject(`not allowed in state ${state.state}`);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
function triggerDelay() {
|
|
555
|
+
window.dispatchEvent(new CustomEvent('h5v.trigger-delay'));
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
function getState() {
|
|
559
|
+
return state.state;
|
|
560
|
+
}
|
|
561
|
+
function openConsole(path) {
|
|
562
|
+
switch (state.state) {
|
|
563
|
+
case 'configurable': {
|
|
564
|
+
getLogger(state.runtimeConfig, window).error('MoliGlobal', 'Cannot open console before configuration');
|
|
565
|
+
break;
|
|
566
|
+
}
|
|
567
|
+
default: {
|
|
568
|
+
assetLoaderService
|
|
569
|
+
.loadScript({
|
|
570
|
+
assetUrl: path ??
|
|
571
|
+
`https://highfivve.github.io/moli-ad-tag/assets/bundle/v${packageJson.version}/console.js`,
|
|
572
|
+
loadMethod: AssetLoadMethod.TAG,
|
|
573
|
+
name: 'moli-debugger'
|
|
574
|
+
})
|
|
575
|
+
.catch(error => console.error('failed to load moli debugger', error));
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
function setABtestTargeting() {
|
|
580
|
+
const key = 'ABtest';
|
|
581
|
+
const params = parseQueryString(window.location.search);
|
|
582
|
+
const param = params.get(key);
|
|
583
|
+
const abTest = param ? Number(param) : Math.floor(Math.random() * 100) + 1;
|
|
584
|
+
setTargeting(key, abTest.toString());
|
|
585
|
+
}
|
|
586
|
+
function addDomainLabel(domainFromConfig) {
|
|
587
|
+
const domain = domainFromConfig || extractTopPrivateDomainFromHostname(window.location.hostname);
|
|
588
|
+
if (domain) {
|
|
589
|
+
addLabel(domain);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
function newEmptyRuntimeConfig(previous, options) {
|
|
593
|
+
return {
|
|
594
|
+
environment: previous?.environment ?? 'production',
|
|
595
|
+
hooks: {
|
|
596
|
+
beforeRequestAds: previous?.hooks.beforeRequestAds ?? [],
|
|
597
|
+
afterRequestAds: previous?.hooks.afterRequestAds ?? []
|
|
598
|
+
},
|
|
599
|
+
logger: previous?.logger ?? undefined,
|
|
600
|
+
adUnitPathVariables: options?.keepTargeting === true ? (previous?.adUnitPathVariables ?? {}) : {},
|
|
601
|
+
labels: options?.keepTargeting === true ? (previous?.labels ?? []) : [],
|
|
602
|
+
keyValues: options?.keepTargeting === true ? (previous?.keyValues ?? {}) : {},
|
|
603
|
+
refreshSlots: [],
|
|
604
|
+
refreshInfiniteSlots: [],
|
|
605
|
+
refreshBuckets: [],
|
|
606
|
+
adPipelineConfig: {
|
|
607
|
+
initSteps: [],
|
|
608
|
+
configureSteps: [],
|
|
609
|
+
prepareRequestAdsSteps: [],
|
|
610
|
+
requestBidsSteps: [],
|
|
611
|
+
prebidBidsBackHandler: previous?.adPipelineConfig.prebidBidsBackHandler ?? []
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
}
|
|
615
|
+
const que = {
|
|
616
|
+
push(cmd) {
|
|
617
|
+
cmd(moliWindow.moli);
|
|
618
|
+
}
|
|
619
|
+
};
|
|
620
|
+
return {
|
|
621
|
+
que: que,
|
|
622
|
+
version: packageJson.version,
|
|
623
|
+
setTargeting: setTargeting,
|
|
624
|
+
addLabel: addLabel,
|
|
625
|
+
setLogger: setLogger,
|
|
626
|
+
setAdUnitPathVariables: setAdUnitPathVariables,
|
|
627
|
+
resolveAdUnitPath: resolveAdUnitPath,
|
|
628
|
+
beforeRequestAds: beforeRequestAds,
|
|
629
|
+
afterRequestAds: afterRequestAds,
|
|
630
|
+
getConfig: getConfig,
|
|
631
|
+
getRuntimeConfig: getRuntimeConfig,
|
|
632
|
+
getPageTargeting: getPageTargeting,
|
|
633
|
+
registerModule: registerModule,
|
|
634
|
+
configure: configure,
|
|
635
|
+
requestAds: requestAds,
|
|
636
|
+
refreshAdSlot: refreshAdSlot,
|
|
637
|
+
refreshBucket: refreshBucket,
|
|
638
|
+
refreshInfiniteAdSlot: refreshInfiniteAdSlot,
|
|
639
|
+
triggerDelay: triggerDelay,
|
|
640
|
+
getState: getState,
|
|
641
|
+
openConsole: openConsole,
|
|
642
|
+
addEventListener: eventService.addEventListener,
|
|
643
|
+
removeEventListener: eventService.removeEventListener
|
|
644
|
+
};
|
|
645
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { createMoliTag } from './moli';
|
|
2
|
+
export const initAdTag = (window) => {
|
|
3
|
+
const moliWindow = window;
|
|
4
|
+
const queueCommands = moliWindow.moli
|
|
5
|
+
? [...moliWindow.moli.que] || []
|
|
6
|
+
: [];
|
|
7
|
+
const moli = createMoliTag(window);
|
|
8
|
+
moliWindow.moli = moli;
|
|
9
|
+
queueCommands.forEach(cmd => cmd(moli));
|
|
10
|
+
return moli;
|
|
11
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { getDefaultLogger } from '../util/logging';
|
|
2
|
+
export const prebidOutstreamRenderer = (domId, url, config = {}) => ({
|
|
3
|
+
url: url,
|
|
4
|
+
render: bid => renderPrebidOutstream(bid, domId, config),
|
|
5
|
+
backupOnly: true
|
|
6
|
+
});
|
|
7
|
+
export const renderPrebidOutstream = (bid, domId, config = {}) => {
|
|
8
|
+
if (!bid.renderer) {
|
|
9
|
+
getDefaultLogger().error('Can not initialize prebid outstream player, because bid.renderer is not defined');
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
bid.renderer.push(() => window.outstreamPlayer?.(bid, domId, config));
|
|
13
|
+
};
|