How to log user activities using the Beacon Web API?
Tags: javascript, webdev, codenewbie, beginners
Published: 2020-10-27 04:31:29

The `Beacon API` is a relatively unknown, lightweight, and efficient way to log web page activities to a server. It is a JavaScript API that helps the developer to send a small amount of data such as, analytics or tracking information, debugging, or diagnostic data from the browser to the server.

In this article, we will learn about the `Beacon API` and use it to log some user activities to the server. Hope you enjoy knowing it.

# The Beacon Web API
The `Beacon API` schedules an ***asynchronous and non-blocking*** request to a web server. There are a few specialties of the beacon request,

- Beacon requests do not require a response. This is a huge difference from the regular `XHR` or `fetch` requests where the client(browser) expects a response from the server.
- Beacon requests are guaranteed to be initiated before a page is unloaded, even when you close the browser.
- Beacon requests complete without requiring a blocking request (XHR, for example).
- Beacon requests use the HTTP POST method.

Some of the characteristics like, `non-blocking`, no expectations on the `response` make the beacon requests extremely useful to send data to the server when a page unloads(example, closing the browser, page navigations, etc.).

# How to use the Beacon API?
The Beacon API has wide browser support. It works on [most of the browsers](https://caniuse.com/?search=Beacon) except the older internet explorer versions. 

Just to be on the safer side, we can test the browser support using this simple check,

```js
if (navigator.sendBeacon) {
  // Initiate a beacon request
} else {
  // May be, fallback to XHR or fetch?
}
```

The ` Navigator.sendBeacon()` method sends a beacon request to the server. The method takes two arguments, the URL to the server and the data. The `sendBeacon()` method returns a boolean. It returns `true` when the request is placed correctly in the queue and a `false` otherwise.

```js
if (navigator.sendBeacon) {
  navigator.sendBeacon('/log-tracking', data);
} else {
  // May be, fallback to XHR or fetch?
}
```
The `data` argument of the `sendBeacon()` method is optional and it is of type of an `ArrayBufferView`, `Blob`, `DOMString`, or `FormData`. Let us use the `FormData` to create the data for our example.

```js
function sendAnalytics(msg) {
  if (navigator.sendBeacon) {
    let data = new FormData();
    data.append('start', startTime);
    data.append('end', performance.now());
    data.append('msg', msg);
        
    navigator.sendBeacon('/log-tracking', data);
  } else {
    // May be, fallback to XHR or fetch?
  }
}
```
In the above example, we are sending the `start` and `end` time that a user would have spent on the application. we are also sending a tracking `msg` that captures what are the activities user would have performed(like, button clicked, scrolled to a page section, etc.).

We can specify a handler for the `unload` and/or `beforeunload` events and call the `sendAnalytics()` method.

```js
window.addEventListener('unload', function() {
  sendAnalytics(msg);
});
```
As we are sending the `data` using the URL `/log-tracking`, the server-side code can log this information anywhere and use it for analytics purposes. 

Here is a sample `express` server code that logs this information in the console. We can be creative enough to log it in the file system, database, etc. Please note, server is not sending back any response here.

```js
app.post('/log-tracking', function(req, res) {
  console.log('**** Tracked. Now logging ****');

  let startTime = req.body.start;
  let endTime = req.body.end;
  let trackInfo = req.body.msg;

  let logMsg = '';
  let time = (endTime - startTime) / 1000;
  logMsg = `${time.toFixed(2)} seconds`;

  if (time > 60) {
      time = time / 60;
      logMsg = `${time.toFixed(2)} minutes`;
  }
  console.log('In Session for: ', logMsg);
  console.log('Tracking info: ', trackInfo);
});
```

# Demo
Here is a quick demo(12 seconds) to showcase how `Beacon` requests work. We have two buttons here. One button is to send an ad-hoc beacon request to the server and another one simulates the browser `unload` event.

As you see below, the server console logs the time spent information with a sample message. Also note, the information logs when the user closes the browser.

{% youtube 6e07T1Qn-2w %}

If we see the beacon request in the developer tool(Network tab), we will see the request as `pending` because the server doesn't send a response. That's why it is a better use when we send a beacon request on browser unload event.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1603688246339/OSyaCaTwH.png?border=1,CCCCCC&auto=compress)

Another note is, the beacon request is not an `XHR` request. You can see the `All` option is selected above to trace this request.

# Source Code
All the source code used in this article and for the demo is in the GitHub repo mentioned below. Please feel free to fork, modify, and use. Show your support with a star(⭐) if you liked the project. You are welcome to follow 🤝 me on GitHub to stay connected.

{% github atapas/tracker-beacon-api %}

# Primary Use-cases
There are two primary use-cases where the `Beacon API` can be useful.

## User activity tracking and analytics
You may want to capture and send an analytics report of your user activities and behavior. These activities may include,
- How long a user was in the session?
- What are the user interface controls users used?
- Any other kind of telemetry information to capture.

We may want to use any of the analytics tools and services like Google analytics for this but, it is hard to convenience our customers especially with an enterprise application.

One more point about the analytics and user activity tracking is, you need to take the end user's consent before you enable a feature like this.

## Debugging and diagnostics
Have you ever faced situations like a feature works locally(in the dev mode) but doesn't work as expected in the customer environment(production mode)? This is a typical situation where the `Beacon API` can be a day(or night) saver. 

You can logically send these lightweight beacon requests to log useful trace path information and debug them as needed.

# Data limit with Beacon API
There is a limit on the data that can be sent to the server using Beacon API. However, this limit is not uniform across all the browsers and user-agents.

As per the spec,

> The user agent must restrict the maximum data size to ensure that beacon requests are able to complete quickly and in a timely manner.

Please read through the [beacon API specifications](https://www.w3.org/TR/beacon/#sec-sendBeacon-method) from w3c.org for more information.

# Summary
In Summary,

- The Beacon API is a lightweight API to send a small amount of data from the browser to the server.
- The beacon requests are non-blocking asynchronous requests. There is no expectation from the server to send a response for a beacon request.
- The beacon requests are guaranteed to be initiated before a page is unloaded.
- We can use it for user activities, behavior analysis, and production time debugging.
- There are plenty of tools out that are doing the user activity, behavior analysis, and create logs. However, they are not viable many times due to the cost and our enterprise user's unfriendliness to these apps.
- It is also important to know what is available natively with JavaScript to understand the basics better.



More read on the Beacon API is from here,
- [Beacon API from MDN](https://developer.mozilla.org/en-US/docs/Web/API/Beacon_API)

Hope you learned something new today and all set to give the `Beacon API` a try sooner. You may also like,
- [10 lesser-known Web APIs you may want to use](https://blog.greenroots.info/10-lesser-known-web-apis-you-may-want-to-use-ckejv75cr012y70s158n85yhn)
- [What exactly is JavaScript Tagged Template Literal?](https://blog.greenroots.info/what-exactly-is-javascript-tagged-template-literal-ckg6hyekf000n8bs1hz9udvzc)
- [Explain Me Like I am Five: What are ES6 Symbols?](https://blog.greenroots.info/explain-me-like-i-am-five-what-are-es6-symbols-ckeuz5sb8001qafs14of305dw)

<hr />

If it was useful to you, please Like/Share so that, it reaches others as well. 

You can @ me on Twitter ([@tapasadhikary](https://twitter.com/home)) with comments, or feel free to follow.