Next.js
Initialize Ucoder Insight in a Next.js application (App Router and Pages Router).
Next.js
Ucoder Insight supports both the App Router and the Pages Router. Initialize the SDK once, near the root of your application, using the pattern for your router below.
Using plain React (no Next.js)? See the React guide instead.
Setup
Create a client component and mount it once in your root layout.
"use client";
import { useEffect } from "react";
import { initUcoderInsight } from "ucoder-insight";
export function Analytics() {
useEffect(() => {
void initUcoderInsight("YOUR_PUBLIC_TRACKING_ID");
}, []);
return null;
}import { Analytics } from "./analytics";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body>
<Analytics />
{children}
</body>
</html>
);
}The "use client" directive is required — initUcoderInsight runs in the browser and cannot execute in a Server Component.
In development, React's StrictMode intentionally mounts effects twice.
You may see initUcoderInsight run twice in the console — this is
expected and does not cause duplicate tracking in production.
Tracking route changes
Ucoder Insight automatically tracks page views on navigation by patching history.pushState / history.replaceState and listening for popstate — see Tracking route changes in a single-page app for how this works. Since Next.js client-side navigation (via <Link>, useRouter().push(), etc.) uses the History API under the hood, this works automatically in both routers without extra code.
If you notice route changes that aren't appearing as page views — for example, during heavy use of prefetching or streaming in the App Router — you can track a page view manually as a fallback. See below for router-specific patterns.
App Router: manual fallback
If you need to guarantee a page view fires on every route change, track it explicitly using usePathname and useSearchParams:
"use client";
import { useEffect } from "react";
import { usePathname, useSearchParams } from "next/navigation";
import { initUcoderInsight, trackPageView } from "ucoder-insight";
export function Analytics() {
const pathname = usePathname();
const searchParams = useSearchParams();
useEffect(() => {
void initUcoderInsight("YOUR_PUBLIC_TRACKING_ID");
}, []);
useEffect(() => {
const url = searchParams?.toString()
? `${pathname}?${searchParams.toString()}`
: pathname;
trackPageView(url);
}, [pathname, searchParams]);
return null;
}useSearchParams() requires the component to be wrapped in a <Suspense> boundary in the App Router — wrap <Analytics /> in <Suspense fallback={null}> if you see a build warning about this.
Pages Router: manual fallback
Use the next/router events API to fire a page view on every completed route change:
import { useEffect } from "react";
import { useRouter } from "next/router";
import type { AppProps } from "next/app";
import { initUcoderInsight, trackPageView } from "ucoder-insight";
export default function App({ Component, pageProps }: AppProps) {
const router = useRouter();
useEffect(() => {
void initUcoderInsight("YOUR_PUBLIC_TRACKING_ID");
}, []);
useEffect(() => {
const handleRouteChange = (url: string) => trackPageView(url);
router.events.on("routeChangeComplete", handleRouteChange);
return () => {
router.events.off("routeChangeComplete", handleRouteChange);
};
}, [router.events]);
return <Component {...pageProps} />;
}See Configuration for supported SDK options.