Skip to main content
The browser shows Corbado Observe how a login went. Your backend often knows facts the page does not. Frequent examples are who signed in (when your internal user ID is not exposed in the frontend), which login methods the account has and how trustworthy the attempt was. Enrichment attaches such facts to the journey the browser captured, so you can analyze them together. Enrichment is optional. Autocapture and custom events already record the complete journey: methods, attempts, errors and outcomes. Add enrichment only when you need an analysis that depends on a fact the browser cannot observe, as described in where Autocapture stops.
A login flow in the browser: open login, enter email, password, signed in. Below it, your backend adds three facts at matching moments: the account lookup adds login_methods passkey when the email is entered, the bot check adds bot_level 1 during the password step and the confirmed login adds userId user_42. Corbado Observe shows one login flow carrying all three values.A login flow in the browser: open login, enter email, password, signed in. Below it, your backend adds three facts at matching moments: the account lookup adds login_methods passkey when the email is entered, the bot check adds bot_level 1 during the password step and the confirmed login adds userId user_42. Corbado Observe shows one login flow carrying all three values.

In this example, each backend fact attaches at its own moment of the same login. Observe stores all of them on that one flow.

1. Possible use cases

You can send any fact your backend knows as a user reference, a tag or an experiment assignment. These are common examples; add only what your analyses need: The user ID is usually the most valuable one. It powers user search, per-user analysis and exports that join your own records. Account login methods turn adoption numbers into a planning basis: they separate users who cannot use a passkey yet from users who have one and do not use it. A bot verdict keeps automated traffic out of your conversion rates.

2. Choose how the value reaches Observe

There are two routes. Both produce the same flow_enriched event and the same result in analytics. Prefer the page when the value is already there: it needs no API key and no correlation. With Autocapture, the backend route adds the values without changing your frontend. Send values that remove traffic from your KPIs, such as a bot verdict, from your backend even if the page knows them. A value set in the browser can be faked, so a bot could mark itself as human.

3. Choose the moment

Send each value when your backend learns it, while the journey runs:
  • Account lookup: after the user enters an identifier, your backend checks whether the account exists. It knows the account’s login methods at this point. Use "at": "during".
  • Bot or risk check: send the verdict with the time of the check. Run the check while the login is in progress, not on page load before it starts. Use "at": "during": the default finished only reaches journeys that finished, so blocked or abandoned attempts would get no verdict.
  • Login confirmed: your backend knows the authenticated user. Use the default "at": "finished".
Logins without an identifier entry, such as a passkey from autofill or a direct social login, never reach the account lookup. Send account values again when the login is confirmed, or these logins arrive without them and distort your rates.
A user ID sent at the account lookup names the account that was targeted. It does not prove who made the attempt. Only the confirmed login establishes the user; see users and identifiers.

4. Connect the backend to the journey

Skip this section if you send from the page. A backend request has to identify the browser session. Set exactly one of these fields: A good shared ID is one your page already sends to your backend, such as a request, correlation, debug or support ID per attempt in UUID format. Use one ID per attempt, not per user. Never use a secret such as a session token or the token of a bot check.
1

Create an API key

Create a key with permission observe:events:write under Observe → Settings → API keys. Keep it in your backend. See authentication.
2

Share the ID from the browser

With the transaction ID, record it on the open login flow:
With the session ID, read it and send it with your login request instead:
If the session ID is empty, your backend skips the enrichment.
3

Send events from your backend

Post to https://api.cloud.corbado.io/v1/observe/events with the key as bearer token. The examples in section 5 show the request body. Use a new event id per event and keep it on retries: retries with the same transaction ID and event id are deduplicated. The request may arrive before or after the browser events.

5. Examples

Send the authenticated user when the login is confirmed.From the page:
From your backend:
Without data, the event matches the login finishing nearest to that time. You can send a hash as userId; see user references.
The backend requests use these fields:

6. Example in detail: bot verdict

Bot detection is the typical value that never reaches the browser. The detection service scores the attempt and returns the result to your backend only. Your other analytics tools usually receive it the same way, through a backend export.
Two lanes joined by a shared transaction ID. In the browser lane, the Observe SDK captures the login flow and sends the transaction ID with it. In the backend lane, your server receives a bot level from its bot-detection service and sends a flow_enriched event with the same transaction ID and the tag bot_level 4. Observe matches both by the transaction ID and the time of the check and attaches bot_level 4 to the login flow. A saved filter then excludes high bot levels from the dashboard.Two lanes joined by a shared transaction ID. In the browser lane, the Observe SDK captures the login flow and sends the transaction ID with it. In the backend lane, your server receives a bot level from its bot-detection service and sends a flow_enriched event with the same transaction ID and the tag bot_level 4. Observe matches both by the transaction ID and the time of the check and attaches bot_level 4 to the login flow. A saved filter then excludes high bot levels from the dashboard.

The browser and your backend share one transaction ID per attempt. Observe uses it to attach the backend verdict to the login running at that time.

  1. Map the verdict: send a level or category, not a raw score or the vendor response. Agree which levels count as bots, for example 4 and 5.
  2. Send one event per check: use the time of the check as timestamp. If a journey has several checks, the last level wins.
  3. Add your decision (optional): send what your backend did with the attempt, for example risk_action with allow, challenge or block. This separates attempts you blocked from attempts where the user failed.
  4. No verdict, no event: if the check did not run, send nothing. The journey then carries no level and stays in your KPIs.
  5. Filter in analytics: save a filter that excludes the bot levels, so dashboards match the bot filter of your other analytics tools.

7. How Observe matches the event

Observe attaches each enrichment to the journey that runs at the time of the event, by default the login. Small clock differences between browser and backend are tolerated. If a value arrives twice, the latest one wins. If no journey matches, the value is dropped. You can choose another flow type or target a specific browser event instead. The Create new events reference lists all options.

8. Test before a production rollout

You can test the backend route without deploying it:
  1. Run your login page locally with the Observe SDK pointed at a test project.
  2. Complete a login and note the transaction ID or session ID.
  3. Send the example requests from section 5 with test values, for example bot_level: "5".
  4. Open the flow in Observe → Debugging → User search and check the user and tags.
Also test a login without identifier entry. Volume and timing under real traffic are only visible in staging or production.

9. Use the result in analytics

User IDs work in user search and exports without further setup. Enriched tags behave like any other tag: ask Corbado to add the key to the relevant time series, then filter or segment by it.
  • Values: short, predictable, lowercase strings.
  • Missing values: leave the key out instead of sending unknown.
  • No personal data: never send IP addresses, locations, network providers or device fingerprints as tags.

10. Next steps