@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.
@@ -0,0 +1,61 @@
1
+ import 'wxt';
2
+ import 'wxt/sandbox';
3
+ import { defineWxtModule, addAlias, addWxtPlugin, addViteConfig } from 'wxt/modules';
4
+ import { resolve } from 'node:path';
5
+
6
+ const index = defineWxtModule({
7
+ name: "analytics",
8
+ imports: [{ name: "analytics", from: "#analytics" }],
9
+ setup(wxt) {
10
+ const wxtAnalyticsFolder = resolve(wxt.config.wxtDir, "analytics");
11
+ const wxtAnalyticsIndex = resolve(wxtAnalyticsFolder, "index.ts");
12
+ const clientModuleId = "@wxt-dev/analytics" ;
13
+ const pluginModuleId = "@wxt-dev/analytics/background-plugin" ;
14
+ wxt.hook("build:manifestGenerated", (_, manifest) => {
15
+ manifest.permissions ?? (manifest.permissions = []);
16
+ if (!manifest.permissions.includes("storage")) {
17
+ manifest.permissions.push("storage");
18
+ }
19
+ });
20
+ const wxtAnalyticsCode = [
21
+ `import { createAnalytics } from '${clientModuleId }';`,
22
+ `import { useAppConfig } from 'wxt/client';`,
23
+ ``,
24
+ `export const analytics = createAnalytics(useAppConfig().analytics);`,
25
+ ``
26
+ ].join("\n");
27
+ addAlias(wxt, "#analytics", wxtAnalyticsIndex);
28
+ wxt.hook("prepare:types", async (_, entries) => {
29
+ entries.push({
30
+ path: wxtAnalyticsIndex,
31
+ text: wxtAnalyticsCode
32
+ });
33
+ });
34
+ wxt.hook("entrypoints:resolved", (_, entrypoints) => {
35
+ const hasBackground = entrypoints.find(
36
+ (entry) => entry.type === "background"
37
+ );
38
+ if (!hasBackground) {
39
+ entrypoints.push({
40
+ type: "background",
41
+ inputPath: "virtual:user-background",
42
+ name: "background",
43
+ options: {},
44
+ outputDir: wxt.config.outDir,
45
+ skipped: false
46
+ });
47
+ }
48
+ });
49
+ addWxtPlugin(wxt, pluginModuleId);
50
+ addViteConfig(wxt, () => ({
51
+ optimizeDeps: {
52
+ // Ensure the "#analytics" import is processed by vite in the background plugin
53
+ exclude: ["@wxt-dev/analytics"],
54
+ // Ensure the CJS subdependency is preprocessed into ESM
55
+ include: ["@wxt-dev/analytics > ua-parser-js"]
56
+ }
57
+ }));
58
+ }
59
+ });
60
+
61
+ export { index as default };
@@ -1,9 +1,9 @@
1
- import { b as AnalyticsProvider } from '../shared/analytics.2893a879.mjs';
1
+ import { AnalyticsProvider } from '../types.mjs';
2
2
 
