@wxt-dev/analytics 0.1.6 → 0.2.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/README.md +3 -3
- package/dist/client.d.mts +3 -4
- package/dist/client.d.ts +3 -4
- package/dist/client.mjs +89 -70
- 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,67 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useAppConfig } from 'wxt/client';
|
|
3
|
-
import uaParser from 'ua-parser-js';
|
|
1
|
+
import { UAParser } from 'ua-parser-js';
|
|
4
2
|
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
]);
|
|
20
|
-
const client = defineWxtPlugin(() => {
|
|
21
|
-
const isBackground = globalThis.window == null;
|
|
22
|
-
analytics = isBackground ? createBackgroundAnalytics() : createAnalyticsForwarder();
|
|
23
|
-
});
|
|
24
|
-
function createAnalyticsForwarder() {
|
|
25
|
-
const port = chrome.runtime.connect({ name: ANALYTICS_PORT });
|
|
26
|
-
const sessionId = Date.now();
|
|
27
|
-
const getMetadata = () => ({
|
|
28
|
-
sessionId,
|
|
29
|
-
timestamp: Date.now(),
|
|
30
|
-
language: navigator.language,
|
|
31
|
-
referrer: globalThis.document?.referrer || void 0,
|
|
32
|
-
screen: globalThis.window ? `${globalThis.window.screen.width}x${globalThis.window.screen.height}` : void 0,
|
|
33
|
-
url: location.href
|
|
34
|
-
});
|
|
35
|
-
const methodForwarder = (fn) => (...args) => port.postMessage({ fn, args: [...args, getMetadata()] });
|
|
36
|
-
const analytics2 = {
|
|
37
|
-
identify: methodForwarder("identify"),
|
|
38
|
-
page: methodForwarder("page"),
|
|
39
|
-
track: methodForwarder("track"),
|
|
40
|
-
setEnabled: methodForwarder("setEnabled"),
|
|
41
|
-
autoTrack: (root) => {
|
|
42
|
-
const onClick = (event) => {
|
|
43
|
-
const element = event.target;
|
|
44
|
-
if (!element || !interactiveTags.has(element.tagName) && !interactiveRoles.has(element.getAttribute("role")))
|
|
45
|
-
return;
|
|
46
|
-
void analytics2.track("click", {
|
|
47
|
-
tagName: element.tagName?.toLowerCase(),
|
|
48
|
-
id: element.id || void 0,
|
|
49
|
-
className: element.className || void 0,
|
|
50
|
-
textContent: element.textContent?.substring(0, 50) || void 0,
|
|
51
|
-
// Limit text content length
|
|
52
|
-
href: element.href
|
|
53
|
-
});
|
|
54
|
-
};
|
|
55
|
-
root.addEventListener("click", onClick, { capture: true, passive: true });
|
|
56
|
-
return () => {
|
|
57
|
-
root.removeEventListener("click", onClick);
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
return analytics2;
|
|
3
|
+
const ANALYTICS_PORT = "@wxt-dev/analytics";
|
|
4
|
+
function createAnalytics(config) {
|
|
5
|
+
if (typeof chrome === "undefined" || !chrome?.runtime?.id)
|
|
6
|
+
throw Error(
|
|
7
|
+
"Cannot use WXT analytics in contexts without access to the browser.runtime APIs"
|
|
8
|
+
);
|
|
9
|
+
if (config == null) {
|
|
10
|
+
console.warn(
|
|
11
|
+
"[@wxt-dev/analytics] Config not provided to createAnalytics. If you're using WXT, add the 'analytics' property to '<srcDir>/app.config.ts'."
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
if (location.pathname === "/background.js")
|
|
15
|
+
return createBackgroundAnalytics(config);
|
|
16
|
+
return createFrontendAnalytics();
|
|
62
17
|
}
|
|
63
|
-
function createBackgroundAnalytics() {
|
|
64
|
-
const config = useAppConfig().analytics;
|
|
18
|
+
function createBackgroundAnalytics(config) {
|
|
65
19
|
const userIdStorage = config?.userId ?? defineStorageItem("local:wxt-analytics:user-id");
|
|
66
20
|
const userPropertiesStorage = config?.userProperties ?? defineStorageItem(
|
|
67
21
|
"local:wxt-analytics:user-properties",
|
|
@@ -69,7 +23,7 @@ function createBackgroundAnalytics() {
|
|
|
69
23
|
);
|
|
70
24
|
const enabled = config?.enabled ?? defineStorageItem("local:wxt-analytics:enabled", false);
|
|
71
25
|
const platformInfo = chrome.runtime.getPlatformInfo();
|
|
72
|
-
const userAgent =
|
|
26
|
+
const userAgent = UAParser();
|
|
73
27
|
let userId = Promise.resolve(userIdStorage.getValue()).then(
|
|
74
28
|
(id) => id ?? globalThis.crypto.randomUUID()
|
|
75
29
|
);
|
|
@@ -92,7 +46,8 @@ function createBackgroundAnalytics() {
|
|
|
92
46
|
timestamp: meta.timestamp,
|
|
93
47
|
screen: meta.screen,
|
|
94
48
|
referrer: meta.referrer,
|
|
95
|
-
language: meta.language
|
|
49
|
+
language: meta.language,
|
|
50
|
+
url: meta.url
|
|
96
51
|
},
|
|
97
52
|
user: {
|
|
98
53
|
id: await userId,
|
|
@@ -109,7 +64,7 @@ function createBackgroundAnalytics() {
|
|
|
109
64
|
}
|
|
110
65
|
};
|
|
111
66
|
};
|
|
112
|
-
const
|
|
67
|
+
const analytics = {
|
|
113
68
|
identify: async (newUserId, newUserProperties = {}, forwardMeta) => {
|
|
114
69
|
userId = Promise.resolve(newUserId);
|
|
115
70
|
userProperties = Promise.resolve(newUserProperties);
|
|
@@ -132,7 +87,11 @@ function createBackgroundAnalytics() {
|
|
|
132
87
|
const baseEvent = await getBaseEvent(forwardMeta);
|
|
133
88
|
const event = {
|
|
134
89
|
...baseEvent,
|
|
135
|
-
page: {
|
|
90
|
+
page: {
|
|
91
|
+
url,
|
|
92
|
+
location: globalThis.location?.href,
|
|
93
|
+
title: globalThis.document?.title
|
|
94
|
+
}
|
|
136
95
|
};
|
|
137
96
|
if (config?.debug)
|
|
138
97
|
console.debug("[analytics] page", event);
|
|
@@ -168,15 +127,75 @@ function createBackgroundAnalytics() {
|
|
|
168
127
|
};
|
|
169
128
|
}
|
|
170
129
|
};
|
|
171
|
-
const providers = config?.providers?.map((provider) => provider(
|
|
130
|
+
const providers = config?.providers?.map((provider) => provider(analytics, config)) ?? [];
|
|
172
131
|
chrome.runtime.onConnect.addListener((port) => {
|
|
173
132
|
if (port.name === ANALYTICS_PORT) {
|
|
174
133
|
port.onMessage.addListener(({ fn, args }) => {
|
|
175
|
-
void
|
|
134
|
+
void analytics[fn]?.(...args);
|
|
176
135
|
});
|
|
177
136
|
}
|
|
178
137
|
});
|
|
179
|
-
return
|
|
138
|
+
return analytics;
|
|
180
139
|
}
|
|
140
|
+
function createFrontendAnalytics() {
|
|
141
|
+
const port = chrome.runtime.connect({ name: ANALYTICS_PORT });
|
|
142
|
+
const sessionId = Date.now();
|
|
143
|
+
const getMetadata = () => ({
|
|
144
|
+
sessionId,
|
|
145
|
+
timestamp: Date.now(),
|
|
146
|
+
language: navigator.language,
|
|
147
|
+
referrer: globalThis.document?.referrer || void 0,
|
|
148
|
+
screen: globalThis.window ? `${globalThis.window.screen.width}x${globalThis.window.screen.height}` : void 0,
|
|
149
|
+
url: location.href
|
|
150
|
+
});
|
|
151
|
+
const methodForwarder = (fn) => (...args) => port.postMessage({ fn, args: [...args, getMetadata()] });
|
|
152
|
+
const analytics = {
|
|
153
|
+
identify: methodForwarder("identify"),
|
|
154
|
+
page: methodForwarder("page"),
|
|
155
|
+
track: methodForwarder("track"),
|
|
156
|
+
setEnabled: methodForwarder("setEnabled"),
|
|
157
|
+
autoTrack: (root) => {
|
|
158
|
+
const onClick = (event) => {
|
|
159
|
+
const element = event.target;
|
|
160
|
+
if (!element || !INTERACTIVE_TAGS.has(element.tagName) && !INTERACTIVE_ROLES.has(element.getAttribute("role")))
|
|
161
|
+
return;
|
|
162
|
+
void analytics.track("click", {
|
|
163
|
+
tagName: element.tagName?.toLowerCase(),
|
|
164
|
+
id: element.id || void 0,
|
|
165
|
+
className: element.className || void 0,
|
|
166
|
+
textContent: element.textContent?.substring(0, 50) || void 0,
|
|
167
|
+
// Limit text content length
|
|
168
|
+
href: element.href
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
root.addEventListener("click", onClick, { capture: true, passive: true });
|
|
172
|
+
return () => {
|
|
173
|
+
root.removeEventListener("click", onClick);
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
return analytics;
|
|
178
|
+
}
|
|
179
|
+
function defineStorageItem(key, defaultValue) {
|
|
180
|
+
return {
|
|
181
|
+
getValue: async () => (await chrome.storage.local.get(key))[key] ?? defaultValue,
|
|
182
|
+
setValue: (newValue) => chrome.storage.local.set({ [key]: newValue })
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
const INTERACTIVE_TAGS = /* @__PURE__ */ new Set([
|
|
186
|
+
"A",
|
|
187
|
+
"BUTTON",
|
|
188
|
+
"INPUT",
|
|
189
|
+
"SELECT",
|
|
190
|
+
"TEXTAREA"
|
|
191
|
+
]);
|
|
192
|
+
const INTERACTIVE_ROLES = /* @__PURE__ */ new Set([
|
|
193
|
+
"button",
|
|
194
|
+
"link",
|
|
195
|
+
"checkbox",
|
|
196
|
+
"menuitem",
|
|
197
|
+
"tab",
|
|
198
|
+
"radio"
|
|
199
|
+
]);
|
|
181
200
|
|
|
182
|
-
export {
|
|
201
|
+
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.1
|
|
3
|
+
"version": "0.2.1",
|
|
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"
|