Skip to content
Last9
Book demo

React Native RUM SDK

Install and configure the Last9 React Native RUM SDK. TypeScript API, CDN-hosted npm tarball, bridges native Android and iOS SDKs. Auto-instruments fetch/XHR, React Navigation, errors, ANRs.

Real User Monitoring for React Native apps. Automatic instrumentation for sessions, views, network requests (fetch/XHR), errors, and resource metrics via OpenTelemetry. ANR detection is available on Android only.

The React Native SDK wraps the Android and iOS native SDKs. Each platform’s CDN repo must be configured so the native dependencies resolve.

Prerequisites

  • React Native >= 0.74
  • iOS 15.1+
  • Android minSdk 21 (Android 5.0+)
  • Native dependencies:
    • Android: io.last9:rum-android:0.8.0 (resolved from CDN Maven)
    • iOS: Last9RUM 0.8.0 (resolved from CDN podspec)

Create Client Monitoring Tokens

Create one Client token per platform — do not combine Android and iOS origins on a single token. Each build uses the native SDK for that platform, so separate tokens keep origin scoping, rotation, and access control aligned with Android and iOS setup.

  1. Open Last9 → Settings → Ingestion Tokens
  2. Click Create Token → choose type Client → create an Android token with allowed origin android://com.yourcompany.yourapp (your app’s exact package name). Copy the token.
  3. Create a second Client token for iOS with allowed origin ios://com.yourcompany.yourapp (your app’s exact bundle ID). Copy the token.
  4. Copy the OTLP endpoint URL (the same URL is used for both platforms)

CDN artifacts

ArtifactStable URLVersioned URL
Tarballhttps://cdn.last9.io/rum-sdk/react-native/builds/stable/v0/last9-rum-react-native.tgzhttps://cdn.last9.io/rum-sdk/react-native/builds/0.8.0/last9-rum-react-native-0.8.0.tgz
Checksumhttps://cdn.last9.io/rum-sdk/react-native/builds/stable/v0/last9-rum-react-native.tgz.sha256https://cdn.last9.io/rum-sdk/react-native/builds/0.8.0/last9-rum-react-native-0.8.0.tgz.sha256

The stable CDN channel is major-pinned at stable/v0. Staging builds use the -alpha.<run_number> suffix and explicit versioned URLs.

Installation

  1. Install the package

    npm install https://cdn.last9.io/rum-sdk/react-native/builds/stable/v0/last9-rum-react-native.tgz
  2. Android — add the CDN Maven repository

    In android/settings.gradle (or android/build.gradle):

    dependencyResolutionManagement {
    repositories {
    google()
    mavenCentral()
    maven { url uri("https://cdn.last9.io/rum-sdk/android/maven/") }
    }
    }
  3. iOS — add the Last9RUM podspec

    In ios/Podfile:

    pod 'Last9RUM', :podspec => 'https://cdn.last9.io/rum-sdk/ios/builds/stable/v0/Last9RUM.podspec'

    Then install pods:

    cd ios && pod install
  4. Initialize the SDK

    At app entry (before any screens render):

    import { Platform } from "react-native";
    import { L9Rum } from "@last9/rum-react-native";
    const isIos = Platform.OS === "ios";
    L9Rum.initialize({
    baseUrl: "https://otlp-ext-aps1.last9.io/v1/otlp/organizations/<org>",
    // Use the platform-matching token and origin pair — see
    // "Create Client Monitoring Tokens" above.
    origin: isIos
    ? "ios://com.yourcompany.yourapp"
    : "android://com.yourcompany.yourapp",
    clientToken: isIos ? "your-ios-client-token" : "your-android-client-token",
    serviceName: "my-rn-app",
    serviceVersion: "1.0.0",
    deploymentEnvironment: "production",
    });

Configuration

L9Rum.initialize({
// --- Required ---------------------------------------------------------
// OTLP collector endpoint
baseUrl: "https://otlp-ext-aps1.last9.io/v1/otlp/organizations/<org>",
// Authentication token from Last9 — use the Android or iOS Client token
// for the platform this build is running on.
clientToken: Platform.OS === "ios"
? "your-ios-client-token"
: "your-android-client-token",
// Application identifier (maps to service.name)
serviceName: "my-rn-app",
// App version string (maps to service.version)
serviceVersion: "1.0.0",
// Environment name
deploymentEnvironment: "production",
// --- Optional ---------------------------------------------------------
// Origin sent as X-LAST9-ORIGIN header. Required for client_monitoring
// tokens. Must match the origin on the platform's Client token —
// android://<package> on Android, ios://<bundle-id> on iOS. Pass the
// matching clientToken for the same platform. Needs `import { Platform }
// from "react-native"` as shown in the Installation section above.
origin: Platform.OS === "ios"
? "ios://com.yourcompany.yourapp"
: "android://com.yourcompany.yourapp",
// Specific build identifier (maps to app.build_id)
appBuildId: "1.0.0-build-42",
// Optional override for the app.installation.id resource attribute.
// The Client-ID header always uses the native SDK-generated per-install UUID.
appInstallationId: undefined,
// Session sampling rate: 0-100 (percentage). 100 = sample everything.
sampleRate: 100,
// Print debug logs to console
debugLogs: false,
// Automatically instrument network requests through native hooks
networkInstrumentation: true,
// Automatically capture unhandled JS errors
errorInstrumentation: true,
// Max spans per export batch
maxExportBatchSize: 100,
// Export timeout in milliseconds
exportTimeoutMs: 30000,
// ANR detection (Android only)
anrDetectionEnabled: true,
anrThresholdMs: 5000,
// Periodically sample memory and CPU
resourceMonitoringEnabled: true,
resourceSamplingIntervalMs: 30000,
// Setting this to true will hide network requests (and their
// DNS/TCP/TLS/TTFB phase child spans) from the Last9 dashboard's
// Sessions → APIs tab. Each request would get its own traceId
// instead of sharing the current view's traceId, and that tab
// only fetches spans that share the View's traceId. Keep this
// false unless you specifically need per-request trace isolation.
isolateTracePerRequest: false,
// Fine-grained network ignore rules. Strings use substring matching;
// RegExp uses regex search semantics. Matched URLs are dropped before
// span creation.
ignorePatterns: {
fullUrl: ["https://cdn.example.com", /^https:\/\/.*\.example\.com/i],
pathname: [".pdf", ".jpg", /^\/internal\/metrics/],
hostname: ["cdn.example.com", /(^|\.)assets\.example\.com$/i],
},
// 'preserve' (default): keep traceparent on ignored requests.
// 'strip': remove traceparent from ignored requests.
propagationMode: "preserve",
// Custom resource attributes added to every span
resourceAttributes: {
"app.platform": "react-native",
},
// W3C Baggage propagation on outgoing requests
baggage: {
enabled: false,
allowedKeys: ["session.id", "user.id"],
maxTotalBytes: 8192,
warnAtPercentage: 80,
},
});

