Real User Monitoring (RUM)
Access the RUM dashboard at https://app.watchlog.ir/rum to see real-user traffic, Web Vitals, JavaScript errors, slow resources, and session activity across your applications.
WordPress
Works with WordPress 5.8 or higher and PHP 7.4 or higher.
Installation
Install the Watchlog RUM plugin from the WordPress Plugin Directory:
- Go to Plugins → Add New in your WordPress admin panel
- Search for "Watchlog RUM"
- Click Install Now and then Activate
Or install via WP-CLI:
wp plugin install watchlog-rum --activateNavigate to Settings → Watchlog RUM in your WordPress admin panel
Configure your RUM credentials:
- Copy your API Key and Endpoint from the Watchlog panel: RUM → Your RUM Credentials
- Paste them into the plugin settings
Configuration
The plugin provides a settings page at Settings → Watchlog RUM with the following options:
Required Settings
- API Key — Copy from RUM → Your RUM Credentials in the Watchlog panel
- Endpoint — Copy from RUM → Your RUM Credentials in the Watchlog panel (e.g.,
https://api.watchlog.ir/rum) - App Name — Required. Your application name as shown in the dashboard (e.g.,
my-wordpress-site)
Optional Settings
- Environment — Environment tag for filtering (e.g.,
production,staging,development). Default: empty - Release — Release version (e.g.,
1.0.0). Default: empty
Sampling Configuration
All sample rates accept values between 0.0 and 1.0:
Session Sample Rate — Fraction of sessions to record. Maximum allowed: 0.5 (50%) to prevent server overload. Values above 0.5 will be automatically capped.
- Default:
1.0(100%) - Recommended for production:
0.1to0.3(10-30%) - Recommended for high traffic:
0.1(10%)
- Default:
Network Sample Rate — Sampling for network requests (fetch/XHR). Network requests can be very frequent.
- Default:
0.1(10%) - Recommended:
0.1(10%) or lower for production
- Default:
Interaction Sample Rate — Sampling for user interactions (clicks, scrolls, form submissions). User interactions can be extremely frequent.
- Default:
0.1(10%) - Recommended:
0.1(10%) or lower for production
- Default:
Performance Settings
Flush Interval (ms) — How often to send buffered events to the server in milliseconds.
- Default:
10000(10 seconds) - Lower values send data more frequently but may increase network usage
- Default:
Session Timeout (minutes) — How long a session remains active after the last activity.
- Default:
30minutes - After this period of inactivity, a new session will start on the next page view
- Default:
Feature Toggles
Enable Web Vitals — Capture CLS, LCP, INP, TTFB, and FID metrics using the bundled
web-vitalslibrary.- Default: Enabled
- Uses the bundled
web-vitals.iife.js(Apache-2.0 license, from GoogleChrome/web-vitals)
Capture Long Tasks — Record long-running JavaScript tasks (>50ms on main thread) using PerformanceObserver.
- Default: Enabled
- Helps identify performance bottlenecks
Capture Fetch — Instrument
window.fetchcalls to track network requests.- Default: Enabled
- Tracks all fetch API requests with timing and size information
Capture XHR — Instrument
XMLHttpRequestcalls to track network requests.- Default: Enabled
- Tracks all XHR requests with timing and size information
Capture User Interactions — Track sampled clicks, scroll depth, and form submissions.
- Default: Disabled
- When enabled, uses
interactionSampleRatefor sampling
Capture Breadcrumbs — Attach last breadcrumbs to each event for better debugging context.
- Default: Enabled
- Stores up to 100 breadcrumbs per session
Debug Logging — Output verbose logs to the browser console for troubleshooting.
- Default: Disabled
- Enable only when debugging issues
How It Works
Once configured and saved, the plugin automatically:
- Loads the RUM SDK on all public-facing pages
- Sends
session_starton first page load - Sends
page_viewon every page navigation - Sends
session_endwhen the session ends (on unload) - Captures JavaScript errors automatically
- Tracks performance metrics, Web Vitals, network requests, and resources
- Normalizes WordPress routes (e.g.,
/post/123→/post/:id) for better aggregation
The plugin mirrors the Watchlog Vue/React SDK event format, ensuring consistent data structure across all platforms.
Event Types Collected
The WordPress plugin automatically captures the same event types as the React/Vue SDKs:
- session_start — Emitted when a new session begins
- page_view — Page navigations with WordPress route normalization
- session_end — Emitted when session ends (on unload)
- web_vital — LCP / INP / CLS / TTFB / FID values, with attribution when available
- performance — Navigation timing, paint metrics, and resource timing
- resource — Browser resource timings (duration, size, initiator type)
- network — Fetch/XHR requests with detailed timing and size information
- error — JavaScript errors with message, stack, fingerprint and top paths
- longtask — Long-running JavaScript tasks (>50ms on main thread)
- interaction — User interactions (clicks, scrolls, form submissions) if enabled
- custom — Optional, user-defined events (e.g., business actions)
WordPress-Specific Features
- Route Normalization — Automatically normalizes WordPress URLs (e.g.,
/post/123→/post/:id,/page/about→/page/:slug) - Session Persistence — Sessions persist across page navigations using localStorage
- WordPress-Aware — Integrates seamlessly with WordPress's page lifecycle and routing
Sample Rate Best Practices
Session Sample Rate
To protect server resources and prevent overload, the maximum allowed Session Sample Rate is 0.5 (50%). If you set a value higher than 0.5, it will be automatically capped.
Recommended values:
- Development/Testing:
0.5(50%) - Full visibility for debugging - Production (Low Traffic):
0.3(30%) - Good balance between data and performance - Production (High Traffic):
0.1(10%) - Efficient data collection without server strain
Why limit sample rate? High sample rates can generate massive amounts of data, leading to:
- Server overload and potential crashes
- Increased storage costs
- Slower query performance
- Network bandwidth issues
Network Sample Rate
Network requests can be very frequent. We recommend keeping this at 0.1 (10%) or lower for production environments.
Interaction Sample Rate
User interactions (clicks, scrolls) can be extremely frequent. We recommend 0.1 (10%) or lower for production.
Troubleshooting
No data in the dashboard?
- Confirm
EndpointandAPI Keymatch the values from RUM → Your RUM Credentials in the Watchlog panel - Verify
App Nameis set correctly - Check browser console for errors (enable Debug Logging)
- Ensure the plugin is activated
- Confirm
Web Vitals missing?
- Ensure "Enable Web Vitals" is checked in settings
- The plugin bundles
web-vitalsautomatically, no additional installation needed
Too much data?
- Lower
Session Sample Rate/Network Sample Rate - Disable "Capture User Interactions" if not needed
- Increase
Flush Intervalto reduce network frequency
- Lower
Browser blocks third-party scripts?
- Verify CORS settings and that your collector domain is reachable from clients
- Check browser console for network errors
Routes not normalizing correctly?
- The plugin automatically normalizes WordPress routes. If you see issues, check the browser console with Debug Logging enabled.
React
Installation
npm install watchlog-react-rum
Optional: For Web Vitals support (CLS, LCP, INP, TTFB, FID):
npm install web-vitals
Quick Start (Recommended: Hook-based with RouterProvider)
For the most accurate route pattern detection (like Datadog), use the wrapped router functions from watchlog-react-rum/react-router-v6:
// src/main.jsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import { RouterProvider } from 'react-router-dom'
import { createBrowserRouter } from 'watchlog-react-rum/react-router-v6'
import { useWatchlogRUM } from 'watchlog-react-rum'
import App from './App'
import Home from './pages/Home'
import UserDetail from './pages/UserDetail'
import PostDetail from './pages/PostDetail'
// Create router with route definitions (for accurate route pattern extraction)
// IMPORTANT: Use createBrowserRouter from 'watchlog-react-rum/react-router-v6'
// This ensures route patterns are captured for accurate normalization
const router = createBrowserRouter([
{
path: '/',
element: <App />,
children: [
{
index: true,
element: <Home />,
},
{
path: 'users/:userId', // This exact pattern will be used for normalization
element: <UserDetail />,
},
{
path: 'posts/:postId',
element: <PostDetail />,
},
],
},
])
// Root component to initialize RUM tracking
function Root() {
useWatchlogRUM({
apiKey: 'YOUR_API_KEY', // Copy from Watchlog panel
endpoint: 'https://api.watchlog.ir/rum', // or your self-hosted endpoint
app: 'my-react-app', // Your application name (as shown in the dashboard)
environment: 'production', // optional: 'production' | 'staging' | 'development'
release: '1.0.0', // optional: release version
debug: false, // Enable debug logging
flushInterval: 10000, // Flush interval in milliseconds
sampleRate: 0.5, // 0.0 to 1.0 - session sampling (max: 0.5 to prevent server overload)
networkSampleRate: 0.1, // 0.0 to 1.0 - network request sampling (recommended: 0.1)
interactionSampleRate: 0.1, // 0.0 to 1.0 - user interaction sampling (recommended: 0.1)
enableWebVitals: true, // Capture LCP/INP/CLS/TTFB (requires web-vitals package)
captureLongTasks: true, // Capture long tasks (>50ms on main thread)
captureFetch: true, // Instrument window.fetch
captureXHR: true, // Instrument XMLHttpRequest
captureUserInteractions: false, // Set to true to enable click/scroll tracking
captureBreadcrumbs: true, // Capture event breadcrumbs
maxBreadcrumbs: 100, // Maximum number of breadcrumbs to keep
beforeSend: (event) => {
// Optional: filter or modify events before sending
// Return null to drop the event
// Example: redact email-like strings from error messages
if (event.type === 'error' && typeof event.data?.message === 'string') {
event.data.message = event.data.message.replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+/gi, '[redacted]')
}
// Example: strip query strings from page URLs
if (event.context?.page?.url) {
const u = new URL(event.context.page.url)
u.search = ''
event.context.page.url = u.toString()
}
return event
}
})
return <RouterProvider router={router} />
}
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<Root />
</React.StrictMode>
)
Important: Using the wrapped createBrowserRouter from watchlog-react-rum/react-router-v6 ensures that route patterns (like /users/:userId or /users/:uuid) are extracted directly from your route definitions, providing the most accurate normalization.
Alternative: BrowserRouter Setup
If you're using BrowserRouter instead of RouterProvider, the SDK will still work but will use params-based route reconstruction:
// src/App.jsx
import { BrowserRouter } from 'react-router-dom'
import { useWatchlogRUM } from 'watchlog-react-rum'
function App() {
useWatchlogRUM({
apiKey: 'YOUR_API_KEY',
endpoint: 'https://api.watchlog.ir/rum',
app: 'my-react-app',
// ... other config options
})
return (
<BrowserRouter>
{/* Your app routes */}
</BrowserRouter>
)
}
export default App
Manual SDK API (Advanced)
For more control, you can use the SDK directly:
import WatchlogRUM from 'watchlog-react-rum'
// Initialize once at app startup
WatchlogRUM.init({
apiKey: 'YOUR_API_KEY',
endpoint: 'https://api.watchlog.ir/rum',
app: 'my-react-app',
debug: true,
flushInterval: 10000,
})
// Send custom metric
WatchlogRUM.custom('button_clicked', 1, { extra: 'data' })
// Manually capture errors
WatchlogRUM.captureError(new Error('Something went wrong'), {
component: 'MyComponent',
props: { userId: 123 }
})
// Add breadcrumbs
WatchlogRUM.addBreadcrumb('user', 'User clicked button', 'info', {
buttonId: 'submit'
})
// Flush buffered events (e.g., before manual unload)
WatchlogRUM.flush(true)
Note: When using manual API, you need to manually track route changes:
import { useEffect } from 'react'
import { useLocation } from 'react-router-dom'
import WatchlogRUM from 'watchlog-react-rum'
function MyComponent() {
const location = useLocation()
useEffect(() => {
// Manually track page views
WatchlogRUM.bufferEvent({
type: 'page_view',
path: location.pathname,
normalizedPath: location.pathname, // or compute normalized path
navType: 'navigate'
})
}, [location.pathname])
return <div>...</div>
}
Event Types Collected
RUM automatically captures several event types:
- session_start — Emitted when a new session begins
- page_view — Route/page navigations (SPA & traditional)
- session_end — Emitted when session ends (on unload)
- web_vital — LCP / INP / CLS / TTFB / FID values, with attribution when available
- performance — Navigation timing, paint metrics, and resource timing
- resource — Browser resource timings (duration, size, initiator type)
- network — Fetch/XHR requests with detailed timing and size information
- error — JavaScript errors with message, stack, fingerprint and top paths
- longtask — Long-running JavaScript tasks (>50ms on main thread)
- interaction — User interactions (clicks, scrolls, form submissions) if enabled
- custom — Optional, user-defined events (e.g., business actions)
Example payloads
page_view
{
"type": "page_view",
"ts": 1730540000123,
"seq": 1,
"context": {
"apiKey": "your-api-key",
"app": "my-react-app",
"sessionId": "sess-abc123",
"deviceId": "dev-xyz789",
"environment": "production",
"release": "1.0.0",
"page": {
"url": "https://site.com/user/42",
"path": "/user/42",
"normalizedPath": "/user/:userId",
"referrer": "https://google.com",
"title": "User Profile"
},
"client": {
"userAgent": "Mozilla/5.0 ...",
"language": "en-US",
"viewport": { "width": 1920, "height": 1080, "devicePixelRatio": 2 },
"browser": { "name": "Chrome", "version": "120" },
"os": { "name": "macOS", "version": "14.0" }
}
},
"data": {
"name": "page_view",
"navType": "navigate"
}
}
web_vital
{
"type": "web_vital",
"ts": 1730540000456,
"seq": 2,
"context": { /* full context */ },
"data": {
"name": "LCP",
"value": 1835.42,
"rating": "good",
"id": "metric-id",
"delta": 50
}
}
resource
{
"type": "resource",
"ts": 1730540000789,
"seq": 3,
"context": { /* full context */ },
"data": {
"name": "https://cdn.example.com/app.js",
"initiator": "script",
"duration": 342.1,
"transferSize": 128764,
"encodedBodySize": 120000,
"decodedBodySize": 128764
}
}
error
{
"type": "error",
"ts": 1730540000123,
"seq": 4,
"context": { /* full context */ },
"data": {
"name": "window_error",
"message": "TypeError: Cannot read properties of undefined",
"stack": "at MyComponent (App.jsx:42:10)\n at ...",
"source": "https://example.com/app.js",
"filename": "app.js",
"lineno": 42,
"colno": 10,
"component": "MyComponent",
"props": { "userId": 123 }
}
}
network
{
"type": "network",
"ts": 1730540000123,
"seq": 5,
"context": { /* full context */ },
"data": {
"method": "POST",
"url": "https://api.example.com/users",
"status": 200,
"ok": true,
"duration": 150,
"requestSize": 1024,
"responseSize": 2048,
"transferSize": 2500,
"timing": {
"dns": 10,
"tcp": 20,
"request": 30,
"response": 50,
"total": 150
}
}
}
Note: You can intercept/modify any event in
beforeSend. Returnnullto drop it entirely.
Configuration Reference
| Option | Type | Default | Description |
|---|---|---|---|
app | string | required | Application name shown in the dashboard. |
apiKey | string | required | Copy from RUM → Your RUM Credentials in the panel. |
endpoint | string | required | Collector endpoint (cloud or self-hosted). |
environment | string | "prod" | Environment tag (e.g., prod/staging/dev). |
release | string | null | Release version (e.g., '1.0.0'). |
debug | boolean | false | Enable debug logging. |
flushInterval | number | 10000 | Flush interval in milliseconds. |
sampleRate | number (0.0–1.0) | 1.0 | Fraction of sessions to record. Note: Maximum allowed value is 0.5 (50%) to prevent server overload. Values above 0.5 will be automatically capped. |
networkSampleRate | number (0.0–1.0) | 0.1 | Sampling for resource/fetch/xhr events. Recommended: 0.1 (10%) for production. |
interactionSampleRate | number (0.0–1.0) | 0.1 | Sampling for user interactions (clicks, scrolls). Recommended: 0.1 (10%) for production. |
enableWebVitals | boolean | true | Capture LCP/INP/CLS/TTFB/FID (requires web-vitals package). |
autoTrackInitialView | boolean | true | Send first page_view on mount. |
captureLongTasks | boolean | true | Capture long tasks (>50ms on main thread). |
captureFetch | boolean | true | Instrument window.fetch. |
captureXHR | boolean | true | Instrument XMLHttpRequest. |
captureUserInteractions | boolean | false | Capture user interactions (clicks, scrolls, forms). |
captureBreadcrumbs | boolean | true | Capture event breadcrumbs. |
maxBreadcrumbs | number | 100 | Maximum number of breadcrumbs to keep. |
beforeSend | (ev) => ev | null | undefined | Mutate, enrich, or drop events before export. |
Sample Rate Limits & Best Practices
Session Sample Rate (sampleRate)
To protect server resources and prevent overload, the maximum allowed sampleRate is 0.5 (50%). If you set a value higher than 0.5, it will be automatically capped to 0.5.
Recommended values:
- Development/Testing:
0.5(50%) - Full visibility for debugging - Production (Low Traffic):
0.3(30%) - Good balance between data and performance - Production (High Traffic):
0.1(10%) - Efficient data collection without server strain
Why limit sample rate? High sample rates can generate massive amounts of data, leading to:
- Server overload and potential crashes
- Increased storage costs
- Slower query performance
- Network bandwidth issues
Network Sample Rate (networkSampleRate)
Network requests can be very frequent. We recommend keeping this at 0.1 (10%) or lower for production environments.
Interaction Sample Rate (interactionSampleRate)
User interactions (clicks, scrolls) can be extremely frequent. We recommend 0.1 (10%) or lower for production.
Privacy & Redaction
Use beforeSend to drop sensitive events or redact PII. Consider:
- Strip query strings or hashes from URLs
- Remove email addresses, phone numbers, or form values from error messages
- Lower sampling for high-traffic pages to reduce data volume
- Filter out internal/admin routes
Troubleshooting
- No data in the dashboard? Confirm
endpoint,apiKey, andappmatch the panel values. - SPAs not tracking route changes? Ensure you're using
useWatchlogRUMhook or manually tracking route changes. - Routes not normalizing correctly? Use
createBrowserRouterfromwatchlog-react-rum/react-router-v6for accurate route pattern extraction. - Web Vitals missing? Install
web-vitalsand keepenableWebVitals: true. - Browser blocks third-party scripts? Verify CORS and that your collector domain is reachable from clients.
- Too much data? Lower
sampleRate/networkSampleRate, or drop events viabeforeSend.
Vue
Works with Vue 3 and Vue Router v4.
Installation
npm install @watchlog/rum-vue
Optional: For Web Vitals support (CLS, LCP, INP, TTFB, FID):
npm install web-vitals
Quick Start (Plugin-based - Recommended)
Use the createWatchlogRUMPlugin helper in your main.js to initialize tracking globally:
// src/main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { createWatchlogRUMPlugin } from '@watchlog/rum-vue'
const app = createApp(App)
app.use(router)
app.use(createWatchlogRUMPlugin({
router, // Vue Router instance (required for route tracking)
apiKey: 'YOUR_API_KEY', // Copy from Watchlog panel
endpoint: 'https://api.watchlog.ir/rum', // or your self-hosted endpoint
app: 'my-vue-app', // Your application name (as shown in the dashboard)
environment: 'production', // optional: 'production' | 'staging' | 'development'
release: '1.0.0', // optional: release version
debug: false, // Enable debug logging
flushInterval: 10000, // Flush interval in milliseconds
sampleRate: 0.5, // 0.0 to 1.0 - session sampling (max: 0.5 to prevent server overload)
networkSampleRate: 0.1, // 0.0 to 1.0 - network request sampling (recommended: 0.1)
interactionSampleRate: 0.1, // 0.0 to 1.0 - user interaction sampling (recommended: 0.1)
enableWebVitals: true, // Capture LCP/INP/CLS/TTFB (requires web-vitals package)
captureLongTasks: true, // Capture long tasks (>50ms on main thread)
captureFetch: true, // Instrument window.fetch
captureXHR: true, // Instrument XMLHttpRequest
captureUserInteractions: false, // Set to true to enable click/scroll tracking
captureBreadcrumbs: true, // Capture event breadcrumbs
maxBreadcrumbs: 100, // Maximum number of breadcrumbs to keep
beforeSend: (event) => {
// Optional: filter or modify events before sending
// Return null to drop the event
// Example: redact email-like strings from error messages
if (event.type === 'error' && typeof event.data?.message === 'string') {
event.data.message = event.data.message.replace(/[A-Z0-9._%+-]+@[A-Z0-9.-]+/gi, '[redacted]')
}
// Example: strip query strings from page URLs
if (event.context?.page?.url) {
const u = new URL(event.context.page.url)
u.search = ''
event.context.page.url = u.toString()
}
return event
}
}))
app.mount('#app')
This automatically sends:
session_starton first load (with normalized path and referrer)page_viewon every route changesession_endon unloaderrorfor uncaught JS errors, unhandled promise rejections, and Vue component errorsperformancemetrics on each page loadweb_vitalmetrics (CLS, LCP, INP, TTFB, FID, FCP, FP)networkrequests (fetch/XHR) with detailed timingresourceloads (images, scripts, stylesheets, etc.)longtaskevents when JavaScript blocks the main threadinteractionevents (if enabled)
Alternative: Composable Setup
If you prefer to initialize RUM manually in your root component:
// App.vue (script setup)
<script setup>
import { useWatchlogRUM } from '@watchlog/rum-vue'
const { rum, custom, captureError } = useWatchlogRUM({
apiKey: 'YOUR_API_KEY',
endpoint: 'https://api.watchlog.ir/rum',
app: 'my-vue-app',
debug: true,
flushInterval: 5000,
captureUserInteractions: true,
})
// Manually capture errors
const handleError = () => {
try {
// your code
} catch (error) {
captureError(error, { component: 'MyComponent' })
}
}
// Send custom events
const handleClick = () => {
custom('button_clicked', 1, { buttonId: 'submit-btn' })
}
</script>
Manual SDK API (Advanced)
For more control, you can use the SDK directly:
import WatchlogRUM from '@watchlog/rum-vue'
// Initialize once at app startup
WatchlogRUM.init({
apiKey: 'YOUR_API_KEY',
endpoint: 'https://api.watchlog.ir/rum',
app: 'my-vue-app',
debug: true,
flushInterval: 10000,
})
// Send custom metric
WatchlogRUM.custom('button_clicked', 1, { extra: 'data' })
// Manually capture errors
WatchlogRUM.captureError(new Error('Something went wrong'), {
component: 'MyComponent',
props: { userId: 123 }
})
// Add breadcrumbs
WatchlogRUM.addBreadcrumb('user', 'User clicked button', 'info', {
buttonId: 'submit'
})
// Flush buffered events (e.g., before manual unload)
WatchlogRUM.flush(true)
Event Types Collected
Same as React SDK. RUM automatically captures:
- session_start — Emitted when a new session begins
- page_view — Route/page navigations (SPA & traditional)
- session_end — Emitted when session ends (on unload)
- web_vital — LCP / INP / CLS / TTFB / FID values
- performance — Navigation timing, paint metrics, and resource timing
- resource — Browser resource timings (duration, size, initiator type)
- network — Fetch/XHR requests with detailed timing and size information
- error — JavaScript errors with message, stack, fingerprint and top paths
- longtask — Long-running JavaScript tasks (>50ms on main thread)
- interaction — User interactions (clicks, scrolls, form submissions) if enabled
- custom — Optional, user-defined events (e.g., business actions)
What It Sends (Wire Format)
The Vue SDK batches events and POSTs a wrapper to /rum:
{
"apiKey": "your-api-key",
"app": "my-vue-app",
"sdk": "watchlog-rum-vue",
"version": "0.3.0",
"sentAt": 1730540000000,
"sessionId": "sess-abc123",
"deviceId": "dev-xyz789",
"environment": "production",
"release": "1.0.0",
"events": [
{
"type": "page_view",
"ts": 1730540000123,
"seq": 1,
"context": {
"page": {
"url": "https://site.com/user/42",
"path": "/user/42",
"normalizedPath": "/user/:id",
"referrer": ""
},
"client": {
"userAgent": "Mozilla/5.0 …",
"language": "en-US",
"timezone": "Europe/Amsterdam"
},
"app": "my-vue-app",
"environment": "production",
"sessionId": "sess-abc123",
"deviceId": "dev-xyz789"
},
"data": {
"name": "page_view"
}
}
]
}
The server-side accepts
apiKey/appfrom either headers or wrapper body. Events includecontextanddata(used for Mongo/Influx mapping).
Vue Configuration Reference
Same as React where applicable. Additional notes:
app,apiKey,endpoint— requiredrouter— required when usingcreateWatchlogRUMPluginfor automatic route trackingenvironment,release— optional labels shown in dashboards and used for filteringbeforeSend— mutate or drop events before export- Router detection uses normalized paths (e.g.,
/user/:id)
Sample Rate Limits & Best Practices
Same as React SDK. See the React section above for detailed recommendations.
Privacy & Redaction
Use beforeSend to drop sensitive events or redact PII. Consider:
- Strip query strings or hashes from URLs
- Remove email addresses, phone numbers, or form values from error messages
- Lower sampling for high-traffic pages to reduce data volume
- Filter out internal/admin routes
Troubleshooting (Vue)
- 400 "Missing apiKey or app": Ensure both are present in the wrapper or
X-Watchlog-Keyheader. - Empty
context/data: You may be using an older version. Update to the latest@watchlog/rum-vuewhich wraps events and setscontext/dataper event. - No navigations captured: Confirm the router instance is passed to the plugin or
useWatchlogRUMis invoked after router creation. - Routes not normalizing correctly: Ensure your Vue Router routes use dynamic segments (e.g.,
/user/:idinstead of/user/:userIdif your route definition uses:userId). - Web Vitals missing: Install
web-vitalsand keepenableWebVitals: true.
Next steps
- Open the dashboard: https://app.watchlog.ir/rum
- Copy your Endpoint and API Key from Connect to RUM.
- Deploy to your staging or production environment.
- Explore: Overview → Web Vitals → Errors → Resources → Sessions.
