Skip to content

feat(analytics): add run_id to every event and $session_id after login#661

Open
gewenyu99 wants to merge 2 commits into
mainfrom
posthog-code/analytics-run-session-id
Open

feat(analytics): add run_id to every event and $session_id after login#661
gewenyu99 wants to merge 2 commits into
mainfrom
posthog-code/analytics-run-session-id

Conversation

@gewenyu99

@gewenyu99 gewenyu99 commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Problem

Wizard analytics events had no per-run correlation id. Before login the distinct id is a fresh anonymous uuid (unique per run), but OAuth switches the distinct id to the real user id, which is shared across all of that user's runs. So two runs by the same person could not be separated, and there was no way to funnel/group the events of a single run.

Separately, production runs carried no build tag at all — it was only set for non-prod builds — so prod runs were indistinguishable from untagged data.

Change

All analytics-only — no OAuth or backend plumbing touched. Identifiers ride on every capture, captureException, and autocaptured exception via the existing this.tags bag.

Per-run correlation

  • run_id — a per-process uuid minted in the Analytics constructor. Always present, so any two runs (even by the same logged-in user) are distinguishable and filterable.
  • $session_idnull until OAuth completes. Set lazily on first identifyUser(), so pre-login events carry only run_id; once authenticated, every event also carries $session_id and PostHog groups the run into a native Session. The two are independent uuids and will essentially never be equal.
  • The setup wizard finished shutdown event hoists run_id (always) and $session_id (when a session was opened) out of the nested tags so the terminal event is filterable/groupable like every other capture.

Build-type tagging

  • build is now always set: 'prod' for published builds (IS_PRODUCTION_BUILD), 'dev' otherwise. CI runs continue to upgrade it to 'ci' in runWizardCI, so prod / dev / ci segment cleanly. Previously prod runs were untagged.

Testing

  • pnpm build
  • pnpm test896 passed ✅ (incl. new run/session-id and build-tag tests; uuid mock now returns distinct values so run_id !== $session_id is reflected)
  • pnpm lint ✅ (exit 0; only pre-existing project-wide warnings)

Wizard analytics events had no per-run correlation id. Before login the
distinct id is a fresh anonymous uuid (unique per run), but OAuth switches
the distinct id to the real user id, which is shared across all that user's
runs — so two runs by the same person could not be separated.

Add two identifiers, both riding on every capture/exception via the existing
tag bag:

- `run_id`: a per-process uuid minted in the constructor. Always present,
  so any two runs (even by the same logged-in user) are now distinguishable.
- `$session_id`: null until OAuth completes. Set lazily on first
  `identifyUser`, so pre-login events carry only `run_id` and post-login
  events also collapse into a native PostHog Session.

The two are independent uuids and will essentially never match; the test
mock now returns distinct values to reflect that.

Analytics-only change — no OAuth or backend plumbing touched.

Generated-By: PostHog Code
Task-Id: b28e6f20-7e1b-48cc-9403-d634921836e3
@github-actions

Copy link
Copy Markdown

🧙 Wizard CI

Run the Wizard CI and test your changes against wizard-workbench example apps by replying with a GitHub comment using one of the following commands:

Test all apps:

  • /wizard-ci all

Test all apps in a directory:

  • /wizard-ci basic-integration
  • /wizard-ci error-tracking-upload-source-maps
  • /wizard-ci misc
  • /wizard-ci revenue

Test an individual app:

  • /wizard-ci basic-integration/android
  • /wizard-ci basic-integration/angular
  • /wizard-ci basic-integration/astro
Show more apps
  • /wizard-ci basic-integration/django
  • /wizard-ci basic-integration/fastapi
  • /wizard-ci basic-integration/flask
  • /wizard-ci basic-integration/javascript-node
  • /wizard-ci basic-integration/javascript-web
  • /wizard-ci basic-integration/laravel
  • /wizard-ci basic-integration/next-js
  • /wizard-ci basic-integration/nuxt
  • /wizard-ci basic-integration/python
  • /wizard-ci basic-integration/rails
  • /wizard-ci basic-integration/react-native
  • /wizard-ci basic-integration/react-router
  • /wizard-ci basic-integration/sveltekit
  • /wizard-ci basic-integration/swift
  • /wizard-ci basic-integration/tanstack-router
  • /wizard-ci basic-integration/tanstack-start
  • /wizard-ci basic-integration/vue
  • /wizard-ci error-tracking-upload-source-maps/android
  • /wizard-ci error-tracking-upload-source-maps/cicd-docker-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-github-actions-docker-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-github-actions-nested-docker-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-github-actions-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-gitlab-node-raw
  • /wizard-ci error-tracking-upload-source-maps/cicd-ssh-vps-node-raw
  • /wizard-ci error-tracking-upload-source-maps/flutter
  • /wizard-ci error-tracking-upload-source-maps/ios
  • /wizard-ci error-tracking-upload-source-maps/next
  • /wizard-ci error-tracking-upload-source-maps/next-no-posthog
  • /wizard-ci error-tracking-upload-source-maps/node-raw
  • /wizard-ci error-tracking-upload-source-maps/node-rollup
  • /wizard-ci error-tracking-upload-source-maps/node-rollup-typescript-plugin
  • /wizard-ci error-tracking-upload-source-maps/node-webpack
  • /wizard-ci error-tracking-upload-source-maps/nuxt-3-6
  • /wizard-ci error-tracking-upload-source-maps/nuxt-4-3
  • /wizard-ci error-tracking-upload-source-maps/react-native
  • /wizard-ci error-tracking-upload-source-maps/react-vite
  • /wizard-ci error-tracking-upload-source-maps/rust
  • /wizard-ci misc/quack-quack
  • /wizard-ci revenue/stripe

Results will be posted here when complete.

Production builds previously carried no `build` tag at all — it was only
set to 'dev' for non-prod builds, then upgraded to 'ci' in CI runs. So prod
runs were indistinguishable from untagged data.

Always set `build` from IS_PRODUCTION_BUILD: 'prod' for published builds,
'dev' otherwise. CI runs continue to upgrade it to 'ci' in runWizardCI, so
all three run types now segment cleanly.

Adds a `build tag` test block that flips IS_PRODUCTION_BUILD via a mocked
@env getter to cover both the prod and dev paths.

Generated-By: PostHog Code
Task-Id: b28e6f20-7e1b-48cc-9403-d634921836e3
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