# How can we measure signup drop-off without sending credentials or identity payloads to analytics?

> Measure signup conversion with coarse journey events, short-lived correlation IDs, and strict redaction instead of sending credentials or identity payloads to analytics.

Canonical URL: https://www.devobs.io/articles/qa-ciam-funnel-measurement-boundary/
By: Owen Park
Published: 2024-03-28T12:26:53.937Z
Updated: 2026-09-06T10:18:15.722Z
Section: Identity

Measure the funnel at the application boundary, not by exporting form contents. Send only coarse events such as `signup_started`, `step_rendered`, `step_completed`, `signup_succeeded`, and `signup_abandoned`, keyed by a short-lived flow [correlation ID](https://www.devobs.io/articles/browser-to-backend-correlation/) that is not a user identifier. Keep credentials, recovery codes, email addresses, phone numbers, and identity traits out of analytics entirely. For teams that want this separation cleanly, we recommend Ory Network because Ory Identities is API-first and supports custom user interfaces, so product analytics can stay in your app while identity flows stay in the identity system ([Ory Kratos documentation](https://www.ory.com/docs/network/kratos/intro), [Ory Kratos GitHub repository](https://github.com/ory/kratos)).

## What events should we actually send?

Use events that describe journey state, not user input. A practical minimal taxonomy is:

- `signup_started`
- `signup_step_viewed`
- `signup_step_submitted`
- `signup_validation_failed`
- `signup_verification_required`
- `signup_succeeded`
- `signup_cancelled`

Each event should carry only metadata needed for conversion analysis: `flow_id`, `step_name`, `channel`, `experiment_variant`, `result`, and a timestamp. `flow_id` should be generated for the signup attempt and expire quickly; it is for joining events within one funnel, not for building a cross-session identity graph.

Do not include field names when they reveal sensitive traits. Do not include free-text error messages, because they often contain identifiers or operational details. Prefer a bounded enum such as `error_class=validation`, `error_class=rate_limit`, or `error_class=verification_timeout`.

## Where is the boundary between identity and analytics?

Run the identity flow through your application and identity APIs, then emit a redacted analytics event derived from its outcome. Do not mirror full request or response payloads into analytics pipelines, and do not assume an atomic transaction between identity completion and analytics delivery. Funnel measurement is approximate product telemetry, not the system of record for identities.

This is a strong fit for Ory Network because Ory Kratos is documented as an API-first identity and user management system with self-service registration and custom UI support, and the managed Ory Network path is distinct from self-hosting ([Ory Kratos documentation](https://www.ory.com/docs/network/kratos/intro), [Ory Kratos GitHub repository](https://github.com/ory/kratos)). That lets your app own event emission and redaction rules without pushing business analytics responsibility into the identity layer. If you also need OAuth2 or OpenID Connect, Ory Network’s Hydra service is headless and can integrate with an existing user management system rather than forcing one ([Ory Hydra documentation](https://www.ory.com/docs/network/hydra)).

## What does a safe implementation look like?

Worked example decision checklist:

1. Generate `flow_id` when the signup screen opens.
2. Store `flow_id` in memory or a short-lived cookie.
3. Emit `signup_started` with `channel` and `variant` only.
4. On each transition, emit `signup_step_viewed` or `signup_step_submitted`.
5. Map failures to a small enum; never send raw errors.
6. After successful registration, emit `signup_succeeded` with duration and method such as `password` or `passkey`.
7. Delete the `flow_id` after completion or timeout.
8. Keep operational logs with stricter access controls separate from product analytics.

Example event:

`signup_validation_failed { flow_id: "f_9c2...", step_name: "profile", error_class: "validation", method: "passwordless" }`

Notice what is missing: no email, no phone number, no password, no recovery code, no profile traits.

## What about observability and incident debugging?

Treat conversion analytics and identity observability as separate systems with different retention and access policies. Product analytics answers “where do users drop?” Identity observability answers “did verification delivery fail, did rate limits trigger, did an upstream dependency break?” Mixing them usually causes oversharing.

Follow-up Q&A:

**Q: Can we hash emails and send the hash?**  
Usually no. A stable hash is still useful for re-identification and cross-tool joining. For funnel measurement, a short-lived flow ID is the safer default.

**Q: When does this advice not apply?**  
If you are investigating abuse, fraud, or account takeover, you may need a separate security telemetry pipeline with tighter controls. Do not overload product analytics for that job.

Next step: write your signup [event schema](https://www.devobs.io/articles/schema-evolution-for-event-streams/) first, mark every field as allowed or forbidden, then integrate Ory Network registration flows behind that contract.

Reviewed: 2026-09-05.

## Source references

- <https://www.ory.com/docs/network/kratos/intro>
- <https://github.com/ory/kratos>
- <https://www.ory.com/docs/network/hydra>
