@highfivve/ad-tag 5.8.34 → 5.9.1

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/lib/ads/a9.js CHANGED
@@ -126,7 +126,7 @@ export const a9ClearTargetingStep = () => mkPrepareRequestAdsStep('a9-clear-targ
126
126
  adSlot
127
127
  .getTargetingKeys()
128
128
  .filter(key => key === 'amznp' || key === 'amznsz' || key === 'amznbid')
129
- .forEach(key => adSlot.clearTargeting(key));
129
+ .forEach(key => adSlot.setConfig({ targeting: { [key]: null } }));
130
130
  });
131
131
  resolve();
132
132
  });
@@ -64,7 +64,7 @@ export class AdService {
64
64
  requestBids: [],
65
65
  requestAds: () => Promise.resolve()
66
66
  }, getDefaultLogger(), this.window, createGlobalAuctionContext(this.window, getDefaultLogger(), this.eventService));
67
- this.initialize = (config, runtimeConfig) => {
67
+ this.initialize = (config, runtimeConfig, isLabelConditionMet = () => false) => {
68
68
  const env = AdService.getEnvironment(runtimeConfig);
69
69
  const adServer = config.adServer || 'gam';
70
70
  const isGam = adServer === 'gam';
@@ -100,7 +100,7 @@ export class AdService {
100
100
  prepareRequestAds.push(a9ClearTargetingStep());
101
101
  requestBids.push(a9RequestBids(config.a9));
102
102
  }
103
- const globalAuctionContext = createGlobalAuctionContext(this.window, this.logger, this.eventService, config.globalAuctionContext);
103
+ const globalAuctionContext = createGlobalAuctionContext(this.window, this.logger, this.eventService, config.globalAuctionContext, isLabelConditionMet);
104
104
  configure.push(globalAuctionContext.configureStep());
105
105
  init.push(...runtimeConfig.adPipelineConfig.initSteps);
106
106
  configure.push(...runtimeConfig.adPipelineConfig.configureSteps);
@@ -0,0 +1,8 @@
1
+ export const resolveOverridableConfig = (base, isLabelConditionMet) => {
2
+ const { overrides = [], ...defaultConfig } = base;
3
+ const matchedOverrideIndex = overrides.findIndex(isLabelConditionMet);
4
+ const match = overrides[matchedOverrideIndex];
5
+ return match
6
+ ? { config: match.config, matchedOverrideIndex, matchedCondition: match }
7
+ : { config: defaultConfig, matchedOverrideIndex: -1 };
8
+ };
@@ -5,42 +5,59 @@ import { createPreviousBidCpms } from './auctions/previousBidCpms';
5
5
  import { mkConfigureStep } from './adPipeline';
6
6
  import { createInterstitialContext } from 'ad-tag/ads/auctions/interstitialContext';
7
7
  import { createTrackWinningBidder } from 'ad-tag/ads/auctions/trackWinningBidder';
8
- export const createGlobalAuctionContext = (window, logger, eventService, config = {}) => {
9
- const trackWinningBidder = config.trackWinningBidder?.enabled
8
+ import { resolveOverridableConfig } from 'ad-tag/ads/configOverrides';
9
+ export const createGlobalAuctionContext = (window, logger, eventService, config = {}, isLabelConditionMet = () => false) => {
10
+ const resolveFeature = (base, feature) => {
11
+ if (!base) {
12
+ return undefined;
13
+ }
14
+ const { config: resolved, matchedOverrideIndex, matchedCondition } = resolveOverridableConfig(base, isLabelConditionMet);
15
+ if (matchedOverrideIndex >= 0) {
16
+ logger.debug('GlobalAuctionContext', `feature ${feature}: applying config override #${matchedOverrideIndex}`, matchedCondition);
17
+ }
18
+ return resolved;
19
+ };
20
+ const trackWinningBidderConfig = resolveFeature(config.trackWinningBidder, 'trackWinningBidder');
21
+ const biddersDisablingConfig = resolveFeature(config.biddersDisabling, 'biddersDisabling');
22
+ const adRequestThrottlingConfig = resolveFeature(config.adRequestThrottling, 'adRequestThrottling');
23
+ const frequencyCapConfig = resolveFeature(config.frequencyCap, 'frequencyCap');
24
+ const previousBidCpmsConfig = resolveFeature(config.previousBidCpms, 'previousBidCpms');
25
+ const interstitialConfig = resolveFeature(config.interstitial, 'interstitial');
26
+ const trackWinningBidder = trackWinningBidderConfig?.enabled
10
27
  ? createTrackWinningBidder()
11
28
  : undefined;
12
- const biddersDisabling = config.biddersDisabling?.enabled
13
- ? createBiddersDisabling(config.biddersDisabling, window)
29
+ const biddersDisabling = biddersDisablingConfig?.enabled
30
+ ? createBiddersDisabling(biddersDisablingConfig, window)
14
31
  : undefined;
15
- const adRequestThrottling = config.adRequestThrottling?.enabled
16
- ? createAdRequestThrottling(config.adRequestThrottling, window)
32
+ const adRequestThrottling = adRequestThrottlingConfig?.enabled
33
+ ? createAdRequestThrottling(adRequestThrottlingConfig, window)
17
34
  : undefined;
18
- const frequencyCapping = config.frequencyCap?.enabled
19
- ? createFrequencyCapping(config.frequencyCap, window, window.Date.now, logger)
35
+ const frequencyCapping = frequencyCapConfig?.enabled
36
+ ? createFrequencyCapping(frequencyCapConfig, window, window.Date.now, logger)
20
37
  : undefined;
21
- const previousBidCpms = config.previousBidCpms?.enabled ? createPreviousBidCpms() : undefined;
22
- const interstitial = config.interstitial?.enabled
23
- ? createInterstitialContext(config.interstitial, window, window.Date.now, logger)
38
+ const previousBidCpms = previousBidCpmsConfig?.enabled ? createPreviousBidCpms() : undefined;
39
+ const interstitial = interstitialConfig?.enabled
40
+ ? createInterstitialContext(interstitialConfig, window, window.Date.now, logger)
24
41
  : undefined;
25
42
  window.pbjs = window.pbjs || { que: [] };
26
43
  window.googletag = window.googletag || {};
27
44
  window.googletag.cmd = window.googletag.cmd || [];
28
- if (config.biddersDisabling?.enabled ||
29
- config.previousBidCpms?.enabled ||
30
- config.frequencyCap?.enabled ||
31
- config.interstitial?.enabled) {
45
+ if (biddersDisablingConfig?.enabled ||
46
+ previousBidCpmsConfig?.enabled ||
47
+ frequencyCapConfig?.enabled ||
48
+ interstitialConfig?.enabled) {
32
49
  window.pbjs.que.push(() => {
33
50
  window.pbjs.onEvent('auctionEnd', auction => {
34
51
  biddersDisabling?.onAuctionEnd(auction);
35
52
  interstitial?.onAuctionEnd(auction);
36
- if (config.previousBidCpms?.enabled && auction.bidsReceived) {
53
+ if (previousBidCpmsConfig?.enabled && auction.bidsReceived) {
37
54
  previousBidCpms?.onAuctionEnd(auction.bidsReceived);
38
55
  }
39
56
  frequencyCapping?.onAuctionEnd(auction);
40
57
  });
41
58
  });
42
59
  }
43
- if (config.adRequestThrottling?.enabled || config.frequencyCap?.enabled) {
60
+ if (adRequestThrottlingConfig?.enabled || frequencyCapConfig?.enabled) {
44
61
  window.googletag.cmd.push(() => {
45
62
  window.googletag.pubads().addEventListener('slotRequested', event => {
46
63
  adRequestThrottling?.onSlotRequested(event);
@@ -48,19 +65,19 @@ export const createGlobalAuctionContext = (window, logger, eventService, config
48
65
  });
49
66
  });
50
67
  }
51
- if (config.frequencyCap?.enabled || config.trackWinningBidder?.enabled) {
68
+ if (frequencyCapConfig?.enabled || trackWinningBidderConfig?.enabled) {
52
69
  window.pbjs.que.push(() => {
53
70
  window.pbjs.onEvent('bidWon', bid => {
54
- if (config.frequencyCap) {
71
+ if (frequencyCapConfig) {
55
72
  frequencyCapping?.onBidWon(bid);
56
73
  }
57
- if (config.trackWinningBidder) {
74
+ if (trackWinningBidderConfig) {
58
75
  trackWinningBidder?.onBidWon(bid);
59
76
  }
60
77
  });
61
78
  });
62
79
  }
63
- if (config.frequencyCap?.enabled) {
80
+ if (frequencyCapConfig?.enabled) {
64
81
  eventService.addEventListener('beforeRequestAds', () => {
65
82
  frequencyCapping?.beforeRequestAds();
66
83
  });
@@ -68,7 +85,7 @@ export const createGlobalAuctionContext = (window, logger, eventService, config
68
85
  frequencyCapping?.afterRequestAds();
69
86
  });
70
87
  }
71
- if (config.frequencyCap?.enabled || config.interstitial?.enabled) {
88
+ if (frequencyCapConfig?.enabled || interstitialConfig?.enabled) {
72
89
  window.googletag.cmd.push(() => {
73
90
  window.googletag.pubads().addEventListener('slotRenderEnded', event => {
74
91
  frequencyCapping?.onSlotRenderEnded(event);
@@ -28,9 +28,6 @@ const testAdSlot = (domId, adUnitPath) => ({
28
28
  getTargetingKeys() {
29
29
  return [];
30
30
  },
31
- clearTargeting(_key) {
32
- return;
33
- },
34
31
  getResponseInformation() {
35
32
  return null;
36
33
  },
@@ -44,16 +41,17 @@ const testAdSlot = (domId, adUnitPath) => ({
44
41
  const configureTargeting = (window, runtimeKeyValues, serverSideTargeting) => {
45
42
  const staticKeyValues = serverSideTargeting ? serverSideTargeting.keyValues : {};
46
43
  const excludes = serverSideTargeting?.adManagerExcludes ?? [];
44
+ const targeting = {};
47
45
  [staticKeyValues, runtimeKeyValues].forEach(keyValues => {
48
- Object.keys(keyValues)
49
- .filter(key => !excludes.includes(key))
50
- .forEach(key => {
51
- const value = keyValues[key];
52
- if (value) {
53
- window.googletag.pubads().setTargeting(key, value);
46
+ Object.entries(keyValues).forEach(([key, value]) => {
47
+ if (!excludes.includes(key) && value) {
48
+ targeting[key] = value;
54
49
  }
55
50
  });
56
51
  });
52
+ if (Object.keys(targeting).length > 0) {
53
+ window.googletag.setConfig({ targeting });
54
+ }
57
55
  };
58
56
  const useStandardGpt = (tcData, consentConfig) => {
59
57
  if (consentConfig?.useLimitedAds === false) {
@@ -188,7 +186,7 @@ export const gptLDeviceLabelKeyValue = () => mkPrepareRequestAdsStep('gpt-device
188
186
  return new Promise(resolve => {
189
187
  const deviceLabel = ctx.labelConfigService__.getDeviceLabel();
190
188
  ctx.logger__.debug('GAM', 'adding "device_label" key-value with values', deviceLabel);
191
- ctx.window__.googletag.pubads().setTargeting('device_label', deviceLabel);
189
+ ctx.window__.googletag.setConfig({ targeting: { device_label: deviceLabel } });
192
190
  resolve();
193
191
  });
194
192
  });
@@ -211,7 +209,7 @@ export const gptConsentKeyValue = () => mkPrepareRequestAdsStep('gpt-consent-key
211
209
  tcfapi.responses.TCPurpose.APPLY_MARKET_RESEARCH,
212
210
  tcfapi.responses.TCPurpose.DEVELOP_IMPROVE_PRODUCTS
213
211
  ].every(purpose => tcData.purpose.consents[purpose]);
214
- ctx.window__.googletag.pubads().setTargeting('consent', fullConsent ? 'full' : 'none');
212
+ ctx.window__.googletag.setConfig({ targeting: { consent: fullConsent ? 'full' : 'none' } });
215
213
  resolve();
216
214
  });
217
215
  });
@@ -296,7 +294,7 @@ export const gptDefineSlots = () => (context, slots) => {
296
294
  }
297
295
  }
298
296
  else {
299
- adSlot.clearTargeting(formatKey);
297
+ adSlot.setConfig({ targeting: { [formatKey]: null } });
300
298
  }
301
299
  context.window__.googletag.display(adSlot);
302
300
  }
@@ -68,9 +68,9 @@ export const createBlocklistedUrls = () => {
68
68
  const value = blocklistConfig.isBlocklistedValue || 'true';
69
69
  return getBlocklist(blocklistConfig.blocklist, ctx.assetLoaderService__, ctx.logger__)().then(blocklist => {
70
70
  if (isBlocklisted(blocklist, ctx.window__.location.href, ctx.logger__)) {
71
- ctx.window__.googletag
72
- .pubads()
73
- .setTargeting(key, value);
71
+ ctx.window__.googletag.setConfig({
72
+ targeting: { [key]: value }
73
+ });
74
74
  }
75
75
  });
76
76
  case 'block':
@@ -144,9 +144,9 @@ export const createSkin = () => {
144
144
  }
145
145
  if (skinConfig.targeting) {
146
146
  try {
147
- ctx.window__.googletag
148
- .pubads()
149
- .setTargeting(skinConfig.targeting.key, skinConfig.targeting.value ?? '1');
147
+ ctx.window__.googletag.setConfig({
148
+ targeting: { [skinConfig.targeting.key]: skinConfig.targeting.value ?? '1' }
149
+ });
150
150
  }
151
151
  catch (e) {
152
152
  ctx.logger__.error('SkinModule', e);
@@ -40,7 +40,9 @@ export const createPubstack = () => {
40
40
  }
41
41
  const pubstackAbTestCohort = extractPubstackAbTestCohort(ctx);
42
42
  if (pubstackAbTestCohort) {
43
- ctx.window__.googletag.pubads().setTargeting('pbstck_ab_test', pubstackAbTestCohort);
43
+ ctx.window__.googletag.setConfig({
44
+ targeting: { pbstck_ab_test: pubstackAbTestCohort }
45
+ });
44
46
  }
45
47
  return Promise.resolve();
46
48
  })
@@ -40,7 +40,7 @@ export const YieldOptimization = (testYieldOptimizationService) => {
40
40
  .then(() => yieldOptimizationService.getBrowser())
41
41
  .then(browser => {
42
42
  if (context.env__ === 'production' && adServer === 'gam') {
43
- context.window__.googletag.pubads().setTargeting('upr_browser', browser);
43
+ context.window__.googletag.setConfig({ targeting: { upr_browser: browser } });
44
44
  }
45
45
  });
46
46
  });
package/lib/ads/moli.js CHANGED
@@ -9,6 +9,7 @@ import * as adUnitPath from './adUnitPath';
9
9
  import { extractTopPrivateDomainFromHostname } from '../util/extractTopPrivateDomainFromHostname';
10
10
  import { detectGeoFromBrowser } from '../util/detectGeoFromTimezone';
11
11
  import { createLabelConfigService } from './labelConfigService';
12
+ import { resolveOverridableConfig } from './configOverrides';
12
13
  import { allowRefreshAdSlot, allowRequestAds } from './spa';
13
14
  import { QueryParameters } from 'ad-tag/util/queryParameters';
14
15
  import { BrowserStorageKeys } from 'ad-tag/util/browserStorageKeys';
@@ -244,21 +245,31 @@ export const createMoliTag = (window) => {
244
245
  getLogger(state.runtimeConfig, window).debug('MoliGlobal', 'configure modules', state.config.modules ?? {});
245
246
  const labelService = createLabelConfigService(state.config?.labelSizeConfig || [], state.runtimeConfig.labels, window);
246
247
  modules
247
- .filter(module => {
248
+ .map(module => {
248
249
  const moduleName = module.name;
249
- const moduleConfig = state.config?.modules?.[moduleName];
250
- if (moduleConfig?.labelCondition) {
251
- const areLabelConditionsMet = labelService.isLabelConditionMet(moduleConfig.labelCondition);
252
- if (!areLabelConditionsMet) {
253
- getLogger(state.runtimeConfig, window).debug('MoliGlobal', `skipping configuration of ${module.moduleType} module ${moduleName} due to label condition not met.`);
254
- return false;
255
- }
250
+ const base = state.config?.modules?.[moduleName];
251
+ if (!base) {
252
+ return null;
253
+ }
254
+ const { config: effectiveConfig, matchedOverrideIndex, matchedCondition } = resolveOverridableConfig(base, labelService.isLabelConditionMet);
255
+ if (matchedOverrideIndex >= 0) {
256
+ getLogger(state.runtimeConfig, window).debug('MoliGlobal', `module ${moduleName}: applying config override #${matchedOverrideIndex}`, matchedCondition);
256
257
  }
257
- return true;
258
+ if (effectiveConfig.labelCondition &&
259
+ !labelService.isLabelConditionMet(effectiveConfig.labelCondition)) {
260
+ getLogger(state.runtimeConfig, window).debug('MoliGlobal', `skipping configuration of ${module.moduleType} module ${moduleName} due to label condition not met.`);
261
+ return null;
262
+ }
263
+ const resolvedModulesConfig = {
264
+ ...state.config?.modules,
265
+ [moduleName]: effectiveConfig
266
+ };
267
+ return { module, resolvedModulesConfig };
258
268
  })
259
- .forEach(module => {
269
+ .filter((entry) => entry !== null)
270
+ .forEach(({ module, resolvedModulesConfig }) => {
260
271
  try {
261
- module.configure__(state.config?.modules ?? {});
272
+ module.configure__(resolvedModulesConfig);
262
273
  getLogger(state.runtimeConfig, window).debug('MoliGlobal', `configure ${module.moduleType} module ${module.name}`, module.config__());
263
274
  state.runtimeConfig.adPipelineConfig.initSteps.push(...module.initSteps__());
264
275
  state.runtimeConfig.adPipelineConfig.configureSteps.push(...module.configureSteps__());
@@ -296,7 +307,7 @@ export const createMoliTag = (window) => {
296
307
  const isSinglePageApp = config.spa?.enabled === true;
297
308
  if (isSinglePageApp) {
298
309
  const requestAdsRuntimeConfig = state.runtimeConfig;
299
- const initialized = adService.initialize(config, requestAdsRuntimeConfig);
310
+ const initialized = adService.initialize(config, requestAdsRuntimeConfig, labelService.isLabelConditionMet);
300
311
  state = {
301
312
  state: 'spa-requestAds',
302
313
  config: config,
@@ -348,7 +359,7 @@ export const createMoliTag = (window) => {
348
359
  runtimeConfig: Object.freeze(state.runtimeConfig)
349
360
  };
350
361
  return adService
351
- .initialize(config, state.runtimeConfig)
362
+ .initialize(config, state.runtimeConfig, labelService.isLabelConditionMet)
352
363
  .then(config => adService.requestAds(config, state.runtimeConfig))
353
364
  .then(() => {
354
365
  state = {
@@ -1,3 +1,3 @@
1
1
  export const packageJson = {
2
- version: '5.8.34'
2
+ version: '5.9.1'
3
3
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@highfivve/ad-tag",
3
- "version": "5.8.34",
3
+ "version": "5.9.1",
4
4
  "license": "Apache-2.0",
5
5
  "description": "An ad tag implementation called moli",
6
6
  "main": "./lib/index.js",