Getting started with the SpeedCurve RUM JavaScript API (lux.js)

If you're new to RUM, make sure to check out our RUM getting started guide. To get even more out of RUM, read our API below, which explains how to:

  • adjust your sample rate

  • add customer data (such as cart size and conversion rate)

  • add page labels, so you can compare synthetic and RUM data

  • monitor SPAs

  • add custom timers

Note: "LUX" refers to the SpeedCurve RUM JavaScript library lux.js.


RUM works just by loading the lux.js script. Nothing else is needed. But there is an API that provides additional features as described here. All of the API is accessed through the LUX global variable.

LUX Properties

You can set these properties to alter the default behavior of RUM. Since lux.js is loaded asynchronously, use the following pattern to make sure LUX is defined before setting a property:

LUX = window.LUX || {};

(boolean) default: true

If set to false, the beacon is not sent at the window load event. The reason for setting this to false is if your page is a template and the actual content is loaded after the window load event, or something else happens after the onload that you want included in the beacon. If you set to false, then you need to call LUX.send() in order for the beacon to be sent.


LUX = window.LUX || {}; = false;


(string) default: document.title

This is the “page label” used to group RUM data by page type. The default value is the current page title (taken from document.title). It’s a best practice to set pages to the same label used in your SpeedCurve synthetic Settings for the same page type. Maximum length is 255 characters.


LUX = window.LUX || {};
LUX.label = "home";


(boolean) default: true (or false when = false)

SpeedCurve RUM listens for the pagehide and visibilitychange events and automatically sends the beacon when the page is hidden, which is considered to be the last reliable time to save data. This increases the likelihood that RUM data is captured for all users.

This behaviour is enabled by default, unless = false. See the Single-page applications (SPA) documentation for more information.


(boolean) default: true

SpeedCurve RUM captures JavaScript errors by default. This can be disabled by setting LUX.trackErrors = false.

LUX = window.LUX || {};
LUX.trackErrors = false;


(number) default: 5

Control the maximum number of errors reported for a single page load.

LUX = window.LUX || {};
LUX.maxErrors = 1;


(number) default: 0

Force SpeedCurve RUM to capture data for a minimum amount of time before sending the beacon. Specified in milliseconds.

Note: LUX.sendBeaconOnPageHidden takes priority over this setting, so pages that are abandoned before the minimum measure time will still be recorded. Conversely, calling LUX.send() before the minimum measure time has elapsed will force the beacon to be sent early.

LUX = window.LUX || {};
LUX.minMeasureTime = 5000; // Capture data for at least 5 seconds


(number) default: 60,000

Force the beacon to be sent after measuring data for a maximum amount of time. Specified in milliseconds.

Note: This is the maximum measure time. Other mechanisms that would cause a beacon to be sent e.g. the onload event or calling LUX.send() can send the beacon before this timeout is reached.

LUX = window.LUX || {};
LUX.maxMeasureTime = 30_000; // Automatically send the beacon after 30 seconds


This is the sample rate for determining whether the beacon is sent. You can set it to an integer from 0 to 100 inclusive as the percentage of metrics to accept. This is useful for collecting data while staying under your RUM budget of page views per month. The percentage is based on the session ID, therefore, entire sessions are accepted or rejected in whole.

A simpler way to control your sample rate is to specify it under Settings -> RUM. But you can use LUX.samplerate to have more fine-grained control (such as setting different sample rates for different countries, pages, devices, etc.).


LUX = window.LUX || {};
LUX.samplerate = 10; // Collect data for 10% of user sessions

LUX.debug (deprecated)

(boolean) default: false

This flag is deprecated since v300. Please use LUX.getDebug() to retrieve debug messages.

If set to true, debug messages are written to the browser console. Debug messages indicate things like:

  • when lux.js is loaded

  • whether the current session is sampled

  • if the Long Task API and Paint Timing API are supported

  • the user timing and customer data values that are set


LUX = window.LUX || {}; 
LUX.debug = true;

LUX Functions

LUX.addData(name, value)

This function is used to add your own custom data to the beacon. This "customer data" can be used in the SpeedCurve UI to segment the RUM performance data. This is useful for doing A/B testing. You can also store business metrics (e.g., cart size or conversions) and plot those along with performance metrics to see correlations. The maximum allowable size of all name value pairs concatenated is 255 characters. See Customer Data for more information.


