How to Integrate Plausible Analytics in a Next.js App (Without Getting Blocked)

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:

async 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

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

import RouteTracker from "@/src/hooks/plausible"; // adjust path to match your project

Then include it in your layout:


<RouteTracker />
{children}


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.