The Beacon API: Enhancing Web Performance with Background Data Transmission

We all know that sending data from a client to a server, especially as a web page is closing, is essential. This article explains how Beacon API makes this easy - a web standard designed to send small bits of data to the server without slowing down the page or disrupting the user experience.

What is the Beacon API?

The Beacon API is a JavaScript-based interface that allows web pages to send data to a server in the background, asynchronously, and without waiting for a response. As you would have guessed, this is useful for sending analytics or diagnostic information that doesn't typically require a response from your server or backend or just before the user leaves a page (for example, during the unload or beforeunload events).

Key Features of the Beacon API

  • Asynchronous Data Transfer: Unlike AJAX requests, Beacon requests do not require a response from the server, allowing the user to navigate away from the page immediately without delay.

  • Reliability: The data is transmitted to the server more reliably. Even if the page is being unloaded, the browser will attempt to send the Beacon data in the background.

  • Efficiency: It uses HTTP POST requests and does not impact the performance or the loading time of the web page.

Let's get to it. How Does It Work?

The Beacon API's main function is navigator.sendBeacon(url, data), where url is the server endpoint to which data is sent, and data is the payload. The data can be any of several types, including ArrayBuffer, Blob, DOMString, FormData, or URLSearchParams as long as that's what your server or backend is expecting.

Implementation Steps

  1. Check for Support: It's usually a good practice to first check if the user's browser supports it. If it does, then go ahead to use the beacon API

     if (navigator.sendBeacon) {
         // Beacon API is supported
     }
    
  2. Sending Data: To send data with the Beacon API, we simply call navigator.sendBeacon() with the endpoint and data to be sent.

     window.addEventListener('unload', function(event) {
       var data = { userAction: 'pageExit', timestamp: Date.now() };
       var beaconUrl = 'https://example.com/analytics';
       navigator.sendBeacon(beaconUrl, JSON.stringify(data));
     });
    
  3. Server-Side Handling: On the server, you'll receive the Beacon request just like any other POST request. The data can be processed or stored as needed.

Let's see more examples and uses cases

  1. Sending Analytics Data on Page Unload: With the Beacon API, you can send user interaction data to an analytics endpoint when the user leaves the page. This is useful for capturing page session times, button clicks, or any actions the user performed on the page.

     window.addEventListener('beforeunload', function(event) {
       const analyticsData = {
         sessionDuration: Date.now() - window.sessionStartTime, // Assuming sessionStartTime was recorded at page load
         actions: window.userActions, // Assuming userActions were recorded during the session
       };
    
       navigator.sendBeacon('https://youranalyticsendpoint.com/data', JSON.stringify(analyticsData));
     });
    
  2. Tracking Form Data Without Submission: The Beacon API can be used for draft logic to partially save form details. It allows you to send data to your backend asynchronously. It's useful for creating an autosave or draft feature in a web app.

    
     function saveDraft() {
       const formElement = document.getElementById('your-form-id');
       const formData = new FormData(formElement);
    
       // send draft data to the server using Beacon API
       const draftUrl = 'https://yourserver.com/saveDraft';
       const success = navigator.sendBeacon(draftUrl, formData);
       console.log('Draft save initiated:', success ? 'Success' : 'Failed');
     }
    
     // trigger the saveDraft function on form input (throttled)
     formElement.addEventListener('input', () => {
       // it's usually a best practice to use a throttle/debounce function to 
       //prevent too many Beacon requests
       if (window.draftSaveTimeout) {
         clearTimeout(window.draftSaveTimeout);
       }
    
       window.draftSaveTimeout = setTimeout(saveDraft, 500); // save draft every 500 ms of inactivity
     });
    
     // Additional save on page unload
     window.addEventListener('unload', saveDraft);
    

    When implementing this approach, It's important to also take note of the data size limitations and proper server-side handling, which also involves the backend acknowledging partial data and that it's expected that the backend handles these requests "silently"

Advantage Over Traditional Methods

Before the Beacon API, sending data to the server during unload events was less reliable. Traditional AJAX requests might be cancelled if they were initiated during these events, leading to data loss. The Beacon API ensures that the data is transmitted even after the page has started unloading.

Limitations and Considerations

  • Since the Beacon API does not expect a response from the server, it's not suitable for tasks that require any response from the server.

  • Some browsers may impose their own limits on the size of the data payload.

In general, the Beacon API provides a reliable, efficient method to send data to the server without affecting the user experience.

0
Subscribe to my newsletter

Read articles from Oluwafemi Akinde directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Oluwafemi Akinde
Oluwafemi Akinde

I'm an experienced backend and cloud devops engineer with great experience in building microservices, distributed systems, SOAs, event-driven systems and writing Infrastructure as Code (IaC). In my spare time, I love writing technical articles, reading engineering blogs, as well as reading books on engineering leadership.