Add tracker to Next.js App

This guide is still quite new. If you encounter any issues, please contact support.

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.

Note!! - This was the tracking code as of version 6.4.0.

Please update it to match the tracking code given to you in the UXWizz dashboard.

Set your own dashboard URL dashboardURL constant.

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>
...

If you don't use TypeScript, you can simply remove the typings replace this line:

const ust = (window as typeof window & { UST: { trackNewPage: () => void } })['UST'];

with

const ust = window['UST'];

Last updated