Monitors

Monitors evaluate real production traffic as it happens, using the same checks you already defined in a Test Suite — rather than a scripted run against synthetic input. There are two kinds, one for each Test Suite type Litmus Lab runs.

MonitorRuns checks fromSource of traffic
API MonitorAn API Workflow suiteA webhook payload your app sends per interaction
UI MonitorA UI Workflow suiteA browser-session recording snippet on your page

API Monitor

An API Monitor links to a Test Suite and evaluates incoming webhook payloads against that suite's checks, automatically. A project can have multiple API Monitors — typically one per suite or integration point.

Setting one up

  1. Create a Monitor and link it to the Test Suite whose checks you want to run.
  2. Map payload fields to variables using JMESPath — the same variables your suite's assertions already reference. For example, response extracts the top-level response field; context.user_id drills into a nested object.
  3. Choose a deduplication variable — usually whatever represents the user's query or request. Litmus Lab embeds it and skips evaluation if a near-identical one arrived in the last 60 minutes, so a burst of repeat traffic doesn't multiply your evaluation cost.
  4. Send payloads to your Monitor's webhook URL with an X-Litmus-Secret header. Litmus Lab stores the capture and evaluates it asynchronously.

Flow step modes

Each step in the linked suite can be configured independently for monitoring:

  • Execute — call the HTTP endpoint normally, then run assertions against the real response.
  • Bypass + run checks — skip the HTTP call; run assertions directly against the variables extracted from the payload. Status-code and response-time checks are filtered out, since there's no real response to check.
  • Bypass entirely — skip the step. Use for setup steps (login, seeding data) that don't apply to already-happened production traffic.

This same field also controls what happens after a step matched via UI Monitor correlation — see that section for what that unlocks. A step positioned after a correlated match still evaluates at its Bypass + run checks default even if you've never touched its mode, same default every step here has always had; set it to Bypass entirely if you don't want it touched by a UI-Monitor-triggered evaluation specifically.

Sampling

Set a sampling rate below 100% to evaluate only a fraction of non-deduplicated captures — useful for high-volume endpoints where evaluating every single request isn't necessary to catch a real regression.

UI Monitor

A project can have multiple UI Monitors, each scoped to a set of URL patterns and linked to whichever Flow (UI Workflow) suites its traffic should be matched against — a marketing site and an authenticated app on the same domain, for instance, can be watched separately with different sampling and suite selection. All of them share a single embed: one script tag, one stream of session recordings, routed to the right monitor by the page it ran on.

Everything is configured from the UI Monitor tab, split across three pages:

  • Monitors — create and order your monitors, each with its own URL pattern(s), linked Flow suites, sampling rate, and on/off status. Patterns are matched in order, so put more specific patterns before broader catch-alls.
  • Capture — your project's webhook secret and the single embed snippet, described below.
  • Sessions — captured sessions as they arrive, and what they matched or didn't.

How capture works

Pasting the embed snippet onto a page installs a small stub that asynchronously loads your project's own hosted capture script, a single file generated and served per-project. It streams session recordings to Litmus Lab in small chunks every 15 seconds or so, rather than buffering an entire session in the browser's memory, and sends one last flush the moment the page unloads so nothing from the tail end of a session is lost to a closed tab. A session is considered done, and evaluated, once it's gone quiet, usually within a couple of minutes of the user stopping, not only when the tab actually closes.

If the page pauses for a few minutes and then picks back up (someone reading a long page, then coming back to click something), capture automatically re-syncs so the recording can pick back up cleanly rather than losing that later activity.

