Skip to content

Commit dcadb84

Browse files
committed
feat: Analytics module
1 parent 1e8e548 commit dcadb84

File tree

14 files changed

+355
-0
lines changed

14 files changed

+355
-0
lines changed

packages/analytics/README.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
<!--
2+
Get your module up and running quickly.
3+
4+
Find and replace all on all files (CMD+SHIFT+F):
5+
- Name: My Module
6+
- Package name: my-module
7+
- Description: My new WXT module
8+
- GitHub Username: your-org
9+
- Config key: myModule
10+
- Types: MyModule
11+
-->
12+
13+
# My Module
14+
15+
My new WXT module for doing amazing things.
16+
17+
## Features
18+
19+
<!-- Highlight some of the features your module provide here -->
20+
21+
-&nbsp;Foo
22+
- 🚠 &nbsp;Bar
23+
- 🌲 &nbsp;Baz
24+
25+
## Installation
26+
27+
Install the module to your WXT extension with one command:
28+
29+
```bash
30+
pnpm i my-module
31+
```
32+
33+
Then add the module to your `wxt.config.ts` file:
34+
35+
```ts
36+
export default defineConfig({
37+
modules: ['my-module'],
38+
});
39+
```
40+
41+
That's it! You can now use My Module in your WXT extension ✨
42+
43+
## Contribution
44+
45+
<details>
46+
<summary>Local development</summary>
47+
48+
```bash
49+
# Install dependencies
50+
pnpm install
51+
52+
# Generate type stubs
53+
pnpm wxt prepare
54+
55+
# Develop test extension
56+
pnpm dev
57+
58+
# Build the test extension
59+
pnpm dev:build
60+
61+
# Run prettier, publint, and type checks
62+
pnpm check
63+
```
64+
65+
</details>

packages/analytics/app.config.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { googleAnalytics } from './modules/analytics/providers/google-analytics';
2+
import { AnalyticsConfig } from './modules/analytics/types';
3+
4+
interface AppConfig {
5+
analytics: AnalyticsConfig;
6+
}
7+
function defineAppConfig(config: AppConfig): AppConfig {
8+
return config;
9+
}
10+
11+
export default defineAppConfig({
12+
analytics: {
13+
providers: [
14+
googleAnalytics({
15+
apiSecret: '...',
16+
measurementId: '...',
17+
}),
18+
],
19+
debug: true,
20+
},
21+
});

