Google Analytics (GA4) with Next.js 13 App Router

Here's how to implement the new Google Analytics (GA4) with Next.js 13 App Router.

Google Analytics (GA4) with Next.js 13 App Router

Google introduced the next generation of Analytics, Google Analytics 4(GA4), and announced that standard Universal Analytics properties will no longer process data on July 1, 2023.

This article describes how to implement the new Google Analytics (GA4) with Next.js 13 App Router. If you are using the Pages Router, check out the nextjs-google-analytics package instead.

Let's break down the objectives into the following steps.

  1. Inserting the tag
  2. Tracking page views

Inserting The Tag

You will need your Google Analytics Measurement ID and Tag for this step. If you are not sure, check out the Set up your Google Tag article by Google on where to retrieve them.

Create an environment variable for our Google Analytics Measurement ID:

You will need to set this variable on your deployment platform as well.

Create a <GoogleAnalytics> component to insert the tag from your Google Analytics account.

Line 7-9: Add a check so that we do not run any of the code if the measurement ID is not set in environment.

Line 14, 23: Interpolate our measurement ID into the script, and disabled the default page_view event, by settings the send_page_view parameter to false. This is to avoid double pageview counts when the history state changes. (See the GA docs)

Line: 26: Don't worry about the TrackPageViews component yet, we will get to it in the next step

Line 17:  next/script components with inline content require an id attribute to be defined to track and optimize the script. (See the Next.js docs)

Tracking Page Views

In Next.js 13 App Router, we listen for page changes by composing other Client Component hooks like usePathname and useSearchParams (See Next.js docs)

Since we are going to be firing the page_view event on the client side, create a client side component TrackPageViews .

Line 10-14: useEffect hook that listens for changes to the values returned by usePathname and useSearchParams, and fires a page_view event

Line 21-23:  Wrap our event implementation component in a React Suspense boundary, so we don't block the user interactivity,

Putting It Altogether

Last step is to add our <GoogleAnalytics> component to our root layout component at app/layout.tsx .


Use Google Tag Assistant to check that your page_view events are firing.


And that's all!

Hope this has been helpful, if you have any improvements to suggest feel free to comment below.