> For the complete documentation index, see [llms.txt](https://docs.saleschat.pro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.saleschat.pro/application/analytics/events-reference.md).

# Events Reference

What every event and attribute in Analytics means, written in plain English. Your decoder ring for the event and attribute pickers.

Analytics names things the way a system names them — `lead.created`, `participant.sc_type`, `journey.sc_execution_status`. One name always means exactly one thing, which is what makes the numbers reliable, but it does mean the pickers need translating.

That's this page. Keep it open next to the query builder.

{% hint style="info" %}
**The picker is the truth, not this page.**

The event and attribute pickers only ever show what your organisation has **actually produced**. If you've never used campaigns, `journey.started` won't appear. If you've never stored a `city` attribute on a lead, `lead.city` won't appear.

So an event missing from your picker isn't broken — it just hasn't happened yet. And a page like this one can only tell you what a name means, never whether you have it.
{% endhint %}

## How to read a name

**Event names** describe something that happened, in the order *thing → what happened to it*:

```
lead.created            a lead was created
lead.status.updated     a lead's status changed
message.receipt.read    a message was read
```

**Attribute names** are always `area.name`. The part before the dot says which area of the product the detail comes from:

```
lead.sc_status          the lead's status
message.sc_event_sub_type   what kind of message it was
journey.sc_name         the name of the campaign or automation involved
```

The `sc_` in an attribute name simply marks it as a **S**ales**C**hat-defined field. Attributes **you** send never have it — yours appear as `lead.city`, `lead.tier`, `lead.policy_number`.

***

## Events

### Leads

<table><thead><tr><th width="215">Event</th><th width="330">What it means</th><th>Typical use</th></tr></thead><tbody><tr><td><code>lead.created</code></td><td>A new lead was created.</td><td>New-lead volume over time, by source, campaign or any attribute you store</td></tr><tr><td><code>lead.assigned</code></td><td>A lead was assigned to an agent — the first time, or on every reassignment.</td><td>Workload distribution, how leads get routed, how often leads change hands</td></tr><tr><td><code>lead.status.updated</code></td><td>A lead moved between <strong>active</strong>, <strong>inactive</strong> and <strong>expired</strong>. Carries both the old and the new value.</td><td>Churn and expiry, how long leads stay active</td></tr><tr><td><code>lead.attribute.set</code></td><td>A lead's <strong>stage</strong> or <strong>disposition</strong> was set — the SalesChat-managed pipeline fields.</td><td>Pipeline movement: how many leads reached <em>Interested</em>, <em>Qualified</em>, <em>Won</em></td></tr><tr><td><code>lead.attribute.updated</code></td><td>One of <strong>your own</strong> attributes on a lead changed — <code>city</code>, <code>budget</code>, <code>policy_number</code>. Carries every key that changed in that write.</td><td>Tracking data quality and CRM sync; spotting which fields get filled in and when</td></tr><tr><td><code>user.attribute.updated</code></td><td>The same, for an attribute on an <strong>agent</strong> rather than a lead.</td><td>Rare; agent-profile changes</td></tr></tbody></table>

{% hint style="warning" %}
`lead.attribute.updated` does **not** fire when an attribute is deleted. Removing an attribute is currently invisible to Analytics.
{% endhint %}

**Reports built on these:** [new leads and where they come from](/application/analytics/example-reports.md#recipe-1-how-many-new-leads-are-we-getting-and-where-from) · [new vs returning](/application/analytics/example-reports.md#recipe-11-new-leads-vs-returning-conversations) · [new lead to a real conversation](/application/analytics/example-reports.md#recipe-14-from-new-lead-to-a-real-conversation)

### Messages

<table><thead><tr><th width="215">Event</th><th width="330">What it means</th><th>Typical use</th></tr></thead><tbody><tr><td><code>message</code></td><td><strong>Every</strong> message in a lead's conversation, whoever sent it — the lead, an agent, or an automation. Your highest-volume event by far.</td><td>Conversation volume, who is doing the talking, template usage, reply rates</td></tr><tr><td><code>user.message.sent</code></td><td>A message sent <strong>by an agent</strong>, recorded against the agent rather than the lead.</td><td>Agent productivity — use this whenever you want to count <em>agents</em>, not conversations</td></tr><tr><td><code>message.receipt.sent</code></td><td>WhatsApp accepted the message for delivery.</td><td>Delivery funnel</td></tr><tr><td><code>message.receipt.delivered</code></td><td>The message reached the lead's phone.</td><td>Delivery funnel</td></tr><tr><td><code>message.receipt.read</code></td><td>The lead opened the message.</td><td>Read rates by template, campaign or time of day</td></tr></tbody></table>

{% hint style="warning" %}
**Don't add `message` and `user.message.sent` together.**

When an agent sends a message, **both** events are recorded — one about the conversation, one about the agent. Counting both means counting that message twice. Pick the one that matches your question:

* *"How many messages went out?"* → `message`, filtered to `participant.sc_type = user`
* *"How many agents sent something?"* → `user.message.sent`, counted as unique
  {% endhint %}

**Reports built on these:** [who is actually doing the talking](/application/analytics/example-reports.md#recipe-2-who-is-actually-doing-the-talking) · [buttons vs typing](/application/analytics/example-reports.md#recipe-3-are-leads-tapping-our-buttons-or-typing-at-us) · [delivery health](/application/analytics/example-reports.md#recipe-4-is-whatsapp-actually-delivering-our-messages) · [which template earns its place](/application/analytics/example-reports.md#recipe-5-which-template-earns-its-place) · [messages that never went out](/application/analytics/example-reports.md#recipe-6-how-many-of-our-messages-never-went-out)

### Conversations (sessions)

A **session** is one continuous conversation with a lead, from the first message to the point it's closed or times out.

<table><thead><tr><th width="215">Event</th><th width="330">What it means</th><th>Typical use</th></tr></thead><tbody><tr><td><code>lead.session.started</code></td><td>A conversation opened.</td><td>Conversation volume, inbound demand by hour or day</td></tr><tr><td><code>lead.session.queued</code></td><td>The conversation went into the queue waiting for an agent.</td><td>How much of your inbound has to wait for a human</td></tr><tr><td><code>lead.session.ended</code></td><td>The conversation closed. Carries how long it lasted and why it ended.</td><td>Handling time, resolution vs timeout</td></tr></tbody></table>

**Reports built on these:** [how long are our conversations](/application/analytics/example-reports.md#recipe-9-how-long-are-our-conversations) · [how much inbound waits for a human](/application/analytics/example-reports.md#recipe-10-how-much-of-our-inbound-has-to-wait-for-a-human) · [how bad does it get (p90)](/application/analytics/example-reports.md#recipe-20-how-bad-does-it-get-not-how-bad-is-it-on-average)

### Campaigns, automations and inbound rules

Internally, all three are called a **journey** — one name for "something that ran on its own and did something to a lead". `journey.sc_type` tells you which kind you're looking at: `campaign`, `automation` or `inbound`.

<table><thead><tr><th width="215">Event</th><th width="330">What it means</th><th>Typical use</th></tr></thead><tbody><tr><td><code>journey.started</code></td><td>A campaign or automation run began.</td><td>How often automations fire; campaign launches</td></tr><tr><td><code>journey.ended</code></td><td>That run finished.</td><td>Run duration, completion</td></tr><tr><td><code>journey.execution</code></td><td><strong>One attempt against one lead</strong> — the workhorse event. Carries whether it succeeded and, if not, why.</td><td>Automation reliability, failure reasons, how many leads an automation actually reached</td></tr></tbody></table>

{% hint style="info" %}
`journey.execution` counts **runs, not leads**. If an automation fires three times for the same lead, that's three executions. To count leads, use the **Unique** measurement.
{% endhint %}

**Reports built on these:** [is this automation reliable](/application/analytics/example-reports.md#recipe-7-is-this-automation-reliable) · [how many leads did this campaign reach](/application/analytics/example-reports.md#recipe-8-how-many-leads-did-this-campaign-actually-reach) · [which campaign converts best](/application/analytics/example-reports.md#recipe-15-which-campaign-converts-best) · [the full campaign-to-pipeline funnel](/application/analytics/example-reports.md#recipe-26-the-full-campaign-to-pipeline-funnel)

### AI agent events

If your organisation uses the SalesChat AI agent, you'll also see events beginning `ai.`. They behave like any other event here — countable in Trends, usable as a funnel step, filterable and breakable-down.

Agent Studio has a purpose-built surface for reading them, explained in [AI Analytics](/application/ai-analytics.md). That page tells you what a Verdict or a Goal *means*; this one tells you what the names are so you can build your own reports.

<table><thead><tr><th width="180">Event</th><th width="250">One row per…</th><th>Carries</th></tr></thead><tbody><tr><td><code>ai.started</code></td><td>AI conversation, when it begins</td><td>Which agent, and what triggered it</td></tr><tr><td><code>ai.ended</code></td><td>AI conversation, when it finishes</td><td>The verdict, how it ended, how long it took, goals hit</td></tr><tr><td><code>ai.turn</code></td><td>Turn within a conversation</td><td>Tokens, latency, tool calls made in that turn</td></tr><tr><td><code>ai.tool_call</code></td><td><strong>Tool call.</strong> Your highest-volume AI event by far.</td><td>Which tool, whether it worked, and why not</td></tr><tr><td><code>ai.goal</code></td><td>Conversation <strong>×</strong> goal — one row for each goal, for each conversation</td><td>That goal's name, whether it was met, and its score</td></tr></tbody></table>

{% hint style="warning" %}
**Grain is the thing that goes wrong here.** These five events count different objects, and a report built at the wrong one is wrong without looking wrong.

`ai.ended` counts **conversations**. `ai.turn` counts **turns**. `ai.tool_call` counts **calls**. `ai.goal` counts **conversation-and-goal pairs**, so a conversation with three goals contributes three rows — and "how many goals were met" is a different number from "how many conversations met all their goals".

Pick the event that counts the object your question is about, then filter.
{% endhint %}

#### About the conversation — recorded on `ai.ended`

<table><thead><tr><th width="270">Attribute</th><th width="280">What it is</th><th>Values</th></tr></thead><tbody><tr><td><code>ai.sc_verdict</code></td><td>What happened to the conversation. See <a href="/application/ai-analytics.md">AI Analytics</a> for what each one means.</td><td>See the mapping below</td></tr><tr><td><code>ai.sc_end_reason</code></td><td>How the run finished</td><td><code>completed</code>, <code>stopped</code>, <code>handoff</code></td></tr><tr><td><code>ai.sc_ended_by_type</code></td><td><strong>Who</strong> ended it, as distinct from how</td><td><code>ai</code>, <code>human</code>, <code>system</code></td></tr><tr><td><code>ai.sc_handoff_reason</code></td><td>Why it went to a person. Absent when it didn't.</td><td><code>completion</code>, <code>out_of_scope</code>, <code>escalation</code>, <code>timeout</code></td></tr><tr><td><code>ai.sc_duration_secs</code></td><td>How long the conversation lasted, in seconds. A <strong>number</strong> — averageable.</td><td>Any number</td></tr><tr><td><code>ai.sc_agent_name</code></td><td>Which agent handled it</td><td>Your agent names</td></tr><tr><td><code>ai.sc_trigger_source</code></td><td>What started the run</td><td><code>journey</code> (a campaign, automation or inbound rule), <code>user</code> (a person), <code>playground</code> (testing)</td></tr><tr><td><code>ai.sc_category</code></td><td>What the conversation was about</td><td>Your own category labels</td></tr><tr><td><code>ai.sc_goal_achieved</code></td><td>Whether the conversation met its goals — <strong>one value for the whole run</strong></td><td><code>true</code>, <code>false</code></td></tr><tr><td><code>ai.sc_num_goal_achieved</code></td><td>How many goals it met, for the whole run</td><td>Any number</td></tr><tr><td><code>ai.sc_message_count_lead</code> / <code>ai.sc_message_count_agent</code></td><td>Messages each side sent. Distinct from turn count — one turn can carry several lead messages.</td><td>Any number</td></tr><tr><td><code>ai.sc_resolution_kind</code></td><td>Whether a resolution was confirmed or inferred. Only meaningful when the verdict is a resolution.</td><td><code>confirmed</code>, <code>assumed</code></td></tr><tr><td><code>ai.sc_qualification_kind</code></td><td>The same, for qualification and disqualification</td><td><code>confirmed</code>, <code>assumed</code></td></tr><tr><td><code>ai.sc_verdict_reason</code></td><td>Present only when the verdict was not plainly derived</td><td><code>system_failure</code>, <code>backfill</code></td></tr></tbody></table>

**The verdict values are not spelled the way Agent Studio displays them.** Build filters with the left column:

<table><thead><tr><th width="270">Value in the picker</th><th>Shown in Agent Studio as</th></tr></thead><tbody><tr><td><code>resolution</code></td><td>Resolution</td></tr><tr><td><code>procedure_handoff</code></td><td>Procedural handoff</td></tr><tr><td><code>qualification</code></td><td>Qualified</td></tr><tr><td><code>disqualification</code></td><td>Disqualified</td></tr><tr><td><code>escalated</code></td><td>Escalated</td></tr><tr><td><code>spam</code></td><td>Spam</td></tr><tr><td><code>abandoned</code></td><td>Abandoned</td></tr><tr><td><code>abandoned_no_outcome</code></td><td>No outcome</td></tr><tr><td><code>pending</code></td><td>Pending — a rare bookkeeping value on older sessions</td></tr></tbody></table>

#### Per goal — recorded on `ai.goal`

<table><thead><tr><th width="270">Attribute</th><th width="280">What it is</th><th>Values</th></tr></thead><tbody><tr><td><code>ai.sc_goal_name</code></td><td>Which goal this row is about</td><td>Your goal names</td></tr><tr><td><code>ai.sc_goal_met</code></td><td>Whether <strong>this</strong> goal was met in <strong>this</strong> conversation</td><td><code>true</code>, <code>false</code></td></tr><tr><td><code>ai.sc_goal_outcome</code></td><td>The judge's verdict on this goal</td><td>Whatever your goals produce — read the values in the picker</td></tr><tr><td><code>ai.sc_goal_score</code></td><td>The judge's score. A <strong>number</strong>.</td><td>Any number</td></tr></tbody></table>

{% hint style="info" %}
`ai.sc_goal_met` and `ai.sc_goal_achieved` look interchangeable and are not. The first is **per goal** (on `ai.goal`); the second is **per conversation** (on `ai.ended`). Breaking down by `ai.sc_goal_name` only works on the per-goal event — the run-level rollup has no goal name to group by.
{% endhint %}

#### Per turn — recorded on `ai.turn`

<table><thead><tr><th width="270">Attribute</th><th width="280">What it is</th><th>Values</th></tr></thead><tbody><tr><td><code>ai.sc_turn_number</code></td><td>Which turn this was, counting from the start</td><td>Any number</td></tr><tr><td><code>ai.sc_input_tokens</code> / <code>ai.sc_output_tokens</code></td><td>Tokens in and out. Your cost signal.</td><td>Any number</td></tr><tr><td><code>ai.sc_latency_ms</code></td><td>How long the turn took, in milliseconds</td><td>Any number</td></tr><tr><td><code>ai.sc_tool_calls_count</code></td><td>Tool calls made in this turn</td><td>Any number</td></tr><tr><td><code>ai.sc_had_tool_failure</code></td><td>Whether any tool failed during this turn</td><td><code>true</code>, <code>false</code></td></tr><tr><td><code>ai.sc_tool_failures_count</code></td><td>How many failed in this turn</td><td>Any number</td></tr></tbody></table>

#### Per tool call — recorded on `ai.tool_call`

<table><thead><tr><th width="270">Attribute</th><th width="280">What it is</th><th>Values</th></tr></thead><tbody><tr><td><code>ai.sc_tool_name</code></td><td>Which tool was called</td><td>Your tool names</td></tr><tr><td><code>ai.sc_tool_type</code></td><td>What kind of tool</td><td><code>staged</code>, <code>read</code>, <code>mcp</code>, <code>kb</code> (knowledge base), <code>hook</code></td></tr><tr><td><code>ai.sc_result_status</code></td><td>Whether the call worked</td><td><code>ok</code>, <code>tool_error</code>, <code>dry_run</code>, <code>aborted</code></td></tr><tr><td><code>ai.sc_failure_domain</code></td><td><strong>Whose</strong> fault it was. Kept separate from the reason on purpose: a model producing bad arguments is a different problem from a tool being down, and one combined "failure rate" hides both.</td><td><code>model</code>, <code>tool</code>, <code>infra</code></td></tr><tr><td><code>ai.sc_failure_reason</code></td><td>Why it failed</td><td><code>timeout</code>, <code>auth</code>, <code>rate_limited</code>, <code>unavailable</code>, <code>upstream_error</code>, <code>not_found</code>, <code>invalid_args</code>, <code>aborted</code>, <code>other</code></td></tr><tr><td><code>ai.sc_tool_latency_ms</code></td><td>How long the call took</td><td>Any number</td></tr><tr><td><code>ai.sc_checkpoint</code></td><td>Where in the run the call happened</td><td><code>turn</code>, <code>run_close</code></td></tr></tbody></table>

{% hint style="warning" %}
**Counting tool failures: pick your grain deliberately.** These three questions give three different numbers, and only one of them is usually what someone means:

* *How many calls failed?* → `ai.tool_call`, filter `ai.sc_result_status` **is** `tool_error`
* *How many turns had a failure?* → `ai.turn`, filter `ai.sc_had_tool_failure` **is** `true`
* *How many leads were affected?* → the same query, measurement **Unique leads** (see [counting leads once](/application/analytics/example-reports.md#recipe-8-how-many-leads-did-this-campaign-actually-reach))

Failures cluster, so the first number is reliably larger than the second. Counting *conversations* with a failure is not available yet: `ai.sc_had_tool_failure` is recorded on turns, not on `ai.ended`, and **Unique leads** de-duplicates by lead rather than by conversation.
{% endhint %}

#### What isn't offered, and why

Raw identifiers — the run id, the goal id — are deliberately absent from the pickers. Nobody breaks a chart down by a UUID, and a report grouped by one produces a bar per conversation. Use the names instead: `ai.sc_agent_name`, `ai.sc_goal_name`, `ai.sc_tool_name`.

For what the verdicts, goals, qualification and categories actually *mean* — and how to read them without drawing the wrong conclusion — see [AI Analytics](/application/ai-analytics.md).

***

## Attributes

Attributes are what you **filter** and **break down** by. They fall into groups by the part of the product they come from.

{% hint style="info" %}
Not every attribute is on every event — an attribute is only recorded when it's actually relevant to what happened. A `message` event knows about the channel and the sender; a `lead.created` event doesn't.

Rather than memorise this: pick your event first, and the attribute picker will only offer you attributes that event actually carries.
{% endhint %}

### About the lead — `lead.*`

Recorded on **every** event about a lead.

<table><thead><tr><th width="235">Attribute</th><th width="290">What it is</th><th>Values</th></tr></thead><tbody><tr><td><code>lead.sc_status</code></td><td>Where the lead stands right now</td><td><code>active</code>, <code>inactive</code>, <code>expired</code></td></tr><tr><td><code>lead.sc_is_new</code></td><td>Whether the lead was created within 24 hours of this event — new lead vs returning</td><td><code>true</code>, <code>false</code></td></tr><tr><td><code>lead.sc_is_mock</code></td><td>Whether this is an internal or test lead. The <a href="/application/analytics.md#exclude-internal-and-test-leads"><strong>Exclude internal and test leads</strong></a> switch uses this.</td><td><code>true</code>, <code>false</code></td></tr><tr><td><code>lead.sc_campaign</code></td><td>A campaign label, <strong>only if you set one</strong>. Store an attribute named <code>sc_campaign</code> on the lead and it lands here.</td><td>Whatever you send</td></tr><tr><td><code>lead.&#x3C;your key></code></td><td>Every attribute you store on a lead — <code>lead.city</code>, <code>lead.tier</code>, <code>lead.product_interest</code></td><td>Whatever you send</td></tr></tbody></table>

On `lead.attribute.set` events you also get the pipeline fields:

<table><thead><tr><th width="235">Attribute</th><th width="290">What it is</th><th>Values</th></tr></thead><tbody><tr><td><code>lead.sc_stage</code></td><td>The stage the lead was moved to</td><td>Your own stage vocabulary</td></tr><tr><td><code>lead.sc_disposition</code></td><td>The disposition the lead was given</td><td>Your own disposition vocabulary</td></tr></tbody></table>

And on the events that describe a change, the before-and-after:

<table><thead><tr><th width="235">Attribute</th><th width="290">On which event</th><th>Values</th></tr></thead><tbody><tr><td><code>lead.sc_previous_status</code> / <code>lead.sc_new_status</code></td><td><code>lead.status.updated</code></td><td><code>active</code>, <code>inactive</code>, <code>expired</code></td></tr><tr><td><code>lead.sc_assignment_source</code></td><td><code>lead.assigned</code> — how the assignment was made</td><td><code>api</code>, <code>user</code>, <code>support</code></td></tr><tr><td><code>lead.sc_source</code></td><td><code>lead.status.updated</code>, <code>lead.attribute.updated</code> — who made the change</td><td><code>api</code>, <code>user</code>, <code>support</code>, <code>system</code></td></tr></tbody></table>

### About the message — `message.*`

<table><thead><tr><th width="285">Attribute</th><th width="290">What it is</th><th>Values</th></tr></thead><tbody><tr><td><code>message.sc_event_sub_type</code></td><td>What kind of message it was</td><td><code>m.text</code>, <code>m.image</code>, <code>m.video</code>, <code>m.audio</code>, <code>m.file</code>, <code>m.location</code>, <code>sc.template</code>, <code>m.notice</code>, <code>sc.notice</code>, <code>m.emote</code></td></tr><tr><td><code>message.sc_is_template</code></td><td>Whether it was sent from a template</td><td><code>true</code>, <code>false</code></td></tr><tr><td><code>message.sc_reply_kind</code></td><td>How the lead replied — by tapping a button or list option, or by typing</td><td><code>interactive</code>, <code>free_flow</code></td></tr><tr><td><code>message.sc_success</code></td><td>Whether the message actually went out. <code>false</code> means it was blocked before reaching WhatsApp — working hours, moderation, a filtered word or an expired conversation window.</td><td><code>true</code>, <code>false</code></td></tr><tr><td><code>message.sc_event_type</code></td><td>Whether the message was visible in the chat or sent silently</td><td><code>m.room.message</code>, <code>sc.room.message.silent</code></td></tr></tbody></table>

### Who and where — `participant.*` and `room.*`

<table><thead><tr><th width="235">Attribute</th><th width="290">What it is</th><th>Values</th></tr></thead><tbody><tr><td><code>participant.sc_type</code></td><td><strong>Who sent it.</strong> One of the most useful attributes in the whole system.</td><td><code>lead</code> (the customer), <code>user</code> (a human agent), <code>app</code> (a campaign, automation or bot)</td></tr><tr><td><code>room.sc_channel</code></td><td>Which channel the conversation is on</td><td><code>whatsapp</code>, <code>email</code>, <code>call</code>, <code>play</code>, <code>website</code></td></tr></tbody></table>

### The template used — `template.*`

<table><thead><tr><th width="285">Attribute</th><th width="290">What it is</th><th>Values</th></tr></thead><tbody><tr><td><code>template.sc_name</code></td><td>The template's name</td><td>Your template names</td></tr><tr><td><code>template.sc_template_type</code></td><td>Whether it's a WhatsApp-approved template or an internal quick reply</td><td><code>waba</code>, <code>quick reply</code></td></tr><tr><td><code>template.sc_waba_template_category</code></td><td>The category Meta approved it under</td><td><code>marketing</code>, <code>utility</code>, <code>authentication</code>, <code>account_update</code>, <code>issue_resolution</code></td></tr></tbody></table>

### The campaign or automation — `journey.*`

<table><thead><tr><th width="285">Attribute</th><th width="290">What it is</th><th>Values</th></tr></thead><tbody><tr><td><code>journey.sc_name</code></td><td>The name of the campaign, automation or inbound rule</td><td>Your own names</td></tr><tr><td><code>journey.sc_type</code></td><td>Which kind it was</td><td><code>campaign</code>, <code>automation</code>, <code>inbound</code></td></tr><tr><td><code>journey.sc_execution_status</code></td><td>Whether that attempt worked</td><td><code>success</code>, <code>fail</code></td></tr><tr><td><code>journey.sc_execution_failure_type</code></td><td>Why it failed. Absent when it succeeded.</td><td><code>GOVERNANCE_FAILED</code>, <code>MESSAGE_GOVERNANCE_FAILED</code>, <code>ACTIVE_CHATROOM_CONFLICT</code>, <code>SKIPPED</code>, <code>ACTION_FAILED</code>, <code>INTERNAL_ERROR</code></td></tr></tbody></table>

{% hint style="info" %}
**Not every failure is a fault.** The two governance values mean the automation deliberately held back — a send limit or a governance rule stopped it — and `SKIPPED` usually means the lead was already in an AI conversation. Those are the system working as configured. `ACTION_FAILED` and `INTERNAL_ERROR` are the ones worth chasing.
{% endhint %}

`journey.*` is also carried on `message` events, so you can attribute messages back to the campaign or automation that produced them.

### The conversation — `session.*`

<table><thead><tr><th width="285">Attribute</th><th width="290">What it is</th><th>Values</th></tr></thead><tbody><tr><td><code>session.sc_type</code></td><td>Who started it</td><td><code>inbound</code> (the lead), <code>outbound</code> (you)</td></tr><tr><td><code>session.sc_duration_secs</code></td><td>How long it lasted, in seconds. A <strong>number</strong> — you can average it.</td><td>Any number</td></tr><tr><td><code>session.sc_end_reason</code></td><td>Why it closed — closed by the lead, by the agent, or timed out</td><td>See the picker</td></tr></tbody></table>

### How the lead was routed — `assignment_handler.*`

<table><thead><tr><th width="285">Attribute</th><th width="290">What it is</th><th>Values</th></tr></thead><tbody><tr><td><code>assignment_handler.sc_name</code></td><td>The assignment rule that routed the lead to an agent. Absent when no rule was involved.</td><td>Your rule names</td></tr></tbody></table>

***

## Filter operators

<table><thead><tr><th width="200">Operator</th><th>What it does</th></tr></thead><tbody><tr><td><strong>is</strong> / <strong>is not</strong></td><td>Exact match on a single value</td></tr><tr><td><strong>is one of</strong> / <strong>is not one of</strong></td><td>Match against a list — <code>whatsapp</code> or <code>website</code></td></tr><tr><td><strong>contains</strong></td><td>Partial text match, useful for names like <code>diwali_</code></td></tr><tr><td><strong>></strong>, <strong>&#x3C;</strong>, <strong>≥</strong>, <strong>≤</strong></td><td>Number comparisons, for attributes like <code>session.sc_duration_secs</code></td></tr><tr><td><strong>is set</strong> / <strong>is not set</strong></td><td>Whether the attribute was recorded at all. Use this rather than comparing to an empty value.</td></tr></tbody></table>

{% hint style="warning" %}
**"is not" excludes the blanks too.**

`journey.sc_type is not campaign` matches only events that *have* a journey type and it isn't `campaign`. Events with no journey at all are not matched. If you want those as well, use **is not set** as a second condition.
{% endhint %}

Filters apply either to the whole report or to one row of it — [Filters](/application/analytics.md#filters) explains the difference, and [splitting by two things at once](/application/analytics/example-reports.md#recipe-18-split-by-two-things-at-once) is a worked case.

***

## Ready to build something?

Head to [Example Reports](/application/analytics/example-reports.md) — real questions, each with the exact clicks, from a first chart through to attribution and exclusions.
