feat(analytics): add posthog as an analytics provider (#2414)

Co-authored-by: Aaron <aaronklinker1@gmail.com>
This commit is contained in:
Arthur
2026-06-30 23:20:04 +02:00
committed by GitHub
parent f14ec35889
commit a578dbf633
7 changed files with 130 additions and 1 deletions
+1
View File
@@ -89,6 +89,7 @@ words:
- pbbf
- personaltoolbar
- portaling
- posthog
- prebundled
- prefs
- proxified
+30
View File
@@ -6,6 +6,7 @@ Report analytics events from your web extension extension.
- [Google Analytics 4 (Measurement Protocol)](#google-analytics-4-measurement-protocol)
- [Moderok](#moderok)
- [PostHog](#posthog)
- [Umami](#umami)
## Install With WXT
@@ -156,6 +157,35 @@ export default defineAppConfig({
For a full walkthrough — module setup, sending events, and all provider options — see the [Moderok WXT guide](https://docs.moderok.dev/guide/wxt).
### PostHog
[PostHog](https://posthog.com/) is an open source product analytics platform. It supports event tracking, session recording, feature flags, surveys, and more.
In your PostHog project settings, find your **Project API key** and save it to your `.env` file:
```dotenv
WXT_POSTHOG_API_KEY='phc_...'
```
Then add the `posthog` provider to your `<srcDir>/app.config.ts` file:
```ts
import { posthog } from '@wxt-dev/analytics/providers/posthog';
export default defineAppConfig({
analytics: {
providers: [
posthog({
apiKey: import.meta.env.WXT_POSTHOG_API_KEY,
// apiHost defaults to 'https://us.i.posthog.com'.
// Change to 'https://eu.i.posthog.com' for EU Cloud, or your self-hosted URL.
apiHost: 'https://eu.i.posthog.com',
}),
],
},
});
```
### Umami
[Umami](https://umami.is/) is a privacy-first, open source analytics platform.
+4
View File
@@ -1,5 +1,6 @@
import { defineAppConfig } from 'wxt/utils/define-app-config';
import { googleAnalytics4 } from './modules/analytics/providers/google-analytics-4';
import { posthog } from './modules/analytics/providers/posthog';
import { umami } from './modules/analytics/providers/umami';
export default defineAppConfig({
@@ -10,6 +11,9 @@ export default defineAppConfig({
apiSecret: '...',
measurementId: '...',
}),
posthog({
apiKey: '...',
}),
umami({
apiUrl: 'https://umami.aklinker1.io/api',
domain: 'analytics.wxt.dev',
@@ -18,7 +18,7 @@ export const googleAnalytics4 =
eventProperties: Record<string, string | undefined> | undefined,
): Promise<void> => {
const url = new URL(
config?.debug ? '/debug/mp/collect' : '/mp/collect',
config.debug ? '/debug/mp/collect' : '/mp/collect',
options.apiUrl ?? 'https://www.google-analytics.com',
);
if (options.apiSecret)
@@ -38,6 +38,12 @@ export const googleAnalytics4 =
]),
);
if (config.debug) {
console.debug(
'[@wxt-dev/analytics] Sending event to Google Analytics 4:',
{ eventName, eventProperties },
);
}
await fetch(url.href, {
method: 'POST',
body: JSON.stringify({
@@ -0,0 +1,83 @@
import { defineAnalyticsProvider } from '../client';
export interface PostHogProviderOptions {
/** Your PostHog project API key. */
apiKey: string;
/**
* PostHog API host URL.
*
* @default 'https://us.i.posthog.com'
*/
apiHost?: string;
}
export const posthog = defineAnalyticsProvider<PostHogProviderOptions>(
(_, config, options) => {
const apiHost = (options.apiHost ?? 'https://us.i.posthog.com').replace(
/\/$/,
'',
);
const capture = async (
distinctId: string,
event: string,
properties: Record<string, unknown>,
): Promise<void> => {
if (config.debug) {
console.debug('[@wxt-dev/analytics] Sending event to PostHog:', {
event,
properties,
});
}
const body: PostHogCaptureBody = {
api_key: options.apiKey,
distinct_id: distinctId,
event,
properties,
timestamp: new Date().toISOString(),
};
await fetch(`${apiHost}/i/v0/e/`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(body),
});
};
return {
identify: async (event) => {
await capture(event.user.id, '$identify', {
$set: event.user.properties,
});
},
page: async (event) => {
await capture(event.user.id, '$pageview', {
$current_url: event.page.url,
$title: event.page.title,
$session_id: event.meta.sessionId,
$screen: event.meta.screen,
$language: event.meta.language,
$referrer: event.meta.referrer,
$set: event.user.properties,
});
},
track: async (event) => {
await capture(event.user.id, event.event.name, {
...event.event.properties,
$screen: event.meta.screen,
$language: event.meta.language,
$referrer: event.meta.referrer,
$set: event.user.properties,
});
},
};
},
);
/** @see https://posthog.com/docs/api/capture */
interface PostHogCaptureBody {
api_key: string;
distinct_id: string;
event: string;
properties: Record<string, unknown>;
timestamp: string;
}
+4
View File
@@ -62,6 +62,10 @@
"./providers/umami": {
"types": "./dist/providers/umami.d.mts",
"default": "./dist/providers/umami.mjs"
},
"./providers/posthog": {
"types": "./dist/providers/posthog.d.mts",
"default": "./dist/providers/posthog.mjs"
}
},
"module": "./dist/index.mjs",
+1
View File
@@ -10,6 +10,7 @@ export default defineConfig({
'./modules/analytics/providers/google-analytics-4.ts',
'providers/umami': './modules/analytics/providers/umami.ts',
'providers/moderok': './modules/analytics/providers/moderok.ts',
'providers/posthog': './modules/analytics/providers/posthog.ts',
},
deps: {
neverBundle: ['#analytics'],