# RUM Script Installation



The VitalSentinel RUM (Real User Monitoring) script collects Core Web Vitals and performance metrics from your actual visitors. It's lightweight (\~13KB gzipped) and non-blocking.

## Basic Installation [#basic-installation]

Add this script to the `<head>` section of your HTML:

```html
<script
  src="https://rum.vitalsentinel.com/rum.js"
  data-key="YOUR_TRACKING_ID"
  async
></script>
```

<Callout type="info">
  Find your tracking ID in **Domain Settings** → &#x2A;*Real User Monitoring (RUM)**.
</Callout>

## Configuration Options [#configuration-options]

Customize the script behavior using `data-*` attributes:

| Attribute                  | Type    | Default  | Description                                                                                                    |
| -------------------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------- |
| `data-key`                 | string  | required | Your unique tracking ID                                                                                        |
| `data-sample-rate`         | number  | 1.0      | Sampling rate (0.0-1.0)                                                                                        |
| `data-debug`               | boolean | false    | Enable console logging                                                                                         |
| `data-engagement`          | boolean | true     | Track clicks, scroll depth, time on page, and form interactions                                                |
| `data-consent`             | string  | none     | Consent basis you declare for the page. Set to `granted` once your consent banner has the visitor's acceptance |
| `data-mask-text`           | boolean | false    | Suppress the visible text of the elements recorded for Core Web Vitals attribution                             |
| `data-mask-selectors`      | boolean | false    | Suppress the CSS selectors recorded for LCP, CLS, and INP attribution and for engagement events                |
| `data-filter-query-params` | boolean | false    | Remove query parameters                                                                                        |

### Example with Options [#example-with-options]

```html
<script
  src="https://rum.vitalsentinel.com/rum.js"
  data-key="abc123"
  data-sample-rate="0.5"
  data-debug="true"
  data-engagement="true"
  async
></script>
```

## What Data is Collected [#what-data-is-collected]

### Core Web Vitals [#core-web-vitals]

The script automatically tracks all Core Web Vitals:

* **LCP (Largest Contentful Paint)** - Loading performance
* **FCP (First Contentful Paint)** - Initial render time
* **CLS (Cumulative Layout Shift)** - Visual stability
* **INP (Interaction to Next Paint)** - Interactivity
* **TTFB (Time to First Byte)** - Server response time

### Navigation Timing [#navigation-timing]

* DNS lookup time
* TCP connection time
* Request/response time
* DOM load time
* Full page load time

### User Engagement [#user-engagement]

When enabled (default), tracks:

* Scroll depth milestones (25%, 50%, 75%, 90%, 100%)
* Time on page and active time
* Page visibility changes
* Click tracking and rage click detection
* Form engagement (focus, changes, submissions, abandonment)

### Error Tracking [#error-tracking]

* JavaScript errors with stack traces
* Unhandled promise rejections
* Resource loading failures (images, scripts, stylesheets)

### Device Information [#device-information]

Collected in every mode:

* Window size, rounded to the nearest 50 pixels
* Country, browser, operating system, and device type, worked out on our servers from the request headers the browser sends on its own

