Skip to content

fix(analytics): improve PostHog attribution for automations and fix missing user profiles#3179

Open
rafavalls wants to merge 4 commits intomainfrom
rafavalls/debug-chat-failures
Open

fix(analytics): improve PostHog attribution for automations and fix missing user profiles#3179
rafavalls wants to merge 4 commits intomainfrom
rafavalls/debug-chat-failures

Conversation

@rafavalls
Copy link
Copy Markdown
Collaborator

@rafavalls rafavalls commented Apr 24, 2026

What is this contribution about?

Several PostHog attribution issues were found and fixed:

  1. Missing user profilesposthog.identify() was never called server-side, so users appeared as raw IDs (e.g. VWPJPnX0DXgPDMIo5J6CBNTbLOPI6XVS) instead of their name/email in PostHog dashboards.

  2. Automation events attributed to users — Chats and tool calls triggered by automations were captured under the owner user's distinctId, making it impossible to distinguish user-initiated from automation-initiated activity in analytics.

  3. Duplicate/wrong abort events — The server was always firing chat_message_aborted on stream abort, even for user-initiated stops where the frontend already fires chat_message_stopped, causing duplicate events. Non-user aborts also lacked context on why they were aborted.

  4. Missing event context — Events were missing trigger_id, user_agent, virtual_mcp_name, user_id, and automation metadata, making filtering and debugging harder.

Changes

User identity

  • Call posthog.identify() in the user.create hook so every new user gets their name + email linked to their PostHog profile at signup
  • Add name to the existing posthog.identify() call in /domain-setup
  • Refresh user profile and org group (groupIdentify) on every stream run to self-heal legacy users/orgs created before PostHog integration

Automation attribution

  • Automation-triggered runs now use automation_<id> as the PostHog distinctId instead of the owner's user ID
  • Each automation gets posthog.identify()'d with its name, owner, and org so it appears as a named persona in PostHog
  • All events include is_automation, automation_id, automation_name, and trigger_id properties

Abort event semantics

  • RunRegistry now passes typed abort reasons ("cancelled", "server-aborted", "ghost") via AbortController.abort(reason)
  • stream-core reads registrySignal.reason and skips the server event when reason === "cancelled" (user stop button) to avoid duplicating the frontend's chat_message_stopped event
  • All other aborts fire chat_message_aborted with an abort_reason property for debugging

Richer event properties

  • All chat and tool events now include: trigger_id, is_automation, automation_id, automation_name, user_id, user_agent, virtual_mcp_name
  • Credit/quota error detection expanded to catch key_limit and total_limit patterns

Screenshots/Demonstration

N/A — analytics-only change, no UI impact.

How to Test

  1. Sign up a new user → PostHog person should show name + email immediately
  2. Trigger an automation → events in PostHog should appear under automation_<id> persona, not the user
  3. Start a chat and click Stop → only one chat_message_stopped event (from frontend), no server duplicate
  4. Let a stream fail or be force-aborted → chat_message_aborted fires with abort_reason

Review Checklist

  • PR title is clear and descriptive
  • Changes are tested and working
  • No breaking changes (analytics-only)

…arding

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

🧪 Benchmark

Should we run the Virtual MCP strategy benchmark for this PR?

React with 👍 to run the benchmark.

Reaction Action
👍 Run quick benchmark (10 & 128 tools)

Benchmark will run on the next push after you react.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 24, 2026

Release Options

Suggested: Patch (2.275.2) — based on fix: prefix

React with an emoji to override the release type:

Reaction Type Next Version
👍 Prerelease 2.275.2-alpha.1
🎉 Patch 2.275.2
❤️ Minor 2.276.0
🚀 Major 3.0.0

Current version: 2.275.1

Note: If multiple reactions exist, the smallest bump wins. If no reactions, the suggested bump is used (default: patch).

rafavalls and others added 3 commits April 25, 2026 09:56
…ostHog

Use `automation_<id>` as PostHog distinctId for chat and tool events
triggered by automations, so they show up under the automation persona
instead of the owner user. Also propagates automation metadata
(id, name, trigger_id, user_agent) to all captured events and fixes
abort event naming to distinguish user-cancelled from server-aborted runs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… self-heal

Add posthog.identify() for the user and posthog.groupIdentify() for the
organization on every streamCore run. This refreshes the person/group
profile each session so legacy users and orgs that predate the
signup/creation hooks get backfilled automatically.

Also drop the redundant `organization_name` / `organization_slug` event
properties — PostHog resolves them via the organization group. Carry
`virtual_mcp_name` on chat/tool events since virtual MCPs are not a
PostHog group type.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Frontend already emits chat_message_stopped when the user clicks the
stop button (apps/mesh/src/web/components/chat/input.tsx). The server
side was firing the same event for abortReason="cancelled", producing
two events per user cancel. Now we skip the server event for user
cancels and only fire chat_message_aborted for genuine non-user aborts
(tab close, registry race, force-fail, reaped, ghost).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@rafavalls rafavalls changed the title fix(analytics): identify PostHog users server-side on signup and onboarding fix(analytics): improve PostHog attribution for automations and fix missing user profiles Apr 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant