Hera, analytics
PKCE analytics, social-login tracking, MFA challenge stats
Hera emits analytics events for several flow-related decisions. They're collected as stdout JSON (audit log shape) and consumable by your log shipper.
Events emitted
PKCE flow events
{"type":"audit","event":"pkce_authorize","client_id":"...","domain":"ciam","ts":"..."}
{"type":"audit","event":"pkce_token_exchange","client_id":"...","domain":"ciam","ts":"..."}
{"type":"audit","event":"pkce_failed","reason":"verifier_mismatch","client_id":"...","ts":"..."}Useful for:
- Tracking PKCE adoption per client.
- Detecting clients that are misimplementing PKCE.
- Validating that
verify-prod-config.yml's PKCE-enforcement is actually firing.
Social login events
{"type":"audit","event":"social_login_initiated","provider":"google","domain":"ciam","ts":"..."}
{"type":"audit","event":"social_login_completed","provider":"google","first_login":true,"domain":"ciam","ts":"..."}
{"type":"audit","event":"social_link_initiated","provider":"google","domain":"ciam","ts":"..."}Useful for:
- Per-provider login counts.
- First-time vs returning per provider.
- Adoption tracking for new social providers.
MFA events
{"type":"audit","event":"mfa_challenge_displayed","method":"totp","domain":"ciam","ts":"..."}
{"type":"audit","event":"mfa_challenge_succeeded","method":"totp","domain":"ciam","ts":"..."}
{"type":"audit","event":"mfa_challenge_failed","method":"totp","domain":"ciam","ts":"..."}Useful for:
- Step-up frequency.
- MFA method preference.
- Failure rate per method (high TOTP fail = users have clock skew or typos).
Captcha events
{"type":"audit","event":"captcha_displayed","flow":"login","domain":"ciam","ts":"..."}
{"type":"audit","event":"captcha_succeeded","flow":"login","domain":"ciam","ts":"..."}
{"type":"audit","event":"captcha_failed","flow":"login","reason":"timeout","domain":"ciam","ts":"..."}Useful for:
- Captcha rate.
- False-positive rate (challenges shown to real users).
Breach-check events
{"type":"audit","event":"breach_check_passed","domain":"ciam","ts":"..."}
{"type":"audit","event":"breach_check_failed","reason":"in_hibp","domain":"ciam","ts":"..."}Useful for:
- How many users pick weak passwords (need to be redirected).
Why stdout JSON
Three reasons:
- No external dependency for Hera (no metrics client to configure).
- Standard log shipper integration.
- Audit-grade, every event is timestamped, structured, parseable.
Where to consume
Operators' choice of log aggregator:
- Loki + Grafana: parse JSON, build dashboards.
- CloudWatch Insights: query JSON natively.
- Datadog / Honeycomb: same.
- Postgres: log shipper writes to a table; Athena reads for the analytics dashboard.
Athena's /analytics page reads from the security_audit table (which recordSecurityAudit from the SDK writes to). If you also want to surface Hera's per-flow analytics there, ship Hera's stdout to the same table via an external log shipper.
PII handling
Hera's analytics events deliberately exclude:
- Identity ID (use the security audit log for that, where access is gated).
- Email address.
- IP address (Caddy log has it; Hera doesn't echo).
This makes the events safe for less-restricted log destinations.
Sampling
Hera doesn't sample, every event is emitted. For high-traffic deployments where event volume becomes a concern, post-process at the log shipper. The cost of sampling at emission time is losing visibility for low-volume flows (which is exactly when you want full data).
Adding a new event
- Decide the event name (
<noun>_<verb>). - Define the payload shape, add to
hera/src/lib/events.ts. - Emit at the relevant code path:
import { emitEvent } from "@/lib/events"; emitEvent({ event: "new_thing", foo: "bar" }); - Document the event in this page.