Integration Guides

Payload

Add Rybbit analytics to your Payload site

Payload is a headless CMS that installs into a Next.js app: the admin panel lives in the (payload) route group and your site in the (frontend) route group. The tracking snippet goes into the frontend root layout, not into Payload's config or admin panel.

Get your tracking snippet

In your Rybbit dashboard, open Site Settings → Tracking Script and copy your snippet. It looks like this:

<script src="https://app.rybbit.io/api/script.js?siteId=YOUR_SITE_ID" defer></script>

YOUR_SITE_ID is the numeric ID of your site. If you self-host Rybbit, app.rybbit.io is the domain of your own instance.

Add the snippet to Payload

Payload has no template or head setting to paste into. Add the snippet to the root layout of the Next.js frontend that renders your site.

In both the website and blank templates created by npx create-payload-app, the frontend root layout is src/app/(frontend)/layout.tsx. Render next/script there, exactly as in the Next.js guide, so the script loads on every public route and stays out of the admin panel under src/app/(payload)/.

src/app/(frontend)/layout.tsx
import Script from "next/script";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          src="https://app.rybbit.io/api/script.js?siteId=YOUR_SITE_ID"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}

The script tracks client-side route changes automatically, so Next.js <Link> navigation between Payload pages and posts is counted without extra code.

If your frontend is a separate app (Nuxt, Astro, SvelteKit) that fetches from Payload's REST or GraphQL API, follow that framework's guide instead: Nuxt, Astro, SvelteKit, Remix.

Verify installation

Open your live site in a new tab and click through a few pages. Within a few seconds the pageviews appear in the Rybbit dashboard.

If nothing shows up:

  • View the page source and search for script.js?siteId= to confirm the snippet is on the page.
  • Open the browser Network tab and check that script.js returns 200 and that POST requests go to /api/track.
  • Disable ad blockers, or set up a proxy so the script loads from your own domain.
  • See the script troubleshooting guide for other common causes.

Troubleshooting

  • Live Preview counts as visits: the admin panel's Live Preview loads your frontend in an iframe at the URL set in admin.livePreview.url. Editors' preview sessions are tracked like any other visitor. Point livePreview.url at a separate preview deployment registered as its own site in Rybbit, or skip the tag in preview builds.
  • Draft preview routes: if you use the website template's /next/preview route or Next.js draft mode, those pages are also tracked. Add data-skip-patterns='["/next/**"]' to the script tag to exclude them.
  • Admin panel is not tracked: /admin is rendered by the (payload) route group, which has its own layout without the snippet. Put the tag in the (frontend) layout only.

Next steps

On this page