Skip to content

Commit 80f23d3

Browse files
devakoneclaude
andcommitted
feat: track page views on Next.js route changes
- Disable autoCapturePageviews (doesn't work well with App Router) - Manually track pageviews on pathname/searchParams changes - Wrap useSearchParams in Suspense boundary Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent ced53ab commit 80f23d3

1 file changed

Lines changed: 51 additions & 14 deletions

File tree

Lines changed: 51 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
"use client";
22

3-
import { useEffect } from "react";
4-
import { init } from "@plausible-analytics/tracker";
3+
import { Suspense, useEffect, useRef } from "react";
4+
import { usePathname, useSearchParams } from "next/navigation";
5+
import { init, track } from "@plausible-analytics/tracker";
56

67
/**
7-
* Initializes Plausible Analytics on the client side.
8-
* Must be rendered within the app to enable tracking.
8+
* Inner component that uses useSearchParams (requires Suspense boundary).
99
*/
10-
export function PlausibleProvider() {
10+
function PlausibleTracker() {
11+
const pathname = usePathname();
12+
const searchParams = useSearchParams();
13+
const isInitialized = useRef(false);
14+
15+
// Initialize Plausible once
1116
useEffect(() => {
1217
const domain = process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN;
1318

@@ -18,16 +23,48 @@ export function PlausibleProvider() {
1823
return;
1924
}
2025

21-
init({
22-
domain,
23-
// Don't track localhost unless explicitly enabled
24-
captureOnLocalhost: process.env.NEXT_PUBLIC_PLAUSIBLE_CAPTURE_LOCALHOST === "true",
25-
// Track outbound link clicks
26-
outboundLinks: true,
27-
// Track file downloads
28-
fileDownloads: true,
29-
});
26+
if (!isInitialized.current) {
27+
init({
28+
domain,
29+
// Don't track localhost unless explicitly enabled
30+
captureOnLocalhost: process.env.NEXT_PUBLIC_PLAUSIBLE_CAPTURE_LOCALHOST === "true",
31+
// Track outbound link clicks
32+
outboundLinks: true,
33+
// Track file downloads
34+
fileDownloads: true,
35+
// Disable auto capture - we handle it manually for Next.js App Router
36+
autoCapturePageviews: false,
37+
});
38+
isInitialized.current = true;
39+
}
3040
}, []);
3141

42+
// Track page views on route changes
43+
useEffect(() => {
44+
if (!process.env.NEXT_PUBLIC_PLAUSIBLE_DOMAIN || !isInitialized.current) {
45+
return;
46+
}
47+
48+
// Build the full URL for tracking
49+
const url = searchParams.toString()
50+
? `${pathname}?${searchParams.toString()}`
51+
: pathname;
52+
53+
// Track pageview with the current URL
54+
track("pageview", { url });
55+
}, [pathname, searchParams]);
56+
3257
return null;
3358
}
59+
60+
/**
61+
* Initializes Plausible Analytics and tracks page views on route changes.
62+
* Must be rendered within the app to enable tracking.
63+
*/
64+
export function PlausibleProvider() {
65+
return (
66+
<Suspense fallback={null}>
67+
<PlausibleTracker />
68+
</Suspense>
69+
);
70+
}

0 commit comments

Comments
 (0)