Scripts

SpeedCurve LUX

SpeedCurve LUX is a Real User Monitoring (RUM) tool that measures the performance your users experience. It tracks Core Web Vitals, custom timing marks, and JavaScript errors.

SpeedCurve LUX

View source

Nuxt Config Setup

Add this to your nuxt.config.ts to load SpeedCurve LUX globally. Alternatively you can use the useScriptSpeedCurve composable for more control.

export default defineNuxtConfig({
  scripts: {
    registry: {
      speedcurve: {
        trigger: 'onNuxtReady',
      }
    }
  }
})

useScriptSpeedCurve()

The useScriptSpeedCurve composable lets you have fine-grain control over when and how SpeedCurve LUX is loaded on your site.

const { proxy } = useScriptSpeedCurve()

Please follow the Registry Scripts guide to learn more about advanced usage.

Example

Using SpeedCurve LUX in a component.

<script setup lang="ts">
const { proxy } = useScriptSpeedCurve()

// noop in development, ssr
// just works in production, client
function handleAction() {
  // use proxy methods here
}
</script>

<template>
  <div>
    <button @click="handleAction">
      Send Event
    </button>
  </div>
</template>

The composable comes with the following defaults:

  • Trigger: Client The LUX primer is injected into <head> immediately; lux.js loads when Nuxt hydrates.

Setup

SpeedCurve LUX is opt-in. Register it in scripts.registry.speedcurve to resolve and inline the LUX primer at build time. Install the @speedcurve/lux peer dep alongside:

pnpm add -D @speedcurve/lux
nuxt.config.ts: composable-only (no global load)
export default defineNuxtConfig({
  modules: ['@nuxt/scripts'],
  scripts: {
    registry: {
      // Minimum registration — enables the composable per-page.
      // Pass `id` here and you can omit it from each useScriptSpeedCurve() call.
      speedcurve: {},
    },
  },
})
nuxt.config.ts: auto-load globally
export default defineNuxtConfig({
  modules: ['@nuxt/scripts'],
  scripts: {
    registry: {
      speedcurve: { id: 'YOUR_SPEEDCURVE_ID', trigger: 'onNuxtReady' },
    },
  },
})

If speedcurve isn't registered, useScriptSpeedCurve builds with an empty primer fallback. If it's registered but @speedcurve/lux is missing, the build fails with an install hint. Pinning your own @speedcurve/lux version means you control when the primer snippet updates.

You can access the LUX object as a proxy directly, or await $script to get the loaded instance.

const { proxy } = useScriptSpeedCurve({ id: 'YOUR_ID' })
proxy.LUX.label = 'my-page'

SPA navigation

Set spaMode: true to enable SpeedCurve's SPA tracking mode. The composable wires Vue Router automatically:

  • router.beforeEach calls LUX.startSoftNavigation() (closes the previous beacon, starts a new one)
  • nuxt.hook('page:finish') calls LUX.markLoadTime() after the next paint (sets the END mark)
  • Cancelled navigations seal the phantom beacon with addData('luxNavFailed', '1') for easy filtering
app.vue
useScriptSpeedCurve({
  id: 'YOUR_ID',
  spaMode: true,
  autoTrackSpaNavigations: true, // default when spaMode is true
})

To disable auto-wiring and instrument manually:

useScriptSpeedCurve({
  id: 'YOUR_ID',
  spaMode: true,
  autoTrackSpaNavigations: false,
})
// Then call LUX.startSoftNavigation() and LUX.markLoadTime() yourself

Custom page labels

By default the composable uses String(to.name ?? to.path) as the page label for each navigation. Pass a function to label to override it:

useScriptSpeedCurve({
  id: 'YOUR_ID',
  spaMode: true,
  label: to => to.meta.title as string ?? to.path,
})

Set label: false to disable labeling entirely. Pass a plain string to set a static label (only meaningful without spaMode, since the router hook overwrites it on every navigation).

CSP

Add these directives to your Content Security Policy:

script-src  cdn.speedcurve.com;
img-src     lux.speedcurve.com;
connect-src lux.speedcurve.com beacon.speedcurve.com;

Reference: https://support.speedcurve.com/docs/add-rum-to-your-csp

idstring required

Your SpeedCurve customer ID.

spaModeboolean

Enable SPA (single-page application) mode. When true, lux.js tracks soft navigations instead of full page loads.

autoTrackSpaNavigationsboolean = true (when spaMode is true)

Automatically wire Vue Router hooks for SPA tracking when spaMode is true. Set to false to instrument navigations manually.

labelstring | Function | false = String(to.name ?? to.path)

Page label shown in the SpeedCurve dashboard. Accepts a static string, a function `(to) => string | false` for per-navigation labels, or `false` to disable labeling entirely. A callback returning `false` skips updating the label for that navigation.

sampleratenumber

Sampling rate (0–100). Percentage of sessions that send beacons. Upstream spelling is lowercase — matches LUX UserConfig.

sendBeaconOnPageHiddenboolean = true

Send the beacon when the page is hidden (pagehide event).

trackErrorsboolean = true

Track JavaScript errors.

maxErrorsnumber = 5

Maximum number of errors to track per page view.

minMeasureTimenumber

Minimum time (ms) before a beacon can be sent.

maxMeasureTimenumber = 60000

Maximum time (ms) after which the beacon is sent regardless of load state.

newBeaconOnPageShowboolean

Start a new beacon when the page becomes visible after being hidden.

trackHiddenPagesboolean = false

Track pages loaded in background tabs.

cookieDomainstring

Cookie domain for cross-subdomain session tracking.

Example

Loading SpeedCurve LUX through app.vue with SPA tracking enabled.

app.vue
<script setup lang="ts">
useScriptSpeedCurve({
  id: 'YOUR_SPEEDCURVE_ID',
  spaMode: true,
})
</script>