packages/analytics/build.config.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { defineBuildConfig } from 'unbuild';
2+
import * as vite from 'vite';
3+
import { resolve } from 'node:path';
4+
5+
// Build module and plugins
6+
export default defineBuildConfig({
7+
rootDir: 'modules/my-module',
8+
outDir: resolve(__dirname, 'dist'),
9+
entries: ['index.ts', 'plugin.ts'],
10+
replace: {
11+
'process.env.NPM': 'true',
12+
},
13+
declaration: true,
14+
hooks: {
15+
'build:done': prebuildEntrypoints,
16+
},
17+
});
18+
19+
// Prebuild entrypoints
20+
async function prebuildEntrypoints() {
21+
await vite.build({
22+
root: 'modules/my-module',
23+
build: {
24+
emptyOutDir: false,
25+
rollupOptions: {
26+
input: 'modules/my-module/example.html',
27+
output: {
28+
dir: 'dist/prebuilt',
29+
},
30+
},
31+
},
32+
});
33+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Popup</title>
7+
</head>
8+
<body>
9+
<button id="button1">Button 1</button>
10+
<button class="cool-button">Button 2</button>
11+
</body>
12+
</html>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { defineWxtPlugin } from 'wxt/sandbox';
2+
import { Analytics } from './types';
3+
4+
export let analytics: Analytics;
5+
6+
export default <any>defineWxtPlugin(() => {
7+
const isBackground = globalThis.window == null; // TODO: Support MV2
8+
analytics = isBackground
9+
? createBackgroundAnalytics()
10+
: createAnalyticsForwarder();
11+
});
12+
13+
function createBackgroundAnalytics(): Analytics {
14+
return {
15+
identify: () => {},
16+
page: () => {},
17+
track: () => {},
18+
};
19+
}
20+
21+
function createAnalyticsForwarder(): Analytics {
22+
return {
23+
identify: () => {},
24+
page: () => {},
25+
track: () => {},
26+
};
27+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import 'wxt';
2+
import { addWxtPlugin, defineWxtModule } from 'wxt/modules';
3+
import { resolve } from 'node:path';
4+
5+
const pluginId = process.env.NPM
6+
? 'analytics/client'
7+
: resolve(__dirname, 'client.ts');
8+
9+
export default defineWxtModule({
10+
name: 'analytics',
11+
imports: [{ name: 'analytics', from: pluginId }],
12+
setup(wxt, options) {
13+
// Add a plugin
14+
addWxtPlugin(
15+
wxt,
16+
resolve(__dirname, process.env.NPM ? 'plugin.mjs' : 'plugin.ts'),
17+
);
18+
},
19+
});
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import type { AnalyticsProvider } from '../types';
2+
3+
export interface GoogleAnalyticsProviderOptions {}
4+
5+
export const googleAnalytics =
6+
(options: GoogleAnalyticsProviderOptions): AnalyticsProvider =>
7+
(analytics, config) => {
8+
return {
9+
identify: async () => {},
10+
page: async () => {},
11+
track: async () => {},
12+
};
13+
};
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export interface UmamiProviderOptions {}
2+
3+
export const umami = (options: UmamiProviderOptions) => (analytics, config) => {
4+
throw Error('TODO');
5+
};
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
export interface Analytics {
2+
/** Report a page change */
3+
page: (url: string | URL) => void;
4+
/** Report a custom event */
5+
track: (eventName: string, eventProperties: string) => void;
6+
/** Save information about the user */
7+
identify: (userId: string, userProperties?: Record<string, string>) => void;
8+
}
9+
10+
export interface AnalyticsConfig {
11+
/** Array of providers to send analytics to. */
12+
providers: AnalyticsProvider[];
13+
/** Enable debug logs and other provider-specific debugging features. */
14+
debug?: boolean;
15+
/** Extension version, defaults to `browser.runtime.getManifest().version`. */
16+
version?: string;
17+
}
18+
19+
export type AnalyticsProvider = (
20+
analytics: Analytics,
21+
config: AnalyticsConfig,
22+
) => {
23+
/** Upload a page view event */
24+
page: (event: AnalyticsPageViewEvent) => Promise<void>;
25+
/** Upload a custom event */
26+
track: (event: AnalyticsTrackEvent) => Promise<void>;
27+
/** Upload or save information about the user */
28+
identify: (event: AnalyticsIdentifyEvent) => Promise<void>;
29+
};
30+
31+
export interface BaseAnalyticsEvent {
32+
/** Identifier of the session the event was fired from */
33+
sessionId: string;
34+
/** `Date.now()` of when the event was reported */
35+
time: number;
36+
}
37+
38+
export interface AnalyticsPageViewEvent extends BaseAnalyticsEvent {
39+
url: string;
40+
sessionId: string;
41+
title: string;
42+
location: string;
43+
}
44+
45+
export interface AnalyticsTrackEvent extends BaseAnalyticsEvent {
46+
eventName: string;
47+
eventProperties: Record<string, string>;
48+
}
49+
50+
export interface AnalyticsIdentifyEvent extends BaseAnalyticsEvent {}

packages/analytics/package.json

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
{
2+
"name": "my-module",
3+
"version": "1.0.0",
4+
"description": "My new WXT module",
5+
"repository": "your-org/my-module",
6+
"license": "MIT",
7+
"type": "module",
8+
"exports": {
9+
".": {
10+
"types": "./dist/index.d.mts",
11+
"default": "./dist/index.mjs"
12+
},
13+
"./plugin": {
14+
"types": "./dist/plugin.d.mts",
15+
"default": "./dist/plugin.mjs"
16+
}
17+
},
18+
"module": "./dist/index.mjs",
19+
"types": "./dist/index.d.ts",
20+
"files": [
21+
"dist"
22+
],
23+
"scripts": {
24+
"dev": "wxt",
25+
"dev:build": "wxt build",
26+
"check": "check",
27+
"build": "unbuild",
28+
"prepack": "unbuild",
29+
"postinstall": "wxt prepare"
30+
},
31+
"peerDependencies": {
32+
"wxt": ">=0.18.10"
33+
},
34+
"devDependencies": {
35+
"@aklinker1/check": "^1.3.1",
36+
"@types/chrome": "^0.0.268",
37+
"prettier": "^3.3.2",
38+
"publint": "^0.2.8",
39+
"typescript": "^5.5.2",
40+
"unbuild": "^2.0.0",
41+
"vite": "^5.3.1",
42+
"wxt": "^0.18.10"
43+
}
44+
}

0 commit comments

Comments
 (0)