The names our clients write for you, and what every one of them carries.
These are the names our clients write without being asked. Every one of them is an ordinary log entry: nothing in the backend branches on any name here, and an event you invent yourself is stored, indexed, filtered and grouped identically. What a premade event buys you is a spelling two projects agree on, and a starting-point board that already knows where to look.
Each has its own page, with every attribute it carries and what it never carries.
Measured by the client, with no call of yours involved. Everything the browser tag does is behind consent: before consent is granted nothing is stored and nothing is sent, unless the tag is in ephemeral mode, which keeps nothing on the device and so has no banner to wait for. Lifecycle tracking in a desktop app is off until you turn it on, because a source has no kind and a client cannot know whether an install means anything where it is running.
| Event | Written by | What it means |
|---|---|---|
| page_view | Browser tag | A page or screen was viewed, including single-page-app navigations. |
| session_start | Browser tag, .NET, Tauri | The first entry of a visit or a run. |
| page_leave | Browser tag | A page was left, with visible time and scroll depth. |
| outbound_click | Browser tag | A link to another site was followed. |
| file_download | Browser tag | A link to a file was followed. |
| form_submit | Browser tag | A form was submitted. The form, never its contents. |
| web_vital | Browser tag | One Core Web Vital sample, once per metric per document. |
| app_install | .NET, Tauri, Python | This installation ran for the first time. Lifecycle tracking only. |
| app_launch | .NET, Tauri, Python | Any run of an installed app. Lifecycle tracking only. |
The helpers fill in a convention and nothing more. Everything they produce, log() can produce by hand, and an entry that follows no convention at all is stored and queried identically.
| Event | From | What it means |
|---|---|---|
| exception | error() | Something threw. The tag can also catch uncaught ones, if you turn it on. |
| log | trace() through fatal() | A free-form line, with the level as the severity. |
| identify | user() | This client now knows its user id. Every SDK, not the browser tag. |
| page_view | page() | The same name a browser writes automatically, from a server or a desktop app. |
Two names with no emitter behind them. They are in the vocabulary so that two projects logging the same thing spell it the same way, and the keys are what the pickers offer.
| Event | Written by | What it means |
|---|---|---|
| http.request | You | One request served, with the http.* attributes. |
| measurement | You | A plain numeric sample. The shape every number here takes. |
A client sends a resource once per batch: what is true of the client rather than of one entry. It is merged underneath each entry's own attributes at the edge, so a row ends up self-contained without the session id travelling fifty times over the wire. None of the event pages repeats these.
| Attribute | Sent by | What it holds |
|---|---|---|
| session.id | Every client | The visit or the run. The tag cuts a new one after 30 minutes idle or a new external referrer; an SDK holds one for the process until you rotate it. |
| user.id | Every client, after user() | Only ever the string you passed. Absent until you pass one, and never inferred from anything. |
| browser.language | Every client | A BCP-47 tag. The tag reads it off the browser; an SDK sends what you configured. |
| service.name | SDKs | What your software is called. Configured, never guessed. |
| service.version | SDKs | The build that wrote the entry. What a crash-by-version breakdown groups on. |
| os.type | SDKs | windows, darwin, linux. Defaults to the platform. |
| host.arch | SDKs | The machine architecture. Defaults to the platform. |
| firstrun.channel | SDKs | stable, beta, nightly. Configured. |
| firstrun.test | Every client, in test mode | The JSON boolean true, and only ever when true. Production omits the key rather than sending false, so a staging build cannot move a number somebody is looking at. |
| firstrun.dropped | Every client, when it has dropped | Entries the bounded queue discarded, cumulative. Absent while nothing has been lost. |
The server then stamps project_id, firstrun.source.id and ingested_at, and those win outright: a client cannot claim to have arrived through a source other than the one whose key it used. The full row shape is in the log event reference.
Any element carrying data-fr-event="name" writes an event of that name when it is clicked, with no attributes and no change to what the element already did. A download button stays a plain link that happens to be counted, and it keeps working whether or not the tag loaded.
An event with a name nobody here has heard of, at a severity we have never used, carrying keys we do not suggest, is stored and queried exactly like a page view. Following a convention buys a suggestion in a picker and a shared spelling with the next project. It buys nothing else, and skipping one costs nothing.