PostHog is the best free (also open source) analytics platform out there, and NextJS is the most used web framework used according to State of JS survey 2024. Though Posthog has great docs, it might be difficult for any beginner to integrate posthog in their NextJS projects.
This blog encompasses how to add posthog analytics to NextJS 15 app router. Assuming you have setup a NextJS app, you’ll need to install the posthog-js
package
npm install posthog-js
# OR
yarn add posthog-js
# OR
pnpm add posthog-js
Create a .env.local
file and paste the given environment variables in it
NEXT_PUBLIC_POSTHOG_KEY=phc_XXX
NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
add a posthog provider in src/providers
directory
"use client";
import posthog from "posthog-js";
import { PostHogProvider } from "posthog-js/react";
if (typeof window !== "undefined") {
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, {
api_host: "/ingest",
ui_host: "https://us.posthog.com",
person_profiles: "always",
capture_pageview: false,
capture_pageleave: true,
});
}
export function NextHogProvider({ children }) {
return <PostHogProvider client={posthog}>{children}</PostHogProvider>;
}
Add a Page view component in src/components
directory
"use client";
import { usePathname, useSearchParams } from "next/navigation";
import { useEffect } from "react";
import { usePostHog } from "posthog-js/react";
export default function PostHogPageView() {
const pathname = usePathname();
const searchParams = useSearchParams();
const posthog = usePostHog();
useEffect(() => {
// Track pageviews
if (pathname && posthog) {
let url = window.origin + pathname;
if (searchParams.toString()) {
url = url + `?${searchParams.toString()}`;
}
posthog.capture("$pageview", {
$current_url: url,
});
}
}, [pathname, searchParams, posthog]);
return null;
}
In the layout.js
wrap auth provider around the body and add the PageView inside too.
<html lang="en">
<body
className={`${geistSans.variable} ${geistMono.variable} antialiased`}
>
<NextHogProvider>
<Suspense fallback={null}>
<PostHogPageView />
</Suspense>
{children}
</NextHogProvider>
</body>
</html>
in the next.config.mjs
/** @type {import('next').NextConfig} */
// next.config.js
const nextConfig = {
async rewrites() {
return [
{
source: "/ingest/:path*",
destination: "https://app.posthog.com/:path*", // Proxy to PostHog cloud service
},
];
},
};
export default nextConfig;
This is done to prevent the request being blocked by client
Top comments (0)