@wxt-dev/analytics 0.1.5 → 0.2.0
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/README.md +3 -3
- package/dist/client.d.mts +3 -4
- package/dist/client.d.ts +3 -4
- package/dist/client.mjs +90 -76
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +20 -11
- package/dist/providers/google-analytics-4.d.mts +1 -1
- package/dist/providers/google-analytics-4.d.ts +1 -1
- package/dist/providers/umami.d.mts +1 -1
- package/dist/providers/umami.d.ts +1 -1
- package/dist/shared/{analytics.c704a57b.d.mts → analytics.5d517cf0.d.mts} +10 -10
- package/dist/shared/{analytics.c704a57b.d.ts → analytics.5d517cf0.d.ts} +10 -10
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,8 +4,8 @@ Add analytics, like google analytics, to your WXT extension.
|
|
|
4
4
|
|
|
5
5
|
## Supported Analytics Providers
|
|
6
6
|
|
|
7
|
-
- Google Analytics (Measurement Protocol)
|
|
8
|
-
- Umami
|
|
7
|
+
- [Google Analytics 4 (Measurement Protocol)](#google-analytics-4-measurement-protocol)
|
|
8
|
+
- [Umami](#umami)
|
|
9
9
|
|
|
10
10
|
## Installation
|
|
11
11
|
|
|
@@ -49,7 +49,7 @@ await analytics.identify('some-user-id');
|
|
|
49
49
|
|
|
50
50
|
## Providers
|
|
51
51
|
|
|
52
|
-
### Google Analytics (Measurement Protocol)
|
|
52
|
+
### Google Analytics 4 (Measurement Protocol)
|
|
53
53
|
|
|
54
54
|
Follow [Google's documentation](https://developer.chrome.com/docs/extensions/how-to/integrate/google-analytics-4#setup-credentials) to obtain your credentials:
|
|
55
55
|
|
package/dist/client.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { a as Analytics } from './shared/analytics.
|
|
1
|
+
import { A as AnalyticsConfig, a as Analytics } from './shared/analytics.5d517cf0.mjs';
|
|
2
2
|
|
|
3
|
-
declare
|
|
4
|
-
declare const _default: any;
|
|
3
|
+
declare function createAnalytics(config: AnalyticsConfig): Analytics;
|
|
5
4
|
|
|
6
|
-
export {
|
|
5
|
+
export { createAnalytics };
|
package/dist/client.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { a as Analytics } from './shared/analytics.
|
|
1
|
+
import { A as AnalyticsConfig, a as Analytics } from './shared/analytics.5d517cf0.js';
|
|
2
2
|
|
|
3
|
-
declare
|
|
4
|
-
declare const _default: any;
|
|
3
|
+
declare function createAnalytics(config: AnalyticsConfig): Analytics;
|
|
5
4
|
|
|
6
|
-
export {
|
|
5
|
+
export { createAnalytics };
|
package/dist/client.mjs
CHANGED
|
@@ -1,80 +1,29 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { storage } from 'wxt/storage';
|
|
3
|
-
import { useAppConfig } from 'wxt/client';
|
|
4
|
-
import { browser } from 'wxt/browser';
|
|
5
|
-
import uaParser from 'ua-parser-js';
|
|
1
|
+
import { UAParser } from 'ua-parser-js';
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"radio"
|
|
17
|
-
]);
|
|
18
|
-
const client = defineWxtPlugin(() => {
|
|
19
|
-
const isBackground = globalThis.window == null;
|
|
20
|
-
analytics = isBackground ? createBackgroundAnalytics() : createAnalyticsForwarder();
|
|
21
|
-
});
|
|
22
|
-
function createAnalyticsForwarder() {
|
|
23
|
-
const port = browser.runtime.connect({ name: ANALYTICS_PORT });
|
|
24
|
-
const sessionId = Date.now();
|
|
25
|
-
const getMetadata = () => ({
|
|
26
|
-
sessionId,
|
|
27
|
-
timestamp: Date.now(),
|
|
28
|
-
language: navigator.language,
|
|
29
|
-
referrer: globalThis.document?.referrer || void 0,
|
|
30
|
-
screen: globalThis.window ? `${globalThis.window.screen.width}x${globalThis.window.screen.height}` : void 0,
|
|
31
|
-
url: location.href
|
|
32
|
-
});
|
|
33
|
-
const methodForwarder = (fn) => (...args) => port.postMessage({ fn, args: [...args, getMetadata()] });
|
|
34
|
-
const analytics2 = {
|
|
35
|
-
identify: methodForwarder("identify"),
|
|
36
|
-
page: methodForwarder("page"),
|
|
37
|
-
track: methodForwarder("track"),
|
|
38
|
-
setEnabled: methodForwarder("setEnabled"),
|
|
39
|
-
autoTrack: (root) => {
|
|
40
|
-
const onClick = (event) => {
|
|
41
|
-
const element = event.target;
|
|
42
|
-
if (!element || !interactiveTags.has(element.tagName) && !interactiveRoles.has(element.getAttribute("role")))
|
|
43
|
-
return;
|
|
44
|
-
void analytics2.track("click", {
|
|
45
|
-
tagName: element.tagName?.toLowerCase(),
|
|
46
|
-
id: element.id || void 0,
|
|
47
|
-
className: element.className || void 0,
|
|
48
|
-
textContent: element.textContent?.substring(0, 50) || void 0,
|
|
49
|
-
// Limit text content length
|
|
50
|
-
href: element.href
|
|
51
|
-
});
|
|
52
|
-
};
|
|
53
|
-
root.addEventListener("click", onClick, { capture: true, passive: true });
|
|
54
|
-
return () => {
|
|
55
|
-
root.removeEventListener("click", onClick);
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
};
|
|
59
|
-
return analytics2;
|
|
3
|
+
const ANALYTICS_PORT = "@wxt-dev/analytics";
|
|
4
|
+
function createAnalytics(config) {
|
|
5
|
+
if (globalThis.chrome?.runtime?.id)
|
|
6
|
+
throw Error(
|
|
7
|
+
"Cannot use WXT analytics in contexts without access to the browser.runtime APIs"
|
|
8
|
+
);
|
|
9
|
+
if (location.pathname === "/background.js")
|
|
10
|
+
return createBackgroundAnalytics(config);
|
|
11
|
+
return createFrontendAnalytics();
|
|
60
12
|
}
|
|
61
|
-
function createBackgroundAnalytics() {
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
const userPropertiesStorage = config?.userProperties ?? storage.defineItem(
|
|
13
|
+
function createBackgroundAnalytics(config) {
|
|
14
|
+
const userIdStorage = config?.userId ?? defineStorageItem("local:wxt-analytics:user-id");
|
|
15
|
+
const userPropertiesStorage = config?.userProperties ?? defineStorageItem(
|
|
65
16
|
"local:wxt-analytics:user-properties",
|
|
66
|
-
{
|
|
17
|
+
{}
|
|
67
18
|
);
|
|
68
|
-
const enabled = config?.enabled ??
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
const platformInfo = browser.runtime.getPlatformInfo();
|
|
72
|
-
const userAgent = uaParser();
|
|
19
|
+
const enabled = config?.enabled ?? defineStorageItem("local:wxt-analytics:enabled", false);
|
|
20
|
+
const platformInfo = chrome.runtime.getPlatformInfo();
|
|
21
|
+
const userAgent = UAParser();
|
|
73
22
|
let userId = Promise.resolve(userIdStorage.getValue()).then(
|
|
74
23
|
(id) => id ?? globalThis.crypto.randomUUID()
|
|
75
24
|
);
|
|
76
25
|
let userProperties = userPropertiesStorage.getValue();
|
|
77
|
-
const manifest =
|
|
26
|
+
const manifest = chrome.runtime.getManifest();
|
|
78
27
|
const getBaseEvent = async (meta = {
|
|
79
28
|
timestamp: Date.now(),
|
|
80
29
|
// Don't track sessions for the background, it can be running
|
|
@@ -92,7 +41,8 @@ function createBackgroundAnalytics() {
|
|
|
92
41
|
timestamp: meta.timestamp,
|
|
93
42
|
screen: meta.screen,
|
|
94
43
|
referrer: meta.referrer,
|
|
95
|
-
language: meta.language
|
|
44
|
+
language: meta.language,
|
|
45
|
+
url: meta.url
|
|
96
46
|
},
|
|
97
47
|
user: {
|
|
98
48
|
id: await userId,
|
|
@@ -109,7 +59,7 @@ function createBackgroundAnalytics() {
|
|
|
109
59
|
}
|
|
110
60
|
};
|
|
111
61
|
};
|
|
112
|
-
const
|
|
62
|
+
const analytics = {
|
|
113
63
|
identify: async (newUserId, newUserProperties = {}, forwardMeta) => {
|
|
114
64
|
userId = Promise.resolve(newUserId);
|
|
115
65
|
userProperties = Promise.resolve(newUserProperties);
|
|
@@ -132,7 +82,11 @@ function createBackgroundAnalytics() {
|
|
|
132
82
|
const baseEvent = await getBaseEvent(forwardMeta);
|
|
133
83
|
const event = {
|
|
134
84
|
...baseEvent,
|
|
135
|
-
page: {
|
|
85
|
+
page: {
|
|
86
|
+
url,
|
|
87
|
+
location: globalThis.location?.href,
|
|
88
|
+
title: globalThis.document?.title
|
|
89
|
+
}
|
|
136
90
|
};
|
|
137
91
|
if (config?.debug)
|
|
138
92
|
console.debug("[analytics] page", event);
|
|
@@ -168,15 +122,75 @@ function createBackgroundAnalytics() {
|
|
|
168
122
|
};
|
|
169
123
|
}
|
|
170
124
|
};
|
|
171
|
-
const providers = config?.providers?.map((provider) => provider(
|
|
125
|
+
const providers = config?.providers?.map((provider) => provider(analytics, config)) ?? [];
|
|
172
126
|
chrome.runtime.onConnect.addListener((port) => {
|
|
173
127
|
if (port.name === ANALYTICS_PORT) {
|
|
174
128
|
port.onMessage.addListener(({ fn, args }) => {
|
|
175
|
-
void
|
|
129
|
+
void analytics[fn]?.(...args);
|
|
176
130
|
});
|
|
177
131
|
}
|
|
178
132
|
});
|
|
179
|
-
return
|
|
133
|
+
return analytics;
|
|
134
|
+
}
|
|
135
|
+
function createFrontendAnalytics() {
|
|
136
|
+
const port = chrome.runtime.connect({ name: ANALYTICS_PORT });
|
|
137
|
+
const sessionId = Date.now();
|
|
138
|
+
const getMetadata = () => ({
|
|
139
|
+
sessionId,
|
|
140
|
+
timestamp: Date.now(),
|
|
141
|
+
language: navigator.language,
|
|
142
|
+
referrer: globalThis.document?.referrer || void 0,
|
|
143
|
+
screen: globalThis.window ? `${globalThis.window.screen.width}x${globalThis.window.screen.height}` : void 0,
|
|
144
|
+
url: location.href
|
|
145
|
+
});
|
|
146
|
+
const methodForwarder = (fn) => (...args) => port.postMessage({ fn, args: [...args, getMetadata()] });
|
|
147
|
+
const analytics = {
|
|
148
|
+
identify: methodForwarder("identify"),
|
|
149
|
+
page: methodForwarder("page"),
|
|
150
|
+
track: methodForwarder("track"),
|
|
151
|
+
setEnabled: methodForwarder("setEnabled"),
|
|
152
|
+
autoTrack: (root) => {
|
|
153
|
+
const onClick = (event) => {
|
|
154
|
+
const element = event.target;
|
|
155
|
+
if (!element || !INTERACTIVE_TAGS.has(element.tagName) && !INTERACTIVE_ROLES.has(element.getAttribute("role")))
|
|
156
|
+
return;
|
|
157
|
+
void analytics.track("click", {
|
|
158
|
+
tagName: element.tagName?.toLowerCase(),
|
|
159
|
+
id: element.id || void 0,
|
|
160
|
+
className: element.className || void 0,
|
|
161
|
+
textContent: element.textContent?.substring(0, 50) || void 0,
|
|
162
|
+
// Limit text content length
|
|
163
|
+
href: element.href
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
root.addEventListener("click", onClick, { capture: true, passive: true });
|
|
167
|
+
return () => {
|
|
168
|
+
root.removeEventListener("click", onClick);
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
};
|
|
172
|
+
return analytics;
|
|
180
173
|
}
|
|
174
|
+
function defineStorageItem(key, defaultValue) {
|
|
175
|
+
return {
|
|
176
|
+
getValue: async () => (await chrome.storage.local.get(key))[key] ?? defaultValue,
|
|
177
|
+
setValue: (newValue) => chrome.storage.local.set({ [key]: newValue })
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
const INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
|
|
181
|
+
"A",
|
|
182
|
+
"BUTTON",
|
|
183
|
+
"INPUT",
|
|
184
|
+
"SELECT",
|
|
185
|
+
"TEXTAREA"
|
|
186
|
+
]);
|
|
187
|
+
const INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
|
|
188
|
+
"button",
|
|
189
|
+
"link",
|
|
190
|
+
"checkbox",
|
|
191
|
+
"menuitem",
|
|
192
|
+
"tab",
|
|
193
|
+
"radio"
|
|
194
|
+
]);
|
|
181
195
|
|
|
182
|
-
export {
|
|
196
|
+
export { createAnalytics };
|
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,25 +1,34 @@
|
|
|
1
1
|
import 'wxt';
|
|
2
2
|
import 'wxt/sandbox';
|
|
3
|
-
import { defineWxtModule,
|
|
4
|
-
import {
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
3
|
+
import { defineWxtModule, addAlias } from 'wxt/modules';
|
|
4
|
+
import { resolve } from 'node:path';
|
|
6
5
|
|
|
7
|
-
const _dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const pluginId = "@wxt-dev/analytics/client" ;
|
|
9
6
|
const index = defineWxtModule({
|
|
10
7
|
name: "analytics",
|
|
11
|
-
imports: [{ name: "analytics", from:
|
|
8
|
+
imports: [{ name: "analytics", from: "#analytics" }],
|
|
12
9
|
setup(wxt) {
|
|
13
|
-
|
|
14
|
-
wxt,
|
|
15
|
-
resolve(_dirname, "client.mjs" )
|
|
16
|
-
);
|
|
17
|
-
wxt.hooks.hook("build:manifestGenerated", (_, manifest) => {
|
|
10
|
+
wxt.hook("build:manifestGenerated", (_, manifest) => {
|
|
18
11
|
manifest.permissions ?? (manifest.permissions = []);
|
|
19
12
|
if (!manifest.permissions.includes("storage")) {
|
|
20
13
|
manifest.permissions.push("storage");
|
|
21
14
|
}
|
|
22
15
|
});
|
|
16
|
+
const analyticsModulePath = resolve(
|
|
17
|
+
wxt.config.wxtDir,
|
|
18
|
+
"analytics/index.ts"
|
|
19
|
+
);
|
|
20
|
+
const analyticsModuleCode = `
|
|
21
|
+
import { createAnalytics } from '@wxt-dev/analytics/client';
|
|
22
|
+
|
|
23
|
+
export const analytics = createAnalytics(useAppConfig().analytics);
|
|
24
|
+
`;
|
|
25
|
+
addAlias(wxt, "#analytics", analyticsModulePath);
|
|
26
|
+
wxt.hook("prepare:types", async (_, entries) => {
|
|
27
|
+
entries.push({
|
|
28
|
+
path: analyticsModulePath,
|
|
29
|
+
text: analyticsModuleCode
|
|
30
|
+
});
|
|
31
|
+
});
|
|
23
32
|
}
|
|
24
33
|
});
|
|
25
34
|
|
|
@@ -26,17 +26,17 @@ interface AnalyticsConfig {
|
|
|
26
26
|
/**
|
|
27
27
|
* Configure how the enabled flag is persisted
|
|
28
28
|
*/
|
|
29
|
-
enabled?:
|
|
29
|
+
enabled?: AnalyticsStorageItem<boolean>;
|
|
30
30
|
/**
|
|
31
31
|
* Configure how the user Id is persisted
|
|
32
32
|
*/
|
|
33
|
-
userId?:
|
|
33
|
+
userId?: AnalyticsStorageItem<string>;
|
|
34
34
|
/**
|
|
35
35
|
* Configure how user properties are persisted
|
|
36
36
|
*/
|
|
37
|
-
userProperties?:
|
|
37
|
+
userProperties?: AnalyticsStorageItem<Record<string, string>>;
|
|
38
38
|
}
|
|
39
|
-
interface
|
|
39
|
+
interface AnalyticsStorageItem<T> {
|
|
40
40
|
getValue: () => T | Promise<T>;
|
|
41
41
|
setValue?: (newValue: T) => void | Promise<void>;
|
|
42
42
|
}
|
|
@@ -55,13 +55,13 @@ interface BaseAnalyticsEvent {
|
|
|
55
55
|
/** `Date.now()` of when the event was reported */
|
|
56
56
|
timestamp: number;
|
|
57
57
|
/** `"1920x1080"` */
|
|
58
|
-
screen
|
|
58
|
+
screen: string | undefined;
|
|
59
59
|
/** `document.referrer` */
|
|
60
|
-
referrer
|
|
60
|
+
referrer: string | undefined;
|
|
61
61
|
/** `navigator.language` */
|
|
62
|
-
language
|
|
62
|
+
language: string | undefined;
|
|
63
63
|
/** `location.href` */
|
|
64
|
-
url
|
|
64
|
+
url: string | undefined;
|
|
65
65
|
};
|
|
66
66
|
user: {
|
|
67
67
|
id: string;
|
|
@@ -70,8 +70,8 @@ interface BaseAnalyticsEvent {
|
|
|
70
70
|
}
|
|
71
71
|
interface AnalyticsPageInfo {
|
|
72
72
|
url: string;
|
|
73
|
-
title
|
|
74
|
-
location
|
|
73
|
+
title: string | undefined;
|
|
74
|
+
location: string | undefined;
|
|
75
75
|
}
|
|
76
76
|
interface AnalyticsPageViewEvent extends BaseAnalyticsEvent {
|
|
77
77
|
page: AnalyticsPageInfo;
|
|
@@ -26,17 +26,17 @@ interface AnalyticsConfig {
|
|
|
26
26
|
/**
|
|
27
27
|
* Configure how the enabled flag is persisted
|
|
28
28
|
*/
|
|
29
|
-
enabled?:
|
|
29
|
+
enabled?: AnalyticsStorageItem<boolean>;
|
|
30
30
|
/**
|
|
31
31
|
* Configure how the user Id is persisted
|
|
32
32
|
*/
|
|
33
|
-
userId?:
|
|
33
|
+
userId?: AnalyticsStorageItem<string>;
|
|
34
34
|
/**
|
|
35
35
|
* Configure how user properties are persisted
|
|
36
36
|
*/
|
|
37
|
-
userProperties?:
|
|
37
|
+
userProperties?: AnalyticsStorageItem<Record<string, string>>;
|
|
38
38
|
}
|
|
39
|
-
interface
|
|
39
|
+
interface AnalyticsStorageItem<T> {
|
|
40
40
|
getValue: () => T | Promise<T>;
|
|
41
41
|
setValue?: (newValue: T) => void | Promise<void>;
|
|
42
42
|
}
|
|
@@ -55,13 +55,13 @@ interface BaseAnalyticsEvent {
|
|
|
55
55
|
/** `Date.now()` of when the event was reported */
|
|
56
56
|
timestamp: number;
|
|
57
57
|
/** `"1920x1080"` */
|
|
58
|
-
screen
|
|
58
|
+
screen: string | undefined;
|
|
59
59
|
/** `document.referrer` */
|
|
60
|
-
referrer
|
|
60
|
+
referrer: string | undefined;
|
|
61
61
|
/** `navigator.language` */
|
|
62
|
-
language
|
|
62
|
+
language: string | undefined;
|
|
63
63
|
/** `location.href` */
|
|
64
|
-
url
|
|
64
|
+
url: string | undefined;
|
|
65
65
|
};
|
|
66
66
|
user: {
|
|
67
67
|
id: string;
|
|
@@ -70,8 +70,8 @@ interface BaseAnalyticsEvent {
|
|
|
70
70
|
}
|
|
71
71
|
interface AnalyticsPageInfo {
|
|
72
72
|
url: string;
|
|
73
|
-
title
|
|
74
|
-
location
|
|
73
|
+
title: string | undefined;
|
|
74
|
+
location: string | undefined;
|
|
75
75
|
}
|
|
76
76
|
interface AnalyticsPageViewEvent extends BaseAnalyticsEvent {
|
|
77
77
|
page: AnalyticsPageInfo;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wxt-dev/analytics",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Add analytics to your web extension",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"publint": "^0.2.8",
|
|
44
44
|
"typescript": "^5.5.2",
|
|
45
45
|
"unbuild": "^2.0.0",
|
|
46
|
-
"wxt": "0.
|
|
46
|
+
"wxt": "0.19.13"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"ua-parser-js": "^1.0.38"
|