@highfivve/ad-tag 5.8.18 → 5.8.22

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.
@@ -0,0 +1,13 @@
1
+ export const createTrackWinningBidder = () => {
2
+ const lastWinningBidderByAdUnit = new Map();
3
+ const onBidWon = (winningBid) => {
4
+ lastWinningBidderByAdUnit.set(winningBid.adUnitCode, winningBid.bidderCode);
5
+ };
6
+ const getLastWinningBidderOnAdUnit = (slotId) => {
7
+ return lastWinningBidderByAdUnit.get(slotId);
8
+ };
9
+ return {
10
+ onBidWon,
11
+ getLastWinningBidderOnAdUnit
12
+ };
13
+ };
@@ -4,7 +4,11 @@ import { createFrequencyCapping } from './auctions/frequencyCapping';
4
4
  import { createPreviousBidCpms } from './auctions/previousBidCpms';
5
5
  import { mkConfigureStep } from './adPipeline';
6
6
  import { createInterstitialContext } from 'ad-tag/ads/auctions/interstitialContext';
7
+ import { createTrackWinningBidder } from 'ad-tag/ads/auctions/trackWinningBidder';
7
8
  export const createGlobalAuctionContext = (window, logger, eventService, config = {}) => {
9
+ const trackWinningBidder = config.trackWinningBidder?.enabled
10
+ ? createTrackWinningBidder()
11
+ : undefined;
8
12
  const biddersDisabling = config.biddersDisabling?.enabled
9
13
  ? createBiddersDisabling(config.biddersDisabling, window)
10
14
  : undefined;
@@ -44,14 +48,19 @@ export const createGlobalAuctionContext = (window, logger, eventService, config
44
48
  });
45
49
  });
46
50
  }
