Single-page applications (SPA)

Real user monitoring (RUM) is the performance industry's way to measure real user traffic. If you're not currently a RUM customer, you can follow the simple steps in the Setup Guide.

Using RUM in a typical separate-page website is pretty easy because each page view has a well-defined start and end (navigationStart and loadEventEnd). There's a little more work involved to make RUM work in a single-page application (SPA) because the definition of a "page view" varies depending on the SPA's implementation.

APIs

There are three main APIs involved in making RUM work with your SPA:

  • LUX.init - Call this function at the beginning of the SPA page transition (but not on the initial page load). For example, if the user clicked a button that causes a SPA transition, you would call LUX.init() immediately after the button is clicked.

  • LUX.markLoadTime - Call this function at the end of the SPA page transition. For example, you would call LUX.markLoadTime() after all JSON responses have been received and the DOM has been updated. If you don't call this function, the load time will be recorded as the time when LUX.send() is called. This function is therefore optional, but recommended.

  • LUX.send - Call this function when you are ready to send the data that has been collected for the current page view.

  • LUX.auto - This variable tells RUM whether to gather the initial performance metrics as part of window.onload. The default is true and that value works in most cases for SPAs. But in some cases even the initial page view is handled by the SPA code and can occur after the onload event. If this is the case for your site, you would set LUX.auto = false and make sure to call LUX.markLoadTime() and/or LUX.send() when that initial page view is complete.

Using page labels in a SPA

In a SPA, RUM page labels can be set at any point before LUX.send() is called.

Using custom data in a SPA

Custom Datacan be added at any point in a SPA, and it will be associated with the current page view. Custom data values are persisted across all SPA page views.

Using user timing marks & measures in a SPA

For the initial page load, user timing marks and measures in a SPA work the same as they do in a regular web application. For subsequent SPA pages, measures continue to work the same but marks are taken relative to the previous LUX.init() call.

Recommended implementation for a SPA

  • Set LUX.auto = false to gain full control over how data is collected and when the beacon is sent.
  • Set LUX.sendBeaconOnPageHidden = true to reduce data loss due to page abandonment.
  • Call LUX.markLoadTime() when the current page or view has completely rendered — usually at the end of the "mounted" lifecycle callback of various frameworks (componentDidMount in React, mounted in Vue v2, etc).
  • Call LUX.send() as late in the page lifecycle as possible to maximize data collection. This can even be called directly before LUX.init().
  • Call LUX.init() as soon as the user navigates to a new page or view.
  • (Optional) set LUX.maxMeasureTime = 30000 if the default time of 60 seconds results in noisy data.

📘

Learn more:

Here's how the team at Unsplash set up RUM for their SPA.