Collected only when you declare consent (see [Consent Mode](#consent-mode)):

* Screen size and device pixel ratio
* Device memory and CPU cores
* Effective network connection type (slow-2g, 2g, 3g, or 4g) and downlink estimate
* Touch capability

## Platform-Specific Installation [#platform-specific-installation]

### WordPress [#wordpress]

Use a header scripts plugin, or add to your theme's `functions.php`:

```php
function vitalsentinel_rum_script() {
    ?>
    <script src="https://rum.vitalsentinel.com/rum.js" data-key="YOUR_TRACKING_ID" async></script>
    <?php
}
add_action('wp_head', 'vitalsentinel_rum_script');
```

See [Platform Guides](/installation/platforms) for the `wp_enqueue_script` alternative.

### Shopify [#shopify]

1. Go to **Online Store** → **Themes**
2. Click &#x2A;*...** → **Edit code** on your active theme
3. Open `theme.liquid` in the Layout folder
4. Add the script before `</head>`

### Next.js [#nextjs]

Using the Script component in your root layout (`app/layout.tsx`):

```jsx
import Script from 'next/script';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <Script
          src="https://rum.vitalsentinel.com/rum.js"
          data-key="YOUR_TRACKING_ID"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}
```

### React (Create React App) [#react-create-react-app]

Add to `public/index.html`:

```html
<script
  src="https://rum.vitalsentinel.com/rum.js"
  data-key="YOUR_TRACKING_ID"
  async
></script>
```

### Vue.js [#vuejs]

Add to `public/index.html` or your main template.

### Nuxt.js [#nuxtjs]

In `nuxt.config.js`:

```js
export default {
  head: {
    script: [
      {
        src: 'https://rum.vitalsentinel.com/rum.js',
        'data-key': 'YOUR_TRACKING_ID',
        async: true
      }
    ]
  }
}
```

## SPA Support [#spa-support]

The RUM script automatically detects Single Page Application navigation using the History API. For manual control:

```javascript
// Trigger navigation tracking manually
window.VitalSentinelRUM.startSoftNavigation();
```

This is useful for:

* Custom routing implementations
* Hash-based navigation
* Complex state transitions

## API Methods [#api-methods]

The script exposes methods for custom tracking via `window.VitalSentinelRUM` (or the shorter alias `window.VSRUM`):

### Track Custom Events [#track-custom-events]

```javascript
window.VitalSentinelRUM.trackCustomEvent('purchase', {
  productId: '12345',
  value: 99.99,
  currency: 'USD'
});
```

### Mark Points in Time [#mark-points-in-time]

```javascript
// Mark points in time
window.VitalSentinelRUM.mark('hero-start');
window.VitalSentinelRUM.mark('hero-loaded');

// Measure time between two marks
window.VitalSentinelRUM.measure('hero-time', { start: 'hero-start', end: 'hero-loaded' });
```

### Add Custom Data [#add-custom-data]

```javascript
// Add data to all subsequent events
window.VitalSentinelRUM.addData('userId', 'user-123');
window.VitalSentinelRUM.addData('plan', 'premium');
```

### Event Hooks [#event-hooks]

```javascript
// Listen to RUM events
window.VitalSentinelRUM.on('mark', (eventType, data) => {
  console.log('Mark created:', data.name, data.startTime);
});

window.VitalSentinelRUM.on('measure', (eventType, data) => {
  console.log('Measure recorded:', data.name, data.duration);
});

window.VitalSentinelRUM.on('soft_navigation', (eventType, data) => {
  console.log('SPA navigation:', data);
});
```

### Grant or Withdraw Consent [#grant-or-withdraw-consent]

`grantConsent('persistent')` and `revokeConsent()` change the consent mode at runtime from your consent banner. Both are queued, so they are safe to call before the script has finished loading. See [Consent Mode](#consent-mode).

### Force Send Data [#force-send-data]

```javascript
// Send all queued events immediately
window.VitalSentinelRUM.forceFlush();
```

### Get Debug Info [#get-debug-info]

```javascript
// Logs the current tracking state (session, sampling, queued events) for debugging
const debug = window.VitalSentinelRUM.getDebug();
console.log(debug);
```

## Command Queue [#command-queue]

The script installs its own command queue as soon as it loads. Once the tag is on the page, queue commands with `cmd()`:

```javascript
// Queue commands with cmd()
window.VitalSentinelRUM.cmd(['mark', 'app-start']);

// trackCustomEvent isn't queueable - call it directly
window.VitalSentinelRUM.trackCustomEvent('page_intent', { category: 'pricing' });
```

## Privacy & Consent [#privacy--consent]

### Privacy by Default [#privacy-by-default]

The RUM script is designed with privacy in mind:

* No cookies, no local storage, and no session storage: the script writes nothing to your visitor's device
* No cross-site tracking
* Session IDs are random and regenerate on every page load
* URL sanitization available via `data-filter-query-params`
* Record identifiers are stripped from page paths before a URL is stored. A long number, a UUID, a hex string, or a long opaque token becomes `:id` or `:uuid`, so `/orders/44172/invoice` is stored as `/orders/:id/invoice`. The path shape survives, so those page views still group as one page. Dates, short segments, and word slugs are left alone.

### Consent Mode [#consent-mode]

The script writes nothing to your visitor's device in any mode. What the consent mode changes is what it is allowed to read from the browser.

**No consent** is the default. In this mode the script reads no device details beyond the window size, rounded to the nearest 50 pixels. It also checks a flag that identifies headless automation and the Do Not Track and Global Privacy Control settings, which it reads in order to honor them. Core Web Vitals, JavaScript errors, and user engagement are all still collected.

**Consent given** adds screen size, device pixel ratio, device memory, CPU cores, touch capability, and connection speed, so you can tell a slow page apart from a slow device or a weak network.

Declare the consented mode on the script tag:

```html
<script
  src="https://rum.vitalsentinel.com/rum.js"
  data-key="YOUR_TRACKING_ID"
  data-consent="granted"
  async
></script>
```

Or set it at runtime from your consent banner, which needs no page reload:

```javascript
// Visitor accepted
window.VitalSentinelRUM.grantConsent('persistent');

// Visitor rejected, or withdrew a previous acceptance
window.VitalSentinelRUM.revokeConsent();
```

Withdrawal is prospective: events already queued are sent with the context they were collected under, and nothing has to be deleted from the device because the script never wrote anything to it.

<Callout type="warn">
  Only declare consent once your banner has the visitor's acceptance. You can switch the mode in **Domain Settings** → &#x2A;*Real User Monitoring (RUM)** → **Consent mode**, which regenerates the snippet for you.
</Callout>

### Privacy Options [#privacy-options]

Enable additional privacy features:

```html
<script
  src="https://rum.vitalsentinel.com/rum.js"
  data-key="YOUR_TRACKING_ID"
  data-mask-text="true"
  data-mask-selectors="true"
  data-filter-query-params="true"
  async
></script>
```

* `data-mask-text` - Suppresses the visible text recorded for the LCP, CLS, and INP attribution elements. Engagement events carry no element text, so this attribute does not change them
* `data-mask-selectors` - Suppresses the CSS selectors recorded for LCP, CLS, and INP attribution and for engagement events. Use it if your element IDs or class names carry record identifiers, such as `#order-88213`
* `data-filter-query-params` - Removes query parameters from tracked URLs

### Do Not Track and Global Privacy Control [#do-not-track-and-global-privacy-control]

The script honors a Do Not Track or Global Privacy Control signal from the browser on its own, so you do not need to gate the tag on it:

* No device details beyond the window size are read, whatever consent mode you declared
* User engagement tracking does not run
* A `grantConsent()` call is ignored, so your consent banner cannot raise the mode for these visitors
* Core Web Vitals and page views are still measured, so the traffic does not disappear from your reports

### GDPR Compliance [#gdpr-compliance]

The RUM script is designed to be GDPR-friendly by default (no cookies, no local storage, no session storage). For additional compliance:

1. **Choose a consent mode** that matches what your banner has obtained (see [Consent Mode](#consent-mode))
2. **Use sampling** (`data-sample-rate`) to reduce data collection
3. **Enable privacy options** (`data-mask-text`, `data-mask-selectors`, `data-filter-query-params`)

### Domain-Level Controls [#domain-level-controls]

One privacy control lives in the dashboard rather than the script tag. In **Domain Settings** → **Web Analytics** → **Advanced settings**, ticking **Do not store page titles or site-search terms** also applies to your RUM data: page titles are no longer stored, and site-search terms are stripped from the URLs recorded for RUM. It is applied when we receive the data, so there is no snippet change and no redeploy, and it reaches all traffic within about a minute.

## Troubleshooting [#troubleshooting]

### Script Not Loading [#script-not-loading]

1. Check browser console for errors
2. Verify the tracking ID is correct
3. Ensure no ad blocker is blocking the script
4. Check Content Security Policy headers

### No Data Appearing [#no-data-appearing]

1. Wait 15-30 minutes for initial data
2. Check sample rate is greater than 0
3. Verify the domain matches your configured domain
4. Enable debug mode to see console logs

### Debug Mode [#debug-mode]

Enable debug logging:

```html
<script
  src="https://rum.vitalsentinel.com/rum.js"
  data-key="YOUR_TRACKING_ID"
  data-debug="true"
  async
></script>
```

Then check your browser console for `[VitalSentinel RUM]` messages.

## Browser Compatibility [#browser-compatibility]

The RUM script supports:

* Chrome/Edge 90+
* Firefox 89+
* Safari 15+
* Opera 76+

Older browsers will gracefully degrade without causing errors.

## Related [#related]

<Cards>
  <Card title="RUM Monitoring" href="/features/rum-monitoring">
    Learn about the metrics and insights available from RUM data
  </Card>

  <Card title="Performance Thresholds" href="/others/performance-thresholds">
    Understand what good, needs improvement, and poor metrics look like
  </Card>

  <Card title="Data & Privacy" href="/others/data-privacy">
    Details on data collection, storage, and GDPR compliance
  </Card>

  <Card title="Troubleshooting" href="/help/troubleshooting">
    Solutions to common installation and tracking issues
  </Card>
</Cards>
