# Real User Monitoring (RUM) for Web and Mobile

> Find out why users quit or rage-click. Sentry's RUM connects every user session to the trace, error, and replay behind it so you can fix UX issues fast

**URL:** https://sentry.io/solutions/real-user-monitoring-rum/

---

Not all bugs crash. Some just make people quit, and you’re left staring at green dashboards, wondering what went wrong. Sentry’s Real User Monitoring shows what actually happens, revealing what backend metrics miss: session-level insights, slow pages, rage clicks — all directly tied to real users and the code-level issues behind the pain.

## Details

### From rage click to root cause

#### Follow the trace to the point of failure

Knowing a session broke is one thing. Knowing why, and how to fix it, is another. Sentry ties frontend behavior to backend traces and context, so you’re not guessing based on vague complaints or dashboards.

With Real User Monitoring, you get:

[Session Replay](https://sentry.io/product/session-replay/) that captures clicks, scrolls, rage-taps, and navigation, linked to stack traces and spans

Trace-level visibility into slow scripts, failed API calls, rendering issues, and more — right from the user’s browser

Impact-first prioritization, so you can focus on the sessions affecting the most users, not just the loudest alerts

Watch what the user saw. See what broke. Fix what matters.

### Monitor your Web Vitals

#### Measure what matters, then fix it fast

[Web Vitals](https://sentry.io/for/web-vitals/) impact everything from SEO to user experience and revenue. But knowing a page is slow isn’t enough, you need to know why. Sentry connects frontend metrics with backend traces and code-level profiling to show exactly what’s causing the lag.

With Web Vitals Monitoring, you get:

Key metrics like LCP, INP, CLS, FCP, and TTFB, tracked in real time and rolled into a single score

Trace waterfalls and replays that reveal which calls, assets, or user actions are behind the slowdown

Code profiling that highlights the specific function or line of code causing the issue

From metric to root cause, Sentry gives you the full picture.

### See what users experience

#### Full visibility into real user behavior

Get real-time visibility into your app’s performance, user behavior, and privacy — all in one place.

With Real User Monitoring, you’ll get:

Instant alerts for slow pages, error spikes, and downtime, with smart routing and anomaly detection to keep noise low

Full session replays that show every user click, scroll, and rage‑tap alongside stack traces and spans — no guesswork

Privacy by default, with sensitive data like passwords and credit cards stripped on the server and masking tools you can control

The result: clear context, real impact, and zero oversharing, all without switching tools.

## Cookbook recipes

- **Track and fix checkout performance in React Native with Sentry tracing**: Use Sentry tracing to instrument a React Native checkout flow with a Python backend, identify slow HTTP requests, and set up alerts and dashboards. — [Learn more](https://sentry.io/cookbook/track-checkout-performance-react-native/)

- **Debug undefined properties in React Native with Sentry Logs**: Use Sentry Logs in React Native and your backend to debug undefined properties, pinpoint timing bugs vs data issues, and verify your fix. — [Learn more](https://sentry.io/cookbook/debug-undefined-react-native/)

## Customer Story

> We’re shipping six to seven times a day across more than 100 teams, keeping up this pace with the visibility we had was nearly impossible before moving to Sentry SaaS.

[Read the full story](https://sentry.io/customers/coveo/)

- **2x** release pace without risking undetected issues in production

- **50%** decrease in debugging time

- **250** projects migrated to Sentry in <2 months

## More RUM content

- [Debug errors faster while protecting user privacy with Session Replay](https://sentry.io/resources/session-replay-privacy-workshop/): Join Butch Mayhew, Head of Quality and Reliability at payment processor Tilled, as he shows how his team uses Sentry’s Session Replay for faster debugging – while meeting stringent financial compliance standards

- [Debugging e-commerce performance issues with Session Replay](https://sentry.io/resources/debugging-ecommerce-session-replay/): See exactly what shoppers experience with Sentry Session Replay for Shopify. Capture sessions, spot issues, and fix checkout bugs faster.

- [Smarter Tools and Best Practices for Mobile Debugging: A Hands-On Workshop](https://sentry.io/resources/smarter-tools-and-best-practices-for-mobile-debugging-workshop/): You get a crash report: “App crashed on checkout page.” But you can’t reproduce it on your Pixel. Maybe it’s only happening on a Samsung device? Maybe it’s a me

- [Session Replay: Debug Faster without the Guesswork](https://blog.sentry.io/getting-started-with-session-replay/): Get full visibility into user errors to see exactly what went wrong and when with Session Replay.

- [Debugging weird stack traces with Session Replay](https://blog.sentry.io/debugging-weird-stack-traces-with-session-replay/): Sometimes errors aren't always easy to understand, the stack trace doesn't give a lot of info. You can see through breadcrumbs that something went wrong when the user was clicking, but not exactly why. This is a classic example of a non-illustrative stack trace, and where [Session Replay](https://sentry.io/for/session-replay/) can come in handy.

- [Monitoring & Debugging a Checkout Flow in Flask & React](https://blog.sentry.io/monitoring-and-debugging-a-checkout-flow-in-flask-and-react/): When your checkout flow breaks, customers disappear faster than most ‘cutting-edge’ JS metaframeworks. Let's walk through how we instrumented, monitored, and fixed a major issue, with minimal effort, using Sentry.

- [Debuggability Explained - Monitoring & Observability in Your Workflow](https://blog.sentry.io/monitoring-observability-and-debuggability-explained/): Monitoring & debugging are critical in every developer's workflow. Learn more about debuggability and the differences between observability vs. monitoring here.

## Comparison

### Traditional RUM

Black‑Box Metrics: You’re staring at waterfall charts and percentile graphs that tell you something is slow, but not why‑or which user flows are paying the price.

Context Vacuum: RUM dashboards sit in their own silo, so you’re forced to juggle separate tools for errors, traces, and logs—good luck matching a Core Web Vital spike to the deploy that caused it.

Privacy Panic: Instrumenting the browser feels risky; masking, scrubbing, and compliance settings live in a different console (or worse, a legal doc), so teams ship half‑baked configs—or none at all.

Single‑Page‑App Blind Spots: Traditional RUM still thinks every navigation is a full page load, so route changes, lazy‑loaded bundles, and long tasks hide in plain sight.

Developer Disengagement: The performance team cares, the business team cares, but the people who can actually fix the code? They’re busy because the RUM tool speaks in metrics, not stack traces.

### RUM with Sentry

Full Visibility into Performance: [Web Vitals](https://sentry.io/for/web-vitals/), custom spans, and error events land in one place—right next to the exact release, commit, and line of code. Move directly from symptom to fix without tab‑surfing.

Session‑Aware Debugging: Jump straight from a 400 ms INP outlier to a Session Replay of the actual click path, console logs, and network chatter that caused it. No more “can you record your screen?”.

Privacy Built‑In: Field‑level scrubbing, domain‑level blocking, and one‑click GDPR/CCPA modes ship with the SDK, so legal sleeps well and you still get the diagnostics you need.

Instrumentation built for SPAs: Route changes, virtual pages, and long tasks are auto‑captured, so modern frameworks (React, Vue, Next, Remix—you name it) finally get monitoring that understands them.

Developer‑First UX: Clean UI, GitHub‑linked stack traces, and IDE‑ready deep links mean the folks writing code actually use the tool—turning “somebody should fix this” into “PR #457 closes it.”

## Quick Start

### Python

Install the Sentry Python SDK with pip

```bash
pip install sentry-sdk
```

Configuration should happen as early as possible in your application's lifecycle.

```python
import sentry_sdk

sentry_sdk.init(
  dsn="https://examplePublicKey@o0.ingest.sentry.io/0",
  # Add data like request headers and IP for users, if applicable;
  # see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
  send_default_pii=True,
  # Set traces_sample_rate to 1.0 to capture 100%
  # of transactions for tracing.
  traces_sample_rate=1.0,
  #Enable logs to be sent to Sentry
  enable_logs=True,
  # To collect profiles for all profile sessions,
  # set profile_session_sample_rate to 1.0.
  profile_session_sample_rate=1.0,
  # Profiles will be automatically collected while
  # there is an active span.
  profile_lifecycle="trace",
)
```

### JavaScript

Install the Sentry JavaScript SDK with npm

```bash
npm install @sentry/browser --save
```

Configuration should happen as early as possible in your application's lifecycle.

```javascript
import * as Sentry from "@sentry/browser";

Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  // Adds request headers and IP for users, for more info visit:
  // https://docs.sentry.io/platforms/javascript/configuration/options/#sendDefaultPii
  sendDefaultPii: true,
  // Set tracesSampleRate to 1.0 to capture 100%
  // of transactions for tracing.
  tracesSampleRate: 1.0,
  // Set tracePropagationTargets to control for which URLs trace propagation should be enabled
  tracePropagationTargets: ["localhost", /^https:\/\/yourserver\.io\/api/],
  // Enable logs to be sent to Sentry
  enableLogs: true,
  // Set profilesSampleRate to 1.0 to profile every transaction.
  // Since profilesSampleRate is relative to tracesSampleRate,
  // the final profiling rate can be computed as tracesSampleRate * profilesSampleRate
  // For example, a tracesSampleRate of 0.5 and profilesSampleRate of 0.5 would
  // result in 25% of transactions being profiled (0.5*0.5=0.25)
  profilesSampleRate: 1.0,
  integrations: [
    Sentry.browserTracingIntegration(),
    Sentry.browserProfilingIntegration(),
  ],
});
```

### React

Run the command for your preferred package manager to add the Sentry SDK to your application:

```bash
npm install @sentry/react --save
```

To import and initialize Sentry, create a file in your project's root directory, for example, `instrument.js`, and add the following code:

```javascript
import * as Sentry from "@sentry/react";

Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  // Adds request headers and IP for users, for more info visit:
  // https://docs.sentry.io/platforms/javascript/guides/react/configuration/options/#sendDefaultPii
  sendDefaultPii: true,
  // Set tracesSampleRate to 1.0 to capture 100%
  // of transactions for tracing.
  // Learn more at
  // https://docs.sentry.io/platforms/javascript/configuration/options/#traces-sample-rate
  tracesSampleRate: 1.0,
  // Set `tracePropagationTargets` to control for which URLs trace propagation should be enabled
  tracePropagationTargets: [/^//, /^https://yourserver.io/api/],
  // Enable logs to be sent to Sentry
  enableLogs: true,
  // Set profilesSampleRate to 1.0 to profile every transaction.
  // Since profilesSampleRate is relative to tracesSampleRate,
  // the final profiling rate can be computed as tracesSampleRate * profilesSampleRate
  // For example, a tracesSampleRate of 0.5 and profilesSampleRate of 0.5 would
  // result in 25% of transactions being profiled (0.5*0.5=0.25)
  profilesSampleRate: 1.0,
  integrations: [
    // If you're using react router, use the integration for your react router version instead.
    // Learn more at
    // https://docs.sentry.io/platforms/javascript/guides/react/features/react-router/
    Sentry.browserTracingIntegration(),
    Sentry.browserProfilingIntegration(),
  ],
});
```

Initialize Sentry as early as possible in your application. We recommend putting the import of your initialization code as the first import in your app's entry point:

```javascript
// Sentry initialization should be imported first!
import "./instrument";
import App from "./App";
import { createRoot } from "react-dom/client";

const container = document.getElementById("app");
const root = createRoot(container);
root.render(<App />);
```

To make sure Sentry captures all your app's errors, configure error handling based on your React version. 
 For React versions 19 and up:  

```javascript
import { createRoot } from "react-dom/client";
import * as Sentry from '@sentry/react';

const container = document.getElementById("app");
const root = createRoot(container, {
  // Callback called when an error is thrown and not caught by an ErrorBoundary.
  onUncaughtError: Sentry.reactErrorHandler((error, errorInfo) => {
    console.warn('Uncaught error', error, errorInfo.componentStack);
  }),
  // Callback called when React catches an error in an ErrorBoundary.
  onCaughtError: Sentry.reactErrorHandler(),
  // Callback called when React automatically recovers from errors.
  onRecoverableError: Sentry.reactErrorHandler(),
});
root.render();
```

For React versions 18 and below, use the ErrorBoundary component to automatically send errors from specific component trees to Sentry and provide a fallback UI:

```javascript
import React from "react";
import * as Sentry from "@sentry/react";

<Sentry.ErrorBoundary fallback={<p>An error has occurred</p>}>
  <Example />
</Sentry.ErrorBoundary>;
```

### Next.js

To install Sentry using the installation wizard, run thrun the following command and step through the prompts:

```bash
npx @sentry/wizard@latest -i nextjs
```

For manual installation run the following command and use the following configurations:

```bash
npm install @sentry/nextjs --save
```

Extend your app's default Next.js options by adding code with `withSentryConfig` into your `next.config.(js|mjs)` file:

```javascript
const { withSentryConfig } = require("@sentry/nextjs");
const nextConfig = {
  // Your existing Next.js configuration
};
// Make sure adding Sentry options is the last code to run before exporting
module.exports = withSentryConfig(nextConfig, {
  org: "example-org",
  project: "example-project",
  // Only print logs for uploading source maps in CI
  // Set to `true` to suppress logs
  silent: !process.env.CI,
  // Automatically tree-shake Sentry logger statements to reduce bundle size
  disableLogger: true,
});
```

#### Client-Side Configuration

```javascript
import * as Sentry from "@sentry/nextjs";
Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  // Adds request headers and IP for users, for more info visit:
  // https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii
  sendDefaultPii: true,
  // Set tracesSampleRate to 1.0 to capture 100%
  // of transactions for tracing.
  // We recommend adjusting this value in production
  // Learn more at
  // https://docs.sentry.io/platforms/javascript/configuration/options/#traces-sample-rate
  tracesSampleRate: 1.0,
  // Enable logs to be sent to Sentry
  enableLogs: true,
  // Set profilesSampleRate to 1.0 to profile every transaction.
  // Since profilesSampleRate is relative to tracesSampleRate,
  // the final profiling rate can be computed as tracesSampleRate * profilesSampleRate
  // For example, a tracesSampleRate of 0.5 and profilesSampleRate of 0.5 would
  // result in 25% of transactions being profiled (0.5*0.5=0.25)
  profilesSampleRate: 1.0,
});

// This export will instrument router navigations, and is only relevant if you enable tracing.
// `captureRouterTransitionStart` is available from SDK version 9.12.0 onwards
export const onRouterTransitionStart = Sentry.captureRouterTransitionStart;
```

#### Server-Side Configuration

```javascript
import * as Sentry from "@sentry/nextjs";
Sentry.init({
  dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  // Adds request headers and IP for users, for more info visit:
  // https://docs.sentry.io/platforms/javascript/guides/nextjs/configuration/options/#sendDefaultPii
  sendDefaultPii: true,
  // Set tracesSampleRate to 1.0 to capture 100%
  // of transactions for tracing.
  // We recommend adjusting this value in production
  // Learn more at
  // https://docs.sentry.io/platforms/javascript/configuration/options/#traces-sample-rate
  tracesSampleRate: 1.0,
  // Enable logs to be sent to Sentry
  enableLogs: true,
});
```

#### Register Sentry Server-Side SDK Initialization

Create a Next.js Instrumentation file named `instrumentation.(js|ts)` in your project root or inside the `src` folder if you have one. Import your server and edge configurations, making sure that the imports point to your specific files:

```javascript
export async function register() {
  if (process.env.NEXT_RUNTIME === "nodejs") {
    await import("./sentry.server.config");
  }
  if (process.env.NEXT_RUNTIME === "edge") {
    await import("./sentry.edge.config");
  }
}
```

### Go

Grab the Sentry Go SDK:

```bash
go get "github.com/getsentry/sentry-go"
```

Configuration should happen as early as possible in your application's lifecycle.

```text
err := sentry.Init(sentry.ClientOptions{
  Dsn: "https://examplePublicKey@o0.ingest.sentry.io/0",
  // Enable printing of SDK debug messages.
  // Useful when getting started or trying to figure something out.
  Debug: true,
  // Adds request headers and IP for users,
  // visit: https://docs.sentry.io/platforms/go/data-management/data-collected/ for more info
  SendDefaultPII: true,
  EnableTracing: true,
  // Set TracesSampleRate to 1.0 to capture 100%
  // of transactions for tracing.
  TracesSampleRate: 1.0,
})
if err != nil {
  log.Fatalf("sentry.Init: %s", err)
}
// Flush buffered events before the program terminates.
// Set the timeout to the maximum duration the program can afford to wait.
defer sentry.Flush(2 * time.Second)
```

### Ruby

Add the sentry-ruby gem to your Gemfile:

```ruby
gem "sentry-ruby"
```

Configuration should happen as early as possible in your application's lifecycle.

```ruby
require 'sentry-ruby'

Sentry.init do |config|
  config.dsn = 'https://examplePublicKey@o0.ingest.sentry.io/0'

  # get breadcrumbs from logs
  config.breadcrumbs_logger = [:sentry_logger, :http_logger]

  # Add data like request headers and IP for users, if applicable;
  # see https://docs.sentry.io/platforms/ruby/data-management/data-collected/ for more info
  config.send_default_pii = true
  # enable tracing
  # we recommend adjusting this value in production
  config.traces_sample_rate = 1.0
  # Enable logs to be sent to Sentry
  config.enable_logs = true
  # enable profiling
  # this is relative to traces_sample_rate
  config.profiles_sample_rate = 1.0
end
```

### PHP

Install the Sentry SDK using Composer:

```bash
composer require sentry/sentry
```

To use Profiling, you'll also need to install the Excimer extension via PECL:

```bash
pecl install excimer
```

To capture all errors, even the one during the startup of your application, you should initialize the Sentry PHP SDK as soon as possible.

```php
\Sentry\init([
  'dsn' => 'https://examplePublicKey@o0.ingest.sentry.io/0',
  // Add request headers, cookies and IP address,
  // see https://docs.sentry.io/platforms/php/data-management/data-collected/ for more info
  'send_default_pii' => true,
  // Specify a fixed sample rate
  'traces_sample_rate' => 1.0,
  // Enable logs to be sent to Sentry
  'enable_logs' => true,
  // Set a sampling rate for profiling - this is relative to traces_sample_rate
  'profiles_sample_rate' => 1.0,
]);
```

### .NET

Install the NuGet package to add the Sentry dependency:

```shell
dotnet add package Sentry -v 5.16.2
```

To use Profiling, you'll also need to install the Sentry.Profiling package:

```shell
dotnet add package Sentry.Profiling -v 5.16.2
```

To capture all errors, even the one during the startup of your application, you should initialize the Sentry .NET SDK as soon as possible.

```csharp
SentrySdk.Init(options =>
{
    options.Dsn = "https://examplePublicKey@o0.ingest.sentry.io/0";
    options.Debug = true;
    // Adds request URL and headers, IP and name for users, etc.
    options.SendDefaultPii = true;
    // A fixed sample rate of 1.0 - 100% of all transactions are getting sent
    options.TracesSampleRate = 1.0f;
    // A sample rate for profiling - this is relative to TracesSampleRate
    options.ProfilesSampleRate = 1.0f;
});
```

---

*Source: [sentry.io/solutions/real-user-monitoring-rum/](https://sentry.io/solutions/real-user-monitoring-rum/)*
