Logging Activity with the Web Beacon API

Learn how to implement reliable background data transmission for analytics, error reporting, and user tracking without impacting performance.

Understanding the Beacon API Fundamentals

The Beacon API represents a fundamental shift in how web applications handle background data transmission. Unlike traditional HTTP requests that can block page navigation or fail during page unload events, the Beacon API provides a reliable, asynchronous mechanism for sending analytics, logging, and diagnostic data to your server without impacting user experience.

Traditional methods like fetch() and XMLHttpRequest were designed for interactive communication where the JavaScript runtime expects a response. When a page unloads, the browser prioritizes navigation over pending requests, often cancelling them mid-flight. This data loss creates gaps in your analytics and leaves you with incomplete user journey information. The Beacon API solves this by queuing requests in the background, allowing the browser to manage transmission even after the page has closed.

When you call navigator.sendBeacon(), the browser queues the request and handles transmission in the background without blocking navigation or requiring your JavaScript to remain active. This fire-and-forget approach is specifically designed for analytics and logging scenarios, ensuring you capture every meaningful interaction without compromising performance. The API returns a boolean indicating whether the request was successfully queued, not whether it reached the server--delivery confirmation requires server-side tracking if needed.

Modern web development demands reliable data collection for analytics, error monitoring, and user behavior tracking. Whether you're building a marketing site, a SaaS application, or an enterprise platform, understanding how to implement the Beacon API effectively ensures you capture comprehensive data while maintaining optimal user experience.

Key Beacon API Advantages

Non-Blocking Transmission

Beacon requests don't block page navigation, ensuring smooth user experiences while data transmits in the background.

Unload Reliability

Unlike fetch(), beacons complete transmission even after the page closes or user navigates away.

Browser-Optimized

The browser manages beacon transmission, optimizing for network conditions and system resources.

Simple Implementation

Single method call with straightforward parameters for quick integration into existing codebases.

Basic Analytics Tracking Implementation

The most common use case for the Beacon API is analytics tracking. When users interact with your site, you want to capture their journey without adding latency to their experience. This pattern demonstrates tracking session data when pages become hidden or users navigate away.

The code example captures data at two critical moments: when the page becomes hidden (which covers tab switching and minimizing) and during the beforeunload event. The visibilitychange listener fires when users switch tabs or minimize the browser, while beforeunload captures data during actual page navigation or browser closure. The redundancy ensures you capture data in various navigation scenarios while the fire-and-forget nature means you don't need to worry about response handling.

The session data structure includes the user identifier, session duration calculated from the session start time, a count of page views during the session, and a timestamp for when the data was captured. When either event fires, the data is serialized to JSON and transmitted via navigator.sendBeacon() to your logging endpoint. This approach ensures you never miss critical session data even when users navigate away quickly or close tabs unexpectedly.

For comprehensive analytics implementation, the Beacon API pairs well with our web development services that include performance monitoring and error tracking as part of a complete observability solution.

Basic Analytics Tracking with Beacon API
1const sessionData = {2 userId: 'user123',3 sessionDuration: Date.now() - sessionStart,4 pageViews: pageViewCount,5 timestamp: new Date().toISOString()6};7 8document.addEventListener('visibilitychange', () => {9 if (document.visibilityState === 'hidden') {10 const payload = JSON.stringify(sessionData);11 navigator.sendBeacon('/api/log', payload);12 }13});14 15window.addEventListener('beforeunload', () => {16 const payload = JSON.stringify(sessionData);17 navigator.sendBeacon('/api/log', payload);18});

Error Reporting System

Capturing JavaScript errors reliably is essential for maintaining application quality. Traditional error handlers using fetch() might lose critical error information during page unload. The Beacon API provides a more reliable channel for error reporting that ensures you catch errors even when users navigate away immediately after triggering them.

The error data structure captures comprehensive context for debugging: the error message describes what went wrong, the filename and line/column numbers pinpoint the exact location in your source code, the stack trace provides the call hierarchy when available, the user agent helps you understand which browser and version experienced the error, and the timestamp enables you to correlate errors with user sessions and other events. This comprehensive context is invaluable for reproducing and fixing issues in your production application.

