Tracks: emit studio_telemetry when analytics opt-in/opt-out changes - #4395
Conversation
Emit a studio_telemetry event from the saveAnalyticsEnabled Main-process chokepoint so we can measure how often users opt in or out. The event carries status (on/off) plus surface (onboarding/settings) and ui_version (v1/v2) so the change can be attributed to where and which renderer it came from. Recording is ordered around the config write so the opt-out gate never self-suppresses the event in either direction. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
📊 Performance Test ResultsComparing a3b11c5 vs trunk app-size
site-editor
site-startup
Results are median values from multiple test runs. Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff) |
sejas
left a comment
There was a problem hiding this comment.
The toggle works as expected form the settings modal in Classic and Agentic UI.
@wojtekn , I cannot verify any track event (log) when completing the onboarding. Is that expected?
When completing the onboarding, analyticsOptOut is not saved in shared.json, and therefore there is no opt-out event.
| await updateSharedConfig( { analyticsOptOut: false } ); | ||
| await recordEvent(); | ||
| } else { | ||
| await recordEvent(); | ||
| await updateSharedConfig( { analyticsOptOut: true } ); | ||
| } |
There was a problem hiding this comment.
Out of curiosity, why we execute it in different order?
What do you think about this refactor?
| await updateSharedConfig( { analyticsOptOut: false } ); | |
| await recordEvent(); | |
| } else { | |
| await recordEvent(); | |
| await updateSharedConfig( { analyticsOptOut: true } ); | |
| } | |
| await updateSharedConfig( { analyticsOptOut: false } ); | |
| } else { | |
| await updateSharedConfig( { analyticsOptOut: true } ); | |
| } | |
| await recordEvent(); |
There was a problem hiding this comment.
We execute in a different order to track the event when the user switches from disabled to enabled, and vice versa.
There was a problem hiding this comment.
I don’t think the order will change what is tracked.
I just tried that having a clean state of the app and it worked fine: Is it possible that you already had it off in config file (set during previous test) and when triggered onboarding, it would change value from off to off, so nothing was logged? |
|
I'll try again and remove previous config. |
No, this is the location we already agreed on with the designer. |


Related issues
How AI was used in this PR
Claude Code implemented the change end-to-end from the Linear issue. It traced all four analytics-toggle call sites across both renderers, designed the source-attribution plumbing, wrote the unit tests, and fixed the on-transition self-suppression bug found by me during manual testing. I reviewed the code, ran the app to verify the emitted events, and confirmed the ordering logic.
Proposed Changes
The analytics opt-out toggle shipped across onboarding, legacy Settings, and agentic Settings, but flipping it emitted no telemetry — so we had opt-out with no signal on how often users actually opt in or out. This adds a
studio_telemetryTracks event that fires whenever the toggle changes.The event records:
status—on/offsurface— where it was flipped (onboarding/settings)ui_version— which renderer (v1legacy /v2agentic)recordTracksEventis gated by the current opt-out state, so a naive "record then write" would silently drop the very off-transition we care about (the gate the write just closed suppresses it), and a naive "write then record" would drop the on-transition. Recording is ordered around the config write per direction so the event is always emitted while analytics is still ON, and neither transition self-suppresses.The source attribution is built as a reusable
PreferenceChangeSourcechannel on the preferences write path (not an analytics-only hack), so tracking future settings changes is a small addition in each Main handler rather than new API.No user-visible behavior change — this is telemetry only, and respects the existing opt-out (opted-out users still emit nothing).
Testing Instructions
npm start, then open Settings (agentic or legacy) or onboarding.Would have recorded Tracks event: studio_telemetrylines appear — one withstatus: 'off', one withstatus: 'on'— each carrying the correctsurfaceandui_versionfor where you flipped it.npm test -- apps/studio/src/modules/user-settings/lib/tests/analytics-settings.test.ts— covers both transitions and the record/write ordering.Pre-merge Checklist
Remaining before merge
studio_telemetryand its eventprops (status,surface, plus common propschannel,ui_version,is_a11n,platform,arch,app_version) via the Tracks Registration tool — required for the data to be queryable.