@highfivve/ad-tag 5.8.17 → 5.8.18
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/labelConfigService.js +14 -1
- package/lib/ads/modules/ad-reload/index.js +146 -142
- package/lib/ads/modules/adex/index.js +106 -104
- package/lib/ads/modules/cleanup/index.js +64 -61
- package/lib/ads/modules/confiant/index.js +29 -29
- package/lib/ads/modules/emetriq/index.js +107 -102
- package/lib/ads/modules/generic-skin/index.js +128 -127
- package/lib/ads/modules/identitylink/index.js +37 -36
- package/lib/ads/modules/prebid-first-party-data/index.js +41 -43
- package/lib/ads/modules/pubstack/index.js +26 -24
- package/lib/ads/modules/sticky-footer-ad/index.js +25 -25
- package/lib/ads/modules/sticky-footer-ad-v2/index.js +25 -25
- package/lib/ads/modules/sticky-header-ad/index.js +44 -42
- package/lib/ads/modules/zeotap/index.js +93 -93
- package/lib/ads/moli.js +35 -22
- package/lib/bundle/adReload.js +2 -2
- package/lib/bundle/adex.js +2 -2
- package/lib/bundle/cleanup.js +2 -2
- package/lib/bundle/confiant.js +2 -2
- package/lib/bundle/emetriq.js +2 -2
- package/lib/bundle/identityLink.js +2 -2
- package/lib/bundle/prebidFirstPartyData.js +2 -2
- package/lib/bundle/pubstack.js +2 -2
- package/lib/bundle/skin.js +2 -2
- package/lib/bundle/stickyFooterAd.js +2 -2
- package/lib/bundle/stickyFooterAds2.js +2 -2
- package/lib/bundle/stickyHeaderAd.js +2 -2
- package/lib/bundle/zeotap.js +2 -2
- package/lib/gen/packageJson.js +1 -1
- package/package.json +1 -1
|
@@ -30,11 +30,24 @@ export const createLabelConfigService = (labelSizeConfig, extraLabels, window) =
|
|
|
30
30
|
supportedLabels.push(label);
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
|
+
const isLabelConditionMet = (labelCondition) => {
|
|
34
|
+
if ('labelAll' in labelCondition) {
|
|
35
|
+
return labelCondition.labelAll.every(label => supportedLabels.includes(label));
|
|
36
|
+
}
|
|
37
|
+
if ('labelAny' in labelCondition) {
|
|
38
|
+
return labelCondition.labelAny.some(label => supportedLabels.includes(label));
|
|
39
|
+
}
|
|
40
|
+
if ('labelNone' in labelCondition) {
|
|
41
|
+
return labelCondition.labelNone.every(label => !supportedLabels.includes(label));
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
44
|
+
};
|
|
33
45
|
return {
|
|
34
46
|
filterSlot,
|
|
35
47
|
getSupportedLabels,
|
|
36
48
|
getDeviceLabel,
|
|
37
|
-
addLabel
|
|
49
|
+
addLabel,
|
|
50
|
+
isLabelConditionMet
|
|
38
51
|
};
|
|
39
52
|
};
|
|
40
53
|
export const getDeviceLabel = (window, runtimeConfig, labelSizeConfig, targeting) => {
|
|
@@ -3,162 +3,166 @@ import { UserActivityService } from './userActivityService';
|
|
|
3
3
|
import { mkConfigureStep } from '../../adPipeline';
|
|
4
4
|
import { isNotNull } from 'ad-tag/util/arrayUtils';
|
|
5
5
|
import { isAdvertiserIncluded } from 'ad-tag/ads/isAdvertiserIncluded';
|
|
6
|
-
export
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
yieldGroupIdIncluded
|
|
51
|
-
}, logger, yieldGroupIds, campaignId, advertiserId);
|
|
52
|
-
}
|
|
53
|
-
const slotAlreadyTracked = !!this.adVisibilityService?.isSlotTracked(slotDomId);
|
|
54
|
-
if (trackingSlotAllowed) {
|
|
55
|
-
this.adVisibilityService.trackSlot(googleTagSlot, reloadAdSlotCallback, advertiserId, companyIds);
|
|
56
|
-
}
|
|
57
|
-
else if (slotAlreadyTracked) {
|
|
58
|
-
this.adVisibilityService.removeSlotTracking(googleTagSlot);
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
this.reloadAdSlot = (config, ctx) => (googleTagSlot) => {
|
|
62
|
-
const slotId = googleTagSlot.getSlotElementId();
|
|
63
|
-
const moliSlot = ctx.config__.slots.find(moliSlot => moliSlot.domId === slotId);
|
|
64
|
-
if (moliSlot && moliSlot.behaviour.loaded !== 'infinite') {
|
|
65
|
-
ctx.logger__.debug('AdReload', 'fired slot reload', moliSlot.domId);
|
|
66
|
-
const sizesOverride = this.maybeOptimizeSlotForCls(config, moliSlot, googleTagSlot, ctx.logger__, ctx.window__);
|
|
67
|
-
googleTagSlot.setTargeting(this.reloadKeyValue, 'true');
|
|
68
|
-
const getBucketAndLoadingBehaviour = () => {
|
|
69
|
-
const bucketOverride = config.viewabilityOverrides?.[slotId]?.refreshBucket;
|
|
70
|
-
if (bucketOverride === true) {
|
|
71
|
-
const loaded = moliSlot.behaviour.loaded;
|
|
72
|
-
const bucket = moliSlot.behaviour.bucket;
|
|
73
|
-
const bucketName = typeof bucket === 'string'
|
|
74
|
-
? bucket
|
|
75
|
-
: bucket?.[ctx.labelConfigService__.getDeviceLabel()];
|
|
76
|
-
return bucketName && loaded !== 'infinite' ? { name: bucketName, loaded } : undefined;
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
const bucket = getBucketAndLoadingBehaviour();
|
|
80
|
-
if (bucket) {
|
|
81
|
-
ctx.window__.moli
|
|
82
|
-
.refreshBucket(bucket.name, { loaded: bucket.loaded })
|
|
83
|
-
.then(result => ctx.logger__.debug('AdReload', `refreshBucket '${bucket.name}' result`, result))
|
|
84
|
-
.catch(error => ctx.logger__.error('AdReload', `refreshBucket '${bucket.name}' failed`, error));
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
ctx.window__.moli
|
|
88
|
-
.refreshAdSlot(slotId, {
|
|
89
|
-
loaded: moliSlot.behaviour.loaded,
|
|
90
|
-
...(sizesOverride && { sizesOverride: sizesOverride })
|
|
91
|
-
})
|
|
92
|
-
.catch(error => ctx.logger__.error('AdReload', `refreshing ${slotId} failed`, error));
|
|
6
|
+
export const createAdReload = () => {
|
|
7
|
+
const name = 'moli-ad-reload';
|
|
8
|
+
const defaultRefreshIntervalMs = 20000;
|
|
9
|
+
const reloadKeyValue = 'native-ad-reload';
|
|
10
|
+
let initialized = false;
|
|
11
|
+
let moduleConfig = null;
|
|
12
|
+
let adVisibilityService;
|
|
13
|
+
const config__ = () => moduleConfig;
|
|
14
|
+
const isInitialized = () => initialized;
|
|
15
|
+
const configure__ = (mConfig) => {
|
|
16
|
+
if (mConfig?.adReload?.enabled) {
|
|
17
|
+
moduleConfig = mConfig.adReload;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const initSteps__ = () => [];
|
|
21
|
+
const setupAdVisibilityService = (config, window, logger) => {
|
|
22
|
+
adVisibilityService = new AdVisibilityService(new UserActivityService(window, config.userActivityLevelControl, logger), config.refreshIntervalMs ?? defaultRefreshIntervalMs, config.refreshIntervalMsOverrides ?? {}, false, !!config.disableAdVisibilityChecks, config.viewabilityOverrides ?? {}, window, logger);
|
|
23
|
+
};
|
|
24
|
+
const logTrackingDisallowedReason = (slotDomId, reasons, logger, yieldGroupIds, campaignId, advertiserId) => {
|
|
25
|
+
const { slotIsEmpty, slotIsMonitored, orderIdNotExcluded, orderIdIncluded, advertiserIdIncluded, yieldGroupIdIncluded } = reasons;
|
|
26
|
+
if (slotIsEmpty) {
|
|
27
|
+
logger.debug('AdReload', slotDomId, 'slot not tracked: reported empty');
|
|
28
|
+
}
|
|
29
|
+
if (!slotIsMonitored) {
|
|
30
|
+
logger.debug('AdReload', slotDomId, 'slot not tracked: excluded by DOM id');
|
|
31
|
+
}
|
|
32
|
+
if (!orderIdNotExcluded) {
|
|
33
|
+
logger.debug('AdReload', slotDomId, 'slot not tracked: excluded by order id', campaignId);
|
|
34
|
+
}
|
|
35
|
+
if (!(orderIdIncluded || advertiserIdIncluded || yieldGroupIdIncluded)) {
|
|
36
|
+
logger.debug('AdReload', slotDomId, 'slot not tracked: neither order id', campaignId, 'nor advertiser id', advertiserId, 'nor yieldGroup id', yieldGroupIds, 'included');
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const maybeOptimizeSlotForCls = (config, moliSlot, googleTagSlot, logger, _window) => {
|
|
40
|
+
const slotDomId = moliSlot.domId;
|
|
41
|
+
if (config.optimizeClsScoreDomIds.indexOf(slotDomId) > -1) {
|
|
42
|
+
const slotDomElement = _window.document.getElementById(slotDomId);
|
|
43
|
+
if (slotDomElement && !!slotDomElement.style) {
|
|
44
|
+
const slotHeight = slotDomElement.scrollHeight;
|
|
45
|
+
slotDomElement.style.setProperty('height', `${slotHeight}px`);
|
|
46
|
+
const newSlotSizes = moliSlot.sizes.filter(size => size !== 'fluid' && size[1] <= slotHeight);
|
|
47
|
+
logger.debug('AdReload', `CLS optimization: slot ${slotDomId} received fixed height ${slotHeight}px`, 'new sizes:', newSlotSizes);
|
|
48
|
+
if (newSlotSizes.length < moliSlot.sizes.filter(size => size !== 'fluid').length) {
|
|
49
|
+
_window.googletag.destroySlots([googleTagSlot]);
|
|
93
50
|
}
|
|
51
|
+
return newSlotSizes;
|
|
94
52
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
53
|
+
logger.warn('AdReload', `CLS optimization: slot ${slotDomId} to be optimized but not found in DOM.`);
|
|
54
|
+
}
|
|
55
|
+
return moliSlot.sizes;
|
|
56
|
+
};
|
|
57
|
+
const reloadAdSlot = (config, ctx) => (googleTagSlot) => {
|
|
58
|
+
const slotId = googleTagSlot.getSlotElementId();
|
|
59
|
+
const moliSlot = ctx.config__.slots.find(moliSlot => moliSlot.domId === slotId);
|
|
60
|
+
if (moliSlot && moliSlot.behaviour.loaded !== 'infinite') {
|
|
61
|
+
ctx.logger__.debug('AdReload', 'fired slot reload', moliSlot.domId);
|
|
62
|
+
const sizesOverride = maybeOptimizeSlotForCls(config, moliSlot, googleTagSlot, ctx.logger__, ctx.window__);
|
|
63
|
+
googleTagSlot.setTargeting(reloadKeyValue, 'true');
|
|
64
|
+
const getBucketAndLoadingBehaviour = () => {
|
|
65
|
+
const bucketOverride = config.viewabilityOverrides?.[slotId]?.refreshBucket;
|
|
66
|
+
if (bucketOverride === true) {
|
|
67
|
+
const loaded = moliSlot.behaviour.loaded;
|
|
68
|
+
const bucket = moliSlot.behaviour.bucket;
|
|
69
|
+
const bucketName = typeof bucket === 'string'
|
|
70
|
+
? bucket
|
|
71
|
+
: bucket?.[ctx.labelConfigService__.getDeviceLabel()];
|
|
72
|
+
return bucketName && loaded !== 'infinite' ? { name: bucketName, loaded } : undefined;
|
|
109
73
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
logger.debug('AdReload', slotDomId, 'slot not tracked: reported empty');
|
|
118
|
-
}
|
|
119
|
-
if (!slotIsMonitored) {
|
|
120
|
-
logger.debug('AdReload', slotDomId, 'slot not tracked: excluded by DOM id');
|
|
74
|
+
};
|
|
75
|
+
const bucket = getBucketAndLoadingBehaviour();
|
|
76
|
+
if (bucket) {
|
|
77
|
+
ctx.window__.moli
|
|
78
|
+
.refreshBucket(bucket.name, { loaded: bucket.loaded })
|
|
79
|
+
.then(result => ctx.logger__.debug('AdReload', `refreshBucket '${bucket.name}' result`, result))
|
|
80
|
+
.catch(error => ctx.logger__.error('AdReload', `refreshBucket '${bucket.name}' failed`, error));
|
|
121
81
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
82
|
+
else {
|
|
83
|
+
ctx.window__.moli
|
|
84
|
+
.refreshAdSlot(slotId, {
|
|
85
|
+
loaded: moliSlot.behaviour.loaded,
|
|
86
|
+
...(sizesOverride && { sizesOverride: sizesOverride })
|
|
87
|
+
})
|
|
88
|
+
.catch(error => ctx.logger__.error('AdReload', `refreshing ${slotId} failed`, error));
|
|
127
89
|
}
|
|
128
|
-
};
|
|
129
|
-
}
|
|
130
|
-
config__() {
|
|
131
|
-
return this.moduleConfig;
|
|
132
|
-
}
|
|
133
|
-
isInitialized() {
|
|
134
|
-
return this.initialized;
|
|
135
|
-
}
|
|
136
|
-
configure__(moduleConfig) {
|
|
137
|
-
if (moduleConfig?.adReload?.enabled) {
|
|
138
|
-
this.moduleConfig = moduleConfig.adReload;
|
|
139
90
|
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
const
|
|
91
|
+
};
|
|
92
|
+
const setupSlotRenderListener = (config, slotsToMonitor, reloadAdSlotCallback, window, logger) => window.googletag.pubads().addEventListener('slotRenderEnded', renderEndedEvent => {
|
|
93
|
+
const { slot: googleTagSlot, campaignId, advertiserId, companyIds, yieldGroupIds, isEmpty: slotIsEmpty } = renderEndedEvent;
|
|
94
|
+
const slotDomId = googleTagSlot.getSlotElementId();
|
|
95
|
+
const slotIsMonitored = slotsToMonitor.indexOf(slotDomId) > -1;
|
|
96
|
+
const orderIdNotExcluded = !campaignId || config.excludeOrderIds.indexOf(campaignId) === -1;
|
|
97
|
+
const orderIdIncluded = !!campaignId && config.includeOrderIds.indexOf(campaignId) > -1;
|
|
98
|
+
const advertiserIdIncluded = isAdvertiserIncluded(renderEndedEvent, config.includeAdvertiserIds);
|
|
99
|
+
const yieldGroupIdIncluded = !!yieldGroupIds && config.includeYieldGroupIds.some(id => yieldGroupIds.indexOf(id) > -1);
|
|
100
|
+
const trackingSlotAllowed = !slotIsEmpty &&
|
|
101
|
+
slotIsMonitored &&
|
|
102
|
+
orderIdNotExcluded &&
|
|
103
|
+
(orderIdIncluded || advertiserIdIncluded || yieldGroupIdIncluded);
|
|
104
|
+
if (!trackingSlotAllowed) {
|
|
105
|
+
logTrackingDisallowedReason(slotDomId, {
|
|
106
|
+
slotIsEmpty,
|
|
107
|
+
slotIsMonitored,
|
|
108
|
+
orderIdNotExcluded,
|
|
109
|
+
orderIdIncluded,
|
|
110
|
+
advertiserIdIncluded,
|
|
111
|
+
yieldGroupIdIncluded
|
|
112
|
+
}, logger, yieldGroupIds, campaignId, advertiserId);
|
|
113
|
+
}
|
|
114
|
+
const slotAlreadyTracked = !!adVisibilityService?.isSlotTracked(slotDomId);
|
|
115
|
+
if (trackingSlotAllowed) {
|
|
116
|
+
adVisibilityService.trackSlot(googleTagSlot, reloadAdSlotCallback, advertiserId, companyIds);
|
|
117
|
+
}
|
|
118
|
+
else if (slotAlreadyTracked) {
|
|
119
|
+
adVisibilityService.removeSlotTracking(googleTagSlot);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
const initialize = (context, config, slotsToMonitor, reloadAdSlotCallback) => {
|
|
123
|
+
if (context.env__ === 'test') {
|
|
124
|
+
context.logger__.info('AdReload', 'disabled in environment test');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (initialized) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
context.logger__.debug('AdReload', 'initialize moli ad reload module');
|
|
131
|
+
setupAdVisibilityService(config, context.window__, context.logger__);
|
|
132
|
+
setupSlotRenderListener(config, slotsToMonitor, reloadAdSlotCallback, context.window__, context.logger__);
|
|
133
|
+
initialized = true;
|
|
134
|
+
};
|
|
135
|
+
const configureSteps__ = () => {
|
|
136
|
+
const config = moduleConfig;
|
|
146
137
|
return config
|
|
147
138
|
? [
|
|
148
|
-
mkConfigureStep(
|
|
139
|
+
mkConfigureStep(name, context => {
|
|
149
140
|
const slotsToMonitor = context.config__.slots
|
|
150
141
|
.filter(slot => config.excludeAdSlotDomIds.indexOf(slot.domId) === -1)
|
|
151
142
|
.map(slot => slot.domId)
|
|
152
143
|
.filter(isNotNull);
|
|
153
|
-
const reloadAdSlotCallback =
|
|
144
|
+
const reloadAdSlotCallback = reloadAdSlot(config, context);
|
|
154
145
|
context.logger__.debug('AdReload', 'monitoring slots', slotsToMonitor);
|
|
155
|
-
|
|
146
|
+
initialize(context, config, slotsToMonitor, reloadAdSlotCallback);
|
|
156
147
|
return Promise.resolve();
|
|
157
148
|
})
|
|
158
149
|
]
|
|
159
150
|
: [];
|
|
160
|
-
}
|
|
161
|
-
prepareRequestAdsSteps__()
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
151
|
+
};
|
|
152
|
+
const prepareRequestAdsSteps__ = () => [];
|
|
153
|
+
return {
|
|
154
|
+
name,
|
|
155
|
+
description: 'Moli implementation of an ad reload module.',
|
|
156
|
+
moduleType: 'ad-reload',
|
|
157
|
+
config__,
|
|
158
|
+
configure__,
|
|
159
|
+
initSteps__,
|
|
160
|
+
configureSteps__,
|
|
161
|
+
prepareRequestAdsSteps__,
|
|
162
|
+
isInitialized,
|
|
163
|
+
initialize,
|
|
164
|
+
get adVisibilityService() {
|
|
165
|
+
return adVisibilityService;
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
};
|
|
@@ -6,113 +6,86 @@ import { tcfapi } from 'ad-tag/types/tcfapi';
|
|
|
6
6
|
var TCPurpose = tcfapi.responses.TCPurpose;
|
|
7
7
|
import { toAdexListType, toAdexMapType, toAdexStringOrNumberType } from 'ad-tag/ads/modules/adex/adex-mapping';
|
|
8
8
|
import { trackUtiqId } from 'ad-tag/ads/modules/adex/adexUtiq';
|
|
9
|
-
export
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
this.isLoaded = false;
|
|
16
|
-
this.hasRequiredConsent = (tcData) => !tcData.gdprApplies ||
|
|
17
|
-
(tcData.vendor.consents['44'] &&
|
|
18
|
-
[
|
|
19
|
-
TCPurpose.STORE_INFORMATION_ON_DEVICE,
|
|
20
|
-
TCPurpose.SELECT_BASIC_ADS,
|
|
21
|
-
TCPurpose.CREATE_PERSONALISED_ADS_PROFILE,
|
|
22
|
-
TCPurpose.SELECT_PERSONALISED_ADS,
|
|
23
|
-
TCPurpose.CREATE_PERSONALISED_CONTENT_PROFILE,
|
|
24
|
-
TCPurpose.SELECT_PERSONALISED_CONTENT,
|
|
25
|
-
TCPurpose.MEASURE_AD_PERFORMANCE,
|
|
26
|
-
TCPurpose.MEASURE_CONTENT_PERFORMANCE,
|
|
27
|
-
TCPurpose.APPLY_MARKET_RESEARCH,
|
|
28
|
-
TCPurpose.DEVELOP_IMPROVE_PRODUCTS
|
|
29
|
-
].every(purpose => tcData.purpose.consents[purpose]));
|
|
30
|
-
this.getOrInitAdexQueue = (_window) => {
|
|
31
|
-
const adexWindow = _window;
|
|
32
|
-
adexWindow._adexc = adexWindow._adexc || [];
|
|
33
|
-
return adexWindow;
|
|
34
|
-
};
|
|
35
|
-
this.getAdexKeyValues = (context, config) => {
|
|
36
|
-
const gamKeyValues = {
|
|
37
|
-
...context.config__.targeting?.keyValues,
|
|
38
|
-
...context.runtimeConfig__.keyValues
|
|
39
|
-
};
|
|
40
|
-
if (Object.keys(gamKeyValues).length > 0) {
|
|
41
|
-
return config.mappingDefinitions
|
|
42
|
-
.map(def => {
|
|
43
|
-
switch (def.adexValueType) {
|
|
44
|
-
case 'map':
|
|
45
|
-
return toAdexMapType(gamKeyValues, def, context.logger__);
|
|
46
|
-
case 'list':
|
|
47
|
-
return toAdexListType(gamKeyValues, def, context.logger__);
|
|
48
|
-
default:
|
|
49
|
-
return toAdexStringOrNumberType(gamKeyValues, def, context.logger__);
|
|
50
|
-
}
|
|
51
|
-
})
|
|
52
|
-
.filter(isNotNull);
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
this.configureAdexC = (context, config) => {
|
|
56
|
-
const adexWindow = this.getOrInitAdexQueue(context.window__);
|
|
57
|
-
const adexKeyValues = this.getAdexKeyValues(context, config);
|
|
58
|
-
if (!adexKeyValues) {
|
|
59
|
-
context.logger__.warn('Adex DMP', 'targeting key/values are empty');
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
adexWindow._adexc.push([
|
|
63
|
-
`/${config.adexCustomerId}/${config.adexTagId}/`,
|
|
64
|
-
'ut',
|
|
65
|
-
'_kv',
|
|
66
|
-
[
|
|
67
|
-
adexKeyValues.reduce((aggregator, additionalKeyValue) => ({ ...aggregator, ...additionalKeyValue }), {}),
|
|
68
|
-
config.spaMode ? 1 : 0
|
|
69
|
-
]
|
|
70
|
-
]);
|
|
71
|
-
}
|
|
72
|
-
if (config.enabledPartners?.includes('utiq')) {
|
|
73
|
-
trackUtiqId(config, context.window__);
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
config__() {
|
|
78
|
-
return this.adexConfig;
|
|
79
|
-
}
|
|
80
|
-
configure__(moduleConfig) {
|
|
9
|
+
export const createAdexModule = () => {
|
|
10
|
+
const name = 'the-adex-dmp';
|
|
11
|
+
let adexConfig = null;
|
|
12
|
+
let isLoaded = false;
|
|
13
|
+
const config__ = () => adexConfig;
|
|
14
|
+
const configure__ = (moduleConfig) => {
|
|
81
15
|
if (moduleConfig?.adex && moduleConfig.adex.enabled) {
|
|
82
|
-
|
|
16
|
+
adexConfig = moduleConfig.adex;
|
|
83
17
|
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
18
|
+
};
|
|
19
|
+
const getOrInitAdexQueue = (_window) => {
|
|
20
|
+
const adexWindow = _window;
|
|
21
|
+
adexWindow._adexc = adexWindow._adexc || [];
|
|
22
|
+
return adexWindow;
|
|
23
|
+
};
|
|
24
|
+
const getAdexKeyValues = (context, config) => {
|
|
25
|
+
const gamKeyValues = {
|
|
26
|
+
...context.config__.targeting?.keyValues,
|
|
27
|
+
...context.runtimeConfig__.keyValues
|
|
28
|
+
};
|
|
29
|
+
if (Object.keys(gamKeyValues).length > 0) {
|
|
30
|
+
return config.mappingDefinitions
|
|
31
|
+
.map(def => {
|
|
32
|
+
switch (def.adexValueType) {
|
|
33
|
+
case 'map':
|
|
34
|
+
return toAdexMapType(gamKeyValues, def, context.logger__);
|
|
35
|
+
case 'list':
|
|
36
|
+
return toAdexListType(gamKeyValues, def, context.logger__);
|
|
37
|
+
default:
|
|
38
|
+
return toAdexStringOrNumberType(gamKeyValues, def, context.logger__);
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
.filter(isNotNull);
|
|
89
42
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
43
|
+
};
|
|
44
|
+
const hasRequiredConsent = (tcData) => !tcData.gdprApplies ||
|
|
45
|
+
(tcData.vendor.consents['44'] &&
|
|
46
|
+
[
|
|
47
|
+
TCPurpose.STORE_INFORMATION_ON_DEVICE,
|
|
48
|
+
TCPurpose.SELECT_BASIC_ADS,
|
|
49
|
+
TCPurpose.CREATE_PERSONALISED_ADS_PROFILE,
|
|
50
|
+
TCPurpose.SELECT_PERSONALISED_ADS,
|
|
51
|
+
TCPurpose.CREATE_PERSONALISED_CONTENT_PROFILE,
|
|
52
|
+
TCPurpose.SELECT_PERSONALISED_CONTENT,
|
|
53
|
+
TCPurpose.MEASURE_AD_PERFORMANCE,
|
|
54
|
+
TCPurpose.MEASURE_CONTENT_PERFORMANCE,
|
|
55
|
+
TCPurpose.APPLY_MARKET_RESEARCH,
|
|
56
|
+
TCPurpose.DEVELOP_IMPROVE_PRODUCTS
|
|
57
|
+
].every(purpose => tcData.purpose.consents[purpose]));
|
|
58
|
+
const configureAdexC = (context, config) => {
|
|
59
|
+
const adexWindow = getOrInitAdexQueue(context.window__);
|
|
60
|
+
const adexKeyValues = getAdexKeyValues(context, config);
|
|
61
|
+
if (!adexKeyValues) {
|
|
62
|
+
context.logger__.warn('Adex DMP', 'targeting key/values are empty');
|
|
101
63
|
}
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
64
|
+
else {
|
|
65
|
+
adexWindow._adexc.push([
|
|
66
|
+
`/${config.adexCustomerId}/${config.adexTagId}/`,
|
|
67
|
+
'ut',
|
|
68
|
+
'_kv',
|
|
69
|
+
[
|
|
70
|
+
adexKeyValues.reduce((aggregator, additionalKeyValue) => ({ ...aggregator, ...additionalKeyValue }), {}),
|
|
71
|
+
config.spaMode ? 1 : 0
|
|
72
|
+
]
|
|
73
|
+
]);
|
|
74
|
+
}
|
|
75
|
+
if (config.enabledPartners?.includes('utiq')) {
|
|
76
|
+
trackUtiqId(config, context.window__);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const track = (context, config) => {
|
|
80
|
+
const { adexCustomerId, adexTagId, appConfig, appName } = config;
|
|
81
|
+
configureAdexC(context, config);
|
|
82
|
+
const adexKeyValues = getAdexKeyValues(context, config);
|
|
108
83
|
const gamKeyValues = {
|
|
109
84
|
...context.config__.targeting?.keyValues,
|
|
110
85
|
...context.runtimeConfig__.keyValues
|
|
111
86
|
};
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
Object.keys(gamKeyValues).length > 0) {
|
|
115
|
-
this.isLoaded = true;
|
|
87
|
+
if (hasRequiredConsent(context.tcData__) && !isLoaded && Object.keys(gamKeyValues).length > 0) {
|
|
88
|
+
isLoaded = true;
|
|
116
89
|
const hasValidMobileKeyValues = isNotNull(appConfig) &&
|
|
117
90
|
isNotNull(gamKeyValues[appConfig.advertiserIdKey]) &&
|
|
118
91
|
(gamKeyValues[appConfig.clientTypeKey] === 'android' ||
|
|
@@ -127,7 +100,7 @@ export class AdexModule {
|
|
|
127
100
|
else {
|
|
128
101
|
context.assetLoaderService__
|
|
129
102
|
.loadScript({
|
|
130
|
-
name
|
|
103
|
+
name,
|
|
131
104
|
assetUrl: `https://dmp.theadex.com/d/${adexCustomerId}/${adexTagId}/s/adex.js`,
|
|
132
105
|
loadMethod: AssetLoadMethod.TAG
|
|
133
106
|
})
|
|
@@ -135,8 +108,37 @@ export class AdexModule {
|
|
|
135
108
|
}
|
|
136
109
|
}
|
|
137
110
|
return Promise.resolve();
|
|
138
|
-
}
|
|
139
|
-
|
|
111
|
+
};
|
|
112
|
+
const initSteps__ = () => {
|
|
113
|
+
const config = adexConfig;
|
|
114
|
+
if (config) {
|
|
115
|
+
return [mkInitStep('DMP module setup', context => track(context, config))];
|
|
116
|
+
}
|
|
117
|
+
return [];
|
|
118
|
+
};
|
|
119
|
+
const configureSteps__ = () => {
|
|
120
|
+
const config = adexConfig;
|
|
121
|
+
if (config?.spaMode) {
|
|
122
|
+
return [
|
|
123
|
+
mkConfigureStep('DMP module setup', context => {
|
|
124
|
+
configureAdexC(context, config);
|
|
125
|
+
return Promise.resolve();
|
|
126
|
+
})
|
|
127
|
+
];
|
|
128
|
+
}
|
|
140
129
|
return [];
|
|
141
|
-
}
|
|
142
|
-
|
|
130
|
+
};
|
|
131
|
+
const prepareRequestAdsSteps__ = () => [];
|
|
132
|
+
return {
|
|
133
|
+
name,
|
|
134
|
+
description: 'Moli DMP module for The Adex.',
|
|
135
|
+
moduleType: 'dmp',
|
|
136
|
+
config__,
|
|
137
|
+
configure__,
|
|
138
|
+
initSteps__,
|
|
139
|
+
configureSteps__,
|
|
140
|
+
prepareRequestAdsSteps__,
|
|
141
|
+
track,
|
|
142
|
+
hasRequiredConsent
|
|
143
|
+
};
|
|
144
|
+
};
|