For React and Next.js applications, you might wrap this with error boundary integration, ensuring that caught errors in component trees also get reported through this channel. The Beacon API's reliability during page unload means you're less likely to miss critical errors that occur during navigation, giving you a more complete picture of your application's health.

Error Reporting with Beacon API
1window.addEventListener('error', (event) => {2 const errorData = {3 message: event.message,4 filename: event.filename,5 line: event.lineno,6 column: event.colno,7 stack: event.error?.stack,8 userAgent: navigator.userAgent,9 timestamp: Date.now()10 };11 12 if (navigator.sendBeacon) {13 navigator.sendBeacon('/api/errors', JSON.stringify(errorData));14 }15});

Complete AnalyticsTracker Class

For applications with complex tracking requirements, a class-based approach provides clean organization, event batching, and session management. This implementation demonstrates best practices for batching, event handling, and session management that scale from simple landing pages to complex SaaS applications.

The class structure centers on a configurable endpoint, session tracking, and event batching. The constructor sets up the logging endpoint, initializes the session start time, creates an empty events array, and sets a configurable batch size. The setupEventListeners method registers handlers for visibility changes, page unload, and JavaScript errors, ensuring comprehensive coverage of tracking scenarios.

The trackEvent method adds events to a queue with a type identifier and timestamp. When the queue reaches the configured batch size, sendBatch is called to transmit all accumulated events in a single beacon request. This batching reduces network overhead while ensuring data isn't lost if the page unloads before a full batch accumulates. The generateSessionId method creates unique identifiers for each session, enabling you to correlate multiple events within a single visit. After successful beacon transmission, the events array is cleared, ready to accumulate new tracking data for the next batch.

Complete AnalyticsTracker Class
1class AnalyticsTracker {2 constructor(endpoint = '/api/log') {3 this.endpoint = endpoint;4 this.sessionStart = Date.now();5 this.events = [];6 this.batchSize = 10;7 this.setupEventListeners();8 }9 10 setupEventListeners() {11 document.addEventListener('visibilitychange', () => {12 if (document.visibilityState === 'hidden') {13 this.sendBatch();14 }15 });16 window.addEventListener('beforeunload', () => {17 this.sendBatch();18 });19 window.addEventListener('error', (event) => {20 this.trackEvent('error', {21 message: event.message,22 filename: event.filename,23 line: event.lineno24 });25 });26 }27 28 trackEvent(type, data) {29 this.events.push({ type, data, timestamp: Date.now() });30 if (this.events.length >= this.batchSize) {31 this.sendBatch();32 }33 }34 35 sendBatch() {36 if (this.events.length === 0) return;37 const payload = {38 sessionId: this.generateSessionId(),39 sessionDuration: Date.now() - this.sessionStart,40 events: this.events,41 url: window.location.href,42 userAgent: navigator.userAgent43 };44 if (navigator.sendBeacon) {45 const success = navigator.sendBeacon(this.endpoint, JSON.stringify(payload));46 if (success) this.events = [];47 }48 }49 50 generateSessionId() {51 return Math.random().toString(36).substring(2, 15);52 }53}

Integration with Next.js

In Next.js applications, you can integrate Beacon API tracking through a custom React hook that works with the App Router's client-side components. The hook must be a client component because it relies on browser APIs like navigator.sendBeacon and window/document event listeners that aren't available during server-side rendering.

The useAnalytics hook sets up event listeners for visibility changes and page unload events when the component mounts. The cleanup function returned by useEffect ensures event listeners are properly removed when components unmount, preventing memory leaks and duplicate tracking. This is especially important in single-page applications where users navigate frequently between routes.

The sendPageViewBeacon function constructs a payload with the current path, timestamp, and referrer, then transmits it via the Beacon API. This hook can be used in any page or layout component, providing consistent page view tracking across your Next.js application. For comprehensive tracking, add this hook to your root layout component so it tracks navigation throughout the entire application without requiring manual integration in every page.

Our web development services include Next.js expertise for building performant applications with robust analytics infrastructure.

