Scanner types

Contents

The scanner type determines the shape of the structured output the model returns. It's chosen when you create a scanner and can't be changed afterwards – to switch types, create a new scanner.

There are four types:

TypeWhat it producesUse it for
MonitorA yes / no verdict, with reasoningFlagging whether a specific condition occurred
ClassifierOne or more tags from a vocabulary you defineBucketing sessions along a dimension
ScorerA numeric score on a scale you defineRating sessions on a dimension
SummarizerA title and prose summaryGenerating a short narrative of what happened

Every type also returns:

  • A confidence score representing how sure the model is about the result – shown as a percentage in the app, stored as a value from 0.0 to 1.0 on the event.
  • Reasoning that explains the result in plain language and may include citations – timestamps that link directly to the relevant moment in the recording's timeline. (Summarizers are the exception: the summary itself plays this role, so there's no separate reasoning field.)
  • A key moment – the single point in the recording the answer rests on. Opening the observation from the What to watch feed starts the recording there.
  • A notability judgment – a score from 0.0 to 1.0 for how much your team would gain from watching the session, with one sentence naming the moment that makes it worth a look. The model judges this on the session's own merits, separately from the scanner's question, and What to watch uses it to pick sessions.

On the $recording_observed event these land as scanner_output_confidence, scanner_output_key_moment_ms, scanner_output_notability, and scanner_output_notability_reason. Observations scanned before key moments and notability existed don't have them.

The reasoning and citations are the most powerful debugging tool you have for tuning a scanner. If the model is making bad calls, the reasoning shows you why.

Monitor

A monitor returns a yes/no verdict for whether the condition in your prompt occurred in the session.

Output

  • verdict – yes or no (or inconclusive if you opt the scanner into it)
  • reasoning – plain-language explanation, with inline citations
  • confidence – how sure the model is

Type-specific config

  • Allow inconclusive verdicts – whether the model can return inconclusive when it genuinely can't tell from the recording. Off by default; turn it on if you'd rather have an explicit "don't know" than push the model into a forced yes/no. It matters most when many matching sessions never reach the flow your question is about.

When to use it

  • "Did the user appear stuck on a page?"
  • "Did the user trigger a billing-related error?"
  • "Did the user complete the onboarding flow?"

Example prompt

Answer yes if the user appears stuck on a page: scrolling without engaging, hovering over elements with no clear CTA, or abandoning the session shortly after arriving. Otherwise answer no.

On $recording_observed – scanner_output_verdict is the string "yes", "no", or "inconclusive". See observations.

PostHog reads your prompt to judge whether a yes is good or bad news (a completed onboarding is good, a payment error is bad) and colors verdicts to match.

An observation page for a monitor scanner: the question, a Yes verdict with confidence, reasoning with timestamp citations, and the rating control, next to the player

Impact and cohorts

The scanner's Overview tab shows the Verdict mix for the selected date range (the last 14 days by default). Each verdict row has a Save as cohort button that saves the users behind that verdict as a static cohort. The cohort covers as many days as the selected range, counted back from today, up to 90 days.

The cohort is a snapshot at creation time and doesn't live-update. Use it anywhere cohorts work: funnel breakdowns, retention analysis, survey targeting, or experiment exclusion.

Classifier

A classifier assigns one or more tags from a vocabulary you define. The app calls these tags categories. You can also allow the model to invent new tags if your vocabulary is incomplete.

Output

  • tags – array of tag strings the model picked
  • reasoning – why these tags
  • confidence – how sure the model is

Type-specific config

  • Categories – the set of allowed tag names. The vocabulary itself is just names – put a short definition of each tag in the prompt so the model knows what it means (see the example below). Include an escape tag such as unclear, because a classifier has to pick something and will otherwise force a weak fit. Once you've written a prompt, Suggest categories with PostHog AI proposes tags, each marked with where it came from: seen in recordings, from your product, or from the goal.
  • Allow multiple categories per session – whether the model can pick more than one per session. Otherwise it picks exactly one.
  • Allow freeform categories – whether the model can invent new tags outside the vocabulary.

When to use it

  • User intent: browsing, purchasing, support_seeking
  • Session outcome: task_completed, task_abandoned, blocked_by_error
  • Page archetype: landing, product_detail, checkout, account

Example prompt + vocabulary

Tag this session with the user's intent. Pick the single best fit from the vocabulary. Don't speculate – if you can't tell, pick unclear.

  • browsing – exploring without a specific goal
  • purchasing – actively trying to buy something
  • support_seeking – looking for help, docs, or a contact channel
  • unclear – not enough signal to decide

