Single Page Applications

Narrowbeam automatically tracks page navigation in Single Page Applications (SPAs) built with React, Vue, Angular, and other modern frameworks.

Automatic tracking: SPA navigation is tracked automatically with no configuration needed!

How SPA Tracking Works

Single Page Applications don't reload the page when navigating. Instead, they use the History API (pushState, replaceState) and client-side routing. Narrowbeam detects these navigation events and automatically tracks them as page views.

What Gets Tracked

  • Initial page load: First page view when the app loads
  • History API navigation: Routes changed via pushState or replaceState
  • Back/forward buttons: Browser navigation via popstate events
  • Hash changes: URL hash navigation (if used for routing)

Supported Frameworks

SPA tracking works automatically with all major frameworks:

React

  • React Router
  • Next.js (App Router & Pages Router)
  • Remix
  • Gatsby

Vue

  • Vue Router
  • Nuxt.js
  • Quasar

Angular

  • Angular Router
  • Angular Universal

Other Frameworks

  • Svelte / SvelteKit
  • Solid.js
  • Any framework using History API

Installation

For framework-specific installation instructions, see:

How It Works Technically

When the Narrowbeam script loads, it automatically sets up SPA tracking by:

1. Intercepting History API Calls

// Narrowbeam wraps pushState and replaceState
const originalPushState = history.pushState;
history.pushState = function(...args) {
  originalPushState.apply(this, args);
  // Track the new page view
  checkForRouteChange();
};

2. Listening for Navigation Events

// Listen for back/forward button clicks
window.addEventListener('popstate', () => {
  checkForRouteChange();
});

3. Detecting Route Changes

// Track when the URL actually changes
function checkForRouteChange() {
  if (currentUrl !== window.location.href) {
    currentUrl = window.location.href;
    trackPageView();
  }
}
All of this happens automatically. You don't need to configure anything or call any APIs.

Manual Page View Tracking

In rare cases where automatic tracking doesn't work (custom routing solutions), you can manually track page views:

// In your custom router
router.on('route-change', () => {
  window.narrowbeam.checkPageChange();
});

Manual Tracking Rarely Needed

Manual tracking is only needed for very custom routing implementations. All standard frameworks and routing libraries work automatically.

Page Leave Events

Narrowbeam also tracks when users leave pages in an SPA. This happens:

  • Before navigating to a new route
  • When the user closes the tab or browser
  • When the user navigates away from your site

Page leave events use navigator.sendBeacon for reliable tracking even during navigation.

Framework-Specific Examples

React with React Router

// No configuration needed!
// Narrowbeam automatically detects React Router navigation

function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </BrowserRouter>
  );
}

Next.js App Router

// No configuration needed!
// Narrowbeam tracks Next.js navigation automatically

import Link from 'next/link';

export default function Nav() {
  return (
    <nav>
      <Link href="/">Home</Link>
      <Link href="/about">About</Link>
    </nav>
  );
}

Vue with Vue Router

// No configuration needed!
// Narrowbeam tracks Vue Router navigation automatically

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About }
  ]
});

Verifying SPA Tracking

To verify that SPA navigation is being tracked:

  1. Open your browser's Developer Tools (F12)
  2. Go to the Network tab
  3. Filter by "Fetch/XHR" or search for your Narrowbeam domain
  4. Navigate between pages in your SPA
  5. You should see a new request to /api/events for each navigation

What to Look For

Each navigation should create a request with:

  • event_type: "pageview"
  • Updated url value
  • New pageview_id
  • Previous page as referrer (for internal navigation)

Common Issues

Hash-Based Routing

If your app uses hash-based routing (example.com/#/page), navigation should still be tracked automatically. However, consider migrating to History API routing for better SEO and cleaner URLs.

Custom Routing Libraries

If you're using a custom routing library that doesn't use the History API, you may need to manually trigger page view tracking:

// After your custom routing logic
customRouter.afterNavigation(() => {
  window.narrowbeam.checkPageChange();
});

Server-Side Rendering (SSR)

For SSR apps (Next.js, Nuxt, etc.):

  • Initial page load is tracked as a normal page view
  • Subsequent client-side navigation is tracked as SPA navigation
  • Hard refreshes create new page views (as expected)

Best Practices

  • Use standard routing: Stick to popular routing libraries that use the History API
  • Test navigation flows: Verify that all navigation patterns trigger page views
  • Clean URLs: Use readable routes like /products/123 instead of /products?id=123
  • Consistent routes: Avoid having the same page accessible via multiple URLs
  • Monitor analytics: Check that page view counts match expected user behavior

Performance Impact

SPA tracking has minimal performance impact:

  • Navigation detection adds less than 1ms of overhead
  • Page view events are sent asynchronously (non-blocking)
  • Uses sendBeacon for reliable, low-overhead transmission
  • No impact on your app's routing or navigation speed

Related Documentation