Skip to content

Commit

Permalink
feat: Analytics module
Browse files Browse the repository at this point in the history
  • Loading branch information
aklinker1 committed Jul 2, 2024
1 parent 5704765 commit 253efb4
Show file tree
Hide file tree
Showing 14 changed files with 355 additions and 0 deletions.
65 changes: 65 additions & 0 deletions packages/analytics/README.md
Original file line number Diff line number Diff line change
@@ -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 -->

-&nbsp;Foo
- 🚠 &nbsp;Bar
- 🌲 &nbsp;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>
21 changes: 21 additions & 0 deletions packages/analytics/app.config.ts
Original file line number Diff line number Diff line change
@@ -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,
},
});
33 changes: 33 additions & 0 deletions packages/analytics/build.config.ts
Original file line number Diff line number Diff line change
@@ -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',
},
},
},
});
}
12 changes: 12 additions & 0 deletions packages/analytics/entrypoints/popup.html
Original file line number Diff line number Diff line change
@@ -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>
27 changes: 27 additions & 0 deletions packages/analytics/modules/analytics/client.ts
Original file line number Diff line number Diff line change
@@ -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: () => {},
};
}
19 changes: 19 additions & 0 deletions packages/analytics/modules/analytics/index.ts
Original file line number Diff line number Diff line change
@@ -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'),
);
},
});
13 changes: 13 additions & 0 deletions packages/analytics/modules/analytics/providers/google-analytics.ts
Original file line number Diff line number Diff line change
@@ -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 () => {},
};
};
5 changes: 5 additions & 0 deletions packages/analytics/modules/analytics/providers/umami.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface UmamiProviderOptions {}

export const umami = (options: UmamiProviderOptions) => (analytics, config) => {
throw Error('TODO');
};
50 changes: 50 additions & 0 deletions packages/analytics/modules/analytics/types.ts
Original file line number Diff line number Diff line change
@@ -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 {}
44 changes: 44 additions & 0 deletions packages/analytics/package.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
Empty file added packages/analytics/public/.keep
Empty file.
6 changes: 6 additions & 0 deletions packages/analytics/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": ["../../tsconfig.base.json", "./.wxt/tsconfig.json"],
"compilerOptions": {
"types": ["chrome"]
}
}
12 changes: 12 additions & 0 deletions packages/analytics/wxt.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { defineConfig } from 'wxt';

export default defineConfig({
vite: () => ({
define: {
'process.env.NPM': 'false',
},
}),
myModule: {
example: 'options',
},
});
48 changes: 48 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 253efb4

Please sign in to comment.