@el7ven/cookie-kit 0.3.1 → 0.3.2
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/package.json +21 -1
- package/src/core/AnalyticsManager.js +400 -0
- package/src/core/ConsentManager.js +710 -0
- package/src/core/ConsentMode.js +109 -0
- package/src/core/FocusTrap.js +130 -0
- package/src/core/GeoDetector.js +144 -0
- package/src/core/ScriptLoader.js +229 -0
- package/src/core/StorageAdapter.js +179 -0
- package/src/geo/GeoDetector.js +536 -0
- package/src/geo/RegionRules.js +126 -0
- package/src/geo/index.js +16 -0
- package/src/index.js +55 -17
- package/src/locales/en.js +54 -0
- package/src/locales/index.js +20 -0
- package/src/locales/ro.js +54 -0
- package/src/plugins/CMPPlugin.js +187 -0
- package/src/plugins/PluginManager.js +234 -0
- package/src/plugins/index.js +7 -0
- package/src/providers/GoogleConsentModeProvider.js +278 -0
- package/src/providers/index.js +6 -0
- package/src/rewriting/ScriptRewriter.js +278 -0
- package/src/rewriting/index.js +6 -0
- package/src/scripts/ScriptLoader.js +310 -0
- package/src/scripts/ScriptManager.js +278 -0
- package/src/scripts/ScriptRegistry.js +175 -0
- package/src/scripts/ScriptScanner.js +178 -0
- package/src/scripts/index.js +9 -0
- package/src/trackers/TrackerDetector.js +488 -0
- package/src/trackers/TrackerPatterns.js +307 -0
- package/src/trackers/TrackerRegistry.js +172 -0
- package/src/trackers/index.js +15 -0
- package/src/utils/cookies.js +37 -0
- package/src/utils/dom.js +58 -0
- package/src/utils/helpers.js +89 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@el7ven/cookie-kit",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"module": "./src/index.js",
|
|
@@ -13,6 +13,26 @@
|
|
|
13
13
|
"./vue": "./src/vue/index.js",
|
|
14
14
|
"./analytics": "./src/core/analytics.js",
|
|
15
15
|
"./config": "./src/core/index.js",
|
|
16
|
+
"./core": "./src/core/index.js",
|
|
17
|
+
"./core/ConsentManager": "./src/core/ConsentManager.js",
|
|
18
|
+
"./core/StorageAdapter": "./src/core/StorageAdapter.js",
|
|
19
|
+
"./core/ConsentMode": "./src/core/ConsentMode.js",
|
|
20
|
+
"./core/FocusTrap": "./src/core/FocusTrap.js",
|
|
21
|
+
"./core/ScriptLoader": "./src/core/ScriptLoader.js",
|
|
22
|
+
"./core/AnalyticsManager": "./src/core/AnalyticsManager.js",
|
|
23
|
+
"./core/GeoDetector": "./src/core/GeoDetector.js",
|
|
24
|
+
"./geo": "./src/geo/index.js",
|
|
25
|
+
"./geo/RegionRules": "./src/geo/RegionRules.js",
|
|
26
|
+
"./locales": "./src/locales/index.js",
|
|
27
|
+
"./providers": "./src/providers/index.js",
|
|
28
|
+
"./providers/GoogleConsentModeProvider": "./src/providers/GoogleConsentModeProvider.js",
|
|
29
|
+
"./plugins": "./src/plugins/index.js",
|
|
30
|
+
"./trackers": "./src/trackers/index.js",
|
|
31
|
+
"./rewriting": "./src/rewriting/index.js",
|
|
32
|
+
"./scripts": "./src/scripts/index.js",
|
|
33
|
+
"./utils/cookies": "./src/utils/cookies.js",
|
|
34
|
+
"./utils/dom": "./src/utils/dom.js",
|
|
35
|
+
"./utils/helpers": "./src/utils/helpers.js",
|
|
16
36
|
"./composables/useCookieConsent": "./src/vue/composables/useCookieConsent.js",
|
|
17
37
|
"./src/composables/useCookieConsent": "./src/vue/composables/useCookieConsent.js",
|
|
18
38
|
"./package.json": "./package.json"
|
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Analytics Manager — integrations with popular analytics services
|
|
3
|
+
* GA4, GTM, Meta Pixel, TikTok Pixel, Hotjar
|
|
4
|
+
* @module AnalyticsManager
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const ANALYTICS_PROVIDERS = {
|
|
8
|
+
ga4: {
|
|
9
|
+
category: 'analytics',
|
|
10
|
+
load: (config) => {
|
|
11
|
+
const id = config.GA_ID || config.id
|
|
12
|
+
if (!id) return
|
|
13
|
+
|
|
14
|
+
// gtag.js is already loaded in head.blade.php, just configure
|
|
15
|
+
if (window.gtag) {
|
|
16
|
+
// Google Consent Mode V2 - update consent to granted
|
|
17
|
+
gtag('consent', 'update', {
|
|
18
|
+
'analytics_storage': 'granted',
|
|
19
|
+
'ad_storage': 'denied',
|
|
20
|
+
'ad_user_data': 'denied',
|
|
21
|
+
'ad_personalization': 'denied'
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
// Configure GA4 with IP anonymization (GDPR requirement)
|
|
25
|
+
gtag('config', id, {
|
|
26
|
+
anonymize_ip: true
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return true // Return success flag
|
|
31
|
+
},
|
|
32
|
+
unload: (config) => {
|
|
33
|
+
const id = config.GA_ID || config.id
|
|
34
|
+
|
|
35
|
+
// Update consent to denied
|
|
36
|
+
if (window.gtag) {
|
|
37
|
+
gtag('consent', 'update', {
|
|
38
|
+
'analytics_storage': 'denied',
|
|
39
|
+
'ad_storage': 'denied',
|
|
40
|
+
'ad_user_data': 'denied',
|
|
41
|
+
'ad_personalization': 'denied'
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Remove ALL GA cookies (including _ga_XXXX and _gat)
|
|
46
|
+
const cookies = document.cookie.split(';')
|
|
47
|
+
cookies.forEach(cookie => {
|
|
48
|
+
const name = cookie.split('=')[0].trim()
|
|
49
|
+
if (name.startsWith('_ga') || name.startsWith('_gid') || name.startsWith('_gat')) {
|
|
50
|
+
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`
|
|
51
|
+
}
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
|
|
56
|
+
gtm: {
|
|
57
|
+
category: 'analytics',
|
|
58
|
+
load: (config) => {
|
|
59
|
+
const id = config.GTM_ID || config.id
|
|
60
|
+
if (!id) return
|
|
61
|
+
|
|
62
|
+
window.dataLayer = window.dataLayer || []
|
|
63
|
+
|
|
64
|
+
// Google Consent Mode V2 - set consent to granted
|
|
65
|
+
window.dataLayer.push({
|
|
66
|
+
'event': 'consent_update',
|
|
67
|
+
'analytics_storage': 'granted',
|
|
68
|
+
'ad_storage': 'denied',
|
|
69
|
+
'ad_user_data': 'denied',
|
|
70
|
+
'ad_personalization': 'denied'
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
window.dataLayer.push({
|
|
74
|
+
'gtm.start': new Date().getTime(),
|
|
75
|
+
event: 'gtm.js'
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
const script = document.createElement('script')
|
|
79
|
+
script.async = true
|
|
80
|
+
script.src = `https://www.googletagmanager.com/gtm.js?id=${id}`
|
|
81
|
+
document.head.appendChild(script)
|
|
82
|
+
|
|
83
|
+
return script
|
|
84
|
+
},
|
|
85
|
+
unload: (config) => {
|
|
86
|
+
const id = config.GTM_ID || config.id
|
|
87
|
+
|
|
88
|
+
// Google Consent Mode V2 - set consent to denied
|
|
89
|
+
if (window.dataLayer) {
|
|
90
|
+
window.dataLayer.push({
|
|
91
|
+
'event': 'consent_update',
|
|
92
|
+
'analytics_storage': 'denied',
|
|
93
|
+
'ad_storage': 'denied',
|
|
94
|
+
'ad_user_data': 'denied',
|
|
95
|
+
'ad_personalization': 'denied'
|
|
96
|
+
})
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const scripts = document.querySelectorAll(`script[src*="googletagmanager.com/gtm.js?id=${id}"]`)
|
|
100
|
+
scripts.forEach(s => s.remove())
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
|
|
104
|
+
metaPixel: {
|
|
105
|
+
category: 'marketing',
|
|
106
|
+
load: (config) => {
|
|
107
|
+
const id = config.PIXEL_ID || config.id
|
|
108
|
+
if (!id) return
|
|
109
|
+
|
|
110
|
+
/* eslint-disable */
|
|
111
|
+
!function(f,b,e,v,n,t,s)
|
|
112
|
+
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
|
|
113
|
+
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
|
|
114
|
+
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
|
|
115
|
+
n.queue=[];t=b.createElement(e);t.async=!0;
|
|
116
|
+
t.src=v;s=b.getElementsByTagName(e)[0];
|
|
117
|
+
s.parentNode.insertBefore(t,s)}(window, document,'script',
|
|
118
|
+
'https://connect.facebook.net/en_US/fbevents.js');
|
|
119
|
+
/* eslint-enable */
|
|
120
|
+
|
|
121
|
+
window.fbq('init', id)
|
|
122
|
+
window.fbq('track', 'PageView')
|
|
123
|
+
},
|
|
124
|
+
unload: () => {
|
|
125
|
+
delete window.fbq
|
|
126
|
+
delete window._fbq
|
|
127
|
+
const scripts = document.querySelectorAll('script[src*="connect.facebook.net"]')
|
|
128
|
+
scripts.forEach(s => s.remove())
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
yandexMetrica: {
|
|
133
|
+
category: 'analytics',
|
|
134
|
+
load: (config) => {
|
|
135
|
+
const id = config.YANDEX_ID || config.id
|
|
136
|
+
console.log('[AnalyticsManager] Yandex Metrica: Attempting to load with ID:', id)
|
|
137
|
+
if (!id) {
|
|
138
|
+
console.log('[AnalyticsManager] Yandex Metrica: No ID provided, skipping')
|
|
139
|
+
return
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Yandex.Metrika initialization with proper parameters
|
|
143
|
+
(function(m,e,t,r,i,k,a){
|
|
144
|
+
m[i]=m[i]||function(){(m[i].a=m[i].a||[]).push(arguments)};
|
|
145
|
+
m[i].l=1*new Date();
|
|
146
|
+
for (var j = 0; j < document.scripts.length; j++) {if (document.scripts[j].src === r) { return; }}
|
|
147
|
+
k=e.createElement(t),a=e.getElementsByTagName(t)[0],k.async=1,k.src=r,a.parentNode.insertBefore(k,a)
|
|
148
|
+
})(window, document,'script','https://mc.yandex.ru/metrika/tag.js?id=' + id, 'ym');
|
|
149
|
+
|
|
150
|
+
ym(id, 'init', {
|
|
151
|
+
ssr: true,
|
|
152
|
+
webvisor: true,
|
|
153
|
+
clickmap: true,
|
|
154
|
+
ecommerce: "dataLayer",
|
|
155
|
+
referrer: document.referrer,
|
|
156
|
+
url: location.href,
|
|
157
|
+
accurateTrackBounce: true,
|
|
158
|
+
trackLinks: true
|
|
159
|
+
});
|
|
160
|
+
console.log('[AnalyticsManager] Yandex Metrica: Initialized with ID:', id)
|
|
161
|
+
|
|
162
|
+
return id
|
|
163
|
+
},
|
|
164
|
+
unload: (config) => {
|
|
165
|
+
const id = config.YANDEX_ID || config.id
|
|
166
|
+
console.log('[AnalyticsManager] Yandex Metrica: Unloading with ID:', id)
|
|
167
|
+
|
|
168
|
+
// Remove Yandex cookies
|
|
169
|
+
const cookies = document.cookie.split(';')
|
|
170
|
+
let removedCookies = []
|
|
171
|
+
cookies.forEach(cookie => {
|
|
172
|
+
const name = cookie.split('=')[0].trim()
|
|
173
|
+
if (name.includes('yandex') || name.includes('ym') || name.includes('_ym')) {
|
|
174
|
+
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`
|
|
175
|
+
removedCookies.push(name)
|
|
176
|
+
}
|
|
177
|
+
})
|
|
178
|
+
console.log('[AnalyticsManager] Yandex Metrica: Removed cookies:', removedCookies)
|
|
179
|
+
|
|
180
|
+
// Remove script
|
|
181
|
+
const scripts = document.querySelectorAll('script[src*="yandex.ru/metrika"]')
|
|
182
|
+
scripts.forEach(s => s.remove())
|
|
183
|
+
console.log('[AnalyticsManager] Yandex Metrica: Removed scripts:', scripts.length)
|
|
184
|
+
|
|
185
|
+
// Remove noscript image
|
|
186
|
+
const noscriptImgs = document.querySelectorAll('img[src*="yandex.ru/watch"]')
|
|
187
|
+
noscriptImgs.forEach(img => img.remove())
|
|
188
|
+
console.log('[AnalyticsManager] Yandex Metrica: Removed noscript images:', noscriptImgs.length)
|
|
189
|
+
}
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
googleRemarketing: {
|
|
193
|
+
category: 'marketing',
|
|
194
|
+
load: (config) => {
|
|
195
|
+
const id = config.REMARKETING_ID || config.id
|
|
196
|
+
console.log('[AnalyticsManager] Google Remarketing: Attempting to load with ID:', id)
|
|
197
|
+
if (!id) {
|
|
198
|
+
console.log('[AnalyticsManager] Google Remarketing: No ID provided, skipping')
|
|
199
|
+
return
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
window.google_tag_params = window.google_tag_params || {};
|
|
203
|
+
window.google_conversion_id = id;
|
|
204
|
+
window.google_conversion_label = '';
|
|
205
|
+
window.google_remarketing_only = true;
|
|
206
|
+
|
|
207
|
+
const script = document.createElement('script')
|
|
208
|
+
script.src = `//www.googleadservices.com/pagead/conversion.js`
|
|
209
|
+
document.head.appendChild(script)
|
|
210
|
+
console.log('[AnalyticsManager] Google Remarketing: Script appended to head')
|
|
211
|
+
|
|
212
|
+
return script
|
|
213
|
+
},
|
|
214
|
+
unload: (config) => {
|
|
215
|
+
const id = config.REMARKETING_ID || config.id
|
|
216
|
+
console.log('[AnalyticsManager] Google Remarketing: Unloading with ID:', id)
|
|
217
|
+
|
|
218
|
+
// Remove remarketing cookies
|
|
219
|
+
const cookies = document.cookie.split(';')
|
|
220
|
+
let removedCookies = []
|
|
221
|
+
cookies.forEach(cookie => {
|
|
222
|
+
const name = cookie.split('=')[0].trim()
|
|
223
|
+
if (name.includes('_ga') || name.includes('google')) {
|
|
224
|
+
document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`
|
|
225
|
+
removedCookies.push(name)
|
|
226
|
+
}
|
|
227
|
+
})
|
|
228
|
+
console.log('[AnalyticsManager] Google Remarketing: Removed cookies:', removedCookies)
|
|
229
|
+
|
|
230
|
+
// Remove script
|
|
231
|
+
const scripts = document.querySelectorAll('script[src*="googleadservices.com"]')
|
|
232
|
+
scripts.forEach(s => s.remove())
|
|
233
|
+
console.log('[AnalyticsManager] Google Remarketing: Removed scripts:', scripts.length)
|
|
234
|
+
}
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
tiktokPixel: {
|
|
238
|
+
category: 'marketing',
|
|
239
|
+
load: (config) => {
|
|
240
|
+
const id = config.TIKTOK_ID || config.id
|
|
241
|
+
if (!id) return
|
|
242
|
+
|
|
243
|
+
/* eslint-disable */
|
|
244
|
+
!function(w,d,t){w.TiktokAnalyticsObject=t;var ttq=w[t]=w[t]||[];
|
|
245
|
+
ttq.methods=["page","track","identify","instances","debug","on","off","once","ready","alias","group","enableCookie","disableCookie"];
|
|
246
|
+
ttq.setAndDefer=function(t,e){t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}};
|
|
247
|
+
for(var i=0;i<ttq.methods.length;i++)ttq.setAndDefer(ttq,ttq.methods[i]);
|
|
248
|
+
ttq.instance=function(t){for(var e=ttq._i[t]||[],n=0;n<ttq.methods.length;n++)ttq.setAndDefer(e,ttq.methods[n]);return e};
|
|
249
|
+
ttq.load=function(e,n){var i="https://analytics.tiktok.com/i18n/pixel/events.js";
|
|
250
|
+
ttq._i=ttq._i||{};ttq._i[e]=[];ttq._i[e]._u=i;ttq._t=ttq._t||{};ttq._t[e]=+new Date;
|
|
251
|
+
ttq._o=ttq._o||{};ttq._o[e]=n||{};
|
|
252
|
+
var o=document.createElement("script");o.type="text/javascript";o.async=!0;o.src=i+"?sdkid="+e+"&lib="+t;
|
|
253
|
+
var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(o,a)};
|
|
254
|
+
}(window,document,"ttq");
|
|
255
|
+
/* eslint-enable */
|
|
256
|
+
|
|
257
|
+
window.ttq.load(id)
|
|
258
|
+
window.ttq.page()
|
|
259
|
+
},
|
|
260
|
+
unload: () => {
|
|
261
|
+
delete window.ttq
|
|
262
|
+
const scripts = document.querySelectorAll('script[src*="analytics.tiktok.com"]')
|
|
263
|
+
scripts.forEach(s => s.remove())
|
|
264
|
+
}
|
|
265
|
+
},
|
|
266
|
+
|
|
267
|
+
hotjar: {
|
|
268
|
+
category: 'analytics',
|
|
269
|
+
load: (config) => {
|
|
270
|
+
const id = config.HOTJAR_ID || config.id
|
|
271
|
+
if (!id) return
|
|
272
|
+
|
|
273
|
+
/* eslint-disable */
|
|
274
|
+
;(function(h,o,t,j,a,r){
|
|
275
|
+
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
|
|
276
|
+
h._hjSettings={hjid:id,hjsv:6};
|
|
277
|
+
a=o.getElementsByTagName('head')[0];
|
|
278
|
+
r=o.createElement('script');r.async=1;
|
|
279
|
+
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
|
|
280
|
+
a.appendChild(r);
|
|
281
|
+
})(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
|
|
282
|
+
/* eslint-enable */
|
|
283
|
+
},
|
|
284
|
+
unload: () => {
|
|
285
|
+
delete window.hj
|
|
286
|
+
delete window._hjSettings
|
|
287
|
+
const scripts = document.querySelectorAll('script[src*="static.hotjar.com"]')
|
|
288
|
+
scripts.forEach(s => s.remove())
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export class AnalyticsManager {
|
|
294
|
+
constructor(consentManager, config = {}) {
|
|
295
|
+
this.manager = consentManager
|
|
296
|
+
this.config = config
|
|
297
|
+
this.activeProviders = new Set()
|
|
298
|
+
|
|
299
|
+
// Initialize Google Consent Mode V2 with default denied consent
|
|
300
|
+
this._initializeConsentMode()
|
|
301
|
+
|
|
302
|
+
this._init()
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
_initializeConsentMode() {
|
|
306
|
+
// Set default consent to denied (GDPR compliant) - only once
|
|
307
|
+
if (!window.gtag) {
|
|
308
|
+
window.dataLayer = window.dataLayer || []
|
|
309
|
+
window.gtag = function gtag() {
|
|
310
|
+
window.dataLayer.push(arguments)
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
// Set default consent to denied (GDPR compliant)
|
|
315
|
+
gtag('consent', 'default', {
|
|
316
|
+
'analytics_storage': 'denied',
|
|
317
|
+
'ad_storage': 'denied',
|
|
318
|
+
'ad_user_data': 'denied',
|
|
319
|
+
'ad_personalization': 'denied',
|
|
320
|
+
'wait_for_update': 500 // Prevent race conditions
|
|
321
|
+
})
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
_init() {
|
|
325
|
+
if (typeof window === 'undefined') return
|
|
326
|
+
|
|
327
|
+
// Listen for consent changes
|
|
328
|
+
this.manager.on('consentChanged', ({ categories }) => {
|
|
329
|
+
this._syncProviders(categories)
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
// Check existing consent
|
|
333
|
+
const consent = this.manager.getConsent()
|
|
334
|
+
if (consent?.hasConsented) {
|
|
335
|
+
this._syncProviders(consent.categories)
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
this.manager._debug('AnalyticsManager: initialized')
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
_syncProviders(categories) {
|
|
342
|
+
// When using direct gtag.js, both GA4 and GTM can work together
|
|
343
|
+
const hasGTM = this.config.gtm && (this.config.gtm.id || this.config.gtm.GTM_ID)
|
|
344
|
+
const hasGA4 = this.config.ga4 && (this.config.ga4.id || this.config.ga4.GA_ID)
|
|
345
|
+
|
|
346
|
+
Object.entries(this.config).forEach(([providerName, providerConfig]) => {
|
|
347
|
+
const provider = ANALYTICS_PROVIDERS[providerName]
|
|
348
|
+
if (!provider || !providerConfig) return
|
|
349
|
+
|
|
350
|
+
const category = providerConfig.category || provider.category
|
|
351
|
+
const granted = categories[category] === true
|
|
352
|
+
|
|
353
|
+
if (granted && !this.activeProviders.has(providerName)) {
|
|
354
|
+
// Load provider
|
|
355
|
+
try {
|
|
356
|
+
provider.load(providerConfig)
|
|
357
|
+
this.activeProviders.add(providerName)
|
|
358
|
+
} catch (e) {
|
|
359
|
+
this.manager._debug('AnalyticsManager: load error', providerName, e)
|
|
360
|
+
}
|
|
361
|
+
} else if (!granted && this.activeProviders.has(providerName)) {
|
|
362
|
+
// Unload provider
|
|
363
|
+
try {
|
|
364
|
+
provider.unload(providerConfig)
|
|
365
|
+
this.activeProviders.delete(providerName)
|
|
366
|
+
} catch (e) {
|
|
367
|
+
this.manager._debug('AnalyticsManager: unload error', providerName, e)
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
})
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Register a custom analytics provider
|
|
375
|
+
*/
|
|
376
|
+
registerProvider(name, provider) {
|
|
377
|
+
ANALYTICS_PROVIDERS[name] = provider
|
|
378
|
+
this.manager._debug('AnalyticsManager: registered custom provider', name)
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
/**
|
|
382
|
+
* Get active providers
|
|
383
|
+
*/
|
|
384
|
+
getActiveProviders() {
|
|
385
|
+
return [...this.activeProviders]
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
destroy() {
|
|
389
|
+
// Unload all active providers
|
|
390
|
+
this.activeProviders.forEach(name => {
|
|
391
|
+
const provider = ANALYTICS_PROVIDERS[name]
|
|
392
|
+
if (provider?.unload) {
|
|
393
|
+
provider.unload(this.config[name] || {})
|
|
394
|
+
}
|
|
395
|
+
})
|
|
396
|
+
this.activeProviders.clear()
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
export { ANALYTICS_PROVIDERS }
|