The PostHog docs are great for setting up for Nuxt. This is how I set it up and includes server-side (Nitro) error tracking (not included in the PostHog setup).
PostHog for frontend
1. Install posthog-js
:
npm install --save posthog-js
yarn add posthog-js
pnpm add posthog-js
bun add posthog-js
2. Add your public PostHog key to your runtimeConfig
in nuxt.config.ts
nuxt.config.ts
export default defineNuxtConfig({
runtimeConfig: {
public: {
posthogPublicKey: '<public_posthog_key>',
}
}
})
3. Create posthog.client.ts
in ~/app/plugins
(or ~/plugins
in Nuxt 3)
app/plugins/posthog.client.ts
import posthog from "posthog-js";
export default defineNuxtPlugin((nuxtApp) => {
const runtimeConfig = useRuntimeConfig();
// Skip PostHog initialization in development
if (import.meta.dev) {
console.log("PostHog disabled in development mode");
return;
}
const posthogClient = posthog.init(runtimeConfig.public.posthogPublicKey, {
api_host: "/ingest",
ui_host: "https://us.posthog.com",
person_profiles: "identified_only", // or 'always' to create profiles for anonymous users as well
});
nuxtApp.hook("vue:error", (error) => {
posthogClient.captureException(error);
});
return {
provide: {
posthog: () => posthogClient,
},
};
});
PostHog for backend (Nitro)
1. Install posthog-node
npm install --save posthog-node
yarn add posthog-node
pnpm add posthog-node
bun add posthog-node
2. Create posthog.ts
in ~/server/plugins/posthog.ts
server/plugins/posthog.ts
import { PostHog } from "posthog-node";
// HTTP methods that typically include request bodies
const METHODS_WITH_BODY = new Set(["POST", "PUT", "PATCH"]);
const hasRequestBody = (method: string) => METHODS_WITH_BODY.has(method);
export default defineNitroPlugin((nitro) => {
// Skip PostHog initialization in development
if (import.meta.dev) {
console.log("PostHog disabled in development mode (server)");
return;
}
// Capture server-side errors
nitro.hooks.hook("error", async (error, { event }) => {
if (!event) return;
const config = useRuntimeConfig(event);
const client = new PostHog(config.public.posthogPublicKey);
client.captureException(error, undefined, {
path: event.path,
method: event.method,
query: JSON.stringify(getQuery(event)),
headers: JSON.stringify(getHeaders(event)),
body: hasRequestBody(event.method) ? readRawBody(event) : undefined,
});
await client.shutdown();
});
});
Conclusion
This setup will give you PostHog analytics in the frontend + PostHog error tracking in the backend. Happy coding!