Setting up Simple Analytics for Next.js (App Router)

Learn how to configure external analytics with a noscript fallback for Next.js 13 and 14 using the App Router.


Disclaimer: Links to Simple Analytics on this page are affiliate links. If you sign up for a paid plan using my referral code, I will get a small commission.

If you’re worried Vercel’s built-in analytics product might at some point randomly charge you $300 overnight (😰), you probably have another analytics service that you use for sites and apps.

In my case that’s Simple Analytics which I’ve been happily using for over 6 years with no surprises.

Using external analytics with the App Router

Things have gotten slightly complicated with Next.js 13 and 14 when using the App Router.

  • Vercel’s docs about Script Optimization are not very clear on how to set up external analytics that have a <noscript> fallback.

  • next/head is being deprecated and is not recommended for React Server Components and SSR.

  • You can still use next/head with the App Router rather than the metadata object but the penalties are unclear.

Here is a snippet that uses the new next/script method while also providing a <noscript> fallback when someone has JavaScript disabled in their browser.

Add it to your app/layout.tsx file:

1import Script from "next/script";
3export default function RootLayout({ children }: { children: React.ReactNode }) {
4 return (
5 <html lang="en">
6 <body>
7 {children}
8 <noscript>
9 <img
10 src="https://<your_custom_sa_domain>/noscript.gif?collect-dnt=true&hostname=<your_website_domain>"
11 alt=""
12 referrerPolicy="no-referrer-when-downgrade"
13 />
14 </noscript>
15 </body>
16 <Script
17 strategy="afterInteractive"
18 async
19 defer
20 src="https://<your_custom_sa_domain>/latest.js"
21 data-collect-dnt="true"
22 data-hostname="<your_website_domain>"
23 />
24 </html>
25 );

✦ You can adapt the code above to work with any other analytics provider that also has a <noscript> fallback option.

Getting all the data

To make sure all your visits are being tracked correctly, you should set up a custom subdomain for Simple Analytics. This way your script will bypass ad blockers.

✦ Avoid using common words like analytics or stats in your subdomain name.

I’m also using the data-collect-dnt attribute to overwrite the default behavior of not tracking people with DNT enabled.

There is no identifiable information being collected so I don’t see a reason not to track those visits. Everything is anonymous.

Dashboard showing the most recent visitors to my website.

If you have any questions or this guide is completely wrong, feel free to reach out on Twitter or Telegram.

get notified when i write something new or launch a new project right into your inbox.


subscribe on telegram

Thanks for your time & attention.