On $recording_observed – scanner_output_tags is the array of vocabulary tags. Freeform tags, when allowed, land separately in scanner_output_tags_freeform.

An observation page for a classifier scanner: the assigned categories with confidence and the reasoning with timestamp citations

Impact and cohorts

The scanner's Overview tab ranks the top configured categories and, when freeform categories are allowed, the top freeform ones, for the selected date range (the last 14 days by default). Each category has a Save as cohort button that saves the users tagged with it as a static cohort, covering as many days as the selected range, counted back from today, up to 90 days.

The cohort is a snapshot at creation time and doesn't live-update. Use it anywhere cohorts work: funnel breakdowns, retention analysis, survey targeting, or experiment exclusion.

Scorer

A scorer assigns a numeric score on a scale you define – e.g. 0 to 10 for frustration, or 1 to 5 for clarity. Use it when "how much" matters and a yes/no verdict would lose information.

Output

  • score – numeric value on the scale you defined
  • reasoning – why this score
  • confidence – how sure the model is

Type-specific config

  • Scale – minimum and maximum values. Any numbers will do (decimals included) as long as the minimum is lower, though whole numbers are easier to reason about when you're reading scores later.
  • Score label – optional one-word name for what the scale measures (e.g. "frustration"). Describe what the low and high ends look like in the prompt instead.

When to use it

  • Frustration / friction level
  • Likelihood of completing a goal
  • Severity of an error encountered

Example prompt

Score this session 0 to 10 for how frustrated the user appeared, based on signals like rage clicks, repeated retries of the same action, hovering with no progress, and time spent on dead-end pages. 0 means no visible frustration, 10 means severe and sustained frustration.

On $recording_observed – scanner_output_score is the numeric score. Histograms and percentiles over this field tend to be the most useful insights.

As with monitors, PostHog reads your prompt to judge whether a high score is good or bad news and colors scores to match.

An observation page for a scorer scanner: a score of 5 out of 5 with confidence and the reasoning with timestamp citations

The scanner's Overview tab shows the Score distribution for the selected date range, with the minimum, median, average, and maximum score. There's no cohort button for scorers in the app yet. The API can count affected sessions and create a cohort by score threshold with the min_score and max_score parameters.

Summarizer

A summarizer produces a prose summary of what happened in the session, plus a title and a breakdown of the session into chapters. Think of it as a TL;DR you can drop into a dashboard or feed to another tool.

Output

  • title – one-line summary
  • summary – narrative summary, with inline citations
  • chapters – the session split into parts, each with a short heading, its time span, and a frame that shows it. The observation and the replay player show these as a breakdown of the session.
  • confidence – how sure the model is

Type-specific config

  • Additional context – the core summarizer prompt is built in, so instead of a full prompt you add product context or steering – for example, what the ideal user flow looks like.
  • Summary length – short (1-2 sentences), medium (4-6 sentences, the default), or long (3-5 paragraphs).

When to use it

  • Daily digest of high-signal sessions
  • Triage queues where humans need a one-line preview before clicking in
  • Feeding into a downstream analytics or retrieval pipeline

Example context

Our product is a B2B file-sharing app. The happy path is signing up, creating a workspace, then uploading a first file. Call out where sessions deviate from that flow, and name the exact page where any error appears.

On $recording_observed – scanner_output_title and scanner_output_summary carry the title and summary. The chapters themselves stay on the observation; the event carries only their number, as scanner_output_chapter_count. See observations.

An observation page for a summarizer scanner on its Timeline tab: chapters with thumbnails and durations

Note: Summarizers don't support impact tracking or cohort creation since they produce narrative summaries rather than categorical findings.

Picking a type

Some heuristics:

  • Binary yes/no? Monitor.
  • A small fixed set of buckets? Classifier.
  • A magnitude or "how much"? Scorer.
  • Don't know what you're looking for yet, but want to skim? Summarizer.

If you find yourself encoding a number range as classifier tags ("low / medium / high"), use a scorer instead and bucket downstream in SQL.

Confidence and citations

Confidence is the model's self-reported certainty. It's useful as a filter (e.g. "only alert when confidence > 0.7") but not as ground truth – treat it as a signal, not a guarantee. For actual ground truth, rate observations with a thumbs up or down. The scanner learns from your team's ratings and notes, and applies what it learned on later scans. See improving scanners with ratings.

Citations are emitted inline in the model's free-text output (the reasoning field for monitors, classifiers, and scorers; the summary field for summarizers) and rendered as clickable links in the observation detail view. They jump the embedded player to the timestamp the model points at. They're the single best tool for understanding why a model returned what it did.

Still have questions?

Was this page useful?