Observations
Contents
Not yet available to everyone – join the waitlist to get updates.
Each scanner has an Observations tab listing every observation it's produced. Click into one to open the detail view: the structured result, the model's reasoning (with clickable citations that jump the embedded player to the cited moment), and the prompt that produced it – frozen even if you've since edited the scanner.
Observations also surface in the replay player: the observations dock at the bottom of the player lists everything scanners have found about the session you're watching, and is where the Scan this recording action lives.

Observations move through a small state machine:
pending → running → succeeded | failed | ineligible
succeeded– terminal. The structured result is saved and a$recording_observedevent is emitted.failed– terminal. The detail view shows an error reason. See troubleshooting for what each failure kind means.ineligible– terminal. The session can't be analyzed (no recording, too short, no events, etc.). Doesn't count against your quota. See running scanners.
Succeeded, pending, and running observations count against your monthly quota; failed and ineligible ones don't.
Querying observations as events
Every successful observation is captured as a $recording_observed event in your project, so you can build insights, dashboards, and alerts on top of Replay Vision output using PostHog's SQL.
Event properties
| Property | Description |
|---|---|
scanner_name | Human-readable name of the scanner |
scanner_id | Scanner UUID |
scanner_type | monitor, classifier, scorer, or summarizer |
scanner_version | Version of the scanner config that produced this observation |
session_id | The recording that was observed |
triggered_by | schedule (background sweep) or on_demand |
triggered_by_user_id | The user who triggered an on-demand observation; null for background sweeps |
model_used | The model that produced the result |
provider_used | The LLM provider behind model_used |
scanner_output_confidence | The model's confidence (0.0 to 1.0) |
scanner_output_reasoning | Monitor, classifier, and scorer – the model's reasoning text, including any inline citations. Summarizers don't have a separate reasoning field |
scanner_output_verdict | Monitor only – "yes", "no", or "inconclusive" |
scanner_output_tags | Classifier only – the array of vocabulary tags assigned |
scanner_output_tags_freeform | Classifier only – tags outside the vocabulary, when the scanner allows them |
scanner_output_score | Scorer only – the numeric score |
scanner_output_title | Summarizer only – the generated one-line title |
scanner_output_summary | Summarizer only – the generated prose summary |
scanner_output_intent | Summarizer only – one sentence on what the user set out to do |
scanner_output_outcome | Summarizer only – one sentence on how the session ended |
scanner_output_friction_points | Summarizer only – array of named blockers or frustrations (empty if none) |
scanner_output_keywords | Summarizer only – array of lowercase keywords describing the session |
The timestamp on the event is the moment the observation completed, not the moment the underlying recording was captured.
SQL recipes
Monitor: count flagged sessions over time
Sessions a "Dead-end pages" monitor flagged yes, daily, over the last week:
Monitor: true rate (flagged / total)
The proportion of observed sessions a monitor flagged yes:
A gradually rising true rate is often a more useful early-warning signal than the absolute count.
Classifier: top tags
Most common intent tags from a classifier:
Scorer: distribution
Histogram of frustration scores:
For a percentile view:
Summarizer: recent summaries
Latest summaries from a summarizer scanner:
Summarizer: top friction points
Summarizers also emit a scanner_output_friction_points array naming the blockers and frustrations the user hit. Unnesting it gives you a ranked list of what's tripping people up:
Cross-scanner: filter only high-confidence verdicts
Confidence is self-reported, so this is a heuristic, not a guarantee – but it's often a useful filter for downstream automation.
Wiring observations into the rest of PostHog
Insights and dashboards
The recipes above all become insights by saving the query. From there they go on dashboards like any other insight.

Alerts
Alerts on an insight built from $recording_observed give you a notification when the metric crosses a threshold – e.g. "alert me when the dead-end true rate over the last hour exceeds 5%."
Joining to other PostHog data
Because $recording_observed events live alongside everything else in your project, you can join them to anything – pageviews, custom events, person properties, cohorts. A useful pattern: find the events the user fired before the moment a monitor flagged them, grouped by URL.
The join is by session_id. From there it's the same SQL you'd write for any other event.