useAnalytics Hook for Next.js
1'use client';2 3import { useEffect } from 'react';4 5export function useAnalytics() {6 useEffect(() => {7 const handleVisibilityChange = () => {8 if (document.visibilityState === 'hidden') {9 sendPageViewBeacon();10 }11 };12 const handleBeforeUnload = () => {13 sendPageViewBeacon();14 };15 document.addEventListener('visibilitychange', handleVisibilityChange);16 window.addEventListener('beforeunload', handleBeforeUnload);17 return () => {18 document.removeEventListener('visibilitychange', handleVisibilityChange);19 window.removeEventListener('beforeunload', handleBeforeUnload);20 };21 }, []);22 23 const sendPageViewBeacon = () => {24 if (navigator.sendBeacon) {25 const payload = JSON.stringify({26 path: window.location.pathname,27 timestamp: new Date().toISOString(),28 referrer: document.referrer29 });30 navigator.sendBeacon('/api/analytics/pageview', payload);31 }32 };33 return { sendPageViewBeacon };34}

Best Practices for Beacon Implementation

Payload Size Optimization

The Beacon API is designed for small data packets. Keeping payloads focused on essential information reduces bandwidth usage and improves reliability, especially on mobile networks. Avoid sending large objects or unnecessary metadata like entire DOM state, cookie contents, or complete user history. Focus on the minimum information needed for your analytics or logging use case--event type, relevant data points, and timestamp.

Event Batching Strategy

Instead of sending individual beacons for each event, batching multiple events together reduces network overhead and server load. This approach is particularly valuable for high-frequency tracking scenarios like scroll depth monitoring or button click tracking. Sending events in groups reduces the number of HTTP connections your application makes, improving overall performance while ensuring no data is lost when pages unload unexpectedly.

Fallback Strategy

While modern browsers support the Beacon API, implementing a fallback ensures broad compatibility with older browsers and edge cases. The fallback pattern checks for navigator.sendBeacon support first, then falls back to synchronous XMLHttpRequest for older browsers. This synchronous approach can block navigation but ensures data is sent when the Beacon API isn't available. For production applications, consider using asynchronous requests with a timeout for better user experience while maintaining compatibility.

Implementing these best practices is essential for building robust web applications that deliver accurate analytics without compromising user experience.

Beacon API Fallback for Older Browsers
1function sendData(url, data) {2 if (navigator.sendBeacon) {3 return navigator.sendBeacon(url, data);4 }5 try {6 const xhr = new XMLHttpRequest();7 xhr.open('POST', url, false);8 xhr.setRequestHeader('Content-Type', 'application/json');9 xhr.send(data);10 return true;11 } catch (error) {12 console.warn('Failed to send data:', error);13 return false;14 }15}

Common Use Cases

Session Analytics

Understanding user sessions helps you optimize user journeys and identify engagement patterns. Beacon-based session tracking captures session start time and duration, pages visited during the session, actions taken within the session, and navigation patterns and flow. This data enables you to identify where users drop off, which content engages them most, and how they move through your conversion funnels.

Performance Monitoring

Track Core Web Vitals and custom performance metrics to identify optimization opportunities. Send beacon requests containing navigation timing data (FCP, LCP, CLS, FID/INP), resource loading performance, JavaScript execution metrics, and custom timing markers for key interactions. This real-time performance data helps you continuously improve user experience across your web application.

A/B Test Tracking

When running experiments, reliable tracking is essential for valid results. The Beacon API ensures your experiment events reach your analytics system even when users bounce or navigate quickly between variants. Track experiment variant assignment, conversion events by variant, drop-off points in funnels, and time-on-page by variant to get accurate experiment results.

User Action Tracking

Monitor specific interactions to understand engagement patterns across your e-commerce platform or SaaS application. Track button clicks and form submissions, scroll depth and content consumption, video playback events, and feature usage patterns. This granular engagement data helps you optimize user experience and identify opportunities for conversion optimization.

These use cases demonstrate how the Beacon API supports comprehensive analytics and tracking for modern web applications.

Frequently Asked Questions

Ready to Implement Reliable Analytics?

Our web development team can help you implement robust tracking and analytics solutions using modern APIs like the Beacon API. From error reporting systems to comprehensive session analytics, we build data collection infrastructure that scales with your application.

Sources

  1. OpenReplay: Sending Background Data with the Beacon API - Comprehensive technical guide with code examples for analytics tracking, error reporting, and user action tracking
  2. Wikipedia: Web beacon - Authoritative reference on web beacons, Beacon API specifications, and browser support history