Plausible Analytics is a lightweight, privacy-focused, cookie-free analytics solution. In this article, we’ll implement it inside a Next.js App Router project in a way that bypasses ad blockers using proxying. By proxying the tracking script and API requests through your own domain, you significantly reduce the chance of them being blocked by common ad-blocking extensions.
We’ll also ensure that page views are correctly tracked on every route change in a client-side rendered app.
This guide assumes you are self-hosting Plausible on a custom subdomain such as
analytics.yourdomain.com
.
Proxy the Plausible Script and API
To reduce the chance of being blocked by ad blockers, we'll proxy Plausible's script and API through your own domain.
In your next.config.js
, add the following:
jsCopy codeasync rewrites() { return [ { source: "/js/script.js", destination: "https://analytics.yourdomain.com/js/script.file-downloads.hash.outbound-links.pageview-props.revenue.tagged-events.js", }, { source: "/api/event", destination: "https://analytics.yourdomain.com/api/event", }, ]; }
Next.js uses this to route requests internally without triggering a redirect (i.e., the user sees the original URL in their browser).
- When a user or script on your site requests
/js/script.js
or/api/event
, the request is internally proxied to the external URL. - The browser still thinks it loaded locally, but the content is coming from
analytics.yourdomain.com
.
What is this script variant?
The URL points to a self-hosted and enhanced version of the Plausible tracking script:
script.file-downloads.hash.outbound-links.pageview-props.revenue.tagged-events.js
This version includes support for:
- File downloads
- URL hash tracking
- Outbound link clicks
- Custom pageview properties
- Revenue tracking
- Tagged events
This is ideal if you want richer insights without modifying your app further.
Create a Route Tracker Component
Create a new file: app/RouteTracker.tsx
tsxCopy code'use client'; import { usePathname } from 'next/navigation'; import { useEffect } from 'react'; const RouteTracker = () => { const pathname = usePathname(); useEffect(() => { // 1. Add the Plausible script to the DOM if not already added if (!document.getElementById("next-p")) { const script = document.createElement("script"); script.id = "next-p"; script.async = true; script.defer = true; script.setAttribute("data-domain", "yourdomain.com"); script.src = "/js/script.js"; // Note: this uses the proxied script document.head.appendChild(script); } // 2. Add Plausible's minimal global initializer if (!document.getElementById("next-p-init")) { const initScript = document.createElement("script"); initScript.id = "next-p-init"; initScript.innerHTML = "window.plausible = window.plausible || function() { (window.plausible.q = window.plausible.q || []).push(arguments) }"; document.head.appendChild(initScript); } // 3. Manually track a pageview when route changes const trackPageview = (url: string) => { const eventData = { name: "pageview", url, domain: window.location.hostname, ...(document.referrer && { referrer: document.referrer }), }; fetch("/api/event", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(eventData), }).catch((err) => console.error("Error tracking pageview:", err)); }; trackPageview(pathname); }, [pathname]); return null; }; export default RouteTracker;
What this does
- Dynamically injects the Plausible script into the page, ensuring it's only loaded once.
- Adds a global Plausible initializer, so custom events can be tracked if needed.
- Manually sends a pageview event whenever the route changes in the client, which is essential in App Router / SPA apps.
Use the Component in Your Layout
Open your root layout file (app/layout.tsx
) and import the tracker:
tsxCopy codeimport RouteTracker from "@/src/hooks/plausible"; // adjust path to match your project
Then include it in your layout:
tsxCopy code<body> <RouteTracker /> {children} </body>
Final Notes
- This implementation ensures Plausible is loaded only on the client and is less likely to be blocked.
- All route changes are tracked, making it perfect for SPA-like behavior with App Router.
- You benefit from all of Plausible’s extended features using the custom script variant.
By combining script proxying and client-side tracking, you get powerful, privacy-compliant analytics without sacrificing usability or insight.