PostHog makes it easy to get data about traffic and usage of your Remix app. Integrating PostHog into your site enables analytics about user behavior, custom events capture, session recordings, feature flags, and more.
This guide walks you through integrating PostHog into your Remix app using the JavaScript Web SDK.
Installation
Install posthog-js
using your package manager:
yarn add posthog-js# ornpm install --save posthog-js
First, you'll need to pass the POSTHOG_API_KEY
to your client through Remix. We recommend placing them on window.ENV
by following this guide. You'll need both your API key and instance address (you can find these in your project settings).
Next, create a new PostHog context in app/contexts/posthog-context.tsx
. This is necessary because of a missing export statement in posthog-js
's package.json
.
import posthog from "posthog-js";import React, { createContext, useContext, useRef } from "react";type PosthogType = typeof posthog | undefined;const PosthogContext = createContext<PosthogType>(undefined);interface PosthogProviderProps {children: React.ReactNode;}/** We need this file because posthog-js is missing an exports property that* allows the library to be used with Remix Vite.* https://github.com/PostHog/posthog-js/issues/908*/export function PosthogProvider({ children }: PosthogProviderProps) {const posthogInstanceRef = useRef<PosthogType>(undefined);// https://react.dev/reference/react/useRef#avoiding-recreating-the-ref-contents// Note that in StrictMode, this will run twice.function getPosthogInstance() {if (posthogInstanceRef.current) return posthogInstanceRef.current;if (!window.ENV.POSTHOG_API_KEY) return undefined;posthogInstanceRef.current = posthog.init(window.ENV.POSTHOG_API_KEY, {// ...your_options_here});return posthogInstanceRef.current;}return (<PosthogContext.Provider value={getPosthogInstance()}>{children}</PosthogContext.Provider>);}export const usePosthog = () => useContext(PosthogContext);
Lastly, we need to add this context to your React tree. Go to app/entry.client.tsx
and add the following:
import { RemixBrowser } from "@remix-run/react";import { startTransition, StrictMode, useEffect } from "react";import { hydrateRoot } from "react-dom/client";import { PosthogProvider } from "./contexts/posthog-context";startTransition(() => {hydrateRoot(document,<StrictMode><PosthogProvider><RemixBrowser /></PosthogProvider></StrictMode>,);});
Identifying Users
If your app supports identifying users, you'll want to call posthog?.identify()
wherever you have a Distinct ID.
import { usePosthog } from "./contexts/posthog-context";function SomeAuthedComponent() {const posthog = usePosthog();useEffect(() => {posthog?.identify(user.distinctId);}, [posthog, user.distinctId]);// ...}
Setting up Pageviews
Because Remix is a single-page app that uses client-side routing, we need to track pageviews whenever the page location changes. In app/root.tsx
:
export default function App() {const location = useLocation();const posthog = usePosthog();useEffect(() => {posthog?.capture('$pageview');}, [posthog, location]);return (<html lang="en">//... rest of code
Next steps
For any technical questions for how to integrate specific PostHog features into Remix (such as analytics, feature flags, A/B testing, surveys, etc.), have a look at our JavaScript Web SDK docs.
Alternatively, the following tutorials can help you get started: