Skip to main content
View all posts

Segment Implementation for Next.js 14 (App Router)

Marshall Hahn
Marshall HahnSoftware Engineer
Segment Implementation for Next.js 14 (App Router)

I created a brand new Next.js 14 project recently and when I tried to implement Segment using @segment/analytics-next , I ran into a few issues along the way. I wanted to document how I ended up resolving those issues, especially because I was not able to find any good explanations online about how to resolve them and I found the example Next.js project in the documentation a bit misleading.

The issues I ran into during implementation were:

  1. Anonymous ID: My ajs_anonymous_id cookie was being set to undefined instead of a random uuid being generated by Segment (and events in Segment were showing up as coming from "anonymousId": "undefined" instead of something like "anonymousId": "24cf5c11-d6d0-450c-b85c-7353fcb7467f")
  2. Suspense and useSearchParams hook: Rendering and loading Segment Analytics in the the layout component (which included the useSearchParams hook) was causing hydration errors
  3. Duplicate page events: I noticed that duplicate page events were showing up in the Segment debugger (for my development environment source)

Anonymous ID

The concept of server components (leveraging react server components) was introduced in Next.js 13 with the app router, and because @segment/analytics-next relies on Browser APIs – window specifically – loading analytics directly in the layout file was not working for me.

Note: Next.js 14 considers everything a server component unless you add "use client" at the top of the file to specify otherwise, which signals that the component should be a client component. The naming is a bit misleading, however, because client components are still rendered on the server first and then re-hydrated on the client. This is a new paradigm and I would highly recommend reading this section of the Next.js documentation to learn more about this.

Suspense and useSearchParams hook

Loading @segment/analytics-next in the Layout component appeared to work, but Next.js raised hydration errors and pointed to the fact the component should be wrapped within a Suspense boundary. To resolve these errors, I ended up creating a new component for the Segment page view event and wrapped that component within Suspense in the Layout component (see analytics_provider.tsx below).

Duplicate page events

This one was a bit tricky to troubleshoot because I noticed it was only happening on my local environment in development. I could not reproduce the issue when I deploying the project in a production environment. After some research in addition to some trial and error, the issue traced back to a feature in React – Strict Mode.

According to the documentation, Strict Mode has been enabled by default with the app router since Next.js version 13.4. React's Strict Mode is a development mode only feature that highlights potential problems, and one of the main behaviors of Strict Mode is that components will re-render an extra time to catch bugs. This means that when the Analytics component was being rendered, it was actually being rendered two times in development and causing the extra page view.

Putting it All Together (The Full Solution)

To get @segment/analytics-next working in Next.js 14, I ended up having to separate things out into a few files in addition to leverage React context and an associated provider to wrap child components in my Layout file. I also needed to wrap my Segment page view event within a suspense boundary. Here's what the files ended up looking like:

@/lib/segment.ts

layout.tsx

segment_context.ts

segment_provider.tsx

analytics_provider.tsx (with SegmentPageView)


I hope this helps someone, and if any questions about this comes up or if you come across any issues with the above feel free to reach out.