Remix

Last updated:

|Edit this page

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:

Terminal
yarn add posthog-js
# or
npm install --save posthog-js

First, you'll need to pass both your project API key and instance address from your project settings to your client through Remix. We recommend placing the project API key on window.ENV like Remix recommends in this guide.

app/root.tsx
import { Links, Meta, Outlet, Scripts, ScrollRestoration, useLoaderData } from "@remix-run/react";
import type { LinksFunction } from "@remix-run/node";
import { json } from "@remix-run/node";
//... other imports, links, etc.
export const loader = () => {
return json({
ENV: {
POSTHOG_API_KEY: process.env.POSTHOG_API_KEY,
},
});
};
export default function App() {
const { ENV } = useLoaderData<typeof loader>();
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<Outlet />
<ScrollRestoration />
<script
dangerouslySetInnerHTML={{
__html: `window.ENV = ${JSON.stringify(ENV)}`,
}}
/>
<Scripts />
</body>
</html>
);
}

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.

app/contexts/posthog-context.tsx
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;
}
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, {
api_host: 'https://us.i.posthog.com',
person_profiles: 'identified_only'
});
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:

app/entry.client.tsx
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

To identify users call posthog?.identify() when you have a distinct ID.

TypeScript
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:

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:

Questions?

Was this page useful?

Next article

Retool

Objective Integrating PostHog with Retool. Why is this useful? Retool is a platform you can use to quickly build internal tools that leverage your data from different sources with little to no-code. Prerequisites To follow this tutorial along, you should: Have deployed PostHog . Have a Retool account Step-by-step instructions Retool app setup First, create a new app from the Retool dashboard: You will then need to create a new resource i.e. set up the configuration for where you'll pull the…

Read next article