User guide

Getting started with CatchJS

Adding CatchJS error tracking to your site is simple.

  1. Sign up

    The first step is to sign up to a plan. Choose the plan that fits your expected usage pattern. You can change this at any time.

  2. Connect your account with a domain

    Once you have an account and you are logged in, go to the connected site section of your account settings page. Click your name in the top right, and then on "Account settings".

    Show image

    Enter the domain you want to associate with your account. For more information, see the section on associating a domain with your account.

  3. Link the CatchJS script file

    Add the following HTML to your site to start logging errors.

    <script src="https://cdn.catchjs.com/catch.js"></script>

That's it. The CatchJS script will automatically set up continuous JavaScript error monitoring on the pages where it is loaded. Once errors occur in your users' browsers, they will show up in your errors tab.

Disabling screenshots and click trails

You can customize the error reporting to meet your needs. If you want to disable the screenshots feature, or not collect click trails, you can use the configuration builder below to generate an appropriate configuration.

Configuration happens via the configuration object catchjs_config. Defining this object is optional, but if you want to use a custom configuration, you must define the configuration object prior to loading the catch.js script, in order for the catch.js script to be able to use it. The configuration object can be altered at runtime as long as the object is defined prior to loading the script, giving you fine grained control over what is collected and when.

Example syntax:

window.catchjs_config = {
    "screenshots": false,
    "clicks": false
};

catchjs_config.screenshots: If the property is defined and has the value of false, collection of screenshots will be disabled. Default value: true.

catchjs_config.clicks: If the property is defined and has the value of false, collection of clicks will be disabled. Clicks are sent along with screenshots, so setting this property to true while screenshots === false will still not result in the collection of click trails, since the collection of screenshots are needed for clicks to be collected and displayed. Default value: true.

You can use the configuration generator below to build your configuration object.

Configuration generator

<script src="https://cdn.catchjs.com/catch.js"></script>

The above snippet can be added to your site's HTML to load the error tracking script, while using the configuration you've chosen.

Associating a domain with your account

When creating your account, you are asked to enter a domain from which you want to log errors and other data. Accounts on the Developer and Production plans can associate one domain with their account, while accounts on the Enterprise plan can associate 25 domains to their account. You can change the domain associated with your account at any time.

Once a domain has been associated with your account, it will accept logged data from that domain and any of its subdomains.

For example, if you associate your account with example.com, you can log errors from example.com, www.example.com, staging.beta.example.com and so on.

If you associate your account with www.example.com, you can log from that domain, but not from example.com. For this reason, be mindful when adding the "www" prefix before the domain you associate your account with, as this will require "www" prefix to be present for the logged data to be accepted.

You should not add a protocol scheme, such as "http://" or "https://" to the associated domain.

When the CatchJS script sends data, either because an uncaught exception happened or via the catchjs.log() function, it passes along the value of window.location.hostname which holds the domain of the current document, including any subdomains. This value must be the same as or be a sub-domain of the domain associated with your account for the data to be logged.

Associating domains that are on the public suffix list is disallowed. This list contains domains where sub-domains can be registered by the public. An example of such a domain is github.io, where users can create pages on <username>.github.io. Because github.io is on the public suffix list, you can't associate your account to the entirety of github.io, but you are free to associate your CatchJS account with any specific subdomain of it, such as <username>.github.io.

Quotas

Each account type has an associated quota of tracked JavaScript errors and generic catchjs.log() calls that can be logged per month. If the quota is reached, CatchJS will simply ignore any further logged data, without charging you for the extra use. Logged errors and generic log calls are counted separately, so you can fill up one quota and continue using the other. There is a maximum number of screenshots that will be taken per unique error type, which helps ensure that the screenshot quota is used on errors for which screenshots have not been collected.

Screenshot quotas are reset every day. Logging quotas are reset at the start of each month.

Development Production Enterprise
Errors per month 1 000 100 000 1 000 000
catchjs.log() calls per month 1 000 100 000 1 000 000
Screenshots per day 0 100 100
Screenshots requested per unique error type 0 10 10
Number of associated domains 1 1 25
Data retention 3 months 3 months 3 months

How error logging works

When the CatchJS script is loaded, it attaches a handler to the window object's error event (window.onerror). This event is triggered whenever an unhandled JavaScript error happens on the page, which includes syntax errors and unhandled exceptions.

When an unhandled error happens on the page, the CatchJS script will send the error information along with metadata such as the user agent string and screen resolution to the CatchJS server. The CatchJS server will then respond with an indication of whether or not it wants a screenshot to be taken.

Whether or not the CatchJS server asks for a screenshot depends on how many screenshots have already been collected for errors of this type. It will not ask for screenshots if the per error screenshot limit for this error has been reached (see quotas). Whether or not an error is considered to be already seen depends on the error identity determined by the server, which is explained more in depth in the section on error grouping.

Error grouping

A site may produce a log of hundreds of thousands to millions of logged errors. An unstructured list of all these errors does not give a good insight into which specific problems are causing the individual errors. For this reason, CatchJS automatically groups errors.

The error grouping mechanism determines error identity by combining the error type, the error message, and the location in the source code where the error was produced, if available.

Screenshots