Startup timing: by default, capture starts as soon as the page has finished parsing (technically, on the browser's DOMContentLoaded event), not the instant the hosted script itself loads, and not waiting for images/fonts/other subresources to finish either. This matters if you're deciding where on the page to place code that configures capture before it starts: anywhere in a normal, synchronously-parsed part of the page is safe, since DOMContentLoaded only fires after everything like that has already run, regardless of whether it's above or below the snippet itself.

If you need more control than the default (pausing during a sensitive flow, attaching session properties, opting a visitor out, or delaying the start entirely), see the Client API instead of relying on default behavior alone.

Privacy

Passwords, and anything that looks like a payment card number/CVV or a Social Security Number, are always protected automatically on every project, with nothing to configure. Beyond that floor, the Capture tab gives you your own Block / Ignore / Mask selector rules, plus equivalent litmus-block / litmus-ignore / litmus-mask markup classes, to protect anything specific to your own app. See UI Monitor Privacy for the full rundown, worked examples, and the extra precautions taken so a protected element can't leak through some other path.

Ignored User Agents

Also on the Capture tab: a list of User-Agent patterns whose traffic is accepted but never stored, keeping it out of your live-traffic signal entirely.

On by default: LitmusLab's own scripted UI Workflow test runs use the exact same embed snippet as real visitors, so without this they'd show up in your captured sessions looking identical to a real user. Every project excludes this traffic automatically — nothing to configure.

Your own patterns are opt-in, and separate from the built-in exclusion above — a plain substring match (case-insensitive, not a regex) against the incoming User-Agent header, each with a comment for your own reference. Use this for other automated traffic you'd rather not have in your live-traffic data, such as your own QA tooling. There's no default beyond LitmusLab's own test runner, deliberately — automated traffic can be worth seeing occasionally (how a search crawler renders your page, for instance), so nothing else is excluded unless you ask for it.

This check happens server-side, against the actual incoming request, rather than being baked into the hosted script — so toggling it takes effect on the very next chunk sent, with no script regeneration or cache propagation delay involved.

Client API

The hosted script exposes a small command-queue API, litmus('function', { ...params }), for controlling capture from your own code: pausing through a sensitive flow, attaching session properties, identifying a visitor, or opting someone out. It works even before the script has finished loading, since calls made against the stub are queued and replayed once the real script is ready. See UI Monitor Client API for the full function reference, code examples, and how to guarantee an init call lands before capture auto-starts.

What a UI Monitor session becomes

Once a session is captured, Litmus Lab replays it, breaks it into the same kind of page-state sequence a scripted UI Workflow run produces, and matches that sequence against every Flow (UI Workflow suite) registered in the project:

  • Flow coverage — which Flows the session's steps line up with, and how completely. A session doesn't need to walk a Flow from its very first step to count — arriving partway through (an already-logged-in user, for instance) still gets credit for whatever it actually covered.
  • Checks — for each matched step that has assertions configured, Litmus Lab runs them against the session's own real screenshot and page data, same as a scripted run would, subject to a per-project sampling rate and a recency cache (so the same page state isn't re-checked constantly).
  • Uncovered Activity — real page states real users reached that no Flow has ever registered at all. This is often the most actionable signal a UI Monitor surfaces: it's not "your tests failed," it's "here's real behavior nothing is watching yet."

The Graph tab

A visual map of every page state your UI Workflow Flows have registered and the transitions between them, color-coded by health:

  • Active & ready — registered by a Flow, matched against live traffic recently.
  • Untested — real traffic reached this state, but no Flow has ever registered it (the same states as Uncovered Activity).
  • Stale — registered, but no live session has matched it in a while.
  • Orphaned — a data-hygiene state, not a traffic problem; re-running the Flow usually clears it.

Correlating API checks with real UI sessions

A captured UI Monitor session includes the page's own network traffic — the fetch/XHR calls it made while it played out, not just what's visible on screen. Pointing a UI Monitor at one or more API Monitors lets a matching call get checked against that API Monitor's own suite, using the session's real request and response instead of a synthetic one.

Setting it up

On a UI Monitor's own entry (the Monitors tab), set Referenced API Monitors to the API Monitor(s) whose suite steps this UI Monitor's sessions should be checked against. Whenever a captured call's URL and method match one of those suites' steps, Litmus Lab evaluates that step's checks against the real captured request/response and records the result the same way a webhook capture would.

If two steps across your referenced API Monitors share the exact same endpoint and method with nothing to tell them apart, you'll see a collision warning on save. Add a correlation matcher — a JMESPath expression tested against the request body — to one of them so an ambiguous capture doesn't get silently dropped instead of guessed at.

Continuing the flow past the matched step

Once a captured request resolves to a step, evaluation doesn't have to stop there — it can keep walking forward through the suite's own remaining steps, using Flow step modes exactly as already configured. No separate "which steps continue" setting: the suite's own step order and each step's own mode decide it, the same way they already do for the webhook loop above.

This is what makes checking multi-step behavior against a live session possible without touching your app's code. For example: a chat endpoint's response names a document id it drew from; a later "Fetch Document" step, set to Execute, makes a real call for that document and checks the chat answer against it — all triggered by one real, already-happened chat request a UI Monitor observed rather than a scripted run.

Extracting from headers, not just the body

A linked suite's own Extract steps can pull from Request Headers / Response Headers, not just the request/response body — useful for carrying a session's own auth token into a continuation step. See JMESPath for the header-specific syntax (a literal header name, not a JMESPath expression). Which headers the browser actually captures is inferred from this automatically, with its own privacy posture — see UI Monitor Privacy.

Related