Tracking Unhandled JavaScript Errors with Plausible.io
Tags: plausibleio, javascript
Published: 2023-01-10 13:32:30

---
title: Tracking Unhandled JavaScript Errors with Plausible.io
published: true
date: 2022-09-02 12:00:00 UTC
tags: plausibleio, javascript
canonical_url: https://jasonbutz.info/2022/09/plausible-error-tracking?utm_source=dev.to&utm_content=plausible-error-tracking
---

I recently tried out [Plausible](https://plausible.io) as an alternative to running my own [Countly](https://count.ly). With Plausible I was able to reduce the effort I needed to put in as well as my costs, the only trade-off was giving up some advanced capabilities I didn’t use. I like Plausible’s commitment to privacy, which is part of the driver behind avoiding using a SaaS service up to this point, as well as their price point. One thing I appreciated about Countly and some of the platforms I use at work is the ability to track and report on unhandled JavaScript errors. We test our code, but sometimes we miss something.

Plausible supports custom events, and so with a little effort, I was able to add the capability to capture unhandled errors.

First I needed a snippet from [Plausible’s documentation on custom event goals](https://plausible.io/docs/custom-event-goals#1-trigger-custom-events-with-javascript-on-your-site):

```
window.plausible =
  window.plausible ||
  function () {
    (window.plausible.q = window.plausible.q || []).push(arguments);
  };
```

This snippet ensures there is a function on the Window object called `plausible` that pushes the arguments it receives into an array. This is all so that the Plausible script already added to the page can pick up those values and send the event to be processed.

Next, I needed a way to capture unhandled JavaScript errors. Here I was able to take advantage of how events bubble up the DOM and attach an event listener to the window object. In the callback, I use the `plausible` function added by the previous snippet to report the custom event and the custom properties. If you want to read more about event bubbling check out the [Mozilla Developer Network (MDN) _Introduction to events_ page](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#event_bubbling_and_capture), and if you want to know where I figured out the properties to expect on the event object check out [MDN’s page on the `ErrorEvent` object](https://developer.mozilla.org/en-US/docs/Web/API/ErrorEvent).

```
window.addEventListener('error', (e) => {
  plausible('JavaScript Error', {
    props: {
      message: e.message,
      filename: e.filename,
      lineno: e.lineno,
      colno: e.colno,
      url: window.location.href,
    },
  });
});
```

If you want to additionally capture unhandled Promise rejections you’ll need another event listener that handles a different kind of event. This time you listen for an _unhandledrejection_ event and receive a [`PromiseRejectionEvent`](https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent). Due to the different type of event, we aren’t able to use all the same properties.

```
window.addEventListener('unhandledrejection', function (e) {
  plausible('JavaScript Error', {
    props: {
      message:
        'Unhandled rejection (reason: ' +
        (e.reason && e.reason.stack ? e.reason.stack : e.reason) +
        ').',
      url: window.location.href,
    },
  });
});
```

Now we have our three snippets and need to put them together to form a single script. I chose to wrap them inside a try-catch block to ensure they don’t break any pages. With a try-catch block, you do need to include either a `catch` or `finally` block. I included a `catch` block and added a “no-op” or “no operation” comment to show nothing was included purposefully. This is a short-hand I was taught back in college and have been using whenever things like this come up.

```
try {
  window.plausible =
    window.plausible ||
    function () {
      (window.plausible.q = window.plausible.q || []).push(arguments);
    };

  window.addEventListener('error', (e) => {
    plausible('JavaScript Error', {
      props: {
        message: e.message,
        filename: e.filename,
        lineno: e.lineno,
        colno: e.colno,
        url: window.location.href,
      },
    });
  });

  window.addEventListener('unhandledrejection', function (e) {
    plausible('JavaScript Error', {
      props: {
        message:
          'Unhandled rejection (reason: ' +
          (e.reason && e.reason.stack ? e.reason.stack : e.reason) +
          ').',
        url: window.location.href,
      },
    });
  });
} catch (e) {
  /* NOOP */
}
```

You can add this JavaScript inline in a `<script>` tag or include it through a JavaScript file, but that is all it takes. You do need to ensure you add the _JavaScript Error_ goal to your site in Plausible but there isn’t much to this. If you’re not using Plausible and looking for a small challenge you could build yourself a small API to collect this kind of information.

By keeping in mind the event-based nature of analytics you can easily add a variety of custom tracking functionality to many common analytics tools.