47
- if (config.frequencyCap?.enabled) {
51
+ if (config.frequencyCap?.enabled || config.trackWinningBidder?.enabled) {
48
52
  window.pbjs.que.push(() => {
49
53
  window.pbjs.onEvent('bidWon', bid => {
50
54
  if (config.frequencyCap) {
51
55
  frequencyCapping?.onBidWon(bid);
52
56
  }
57
+ if (config.trackWinningBidder) {
58
+ trackWinningBidder?.onBidWon(bid);
59
+ }
53
60
  });
54
61
  });
62
+ }
63
+ if (config.frequencyCap?.enabled) {
55
64
  eventService.addEventListener('beforeRequestAds', () => {
56
65
  frequencyCapping?.beforeRequestAds();
57
66
  });
@@ -86,6 +95,9 @@ export const createGlobalAuctionContext = (window, logger, eventService, config
86
95
  getLastBidCpmsOfAdUnit(slotId) {
87
96
  return previousBidCpms?.getLastBidCpms(slotId) ?? [];
88
97
  },
98
+ getLastWinningBidderOfAdUnit(slotId) {
99
+ return trackWinningBidder?.getLastWinningBidderOnAdUnit(slotId);
100
+ },
89
101
  isBidderDisabled(domId, bidder) {
90
102
  return biddersDisabling?.isBidderDisabled(domId, bidder) ?? false;
91
103
  },
@@ -61,7 +61,7 @@ export class AdVisibilityService {
61
61
  this.setUpdateTimer(true);
62
62
  this.logger?.debug('AdVisibilityService', 'initialized');
63
63
  }
64
- trackSlot(slot, refreshCallback, advertiserId, companyIds) {
64
+ trackSlot(slot, refreshCallback, advertiserId, companyIds, lastWinningBidderCode) {
65
65
  const slotDomId = slot.getSlotElementId();
66
66
  const domElement = this.observedDomElementForSlot(slot);
67
67
  if (domElement) {
@@ -81,7 +81,8 @@ export class AdVisibilityService {
81
81
  ? this.window.performance.now()
82
82
  : undefined,
83
83
  durationVisibleSum: 0,
84
- refreshCallback: refreshCallback
84
+ refreshCallback: refreshCallback,
85
+ lastWinningBidderCode
85
86
  });
86
87
  if (this.intersectionObserver &&
87
88
  (domElement.targetOverride || this.useIntersectionObserver)) {
@@ -110,7 +111,7 @@ export class AdVisibilityService {
110
111
  });
111
112
  Array.from(this.visibilityRecords.values())
112
113
  .filter(record => {
113
- const interval = this.refreshIntervalOverrides[record.slot.getSlotElementId()] || this.refreshInterval;
114
+ const interval = this.resolveRefreshInterval(record);
114
115
  return record.durationVisibleSum > interval;
115
116
  })
116
117
  .forEach(record => {
@@ -120,6 +121,16 @@ export class AdVisibilityService {
120
121
  record.refreshCallback(record.slot);
121
122
  });
122
123
  }
124
+ resolveRefreshInterval(record) {
125
+ const override = this.refreshIntervalOverrides[record.slot.getSlotElementId()];
126
+ if (typeof override === 'number') {
127
+ return override;
128
+ }
129
+ const bidderOverride = record.lastWinningBidderCode && override?.bidders
130
+ ? override.bidders[record.lastWinningBidderCode]
131
+ : undefined;
132
+ return bidderOverride ?? override?.default ?? this.refreshInterval;
133
+ }
123
134
  handleObservedAdVisibilityChanged(entries) {
124
135
  entries.forEach(entry => {
125
136
  const visibilityRecord = this.visibilityRecordForEntry(entry);
@@ -10,6 +10,7 @@ export const createAdReload = () => {
10
10
  let initialized = false;
11
11
  let moduleConfig = null;
12
12
  let adVisibilityService;
13
+ let globalAuctionContext;
13
14
  const config__ = () => moduleConfig;
14
15
  const isInitialized = () => initialized;
15
16
  const configure__ = (mConfig) => {
@@ -113,7 +114,8 @@ export const createAdReload = () => {
113
114
  }
114
115
  const slotAlreadyTracked = !!adVisibilityService?.isSlotTracked(slotDomId);
115
116
  if (trackingSlotAllowed) {
116
- adVisibilityService.trackSlot(googleTagSlot, reloadAdSlotCallback, advertiserId, companyIds);
117
+ const bidderCode = globalAuctionContext?.getLastWinningBidderOfAdUnit(slotDomId);
118
+ adVisibilityService.trackSlot(googleTagSlot, reloadAdSlotCallback, advertiserId, companyIds, bidderCode);
117
119
  }
118
120
  else if (slotAlreadyTracked) {
119
121
  adVisibilityService.removeSlotTracking(googleTagSlot);
@@ -128,6 +130,7 @@ export const createAdReload = () => {
128
130
  return;
129
131
  }
130
132
  context.logger__.debug('AdReload', 'initialize moli ad reload module');
133
+ globalAuctionContext = context.auction__;
131
134
  setupAdVisibilityService(config, context.window__, context.logger__);
132
135
  setupSlotRenderListener(config, slotsToMonitor, reloadAdSlotCallback, context.window__, context.logger__);
133
136
  initialized = true;
@@ -0,0 +1,43 @@
1
+ export const createEventTracker = (url, batchSize, batchDelay, logger) => {
2
+ let batch = [];
3
+ let timer = null;
4
+ const processBatch = () => {
5
+ const currentBatch = batch;
6
+ batch = [];
7
+ fetch(url, {
8
+ method: 'POST',
9
+ headers: {
10
+ 'Content-Type': 'application/json'
11
+ },
12
+ body: JSON.stringify({ events: currentBatch })
13
+ })
14
+ .then(response => {
15
+ if (response.ok) {
16
+ logger?.debug(`moli-analytics: Successfully sent analytics batch of ${currentBatch.length} events`);
17
+ }
18
+ else {
19
+ logger?.error(`moli-analytics: Failed to send analytics batch: ${response.statusText}`);
20
+ }
21
+ })
22
+ .catch(error => {
23
+ logger?.error(`moli-analytics: Failed to send analytics batch: ${error}`);
24
+ });
25
+ };
26
+ const track = (event) => {
27
+ logger?.debug('moli-analytics: event', event);
28
+ batch.push(event);
29
+ if (timer != null) {
30
+ clearTimeout(timer);
31
+ timer = null;
32
+ }
33
+ if (batch.length >= batchSize) {
34
+ processBatch();
35
+ }
36
+ else {
37
+ timer = setTimeout(processBatch, batchDelay);
38
+ }
39
+ };
40
+ return {
41
+ track
42
+ };
43
+ };
@@ -0,0 +1,21 @@
1
+ export const mapGPTSlotRenderEnded = (event, context, adContext) => {
2
+ const timestamp = Date.now();
3
+ return {
4
+ v: 1,
5
+ type: 'gpt.slotRenderEnded',
6
+ publisher: context.publisher,
7
+ pageViewId: context.pageViewId,
8
+ userId: adContext.window__.pbjs.getUserIds().pubcid,
9
+ timestamp,
10
+ analyticsLabels: context.analyticsLabels,
11
+ data: {
12
+ auctionId: context.auctionId,
13
+ gpid: context.gpid,
14
+ adUnitPath: event.slot.getAdUnitPath(),
15
+ adUnitName: context.adUnitName,
16
+ adUnitCode: event.slot.getSlotElementId(),
17
+ size: Array.isArray(event.size) ? event.size.join('x') : event.size,
18
+ isEmpty: event.isEmpty
19
+ }
20
+ };
21
+ };
@@ -0,0 +1,16 @@
1
+ import { mapPrebidAuctionEnd } from 'ad-tag/ads/modules/moli-analytics/events/prebidAuctionEnd';
2
+ import { mapPrebidBidWon } from 'ad-tag/ads/modules/moli-analytics/events/prebidBidWon';
3
+ import { mapGPTSlotRenderEnded } from 'ad-tag/ads/modules/moli-analytics/events/gptSlotRenderEnded';
4
+ import { mapPageView } from 'ad-tag/ads/modules/moli-analytics/events/pageView';
5
+ export const eventMapper = {
6
+ prebid: {
7
+ auctionEnd: mapPrebidAuctionEnd,
8
+ bidWon: mapPrebidBidWon
9
+ },
10
+ gpt: {
11
+ slotRenderEnded: mapGPTSlotRenderEnded
12
+ },
13
+ page: {
14
+ view: mapPageView
15
+ }
16
+ };
@@ -0,0 +1,31 @@
1
+ const parseUTM = (search) => {
2
+ const params = new URLSearchParams(search);
3
+ const v = (k) => params.get(k) || null;
4
+ return {
5
+ source: v('utm_source'),
6
+ medium: v('utm_medium'),
7
+ campaign: v('utm_campaign'),
8
+ content: v('utm_content'),
9
+ term: v('utm_term')
10
+ };
11
+ };
12
+ export const mapPageView = (context, adContext) => {
13
+ const timestamp = Date.now();
14
+ const userIds = adContext.window__.pbjs.getUserIds ? adContext.window__.pbjs.getUserIds() : {};
15
+ return {
16
+ v: 1,
17
+ type: 'page.view',
18
+ publisher: context.publisher,
19
+ pageViewId: context.pageViewId,
20
+ userId: userIds?.pubcid,
21
+ timestamp,
22
+ analyticsLabels: context.analyticsLabels,
23
+ data: {
24
+ sessionId: context.session.getId(),
25
+ device: adContext.labelConfigService__.getDeviceLabel(),
26
+ domain: adContext.window__.moli.resolveAdUnitPath('{domain}'),
27
+ ua: adContext.window__.navigator.userAgent,
28
+ utm: parseUTM(adContext.window__.location.search)
29
+ }
30
+ };
31
+ };
@@ -0,0 +1,39 @@
1
+ export const mapPrebidAuctionEnd = (event, context, adContext) => {
2
+ const timestamp = Date.now();
3
+ return {
4
+ v: 1,
5
+ type: 'prebid.auctionEnd',
6
+ publisher: context.publisher,
7
+ pageViewId: context.pageViewId,
8
+ userId: adContext.window__.pbjs.getUserIds().pubcid,
9
+ timestamp,
10
+ analyticsLabels: context.analyticsLabels,
11
+ data: {
12
+ auctionId: event.auctionId,
13
+ adUnits: Array.from(new Map((event.adUnits || []).map(adUnit => [
14
+ adUnit.code,
15
+ {
16
+ code: adUnit.code,
17
+ adUnitName: adUnit.pubstack?.adUnitName || adUnit.code,
18
+ gpid: adUnit.ortb2Imp?.ext?.gpid
19
+ }
20
+ ])).values()),
21
+ bidderRequests: (event.bidderRequests || []).map(request => {
22
+ return {
23
+ bidderCode: request.bidderCode,
24
+ bids: (request.bids || []).map(bid => ({
25
+ adUnitCode: bid.adUnitCode
26
+ }))
27
+ };
28
+ }),
29
+ bidsReceived: (event.bidsReceived || []).map(bid => ({
30
+ bidder: bid.bidder,
31
+ adUnitCode: bid.adUnitCode,
32
+ size: bid.size,
33
+ currency: bid.currency,
34
+ cpm: bid.cpm,
35
+ timeToRespond: bid.timeToRespond
36
+ }))
37
+ }
38
+ };
39
+ };
@@ -0,0 +1,23 @@
1
+ export const mapPrebidBidWon = (event, context, adContext) => {
2
+ const timestamp = Date.now();
3
+ return {
4
+ v: 1,
5
+ type: 'prebid.bidWon',
6
+ publisher: context.publisher,
7
+ pageViewId: context.pageViewId,
8
+ userId: adContext.window__.pbjs.getUserIds().pubcid,
9
+ timestamp,
10
+ analyticsLabels: context.analyticsLabels,
11
+ data: {
12
+ auctionId: event.auctionId,
13
+ gpid: context.gpid,
14
+ bidderCode: event.bidderCode,
15
+ adUnitCode: event.adUnitCode,
16
+ size: event.size,
17
+ currency: event.currency,
18
+ cpm: event.cpm,
19
+ status: event.status,
20
+ timeToRespond: event.timeToRespond
21
+ }
22
+ };
23
+ };
@@ -0,0 +1,161 @@
1
+ import { mkInitStep } from 'ad-tag/ads/adPipeline';
2
+ import { uuidV4 } from 'ad-tag/util/uuid';
3
+ import { createSession } from 'ad-tag/ads/modules/moli-analytics/session';
4
+ import { createEventTracker } from 'ad-tag/ads/modules/moli-analytics/eventTracker';
5
+ import { eventMapper } from 'ad-tag/ads/modules/moli-analytics/events';
6
+ import { extractPubstackAbTestCohort } from '../pubstack/abTest';
7
+ const SESSION_TTL_MIN = 30;
8
+ export const DEFAULT_CONFIG = {
9
+ batchSize: 4,
10
+ batchDelay: 1000
11
+ };
12
+ export const MoliAnalytics = () => {
13
+ let config;
14
+ let eventContext;
15
+ let eventTracker;
16
+ let adUnitsMap = new Map();
17
+ const generatePageViewId = (adPipelineContext) => `pv-${uuidV4(adPipelineContext.window__)}`;
18
+ const handleAuctionEnd = (event, adPipelineContext) => {
19
+ const auctionEnd = eventMapper.prebid.auctionEnd(event, eventContext, adPipelineContext);
20
+ for (const adUnit of auctionEnd.data.adUnits) {
21
+ adUnitsMap.set(adUnit.code, {
22
+ auctionId: auctionEnd.data.auctionId,
23
+ adUnitName: adUnit.adUnitName,
24
+ gpid: adUnit.gpid
25
+ });
26
+ }
27
+ eventTracker.track(auctionEnd);
28
+ };
29
+ const handleBidWon = (event, adPipelineContext) => {
30
+ const adUnitData = adUnitsMap.get(event.adUnitCode);
31
+ eventTracker.track(eventMapper.prebid.bidWon(event, {
32
+ ...eventContext,
33
+ gpid: adUnitData?.gpid || ''
34
+ }, adPipelineContext));
35
+ };
36
+ const handleSlotRenderEnded = (event, adPipelineContext) => {
37
+ const adUnitCode = event.slot.getSlotElementId();
38
+ const adUnitData = adUnitsMap.get(adUnitCode);
39
+ eventTracker.track(eventMapper.gpt.slotRenderEnded(event, {
40
+ ...eventContext,
41
+ auctionId: adUnitData?.auctionId || '',
42
+ adUnitName: adUnitData?.adUnitName || adUnitCode,
43
+ gpid: adUnitData?.gpid || ''
44
+ }, adPipelineContext));
45
+ };
46
+ const handlePageView = (adPipelineContext) => {
47
+ eventContext.pageViewId = generatePageViewId(adPipelineContext);
48
+ eventTracker.track(eventMapper.page.view(eventContext, adPipelineContext));
49
+ };
50
+ const configValid = (config, logger) => {
51
+ if (!config) {
52
+ logger.error('moli-analytics: not configured');
53
+ return false;
54
+ }
55
+ if (!config.publisher) {
56
+ logger.error('moli-analytics: publisher is required');
57
+ return false;
58
+ }
59
+ if (!config.url) {
60
+ logger.error('moli-analytics: url is required');
61
+ return false;
62
+ }
63
+ if (!config.batchSize || config.batchSize < 1) {
64
+ logger.error('moli-analytics: batchSize must be greater than 0');
65
+ return false;
66
+ }
67
+ if (!config.batchDelay || config.batchDelay < 1) {
68
+ logger.error('moli-analytics: batchDelay must be greater than 0');
69
+ return false;
70
+ }
71
+ return true;
72
+ };
73
+ const initMoliAnalytics = async (adPipelineContext) => {
74
+ if (!configValid(config, adPipelineContext.logger__)) {
75
+ return Promise.reject('failed to initialize moli analytics: invalid configuration');
76
+ }
77
+ eventContext = {
78
+ publisher: config.publisher,
79
+ session: createSession(adPipelineContext.window__, SESSION_TTL_MIN),
80
+ pageViewId: generatePageViewId(adPipelineContext),
81
+ analyticsLabels: null
82
+ };
83
+ eventTracker = createEventTracker(config.url, config.batchSize, config.batchDelay, adPipelineContext.logger__);
84
+ if (adPipelineContext.config__.configVersion?.identifier ||
85
+ adPipelineContext.config__.configVersion?.versionVariant) {
86
+ eventContext.analyticsLabels = {
87
+ ab_test: adPipelineContext.config__.configVersion?.identifier || null,
88
+ variant: adPipelineContext.config__.configVersion?.versionVariant || null
89
+ };
90
+ }
91
+ if (adPipelineContext.config__.spa?.enabled) {
92
+ adPipelineContext.window__.moli.addEventListener('afterRequestAds', event => {
93
+ if (event.state === 'spa-finished' || event.state === 'finished') {
94
+ handlePageView(adPipelineContext);
95
+ }
96
+ });
97
+ }
98
+ const setupPrebid = async () => {
99
+ if (typeof adPipelineContext.window__.pbjs.getUserIdsAsync === 'function') {
100
+ await adPipelineContext.window__.pbjs.getUserIdsAsync();
101
+ }
102
+ handlePageView(adPipelineContext);
103
+ adPipelineContext.window__.pbjs.onEvent('auctionEnd', (event) => handleAuctionEnd(event, adPipelineContext));
104
+ adPipelineContext.window__.pbjs.onEvent('bidWon', (event) => handleBidWon(event, adPipelineContext));
105
+ };
106
+ if (typeof adPipelineContext.window__.pbjs.onEvent === 'function') {
107
+ await setupPrebid();
108
+ }
109
+ else {
110
+ adPipelineContext.window__.pbjs.que.push(setupPrebid);
111
+ }
112
+ const setupGPT = () => {
113
+ adPipelineContext.window__.googletag
114
+ .pubads()
115
+ .addEventListener('slotRenderEnded', (event) => handleSlotRenderEnded(event, adPipelineContext));
116
+ };
117
+ if (typeof adPipelineContext.window__.googletag.pubads === 'function') {
118
+ setupGPT();
119
+ }
120
+ else {
121
+ adPipelineContext.window__.googletag.cmd.push(setupGPT);
122
+ }
123
+ return Promise.resolve();
124
+ };
125
+ const setAnalyticsLabels = (ctx) => {
126
+ const pubstackAbTestCohort = extractPubstackAbTestCohort(ctx);
127
+ const moliConfigVariant = ctx.config__.configVersion?.versionVariant;
128
+ ctx.window__.pbjs.que.push(() => ctx.window__.pbjs.mergeConfig({
129
+ analyticsLabels: {
130
+ pubstackAbCohort: pubstackAbTestCohort,
131
+ configVariant: moliConfigVariant
132
+ }
133
+ }));
134
+ return Promise.resolve();
135
+ };
136
+ return {
137
+ name: 'moli-analytics',
138
+ description: 'ad events tracking and analytics module',
139
+ moduleType: 'reporting',
140
+ config__() {
141
+ return config;
142
+ },
143
+ configure__(moduleConfig) {
144
+ if (moduleConfig?.moliAnalytics?.enabled) {
145
+ config = { ...DEFAULT_CONFIG, ...moduleConfig.moliAnalytics };
146
+ }
147
+ },
148
+ configureSteps__() {
149
+ return [];
150
+ },
151
+ initSteps__() {
152
+ return [
153
+ mkInitStep('moli-analytics-init', (context) => initMoliAnalytics(context)),
154
+ mkInitStep('set-analytics-labels', (context) => setAnalyticsLabels(context))
155
+ ];
156
+ },
157
+ prepareRequestAdsSteps__() {
158
+ return [];
159
+ }
160
+ };
161
+ };
@@ -0,0 +1,60 @@
1
+ import { UserActivityService } from 'ad-tag/ads/modules/ad-reload/userActivityService';
2
+ import { BrowserStorageKeys } from 'ad-tag/util/browserStorageKeys';
3
+ import { uuidV4 } from 'ad-tag/util/uuid';
4
+ export const createSession = (window, ttl) => {
5
+ const userActivityService = new UserActivityService(window, {
6
+ level: 'strict'
7
+ });
8
+ const ttlMs = ttl * 60000;
9
+ const loadJSON = (k, d = null) => {
10
+ try {
11
+ return JSON.parse(window.localStorage.getItem(k) || '') ?? d;
12
+ }
13
+ catch {
14
+ return d;
15
+ }
16
+ };
17
+ const saveJSON = (k, v) => window.localStorage.setItem(k, JSON.stringify(v));
18
+ const getSession = () => {
19
+ const now = Date.now();
20
+ let session = loadJSON(BrowserStorageKeys.molyAnalyticsSession);
21
+ if (!session || !session.id || !session.createdAt || !session.lastActivityAt) {
22
+ session = createSession();
23
+ }
24
+ else {
25
+ const idleMs = now - session.lastActivityAt;
26
+ const isIdle = idleMs > ttlMs;
27
+ if (isIdle) {
28
+ session = createSession();
29
+ }
30
+ }
31
+ return session;
32
+ };
33
+ const createSession = () => {
34
+ const now = Date.now();
35
+ const session = {
36
+ id: `sess-${uuidV4(window)}`,
37
+ createdAt: now,
38
+ lastActivityAt: now
39
+ };
40
+ saveJSON(BrowserStorageKeys.molyAnalyticsSession, session);
41
+ return session;
42
+ };
43
+ const touchSession = () => {
44
+ const session = getSession();
45
+ session.lastActivityAt = Date.now();
46
+ saveJSON(BrowserStorageKeys.molyAnalyticsSession, session);
47
+ };
48
+ const getId = () => {
49
+ return getSession().id;
50
+ };
51
+ userActivityService.addUserActivityChangedListener((isActive) => {
52
+ if (isActive) {
53
+ touchSession();
54
+ }
55
+ });
56
+ getSession();
57
+ return {
58
+ getId
59
+ };
60
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,11 @@
1
+ export const extractPubstackAbTestCohort = (ctx) => {
2
+ const pubstackABTestValues = ['0', '1', '2', '3'];
3
+ if (ctx.env__ === 'test') {
4
+ return null;
5
+ }
6
+ const meta = ctx.window__.document.head.querySelector('meta[name="pbstck_context:pbstck_ab_test"]');
7
+ if (meta && meta.content && pubstackABTestValues.includes(meta.content)) {
8
+ return meta.content;
9
+ }
10
+ return null;
11
+ };
@@ -1,5 +1,6 @@
1
1
  import { AssetLoadMethod } from 'ad-tag/util/assetLoaderService';
2
2
  import { mkConfigureStep, mkInitStep } from '../../adPipeline';
3
+ import { extractPubstackAbTestCohort } from './abTest';
3
4
  export const createPubstack = () => {
4
5
  const name = 'pubstack';
5
6
  let pubstackConfig = null;
@@ -37,10 +38,9 @@ export const createPubstack = () => {
37
38
  if (ctx.env__ === 'test') {
38
39
  return Promise.resolve();
39
40
  }
40
- const validABTestValues = ['0', '1', '2', '3'];
41
- const meta = ctx.window__.document.head.querySelector('meta[name="pbstck_context:pbstck_ab_test"]');
42
- if (meta && meta.content && validABTestValues.includes(meta.content)) {
43
- ctx.window__.googletag.pubads().setTargeting('pbstck_ab_test', meta.content);
41
+ const pubstackAbTestCohort = extractPubstackAbTestCohort(ctx);
42
+ if (pubstackAbTestCohort) {
43
+ ctx.window__.googletag.pubads().setTargeting('pbstck_ab_test', pubstackAbTestCohort);
44
44
  }
45
45
  return Promise.resolve();
46
46
  })
@@ -0,0 +1,2 @@
1
+ import { MoliAnalytics } from 'ad-tag/ads/modules/moli-analytics';
2
+ window.moli.registerModule(MoliAnalytics());
@@ -1,3 +1,3 @@
1
1
  export const packageJson = {
2
- version: '5.8.18'
2
+ version: '5.8.22'
3
3
  };
@@ -21,6 +21,7 @@ export var prebidjs;
21
21
  prebidjs.Pubstack = 'pubstack';
22
22
  prebidjs.Ogury = 'ogury';
23
23
  prebidjs.OneTag = 'onetag';
24
+ prebidjs.Oms = 'oms';
24
25
  prebidjs.OpenX = 'openx';
25
26
  prebidjs.SmartAdServer = 'smartadserver';
26
27
  prebidjs.Smartx = 'smartx';
@@ -2,6 +2,7 @@ export const BrowserStorageKeys = {
2
2
  moliEnv: 'moli-env',
3
3
  moliPubCode: 'moli-pub-code',
4
4
  moliVersion: 'moli-version',
5
+ molyAnalyticsSession: 'moli-analytics-session',
5
6
  testSlotSize: (id) => `moli-test-slot-size-${id}`,
6
7
  debugDelay: 'moli-debug-delay',
7
8
  abTest: 'moli-ab-test'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@highfivve/ad-tag",
3
- "version": "5.8.18",
3
+ "version": "5.8.22",
4
4
  "license": "Apache-2.0",
5
5
  "description": "An ad tag implementation called moli",
6
6
  "main": "./lib/index.js",