Stable release notes

React Native 0.8.0 uses native Android and iOS SDK 0.8.0. The native layers now send an SDK-generated per-install UUID as the ingestion Client-ID header instead of serviceName, so devices no longer share one rate-limit bucket. No React Native app-code change is required.

appInstallationId only overrides the app.installation.id resource attribute. It does not override the Client-ID header, so the header and the resource attribute can differ when you set appInstallationId manually.

The SDK also normalizes non-Error JavaScript throws and promise rejections, including strings, primitives, plain objects, and bridged native fallback errors, so exception.type stays populated.

Network ignore patterns

Skip noisy URLs before span creation by matching against full URL, pathname, or hostname. Strings use substring matching; RegExp uses regex search semantics.

L9Rum.initialize({
ignorePatterns: {
fullUrl: ["https://cdn.example.com", /^https:\/\/.*\.example\.com/i],
pathname: [".pdf", ".jpg", /^\/internal\/metrics/],
hostname: ["cdn.example.com", /(^|\.)assets\.example\.com$/i],
},
// 'preserve' (default): keep traceparent on ignored requests.
// 'strip': remove traceparent from ignored requests.
propagationMode: "strip",
});

Network phase child spans

Network instrumentation is native by default so the SDK emits child spans for individual HTTP phases:

Child spanWhat it measures
dnsDNS lookup duration
tcp_connectTCP connection establishment
tls_handshakeTLS negotiation
ttfbTime from request sent to first response byte

No SDK config change is required. Android wires the OkHttp client factory with the Last9 interceptor and EventListener.Factory. iOS uses native URLProtocol/URLSession instrumentation and reads URLSession task metrics.

Reused connections skip DNS, TCP, and TLS work. For those requests the SDK emits zero-duration child spans with l9rum.network.phase.skipped=true so the waterfall shape stays consistent.

API reference

React Navigation integration

For automatic view tracking with React Navigation:

import { L9ReactNavigationInstrumentation } from '@last9/rum-react-native';
import { NavigationContainer } from '@react-navigation/native';
function App() {
return (
<NavigationContainer
onStateChange={L9ReactNavigationInstrumentation.onStateChange}
>
{/* screens */}
</NavigationContainer>
);
}

Identify a user

L9Rum.identify({
id: "user-123",
name: "Jane",
email: "jane@example.com",
fullName: "Jane Doe",
roles: ["admin"],
});

Clear user on sign-out

L9Rum.clearUser();

Capture errors

try {
// risky operation
} catch (error) {
L9Rum.captureError(error, { screen: "checkout" });
}

Track views manually

L9Rum.startView("ProductDetailsScreen");
L9Rum.setViewName("Product #42");

Custom events

L9Rum.addEvent("purchase_completed", {
product_id: "12345",
amount: 29.99,
});

Global span attributes

L9Rum.spanAttributes({
experiment: "checkout_v2",
feature_flag: "new_cart",
});
// Clear
L9Rum.spanAttributes(null);

Session ID

const sessionId = await L9Rum.getSessionId();

Flush pending data

L9Rum.flush();

WebView correlation

Instrument a react-native-webview WebView to share the native session ID with Browser RUM spans running inside it:

import { useRef } from 'react';
import { WebView } from 'react-native-webview';
import { L9Rum } from '@last9/rum-react-native';
const webViewRef = useRef<WebView>(null);
<WebView
ref={webViewRef}
source={{ uri: 'https://app.example.com' }}
onLoad={() => {
if (webViewRef.current) {
L9Rum.instrumentWebView(webViewRef);
}
}}
/>

The SDK resolves the underlying native WKWebView (iOS) or android.webkit.WebView (Android) and re-injects session context on every navigation automatically.

See the WebView Session Correlation guide for auto-load options and verification steps.

Next steps

Once data is flowing, explore it in Discover > Applications — performance, errors, and sessions.


Troubleshooting

Please get in touch with us on Discord or Email if you have any questions.