You can find your LUX ID on the "Admin > Teams" page.

You need to have "Admin" access to be able to view the LUX ID. If it's not visible please ask your other team members for the LUX ID or admin access.

LUX Snippet

You can insert the lux.js script into your website using one of the two snippets shown below. This script is loaded asynchronously so it won't harm the performance of your site. Insert the lux.js script into your pages like this:

LUX = window.LUX || {};
LUX.samplerate = SAMPLE_RATE;
<script src="" async defer></script>

In the snippet above, replace LUX_ID with the team's LUX ID found in your Settings under Admin | Teams

Set the sample rate to a value that matches the LUX plan you want to sign up for. For example, if your site typically gets 900 million page views per month, and you want one LUX plan that covers a maximum of 10 million page views per month, then set the sample rate to LUX.samplerate=1; (which is 1%).

It's best to put the LUX snippet as early in the page as possible, i.e., at the top of the HEAD element.

At SpeedCurve, we believe strongly that teams should add custom metrics to their pages with the User Timing spec. Unfortunately, some browsers don’t support the User Timing spec (most importantly mobile Safari on iOS). To gather custom metrics on all browsers you can use the LUX.mark() and LUX.measure() functions. If you’d like to do this, you must use this longer snippet:

LUX=(function(){var a=("undefined"!==typeof(LUX)&&"undefined"!==typeof(LUX.gaMarks)?LUX.gaMarks:[]);var d=("undefined"!==typeof(LUX)&&"undefined"!==typeof(LUX.gaMeasures)?LUX.gaMeasures:[]);var h="LUX_start";var j=window.performance;var k=("undefined"!==typeof(LUX)&&LUX.ns?LUX.ns:( Date())));if(j&&j.timing&&j.timing.navigationStart){k=j.timing.navigationStart}function e(){if(j){if({return}else{if(j.webkitNow){return}else{if(j.msNow){return}else{if(j.mozNow){return}}}}}var Date());return m-k}function b(m){if(j){if(j.mark){return j.mark(m)}else{if(j.webkitMark){return j.webkitMark(m)}}}a.push({name:m,entryType:"mark",startTime:e(),duration:0});return}function l(o,s,m){if("undefined"===typeof(s)&&g(h)){s=h}if(j){if(j.measure){if(s){if(m){return j.measure(o,s,m)}else{return j.measure(o,s)}}else{return j.measure(o)}}else{if(j.webkitMeasure){return j.webkitMeasure(o,s,m)}}}var q=0,n=e();if(s){var r=g(s);if(r){q=r.startTime}else{if(j&&j.timing&&j.timing[s]){q=j.timing[s]-j.timing.navigationStart}else{return}}}if(m){var p=g(m);if(p){n=p.startTime}else{if(j&&j.timing&&j.timing[m]){n=j.timing[m]-j.timing.navigationStart}else{return}}}d.push({name:o,entryType:"measure",startTime:q,duration:(n-q)});return}function g(m){return c(m,f())}function c(p,o){for(i=o.length-1;i>=0;i--){var n=o[i];if({return n}}return undefined}function f(){if(j){if(j.getEntriesByType){return j.getEntriesByType("mark")}else{if(j.webkitGetEntriesByType){return j.webkitGetEntriesByType("mark")}}}return a}return{mark:b,measure:l,gaMarks:a,gaMeasures:d}})();LUX.ns=( Date()));[];LUX.cmd=function(a){};LUX.init=function(){LUX.cmd(["init"])};LUX.send=function(){LUX.cmd(["send"])};LUX.addData=function(a,b){LUX.cmd(["addData",a,b])};
LUX.samplerate = SAMPLE_RATE;
<script src="" async defer></script>

This longer snippet defines LUX.mark() and LUX.measure(), so you can use these functions immediately even while the lux.js script is being loading asynchronously.


LUX is a JavaScript library. LUX works just by loading the lux.js script. Nothing else is needed. But there is a LUX 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 LUX. Since lux.js is loaded asynchronously, use the following pattern to make sure LUX is defined before setting a property:

LUX = window.LUX || {};

If false, the LUX beacon is not sent at the window load event. The default value is true. 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;


This is the “page label” used to group LUX data by page type. The default value is window.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';


This is the sample rate for determining whether the LUX 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 LUX budget of page views per month. The percentage is based on the session ID, therefore, entire sessions are accepted or rejected in whole.


LUX = window.LUX || {};
LUX.samplerate = 10; // 10% of metrics are accepted

LUX Functions

Since lux.js is loaded asynchronously, you need to make sure these functions are defined before using them. An easy way to do this is to add an onload handler to the lux.js SCRIPT tag, and call the LUX functions inside that handler.

Because LUX.mark and LUX.measure may need to be called before lux.js has loaded, these two functions are defined in the longer snippet. (See the LUX Snippet section.) In other words, if you use LUX.mark or LUX.measure then you should use the longer snippet.

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 LUX 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.


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


LUX 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 LUX at the beginning of each SPA "page view" and send the LUX beacon at the end. Call this function at the beginning of the SPA page transition.


// start SPA page transition


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("before JSON");

LUX.measure(name, startMark, endMark)

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("JSON request", "before JSON");


This function is used along with LUX.init for SPA sites.


// end of SPA page transition

LUX HTML Attributes


When the first interaction with the page is a click or key press, LUX tracks which DOM element was interacted with. The name that is recorded is based on searching the DOM element and its ancestors for the data-sctrack attribute. If data-sctrack is not found, then the first DOM element ID is used.

Example: If the user clicked on any of these links, then "navbar" would be tracked as the DOM element the user interacted with.

<div data-sctrack="navbar">
    <li> <a href="/" id=home>Home</a>
    <li> <a href="/shop" id=shop>Shop</a>
    <li> <a href="/search" id=search>Search</a>
Did this answer your question?