Add tracker to Next.js App

To add an external analytics tracking snippet in your Next.js application:

Write this in your existing _document.tsx file. Create it in your pages directory if it doesn't exist.

If you are using the new app routing, copy the <head> section into /app/layout.tsx.

1. (Option A) Next.js UXWizz snippet in _document.tsx

import { Html, Head, Main, NextScript } from 'next/document';
import Script from 'next/script';

const dashboardURL = 'https://your.uxwizz.com/server';
const trackedDomain = 'yourappdomain.com';

export default class MyDocument extends Document {
  render() {
    return (
      <Html>
        <Head>
          {/* UXWIZZ SNIPPET START */}
          {/* Global scope */}
          <Script
            id="ust-init"
            strategy="beforeInteractive"
            dangerouslySetInnerHTML={{
              __html: `UST_CT = []; UST = { s: Date.now(), addTag: function(tag) { UST_CT.push(tag) } }; UST.addEvent = UST.addTag;`,
            }}
          />
  
          {/* vvv -- Only include this part to enable A/B tests -- vvv*/}
          <Script
            id="ust-ab-init"
            strategy="beforeInteractive"
            dangerouslySetInnerHTML={{
              __html: `(function() {var ust_s = document.createElement('STYLE');ust_s.id = 'ust_body_style';
                  ust_s.appendChild(document.createTextNode('body {opacity: 0}'));document.head.appendChild(ust_s);})();
                  setTimeout(function(){ var el = document.getElementById('ust_body_style'); el && el.remove()}, 800);`,
            }}
          />
          <Script
            id="ust-ab"
            src={`${dashboardURL}/ab/${trackedDomain}.ab.js?v=x.x.x`}
            strategy="afterInteractive"
            defer
          />
          {/* ^^^ -- Only include this part to enable A/B tests -- ^^^*/}
  
          {/* Main UXWizz script */}
          <Script
            id="uxwizz-script"
            src={`${dashboardURL}/ust.min.js?v=x.x.x`}
            strategy="afterInteractive"
            async
          />
          {/* UXWIZZ SNIPPET END */}
        </Head>
        <body>
          <Main />
          <NextScript />
        </body>
      </Html >
    )
  }
}

1. (Option B) Next.js UXWizz snippet in /app/layout.tsx

const dashboardURL = 'https://your.uxwizz.com/server';
const trackedDomain = 'yourappdomain.com';

...

export default function RootLayout({
  children,
}: Readonly<{
  children: React.ReactNode;
}>) {
  return (
    <html lang="en">
      <head>
        {/* UXWIZZ SNIPPET START */}
        {/* Global scope */}
        <Script
          id="ust-init"
          strategy="beforeInteractive"
          dangerouslySetInnerHTML={{
            __html: `UST_CT = []; UST = { s: Date.now(), addTag: function(tag) { UST_CT.push(tag) } }; UST.addEvent = UST.addTag;`,
          }}
        />

        {/* vvv -- Only include this part to enable A/B tests -- vvv*/}
        <Script
          id="ust-ab-init"
          strategy="beforeInteractive"
          dangerouslySetInnerHTML={{
            __html: `(function() {var ust_s = document.createElement('STYLE');ust_s.id = 'ust_body_style';
                ust_s.appendChild(document.createTextNode('body {opacity: 0}'));document.head.appendChild(ust_s);})();
                setTimeout(function(){ var el = document.getElementById('ust_body_style'); el && el.remove()}, 800);`,
          }}
        />
        <Script
          id="ust-ab"
          src={`${dashboardURL}/ab/${trackedDomain}.ab.js?v=x.x.x`}
          strategy="afterInteractive"
          defer
        />
        {/* ^^^ -- Only include this part to enable A/B tests -- ^^^*/}

        {/* Main UXWizz script */}
        <Script
          id="uxwizz-script"
          src={`${dashboardURL}/ust.min.js?v=x.x.x`}
          strategy="afterInteractive"
          async
        />
        {/* UXWIZZ SNIPPET END */}
      </head>
      <body>
        {children}
      </body>
    </html>
  );
}
...

This will only track the initial page as a pageview. To track all route changes, add this component:

2. Creating UXWizzPageview.tsx

'use client';

import { usePathname, useSearchParams } from "next/navigation";
import { useEffect, useRef } from "react";

export default function UXWizzPageview() {
    const pathname = usePathname();
    const searchParams = useSearchParams();
    const isInitialLoad = useRef(true);

    useEffect(() => {
        if (isInitialLoad.current) {
            isInitialLoad.current = false
            return;
        };
        if (typeof window === 'undefined') return;
        const ust = (window as typeof window & { UST: { trackNewPage: () => void } })['UST'];
        if (!ust || !ust.trackNewPage) return;
        ust.trackNewPage(); // Call on route change, but not on initial load
    }, [pathname, searchParams]);

    return null;
}

3. Adding the pageview component.

You can then import UXWizzPageview in the body section of layout.tsx

...

import dynamic from 'next/dynamic';
const UXWizzPageview = dynamic(() => import('./UXWizzPageview'), { ssr: false });
...
...
...
      <body>
        <UXWizzPageview />
        {children}
      </body>
...

Last updated

Was this helpful?