@wxt-dev/analytics 0.2.8 → 0.4.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 +216 -37
- package/dist/background-plugin.d.mts +3 -0
- package/dist/background-plugin.d.ts +3 -0
- package/dist/background-plugin.mjs +6 -0
- package/dist/index.d.mts +10 -9
- package/dist/index.d.ts +10 -9
- package/dist/index.mjs +204 -32
- package/dist/module.d.mts +11 -0
- package/dist/module.d.ts +11 -0
- package/dist/module.mjs +61 -0
- package/dist/providers/google-analytics-4.d.mts +4 -4
- package/dist/providers/google-analytics-4.d.ts +4 -4
- package/dist/providers/google-analytics-4.mjs +57 -52
- package/dist/providers/umami.d.mts +3 -3
- package/dist/providers/umami.d.ts +3 -3
- package/dist/providers/umami.mjs +51 -41
- package/dist/{shared/analytics.2893a879.d.ts → types.d.mts} +16 -15
- package/dist/{shared/analytics.2893a879.d.mts → types.d.ts} +16 -15
- package/dist/types.mjs +1 -0
- package/package.json +17 -11
- package/dist/client.d.mts +0 -5
- package/dist/client.d.ts +0 -5
- package/dist/client.mjs +0 -201
package/dist/client.mjs
DELETED
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
import { UAParser } from 'ua-parser-js';
|
|
2
|
-
|
|
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();
|
|
17
|
-
}
|
|
18
|
-
function createBackgroundAnalytics(config) {
|
|
19
|
-
const userIdStorage = config?.userId ?? defineStorageItem("wxt-analytics:user-id");
|
|
20
|
-
const userPropertiesStorage = config?.userProperties ?? defineStorageItem(
|
|
21
|
-
"wxt-analytics:user-properties",
|
|
22
|
-
{}
|
|
23
|
-
);
|
|
24
|
-
const enabled = config?.enabled ?? defineStorageItem("local:wxt-analytics:enabled", false);
|
|
25
|
-
const platformInfo = chrome.runtime.getPlatformInfo();
|
|
26
|
-
const userAgent = UAParser();
|
|
27
|
-
let userId = Promise.resolve(userIdStorage.getValue()).then(
|
|
28
|
-
(id) => id ?? globalThis.crypto.randomUUID()
|
|
29
|
-
);
|
|
30
|
-
let userProperties = userPropertiesStorage.getValue();
|
|
31
|
-
const manifest = chrome.runtime.getManifest();
|
|
32
|
-
const getBackgroundMeta = () => ({
|
|
33
|
-
timestamp: Date.now(),
|
|
34
|
-
// Don't track sessions for the background, it can be running
|
|
35
|
-
// indefinitely, and will inflate session duration stats.
|
|
36
|
-
sessionId: void 0,
|
|
37
|
-
language: navigator.language,
|
|
38
|
-
referrer: void 0,
|
|
39
|
-
screen: void 0,
|
|
40
|
-
url: location.href,
|
|
41
|
-
title: void 0
|
|
42
|
-
});
|
|
43
|
-
const getBaseEvent = async (meta) => {
|
|
44
|
-
const platform = await platformInfo;
|
|
45
|
-
return {
|
|
46
|
-
meta,
|
|
47
|
-
user: {
|
|
48
|
-
id: await userId,
|
|
49
|
-
properties: {
|
|
50
|
-
version: config?.version ?? manifest.version_name ?? manifest.version,
|
|
51
|
-
wxtMode: import.meta.env.MODE,
|
|
52
|
-
wxtBrowser: import.meta.env.BROWSER,
|
|
53
|
-
arch: platform.arch,
|
|
54
|
-
os: platform.os,
|
|
55
|
-
browser: userAgent.browser.name,
|
|
56
|
-
browserVersion: userAgent.browser.version,
|
|
57
|
-
...await userProperties
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
};
|
|
61
|
-
};
|
|
62
|
-
const analytics = {
|
|
63
|
-
identify: async (newUserId, newUserProperties = {}, meta = getBackgroundMeta()) => {
|
|
64
|
-
userId = Promise.resolve(newUserId);
|
|
65
|
-
userProperties = Promise.resolve(newUserProperties);
|
|
66
|
-
await Promise.all([
|
|
67
|
-
userIdStorage.setValue?.(newUserId),
|
|
68
|
-
userPropertiesStorage.setValue?.(newUserProperties)
|
|
69
|
-
]);
|
|
70
|
-
const event = await getBaseEvent(meta);
|
|
71
|
-
if (config?.debug)
|
|
72
|
-
console.debug("[analytics] identify", event);
|
|
73
|
-
if (await enabled.getValue()) {
|
|
74
|
-
await Promise.allSettled(
|
|
75
|
-
providers.map((provider) => provider.identify(event))
|
|
76
|
-
);
|
|
77
|
-
} else if (config?.debug) {
|
|
78
|
-
console.debug(
|
|
79
|
-
"[analytics] Analytics disabled, identify() not uploaded"
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
},
|
|
83
|
-
page: async (location2, meta = getBackgroundMeta()) => {
|
|
84
|
-
const baseEvent = await getBaseEvent(meta);
|
|
85
|
-
const event = {
|
|
86
|
-
...baseEvent,
|
|
87
|
-
page: {
|
|
88
|
-
url: meta?.url ?? globalThis.location?.href,
|
|
89
|
-
location: location2,
|
|
90
|
-
title: meta?.title ?? globalThis.document?.title
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
if (config?.debug)
|
|
94
|
-
console.debug("[analytics] page", event);
|
|
95
|
-
if (await enabled.getValue()) {
|
|
96
|
-
await Promise.allSettled(
|
|
97
|
-
providers.map((provider) => provider.page(event))
|
|
98
|
-
);
|
|
99
|
-
} else if (config?.debug) {
|
|
100
|
-
console.debug("[analytics] Analytics disabled, page() not uploaded");
|
|
101
|
-
}
|
|
102
|
-
},
|
|
103
|
-
track: async (eventName, eventProperties, meta = getBackgroundMeta()) => {
|
|
104
|
-
const baseEvent = await getBaseEvent(meta);
|
|
105
|
-
const event = {
|
|
106
|
-
...baseEvent,
|
|
107
|
-
event: { name: eventName, properties: eventProperties }
|
|
108
|
-
};
|
|
109
|
-
if (config?.debug)
|
|
110
|
-
console.debug("[analytics] track", event);
|
|
111
|
-
if (await enabled.getValue()) {
|
|
112
|
-
await Promise.allSettled(
|
|
113
|
-
providers.map((provider) => provider.track(event))
|
|
114
|
-
);
|
|
115
|
-
} else if (config?.debug) {
|
|
116
|
-
console.debug("[analytics] Analytics disabled, track() not uploaded");
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
setEnabled: async (newEnabled) => {
|
|
120
|
-
await enabled.setValue?.(newEnabled);
|
|
121
|
-
},
|
|
122
|
-
autoTrack: () => {
|
|
123
|
-
return () => {
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
const providers = config?.providers?.map((provider) => provider(analytics, config)) ?? [];
|
|
128
|
-
chrome.runtime.onConnect.addListener((port) => {
|
|
129
|
-
if (port.name === ANALYTICS_PORT) {
|
|
130
|
-
port.onMessage.addListener(({ fn, args }) => {
|
|
131
|
-
void analytics[fn]?.(...args);
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
return analytics;
|
|
136
|
-
}
|
|
137
|
-
function createFrontendAnalytics() {
|
|
138
|
-
const port = chrome.runtime.connect({ name: ANALYTICS_PORT });
|
|
139
|
-
const sessionId = Date.now();
|
|
140
|
-
const getFrontendMetadata = () => ({
|
|
141
|
-
sessionId,
|
|
142
|
-
timestamp: Date.now(),
|
|
143
|
-
language: navigator.language,
|
|
144
|
-
referrer: globalThis.document?.referrer || void 0,
|
|
145
|
-
screen: globalThis.window ? `${globalThis.window.screen.width}x${globalThis.window.screen.height}` : void 0,
|
|
146
|
-
url: location.href,
|
|
147
|
-
title: document.title || void 0
|
|
148
|
-
});
|
|
149
|
-
const methodForwarder = (fn) => (...args) => {
|
|
150
|
-
port.postMessage({ fn, args: [...args, getFrontendMetadata()] });
|
|
151
|
-
};
|
|
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
|
-
]);
|
|
200
|
-
|
|
201
|
-
export { createAnalytics };
|