LUX.addData('cartsize', 128);
LUX.addData('experiment A', 'control');


This function is incredibly handy if you have set a RUM sample rate and are trying to debug RUM on your site. Imagine that your sample rate is 1% and you're loading one of your pages in the browser to see whether RUM data is generated. 99% of the time no RUM data is generated, but you won't know if that's because RUM isn't working or you're not being sampled.

In RUM, sampling is based on your session cookie. So the only way to make sure you get sampled is to change your cookie. Calling LUX.forceSample() changes your session cookie so that on all subsequent page views you will be sampled and should see RUM data being generated. Note that session cookies expire after 24 hours or 30 minutes of inactivity, so you might have to call LUX.forceSample() again.


Sampling has been turned on for this session.


Returns debug data for the current session. The debug data is returned in an encoded format, so you will need to use the RUM Debug Parser to interpret the data. Hint: run copy(LUX.getDebug()) in your browser console to copy the results directly to your clipboard.

If you're experiencing problems getting RUM working on your site, we recommend using LUX.getDebug() in the browser console as a first step to get more insight into what is, and is not, happening. Also see LUX.forceSample().


(23) ["lux.js evaluation start.", ...


RUM works automatically for normal ("Web 1.0") pages. But if your site is a Single Page App (SPA) then you need to add code to initialize RUM at the beginning of each SPA "page view" and send the beacon at the end. Call this function at the beginning of the SPA page transition.


// start SPA page transition


or LUX.mark(markName, markOptions)

This function is identical to performance.mark from the User Timing spec for marking a specific time milestone in the page. It's provided as a shim for browsers that don't support the User Timing spec, most notably Safari. Maximum length for markName is 128 characters.


LUX.mark("customStarTime", { startTime: 200 });

LUX.measure(name, startMark, endMark)

or LUX.measure(measureName, measureOptions)

This function is identical to performance.measure from the User Timing spec for measuring the delta between two time milestones in the page. It's provided as a shim for browsers that don't support the User Timing spec, most notably Safari. Maximum length for name is 128 characters.


LUX.measure("jsonLoadTime", "beforeJson");
LUX.measure("jsonLoadTime", "beforeJson", "afterJson");
LUX.measure("customDuration", { start: "beforeJson", duration: 450 });


Manually send the data that has been collected for the current page view. This function is normally used along with LUX.init() to measure single page applications (SPAs). It can also be used in normal pages to halt data collection and send the page data before the onload event.

If LUX.markLoadTime() has not already been called, the load time will be recorded as the time that LUX.send() was called.


// end of SPA page transition


Record when a single page application (SPA) page has finished loading. This will be used as the "Load Time" metric in SpeedCurve dashboards.

If possible this function should be called after all data has loaded and the page has been fully rendered, however in some circumstances it may be sufficient to call it during the "mounted" lifecycle callback of various frameworks (componentDidMount in React, mounted in Vue v2, etc).

fetch("/page-data").then((response) => {
  response.json().then((pageData) => {

LUX HTML Attributes


When the first interaction with the page is a click or key press, SpeedCurve RUM attempts to identify the element that was interacted with. The data-sctrack attribute can be used to override the normal element identification. If an element or any of its ancestors has the data-sctrack attribute, SpeedCurve RUM will use the value of this attribute as the interaction name.

If no data-sctrack attribute is found on the interaction element or any of its ancestors, SpeedCurve RUM will attempt to use the following identification methods on the element and then on the element's ancestors:

  • The id attribute of the element.
  • The value attribute of the element (only for <input type="submit"> elements).
  • The innerText value of the element (only for <a> and <button> elements).

In the example markup below, the following interaction names would be chosen:

  • For the Home link, the interaction name would be index (from the data-sctrack attribute).
  • For the Shop and Search links, the interaction name would be navbar (from the ancestor's data-sctrack attribute).
  • For the Go Back button, the interaction name would be back (from the id attribute).
  • For the Go Forward button, the interaction name would be Go Forward (from the button text).
  <a href="/" id="home" data-sctrack="index">Home</a>
  <ul data-sctrack="navbar">
    <li> <a href="/shop" id="shop">Shop</a>
    <li> <a href="/search">Search</a>
  <button id="back">Go Back</button>
  <button>Go Forward</button>

Did this page help you?