feat: Analytics module
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
<!--
|
||||
Get your module up and running quickly.
|
||||
|
||||
Find and replace all on all files (CMD+SHIFT+F):
|
||||
- Name: My Module
|
||||
- Package name: my-module
|
||||
- Description: My new WXT module
|
||||
- GitHub Username: your-org
|
||||
- Config key: myModule
|
||||
- Types: MyModule
|
||||
-->
|
||||
|
||||
# My Module
|
||||
|
||||
My new WXT module for doing amazing things.
|
||||
|
||||
## Features
|
||||
|
||||
<!-- Highlight some of the features your module provide here -->
|
||||
|
||||
- ⛰ Foo
|
||||
- 🚠 Bar
|
||||
- 🌲 Baz
|
||||
|
||||
## Installation
|
||||
|
||||
Install the module to your WXT extension with one command:
|
||||
|
||||
```bash
|
||||
pnpm i my-module
|
||||
```
|
||||
|
||||
Then add the module to your `wxt.config.ts` file:
|
||||
|
||||
```ts
|
||||
export default defineConfig({
|
||||
modules: ['my-module'],
|
||||
});
|
||||
```
|
||||
|
||||
That's it! You can now use My Module in your WXT extension ✨
|
||||
|
||||
## Contribution
|
||||
|
||||
<details>
|
||||
<summary>Local development</summary>
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
pnpm install
|
||||
|
||||
# Generate type stubs
|
||||
pnpm wxt prepare
|
||||
|
||||
# Develop test extension
|
||||
pnpm dev
|
||||
|
||||
# Build the test extension
|
||||
pnpm dev:build
|
||||
|
||||
# Run prettier, publint, and type checks
|
||||
pnpm check
|
||||
```
|
||||
|
||||
</details>
|
||||
@@ -0,0 +1,21 @@
|
||||
import { googleAnalytics } from './modules/analytics/providers/google-analytics';
|
||||
import { AnalyticsConfig } from './modules/analytics/types';
|
||||
|
||||
interface AppConfig {
|
||||
analytics: AnalyticsConfig;
|
||||
}
|
||||
function defineAppConfig(config: AppConfig): AppConfig {
|
||||
return config;
|
||||
}
|
||||
|
||||
export default defineAppConfig({
|
||||
analytics: {
|
||||
providers: [
|
||||
googleAnalytics({
|
||||
apiSecret: '...',
|
||||
measurementId: '...',
|
||||
}),
|
||||
],
|
||||
debug: true,
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,33 @@
|
||||
import { defineBuildConfig } from 'unbuild';
|
||||
import * as vite from 'vite';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
// Build module and plugins
|
||||
export default defineBuildConfig({
|
||||
rootDir: 'modules/my-module',
|
||||
outDir: resolve(__dirname, 'dist'),
|
||||
entries: ['index.ts', 'plugin.ts'],
|
||||
replace: {
|
||||
'process.env.NPM': 'true',
|
||||
},
|
||||
declaration: true,
|
||||
hooks: {
|
||||
'build:done': prebuildEntrypoints,
|
||||
},
|
||||
});
|
||||
|
||||
// Prebuild entrypoints
|
||||
async function prebuildEntrypoints() {
|
||||
await vite.build({
|
||||
root: 'modules/my-module',
|
||||
build: {
|
||||
emptyOutDir: false,
|
||||
rollupOptions: {
|
||||
input: 'modules/my-module/example.html',
|
||||
output: {
|
||||
dir: 'dist/prebuilt',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Popup</title>
|
||||
</head>
|
||||
<body>
|
||||
<button id="button1">Button 1</button>
|
||||
<button class="cool-button">Button 2</button>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,27 @@
|
||||
import { defineWxtPlugin } from 'wxt/sandbox';
|
||||
import { Analytics } from './types';
|
||||
|
||||
export let analytics: Analytics;
|
||||
|
||||
export default <any>defineWxtPlugin(() => {
|
||||
const isBackground = globalThis.window == null; // TODO: Support MV2
|
||||
analytics = isBackground
|
||||
? createBackgroundAnalytics()
|
||||
: createAnalyticsForwarder();
|
||||
});
|
||||
|
||||
function createBackgroundAnalytics(): Analytics {
|
||||
return {
|
||||
identify: () => {},
|
||||
page: () => {},
|
||||
track: () => {},
|
||||
};
|
||||
}
|
||||
|
||||
function createAnalyticsForwarder(): Analytics {
|
||||
return {
|
||||
identify: () => {},
|
||||
page: () => {},
|
||||
track: () => {},
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import 'wxt';
|
||||
import { addWxtPlugin, defineWxtModule } from 'wxt/modules';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
const pluginId = process.env.NPM
|
||||
? 'analytics/client'
|
||||
: resolve(__dirname, 'client.ts');
|
||||
|
||||
export default defineWxtModule({
|
||||
name: 'analytics',
|
||||
imports: [{ name: 'analytics', from: pluginId }],
|
||||
setup(wxt, options) {
|
||||
// Add a plugin
|
||||
addWxtPlugin(
|
||||
wxt,
|
||||
resolve(__dirname, process.env.NPM ? 'plugin.mjs' : 'plugin.ts'),
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
import type { AnalyticsProvider } from '../types';
|
||||
|
||||
export interface GoogleAnalyticsProviderOptions {}
|
||||
|
||||
export const googleAnalytics =
|
||||
(options: GoogleAnalyticsProviderOptions): AnalyticsProvider =>
|
||||
(analytics, config) => {
|
||||
return {
|
||||
identify: async () => {},
|
||||
page: async () => {},
|
||||
track: async () => {},
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
export interface UmamiProviderOptions {}
|
||||
|
||||
export const umami = (options: UmamiProviderOptions) => (analytics, config) => {
|
||||
throw Error('TODO');
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
export interface Analytics {
|
||||
/** Report a page change */
|
||||
page: (url: string | URL) => void;
|
||||
/** Report a custom event */
|
||||
track: (eventName: string, eventProperties: string) => void;
|
||||
/** Save information about the user */
|
||||
identify: (userId: string, userProperties?: Record<string, string>) => void;
|
||||
}
|
||||
|
||||
export interface AnalyticsConfig {
|
||||
/** Array of providers to send analytics to. */
|
||||
providers: AnalyticsProvider[];
|
||||
/** Enable debug logs and other provider-specific debugging features. */
|
||||
debug?: boolean;
|
||||
/** Extension version, defaults to `browser.runtime.getManifest().version`. */
|
||||
version?: string;
|
||||
}
|
||||
|
||||
export type AnalyticsProvider = (
|
||||
analytics: Analytics,
|
||||
config: AnalyticsConfig,
|
||||
) => {
|
||||
/** Upload a page view event */
|
||||
page: (event: AnalyticsPageViewEvent) => Promise<void>;
|
||||
/** Upload a custom event */
|
||||
track: (event: AnalyticsTrackEvent) => Promise<void>;
|
||||
/** Upload or save information about the user */
|
||||
identify: (event: AnalyticsIdentifyEvent) => Promise<void>;
|
||||
};
|
||||
|
||||
export interface BaseAnalyticsEvent {
|
||||
/** Identifier of the session the event was fired from */
|
||||
sessionId: string;
|
||||
/** `Date.now()` of when the event was reported */
|
||||
time: number;
|
||||
}
|
||||
|
||||
export interface AnalyticsPageViewEvent extends BaseAnalyticsEvent {
|
||||
url: string;
|
||||
sessionId: string;
|
||||
title: string;
|
||||
location: string;
|
||||
}
|
||||
|
||||
export interface AnalyticsTrackEvent extends BaseAnalyticsEvent {
|
||||
eventName: string;
|
||||
eventProperties: Record<string, string>;
|
||||
}
|
||||
|
||||
export interface AnalyticsIdentifyEvent extends BaseAnalyticsEvent {}
|
||||
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "my-module",
|
||||
"version": "1.0.0",
|
||||
"description": "My new WXT module",
|
||||
"repository": "your-org/my-module",
|
||||
"license": "MIT",
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.mts",
|
||||
"default": "./dist/index.mjs"
|
||||
},
|
||||
"./plugin": {
|
||||
"types": "./dist/plugin.d.mts",
|
||||
"default": "./dist/plugin.mjs"
|
||||
}
|
||||
},
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"dev": "wxt",
|
||||
"dev:build": "wxt build",
|
||||
"check": "check",
|
||||
"build": "unbuild",
|
||||
"prepack": "unbuild",
|
||||
"postinstall": "wxt prepare"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"wxt": ">=0.18.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aklinker1/check": "^1.3.1",
|
||||
"@types/chrome": "^0.0.268",
|
||||
"prettier": "^3.3.2",
|
||||
"publint": "^0.2.8",
|
||||
"typescript": "^5.5.2",
|
||||
"unbuild": "^2.0.0",
|
||||
"vite": "^5.3.1",
|
||||
"wxt": "^0.18.10"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": ["../../tsconfig.base.json", "./.wxt/tsconfig.json"],
|
||||
"compilerOptions": {
|
||||
"types": ["chrome"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import { defineConfig } from 'wxt';
|
||||
|
||||
export default defineConfig({
|
||||
vite: () => ({
|
||||
define: {
|
||||
'process.env.NPM': 'false',
|
||||
},
|
||||
}),
|
||||
myModule: {
|
||||
example: 'options',
|
||||
},
|
||||
});
|
||||
Generated
+124
@@ -84,6 +84,33 @@ importers:
|
||||
specifier: ^2.5.0
|
||||
version: 2.5.0
|
||||
|
||||
packages/analytics:
|
||||
devDependencies:
|
||||
'@aklinker1/check':
|
||||
specifier: ^1.3.1
|
||||
version: 1.4.5(typescript@5.5.4)
|
||||
'@types/chrome':
|
||||
specifier: ^0.0.268
|
||||
version: 0.0.268
|
||||
prettier:
|
||||
specifier: ^3.3.2
|
||||
version: 3.3.3
|
||||
publint:
|
||||
specifier: ^0.2.8
|
||||
version: 0.2.9
|
||||
typescript:
|
||||
specifier: ^5.5.2
|
||||
version: 5.5.4
|
||||
unbuild:
|
||||
specifier: ^2.0.0
|
||||
version: 2.0.0(sass@1.77.8)(typescript@5.5.4)
|
||||
vite:
|
||||
specifier: ^5.3.1
|
||||
version: 5.3.5(@types/node@20.14.12)(sass@1.77.8)
|
||||
wxt:
|
||||
specifier: ^0.18.10
|
||||
version: 0.18.15(@types/node@20.14.12)(rollup@4.19.0)(sass@1.77.8)
|
||||
|
||||
packages/auto-icons:
|
||||
dependencies:
|
||||
defu:
|
||||
@@ -1913,6 +1940,9 @@ packages:
|
||||
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
async-mutex@0.4.1:
|
||||
resolution: {integrity: sha512-WfoBo4E/TbCX1G95XTjbWTE3X2XLG0m1Xbv2cwOtuPdyH9CZvnaA5nCt1ucjaKEgW2A5IF71hxrRhr83Je5xjA==}
|
||||
|
||||
async-mutex@0.5.0:
|
||||
resolution: {integrity: sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==}
|
||||
|
||||
@@ -3553,6 +3583,10 @@ packages:
|
||||
resolution: {integrity: sha512-ERAyNnZOfqM+Ao3RAvIXkYh5joP220yf59gVe2X/cI6SiCxIdi4c9HZKZD8R6q/RDXEje1THBju6iExiSsgJaQ==}
|
||||
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||
|
||||
ora@7.0.1:
|
||||
resolution: {integrity: sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
ora@8.1.0:
|
||||
resolution: {integrity: sha512-GQEkNkH/GHOhPFXcqZs3IDahXEQcQxsSjEkK4KvEEST4t7eNzoMjxTzef+EZ+JluDEV+Raoi3WQ2CflnRdSVnQ==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -4279,6 +4313,10 @@ packages:
|
||||
resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
string-width@6.1.0:
|
||||
resolution: {integrity: sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==}
|
||||
engines: {node: '>=16'}
|
||||
|
||||
string-width@7.2.0:
|
||||
resolution: {integrity: sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -4742,6 +4780,9 @@ packages:
|
||||
resolution: {integrity: sha512-5D11VcjdGkA1/xax5UWL0YeAbDySKHzWFe6EpsoPNUMw5Uk9tKk9p6GUOfcaI5N7sINKfBMZYNsTBiu5dzJB9A==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
|
||||
webextension-polyfill@0.10.0:
|
||||
resolution: {integrity: sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g==}
|
||||
|
||||
webextension-polyfill@0.12.0:
|
||||
resolution: {integrity: sha512-97TBmpoWJEE+3nFBQ4VocyCdLKfw54rFaJ6EVQYLBCXqCIpLSZkwGgASpv4oPt9gdKCJ80RJlcmNzNn008Ag6Q==}
|
||||
|
||||
@@ -4825,6 +4866,10 @@ packages:
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
|
||||
wxt@0.18.15:
|
||||
resolution: {integrity: sha512-rzFLinUyugBsoC+mJZFMIQILrA4OUk/XG0mAW30zF3pqegIwawrEx5JXFXg/D1XW6//uew/FLTm12t3mcpbw+Q==}
|
||||
hasBin: true
|
||||
|
||||
xdg-basedir@5.1.0:
|
||||
resolution: {integrity: sha512-GCPAHLvrIH13+c0SuacwvRYj2SxJXQ4kaVTT5xgL3kPrz56XxkF21IGhjSE1+W0aw7gpBWRGXLCPnPby6lSpmQ==}
|
||||
engines: {node: '>=12'}
|
||||
@@ -6173,6 +6218,10 @@ snapshots:
|
||||
|
||||
assertion-error@2.0.1: {}
|
||||
|
||||
async-mutex@0.4.1:
|
||||
dependencies:
|
||||
tslib: 2.6.0
|
||||
|
||||
async-mutex@0.5.0:
|
||||
dependencies:
|
||||
tslib: 2.6.0
|
||||
@@ -8008,6 +8057,18 @@ snapshots:
|
||||
strip-ansi: 7.1.0
|
||||
wcwidth: 1.0.1
|
||||
|
||||
ora@7.0.1:
|
||||
dependencies:
|
||||
chalk: 5.3.0
|
||||
cli-cursor: 4.0.0
|
||||
cli-spinners: 2.9.2
|
||||
is-interactive: 2.0.0
|
||||
is-unicode-supported: 1.3.0
|
||||
log-symbols: 5.1.0
|
||||
stdin-discarder: 0.1.0
|
||||
string-width: 6.1.0
|
||||
strip-ansi: 7.1.0
|
||||
|
||||
ora@8.1.0:
|
||||
dependencies:
|
||||
chalk: 5.3.0
|
||||
@@ -8770,6 +8831,12 @@ snapshots:
|
||||
emoji-regex: 9.2.2
|
||||
strip-ansi: 7.1.0
|
||||
|
||||
string-width@6.1.0:
|
||||
dependencies:
|
||||
eastasianwidth: 0.2.0
|
||||
emoji-regex: 10.3.0
|
||||
strip-ansi: 7.1.0
|
||||
|
||||
string-width@7.2.0:
|
||||
dependencies:
|
||||
emoji-regex: 10.3.0
|
||||
@@ -9354,6 +9421,8 @@ snapshots:
|
||||
- supports-color
|
||||
- utf-8-validate
|
||||
|
||||
webextension-polyfill@0.10.0: {}
|
||||
|
||||
webextension-polyfill@0.12.0: {}
|
||||
|
||||
webidl-conversions@7.0.0: {}
|
||||
@@ -9436,6 +9505,61 @@ snapshots:
|
||||
|
||||
ws@8.18.0: {}
|
||||
|
||||
wxt@0.18.15(@types/node@20.14.12)(rollup@4.19.0)(sass@1.77.8):
|
||||
dependencies:
|
||||
'@aklinker1/rollup-plugin-visualizer': 5.12.0(rollup@4.19.0)
|
||||
'@types/webextension-polyfill': 0.10.7
|
||||
'@webext-core/fake-browser': 1.3.1
|
||||
'@webext-core/isolated-element': 1.1.2
|
||||
'@webext-core/match-patterns': 1.0.3
|
||||
async-mutex: 0.4.1
|
||||
c12: 1.11.1(magicast@0.3.4)
|
||||
cac: 6.7.14
|
||||
chokidar: 3.6.0
|
||||
ci-info: 4.0.0
|
||||
defu: 6.1.4
|
||||
dequal: 2.0.3
|
||||
esbuild: 0.19.12
|
||||
fast-glob: 3.3.2
|
||||
filesize: 10.1.4
|
||||
fs-extra: 11.2.0
|
||||
get-port: 7.1.0
|
||||
giget: 1.2.3
|
||||
hookable: 5.5.3
|
||||
is-wsl: 3.1.0
|
||||
jiti: 1.21.6
|
||||
json5: 2.2.3
|
||||
jszip: 3.10.1
|
||||
linkedom: 0.18.4
|
||||
magicast: 0.3.4
|
||||
minimatch: 9.0.5
|
||||
natural-compare: 1.4.0
|
||||
normalize-path: 3.0.0
|
||||
nypm: 0.3.9
|
||||
ohash: 1.1.3
|
||||
open: 10.1.0
|
||||
ora: 7.0.1
|
||||
picocolors: 1.0.1
|
||||
prompts: 2.4.2
|
||||
publish-browser-extension: 2.1.3
|
||||
unimport: 3.11.1(rollup@4.19.0)
|
||||
vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8)
|
||||
vite-node: 1.6.0(@types/node@20.14.12)(sass@1.77.8)
|
||||
web-ext-run: 0.2.1
|
||||
webextension-polyfill: 0.10.0
|
||||
transitivePeerDependencies:
|
||||
- '@types/node'
|
||||
- bufferutil
|
||||
- less
|
||||
- lightningcss
|
||||
- rollup
|
||||
- sass
|
||||
- stylus
|
||||
- sugarss
|
||||
- supports-color
|
||||
- terser
|
||||
- utf-8-validate
|
||||
|
||||
xdg-basedir@5.1.0: {}
|
||||
|
||||
xml2js@0.5.0:
|
||||
|
||||
Reference in New Issue
Block a user