When an error happens for which sufficient screenshots have not yet been collected, and the account is on a plan that includes screenshot functionality, the CatchJS server responds with a request for a screenshot (see the sections on quotas and the error logging protocol.

When a screenshot is requested by the server, the client side CatchJS script will load a JavaScript file containing the rendering machinery necessary to render a screen shot of the document. Once the screenshot is rendered, it will be sent to the CatchJS server along with a list of the location of clicks that have happened on the page. The click trail can be seen overlaid on the screenshot in the web app.

Because there is a delay between the error occurring and the rendering of the screenshot, the screenshot will reflect the state of the document at some point after the error. This delay means there may be a mismatch between the screenshot and what the document looked like when the error happened, depending on the application and the interactions performed by the user.

The screenshot rendering is based on the excellent html2canvas project. Since current browser APIs do not provide a built-in mechanism to take screenshots, this code takes the current document tree and renders it to an HTML canvas object. Due to the complexity of a modern web browser's rendering engine, it is infeasible to reimplement this logic with complete fidelity in JavaScript, for many reasons. However, since this JavaScript code can piggyback on the positioning and sizing of elements that the browser has already determined, it is in many cases possible to make renderings of the document that are exact matches, or close to it, to the pixels seen by the user.

There are circumstances where this mechanism fails to capture a screenshot. One scenario is if the error happens right before a user navigates away from a page. In this case, the error is submitted to the CatchJS server, but by the time the response requesting a screenshot is produced, the user has navigated away from the page, thus no screenshot can be produced. The screenshot rendering machinery may fail to produce screenshots due to unhandled combinations of document state and browser version. The CatchJS server limits the number of times it requests screenshots for a particular error instance, which will avoid repeatedly attempting to render screenshots where this has failed in the past.

Images may show up as blank rectangles in the rendered screenshots. This happens if the images reside in a different origin to that of the web page, due to the Same Origin Policy. Similarly, if a canvas object is tainted with content from a different origin, it will not show up in screenshots.

Screenshots capture the contents of the page, so you should consider what the privacy implications are of taking screenshots in your app. CatchJS does not track users or personally identifiable information in general. Whether screenshots can contain such information depends on the application. For this reason, CatchJS gives you fine grained control over when screenshots are taken. By setting the window.catchjs_config.screenshots property to false before loading the CatchJS script, you can turn off screenshots altogether. You can also alter this property at runtime, allowing for fine-grained control over when screenshots can be taken. See the section on configuration for more information.

Generic logging via catchjs.log()

In your code, you can use the catchjs.log() function to log any data you'd like. It works like the console.log() function, except the logged data will show up in your CatchJS log.

The function takes a variable number of arguments, serializes them, and sends them to the CatchJS server. These logged objects will then be immediately available and inspectable in your log, along with the associated timestamp and user-agent as well as the page they were logged from. The CatchJS script will intercept calls to console.error() and pass them through catchjs.log() as well.

The logged objects can be of any JavaScript type, and will be serialized to JSON before being sent to the server. The objects will first be decycled, meaning cyclic references will be detached before serialization and reattached server side before being displayed. Very large objects will be truncated via an adaptive truncation algorithm, that truncates the representation of properties in order to keep the object within a manageable size. In other words, you can use catchjs.log() without worrying about the various pitfalls of serialization and logged data size, it will just work.

In your code, you can make a call like this:

catchjs.log("Unexpected parameter: ", obj);

Which would result in a log entry like this:

What makes CatchJS fast?

Web site owners are rightly concerned with the speed of their site, as speed is an important determinant of a good user experience. Creating a fast web site often amounts to reducing the amount of stuff that is on a page, so adding anything new should rightly be evaluated for its performance implications.

The CatchJS error tracking script particularly shines when it comes to front-end performance. It achieves this by having an extremely small file size, zero runtime overhead, and being served by fast globally distributed content distribution network.

Slow page load speeds are detrimental to the user experience. For example, a study by Amazon found that every 100ms of latency cost them 1% in sales. Google found that an extra 0.5 seconds in search page generation time dropped revenue by 20%. Page load speed really matters and adding an error logging service shouldn't slow down your site.

A lot of work has been put into making the CatchJS script small and light: Over the years, as features have been added to the script, its file size has shrunk.

To cut load latency the file is served over HTTP2 on a globally distributed CDN, that has over 100 servers spread across the globe. This means your users will get the file from a server that is close to them geographically, thus cutting down latency. To cut down latency further you might consider adding an async attribute on the script tag that loads the catch.js script. This will load the script asynchronously, which has the effect that errors happening while the catch.js script is being loaded will not be logged. This may be a fine trade-off for many sites: On catchjs.com, the error tracking script is loaded asynchronously for the root landing page of the domain.

Privacy protection

CatchJS tracks JavaScript errors, not users. When errors are logged, the service does not store the IP from which the error was logged, nor is there any other attempt at tracking user identity.

Regulators globally have taken interest in regulating the processing of personally identifiable information (PII). The European Union has introduced the General Data Protection Regulation (GDPR), the state of California has introduced the California Consumer Privacy Act (CCPA), and in general many countries have laws of similar scope and intent.

CatchJS takes a simple approach to this: The error tracking service does not track personally identifiable information.

If you sign up as a customer to the service, we'll need your email, name and address for billing purposes, but that's where it stops. We won't do any tracking of the users of your web site.

JavaScript errors in general relate to the inner workings of a program, not to any personal identity. Since you can write code to log any data via the catchjs.log() function, it is up to you to comply with relevant laws relating to the data you log using the service. Since screenshots capture the contents of the screen, you should consider the privacy implications of enabling this feature. For many apps, there is never any personal information on screen, while for others it may be appropriate to disable screenshots for some or all parts of the app. You have fine grained control of when this feature is enabled at runtime, see the sections on configuration and screenshots. Should you end up logging any sensitive data by mistake, you can contact us and we will assist in deleting the relevant data.