3
- interface GoogleAnalyticsProviderOptions {
3
+ interface GoogleAnalytics4ProviderOptions {
4
4
  apiSecret: string;
5
5
  measurementId: string;
6
6
  }
7
- declare const googleAnalytics4: (options: GoogleAnalyticsProviderOptions) => AnalyticsProvider;
7
+ declare const googleAnalytics4: (options: GoogleAnalytics4ProviderOptions) => AnalyticsProvider;
8
8
 
9
- export { type GoogleAnalyticsProviderOptions, googleAnalytics4 };
9
+ export { type GoogleAnalytics4ProviderOptions, googleAnalytics4 };
@@ -1,9 +1,9 @@
1
- import { b as AnalyticsProvider } from '../shared/analytics.2893a879.js';
1
+ import { AnalyticsProvider } from '../types.js';
2
2
 
3
- interface GoogleAnalyticsProviderOptions {
3
+ interface GoogleAnalytics4ProviderOptions {
4
4
  apiSecret: string;
5
5
  measurementId: string;
6
6
  }
7
- declare const googleAnalytics4: (options: GoogleAnalyticsProviderOptions) => AnalyticsProvider;
7
+ declare const googleAnalytics4: (options: GoogleAnalytics4ProviderOptions) => AnalyticsProvider;
8
8
 
9
- export { type GoogleAnalyticsProviderOptions, googleAnalytics4 };
9
+ export { type GoogleAnalytics4ProviderOptions, googleAnalytics4 };
@@ -1,56 +1,61 @@
1
+ import { defineAnalyticsProvider } from '../index.mjs';
2
+ import 'ua-parser-js';
3
+
1
4
  const DEFAULT_ENGAGEMENT_TIME_IN_MSEC = 100;
2
- const googleAnalytics4 = (options) => (_, config) => {
3
- const send = async (data, eventName, eventProperties) => {
4
- const url = new URL(
5
- config?.debug ? "/debug/mp/collect" : "/mp/collect",
6
- "https://www.google-analytics.com"
7
- );
8
- if (options.apiSecret)
9
- url.searchParams.set("api_secret", options.apiSecret);
10
- if (options.measurementId)
11
- url.searchParams.set("measurement_id", options.measurementId);
12
- const userProperties = {
13
- language: data.meta.language,
14
- screen: data.meta.screen,
15
- ...data.user.properties
16
- };
17
- const mappedUserProperties = Object.fromEntries(
18
- Object.entries(userProperties).map(([name, value]) => [
19
- name,
20
- value == null ? void 0 : { value }
21
- ])
22
- );
23
- await fetch(url.href, {
24
- method: "POST",
25
- body: JSON.stringify({
26
- client_id: data.user.id,
27
- consent: {
28
- ad_user_data: "DENIED",
29
- ad_personalization: "DENIED"
30
- },
31
- user_properties: mappedUserProperties,
32
- events: [
33
- {
34
- name: eventName,
35
- params: {
36
- session_id: data.meta.sessionId,
37
- engagement_time_msec: DEFAULT_ENGAGEMENT_TIME_IN_MSEC,
38
- ...eventProperties
5
+ const googleAnalytics4 = defineAnalyticsProvider(
6
+ (_, config, options) => {
7
+ const send = async (data, eventName, eventProperties) => {
8
+ const url = new URL(
9
+ config?.debug ? "/debug/mp/collect" : "/mp/collect",
10
+ "https://www.google-analytics.com"
11
+ );
12
+ if (options.apiSecret)
13
+ url.searchParams.set("api_secret", options.apiSecret);
14
+ if (options.measurementId)
15
+ url.searchParams.set("measurement_id", options.measurementId);
16
+ const userProperties = {
17
+ language: data.meta.language,
18
+ screen: data.meta.screen,
19
+ ...data.user.properties
20
+ };
21
+ const mappedUserProperties = Object.fromEntries(
22
+ Object.entries(userProperties).map(([name, value]) => [
23
+ name,
24
+ value == null ? void 0 : { value }
25
+ ])
26
+ );
27
+ await fetch(url.href, {
28
+ method: "POST",
29
+ body: JSON.stringify({
30
+ client_id: data.user.id,
31
+ consent: {
32
+ ad_user_data: "DENIED",
33
+ ad_personalization: "DENIED"
34
+ },
35
+ user_properties: mappedUserProperties,
36
+ events: [
37
+ {
38
+ name: eventName,
39
+ params: {
40
+ session_id: data.meta.sessionId,
41
+ engagement_time_msec: DEFAULT_ENGAGEMENT_TIME_IN_MSEC,
42
+ ...eventProperties
43
+ }
39
44
  }
40
- }
41
- ]
42
- })
43
- });
44
- };
45
- return {
46
- identify: () => Promise.resolve(),
47
- // No-op, user data uploaded in page/track
48
- page: (event) => send(event, "page_view", {
49
- page_title: event.page.title,
50
- page_location: event.page.location
51
- }),
52
- track: (event) => send(event, event.event.name, event.event.properties)
53
- };
54
- };
45
+ ]
46
+ })
47
+ });
48
+ };
49
+ return {
50
+ identify: () => Promise.resolve(),
51
+ // No-op, user data uploaded in page/track
52
+ page: (event) => send(event, "page_view", {
53
+ page_title: event.page.title,
54
+ page_location: event.page.location
55
+ }),
56
+ track: (event) => send(event, event.event.name, event.event.properties)
57
+ };
58
+ }
59
+ );
55
60
 
56
61
  export { googleAnalytics4 };
@@ -1,9 +1,9 @@
1
- import { b as AnalyticsProvider } from '../shared/analytics.2893a879.mjs';
1
+ import { AnalyticsProvider } from '../types.mjs';
2
2
 
3
3
  interface UmamiProviderOptions {
4
- baseUrl: string;
4
+ apiUrl: string;
5
5
  websiteId: string;
6
- hostname: string;
6
+ domain: string;
7
7
  }
8
8
  declare const umami: (options: UmamiProviderOptions) => AnalyticsProvider;
9
9
 
@@ -1,9 +1,9 @@
1
- import { b as AnalyticsProvider } from '../shared/analytics.2893a879.js';
1
+ import { AnalyticsProvider } from '../types.js';
2
2
 
3
3
  interface UmamiProviderOptions {
4
- baseUrl: string;
4
+ apiUrl: string;
5
5
  websiteId: string;
6
- hostname: string;
6
+ domain: string;
7
7
  }
8
8
  declare const umami: (options: UmamiProviderOptions) => AnalyticsProvider;
9
9
 
@@ -1,44 +1,54 @@
1
- const umami = (options) => (analytics, config) => {
2
- const send = (payload) => fetch(`${options.baseUrl}/api/send`, {
3
- method: "POST",
4
- headers: {
5
- "Content-Type": "application/json"
6
- },
7
- body: JSON.stringify({ type: "event", payload })
8
- });
9
- return {
10
- identify: () => Promise.resolve(),
11
- // No-op, user data uploaded in page/track
12
- page: async (event) => {
13
- await send({
14
- name: "page_view",
15
- website: options.websiteId,
16
- url: event.page.url,
17
- hostname: options.hostname,
18
- language: event.meta.language ?? "",
19
- referrer: event.meta.referrer ?? "",
20
- screen: event.meta.screen ?? "",
21
- title: event.page.title ?? "<blank>",
22
- data: event.user.properties
23
- });
24
- },
25
- track: async (event) => {
26
- await send({
27
- name: event.event.name,
28
- website: options.websiteId,
29
- url: event.meta.url ?? "/",
30
- title: "<blank>",
31
- hostname: options.hostname,
32
- language: event.meta.language ?? "",
33
- referrer: event.meta.referrer ?? "",
34
- screen: event.meta.screen ?? "",
35
- data: {
36
- ...event.event.properties,
37
- ...event.user.properties
38
- }
1
+ import { defineAnalyticsProvider } from '../index.mjs';
2
+ import 'ua-parser-js';
3
+
4
+ const umami = defineAnalyticsProvider(
5
+ (_, config, options) => {
6
+ const send = (payload) => {
7
+ if (config.debug) {
8
+ console.debug("[@wxt-dev/analytics] Sending event to Umami:", payload);
9
+ }
10
+ return fetch(`${options.apiUrl}/send`, {
11
+ method: "POST",
12
+ headers: {
13
+ "Content-Type": "application/json"
14
+ },
15
+ body: JSON.stringify({ type: "event", payload })
39
16
  });
40
- }
41
- };
42
- };
17
+ };
18
+ return {
19
+ identify: () => Promise.resolve(),
20
+ // No-op, user data uploaded in page/track
21
+ page: async (event) => {
22
+ await send({
23
+ name: "page_view",
24
+ website: options.websiteId,
25
+ url: event.page.url,
26
+ hostname: options.domain,
27
+ language: event.meta.language ?? "",
28
+ referrer: event.meta.referrer ?? "",
29
+ screen: event.meta.screen ?? "",
30
+ title: event.page.title ?? "<blank>",
31
+ data: event.user.properties
32
+ });
33
+ },
34
+ track: async (event) => {
35
+ await send({
36
+ name: event.event.name,
37
+ website: options.websiteId,
38
+ url: event.meta.url ?? "/",
39
+ title: "<blank>",
40
+ hostname: options.domain,
41
+ language: event.meta.language ?? "",
42
+ referrer: event.meta.referrer ?? "",
43
+ screen: event.meta.screen ?? "",
44
+ data: {
45
+ ...event.event.properties,
46
+ ...event.user.properties
47
+ }
48
+ });
49
+ }
50
+ };
51
+ }
52
+ );
43
53
 
44
54
  export { umami };
@@ -1,13 +1,13 @@
1
1
  interface Analytics {
2
- /** Report a page change */
2
+ /** Report a page change. */
3
3
  page: (url: string) => void;
4
- /** Report a custom event */
4
+ /** Report a custom event. */
5
5
  track: (eventName: string, eventProperties?: Record<string, string>) => void;
6
- /** Save information about the user */
6
+ /** Save information about the user. */
7
7
  identify: (userId: string, userProperties?: Record<string, string>) => void;
8
8
  /** Automatically setup and track user interactions, returning a function to remove any listeners that were setup. */
9
9
  autoTrack: (root: Document | ShadowRoot | Element) => () => void;
10
- /** Calls `config.enabled.setValue` */
10
+ /** Calls `config.enabled.setValue`. */
11
11
  setEnabled: (enabled: boolean) => void;
12
12
  }
13
13
  interface AnalyticsConfig {
@@ -20,19 +20,20 @@ interface AnalyticsConfig {
20
20
  */
21
21
  debug?: boolean;
22
22
  /**
23
- * Extension version, defaults to `browser.runtime.getManifest().version`.
23
+ * Your extension's version, reported alongside events.
24
+ * @default browser.runtime.getManifest().version`.
24
25
  */
25
26
  version?: string;
26
27
  /**
27
- * Configure how the enabled flag is persisted. Defaults to using `""` in local extension storage.
28
+ * Configure how the enabled flag is persisted. Defaults to using `browser.storage.local`.
28
29
  */
29
30
  enabled?: AnalyticsStorageItem<boolean>;
30
31
  /**
31
- * Configure how the user Id is persisted
32
+ * Configure how the user Id is persisted. Defaults to using `browser.storage.local`.
32
33
  */
33
34
  userId?: AnalyticsStorageItem<string>;
34
35
  /**
35
- * Configure how user properties are persisted
36
+ * Configure how user properties are persisted. Defaults to using `browser.storage.local`.
36
37
  */
37
38
  userProperties?: AnalyticsStorageItem<Record<string, string>>;
38
39
  }
@@ -41,11 +42,11 @@ interface AnalyticsStorageItem<T> {
41
42
  setValue?: (newValue: T) => void | Promise<void>;
42
43
  }
43
44
  type AnalyticsProvider = (analytics: Analytics, config: AnalyticsConfig) => {
44
- /** Upload a page view event */
45
+ /** Upload a page view event. */
45
46
  page: (event: AnalyticsPageViewEvent) => Promise<void>;
46
- /** Upload a custom event */
47
+ /** Upload a custom event. */
47
48
  track: (event: AnalyticsTrackEvent) => Promise<void>;
48
- /** Upload or save information about the user */
49
+ /** Upload information about the user. */
49
50
  identify: (event: BaseAnalyticsEvent) => Promise<void>;
50
51
  };
51
52
  interface BaseAnalyticsEvent {
@@ -56,11 +57,11 @@ interface BaseAnalyticsEvent {
56
57
  };
57
58
  }
58
59
  interface AnalyticsEventMetadata {
59
- /** Identifier of the session the event was fired from */
60
+ /** Identifier of the session the event was fired from. */
60
61
  sessionId: number | undefined;
61
- /** `Date.now()` of when the event was reported */
62
+ /** `Date.now()` of when the event was reported. */
62
63
  timestamp: number;
63
- /** `"1920x1080"` */
64
+ /** Ex: `"1920x1080"`. */
64
65
  screen: string | undefined;
65
66
  /** `document.referrer` */
66
67
  referrer: string | undefined;
@@ -86,4 +87,4 @@ interface AnalyticsTrackEvent extends BaseAnalyticsEvent {
86
87
  };
87
88
  }
88
89
 
89
- export type { AnalyticsConfig as A, Analytics as a, AnalyticsProvider as b };
90
+ export type { Analytics, AnalyticsConfig, AnalyticsEventMetadata, AnalyticsPageInfo, AnalyticsPageViewEvent, AnalyticsProvider, AnalyticsStorageItem, AnalyticsTrackEvent, BaseAnalyticsEvent };
@@ -1,13 +1,13 @@
1
1
  interface Analytics {
2
- /** Report a page change */
2
+ /** Report a page change. */
3
3
  page: (url: string) => void;
4
- /** Report a custom event */
4
+ /** Report a custom event. */
5
5
  track: (eventName: string, eventProperties?: Record<string, string>) => void;
6
- /** Save information about the user */
6
+ /** Save information about the user. */
7
7
  identify: (userId: string, userProperties?: Record<string, string>) => void;
8
8
  /** Automatically setup and track user interactions, returning a function to remove any listeners that were setup. */
9
9
  autoTrack: (root: Document | ShadowRoot | Element) => () => void;
10
- /** Calls `config.enabled.setValue` */
10
+ /** Calls `config.enabled.setValue`. */
11
11
  setEnabled: (enabled: boolean) => void;
12
12
  }
13
13
  interface AnalyticsConfig {
@@ -20,19 +20,20 @@ interface AnalyticsConfig {
20
20
  */
21
21
  debug?: boolean;
22
22
  /**
23
- * Extension version, defaults to `browser.runtime.getManifest().version`.
23
+ * Your extension's version, reported alongside events.
24
+ * @default browser.runtime.getManifest().version`.
24
25
  */
25
26
  version?: string;
26
27
  /**
27
- * Configure how the enabled flag is persisted. Defaults to using `""` in local extension storage.
28
+ * Configure how the enabled flag is persisted. Defaults to using `browser.storage.local`.
28
29
  */
29
30
  enabled?: AnalyticsStorageItem<boolean>;
30
31
  /**
31
- * Configure how the user Id is persisted
32
+ * Configure how the user Id is persisted. Defaults to using `browser.storage.local`.
32
33
  */
33
34
  userId?: AnalyticsStorageItem<string>;
34
35
  /**
35
- * Configure how user properties are persisted
36
+ * Configure how user properties are persisted. Defaults to using `browser.storage.local`.
36
37
  */
37
38
  userProperties?: AnalyticsStorageItem<Record<string, string>>;
38
39
  }
@@ -41,11 +42,11 @@ interface AnalyticsStorageItem<T> {
41
42
  setValue?: (newValue: T) => void | Promise<void>;
42
43
  }
43
44
  type AnalyticsProvider = (analytics: Analytics, config: AnalyticsConfig) => {
44
- /** Upload a page view event */
45
+ /** Upload a page view event. */
45
46
  page: (event: AnalyticsPageViewEvent) => Promise<void>;
46
- /** Upload a custom event */
47
+ /** Upload a custom event. */
47
48
  track: (event: AnalyticsTrackEvent) => Promise<void>;
48
- /** Upload or save information about the user */
49
+ /** Upload information about the user. */
49
50
  identify: (event: BaseAnalyticsEvent) => Promise<void>;
50
51
  };
51
52
  interface BaseAnalyticsEvent {
@@ -56,11 +57,11 @@ interface BaseAnalyticsEvent {
56
57
  };
57
58
  }
58
59
  interface AnalyticsEventMetadata {
59
- /** Identifier of the session the event was fired from */
60
+ /** Identifier of the session the event was fired from. */
60
61
  sessionId: number | undefined;
61
- /** `Date.now()` of when the event was reported */
62
+ /** `Date.now()` of when the event was reported. */
62
63
  timestamp: number;
63
- /** `"1920x1080"` */
64
+ /** Ex: `"1920x1080"`. */
64
65
  screen: string | undefined;
65
66
  /** `document.referrer` */
66
67
  referrer: string | undefined;
@@ -86,4 +87,4 @@ interface AnalyticsTrackEvent extends BaseAnalyticsEvent {
86
87
  };
87
88
  }
88
89
 
89
- export type { AnalyticsConfig as A, Analytics as a, AnalyticsProvider as b };
90
+ export type { Analytics, AnalyticsConfig, AnalyticsEventMetadata, AnalyticsPageInfo, AnalyticsPageViewEvent, AnalyticsProvider, AnalyticsStorageItem, AnalyticsTrackEvent, BaseAnalyticsEvent };
package/dist/types.mjs ADDED
@@ -0,0 +1 @@
1
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wxt-dev/analytics",
3
- "version": "0.2.8",
3
+ "version": "0.4.1",
4
4
  "description": "Add analytics to your web extension",
5
5
  "repository": {
6
6
  "type": "git",
@@ -14,9 +14,16 @@
14
14
  "types": "./dist/index.d.mts",
15
15
  "default": "./dist/index.mjs"
16
16
  },
17
- "./client": {
18
- "types": "./dist/client.d.mts",
19
- "default": "./dist/client.mjs"
17
+ "./module": {
18
+ "types": "./dist/module.d.mts",
19
+ "default": "./dist/module.mjs"
20
+ },
21
+ "./background-plugin": {
22
+ "types": "./dist/background-plugin.d.mts",
23
+ "default": "./dist/background-plugin.mjs"
24
+ },
25
+ "./types": {
26
+ "types": "./dist/types.d.mts"
20
27
  },
21
28
  "./providers/google-analytics-4": {
22
29
  "types": "./dist/providers/google-analytics-4.d.mts",
@@ -33,17 +40,16 @@
33
40
  "dist"
34
41
  ],
35
42
  "peerDependencies": {
36
- "wxt": ">=0.19.9"
43
+ "wxt": ">=0.19.23"
37
44
  },
38
45
  "devDependencies": {
39
- "@aklinker1/check": "^1.3.1",
46
+ "@aklinker1/check": "^1.4.5",
40
47
  "@types/chrome": "^0.0.268",
41
48
  "@types/ua-parser-js": "^0.7.39",
42
- "prettier": "^3.3.2",
43
- "publint": "^0.2.8",
44
- "typescript": "^5.5.2",
49
+ "publint": "^0.2.12",
50
+ "typescript": "^5.6.3",
45
51
  "unbuild": "^2.0.0",
46
- "wxt": "0.19.13"
52
+ "wxt": "0.19.23"
47
53
  },
48
54
  "dependencies": {
49
55
  "ua-parser-js": "^1.0.38"
@@ -51,7 +57,7 @@
51
57
  "scripts": {
52
58
  "dev": "buildc --deps-only -- wxt",
53
59
  "dev:build": "buildc --deps-only -- wxt build",
54
- "check": "buildc --deps-only -- check",
60
+ "check": "pnpm build && check",
55
61
  "build": "buildc -- unbuild"
56
62
  }
57
63
  }
package/dist/client.d.mts DELETED
@@ -1,5 +0,0 @@
1
- import { A as AnalyticsConfig, a as Analytics } from './shared/analytics.2893a879.mjs';
2
-
3
- declare function createAnalytics(config?: AnalyticsConfig): Analytics;
4
-
5
- export { createAnalytics };
package/dist/client.d.ts DELETED
@@ -1,5 +0,0 @@
1
- import { A as AnalyticsConfig, a as Analytics } from './shared/analytics.2893a879.js';
2
-
3
- declare function createAnalytics(config?: AnalyticsConfig): Analytics;
4
-
5
- export { createAnalytics };