Single-page apps

Automatic tracking for React, Vue, Next.js, and other SPAs.

Automatic navigation tracking

The Glyphex tracking script automatically detects client-side navigation in single-page applications. No additional configuration needed.

It works by listening to the History API (pushState and popstate events), which all modern frameworks use for routing.

Just add the script once - it handles all navigation automatically.

Framework examples

Next.js (App Router)

// app/layout.tsx
import Script from 'next/script'

export default function RootLayout({ children }) {
  return (
    <html>
      <head>
        <Script
          defer
          data-site-id="YOUR_SITE_ID"
          src="https://glyphex.io/tracker.js"
          strategy="afterInteractive"
        />
      </head>
      <body>{children}</body>
    </html>
  )
}

Next.js (Pages Router)

// pages/_app.tsx
import Script from 'next/script'

export default function App({ Component, pageProps }) {
  return (
    <>
      <Script
        defer
        data-site-id="YOUR_SITE_ID"
        src="https://glyphex.io/tracker.js"
        strategy="afterInteractive"
      />
      <Component {...pageProps} />
    </>
  )
}

React Router

// index.html - just add the script
<script
  defer
  data-site-id="YOUR_SITE_ID"
  src="https://glyphex.io/tracker.js"
></script>

// Navigation is tracked automatically!

Vue / Nuxt

<!-- nuxt.config.ts -->
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          defer: true,
          'data-site-id': 'YOUR_SITE_ID',
          src: 'https://glyphex.io/tracker.js'
        }
      ]
    }
  }
})

SvelteKit

<!-- src/app.html -->
<!DOCTYPE html>
<html>
  <head>
    <script
      defer
      data-site-id="YOUR_SITE_ID"
      src="https://glyphex.io/tracker.js"
    ></script>
  </head>
  <body>
    %sveltekit.body%
  </body>
</html>

Astro

<!-- src/layouts/Layout.astro -->
<html>
  <head>
    <script
      defer
      data-site-id="YOUR_SITE_ID"
      src="https://glyphex.io/tracker.js"
    ></script>
  </head>
  <body>
    <slot />
  </body>
</html>

How it works

The tracking script:

  1. Tracks the initial page load
  2. Listens for pushState calls (new navigation)
  3. Listens for popstate events (back/forward navigation)
  4. Sends a page view when the URL changes

Hash-based routing

If your app uses hash-based routing (e.g., example.com/#/page), those hash-only route changes are not tracked automatically. Use History API routing, or call window.analytics.track() yourself on each change.

Page titles

After a route change the pageview is sent 300 ms later, so document.title already holds the new page's title. Time on page for the page you left is sent immediately.

Troubleshooting

Page views not tracked on navigation?

Ensure the script is loaded before your first navigation occurs. Using defer or strategy="afterInteractive" is recommended.

Duplicate page views?

Make sure you haven't added the script multiple times (once is enough). Also check that you're not manually calling the tracker in addition to automatic tracking.