From e34548724dbfd0841a068c47c8493483f2e9f002 Mon Sep 17 00:00:00 2001 From: Christian Byrne Date: Fri, 13 Mar 2026 10:35:13 -0700 Subject: [PATCH] feat(telemetry): add view_mode and is_app_mode to run_button_click event (#9881) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Adds `view_mode` and `is_app_mode` properties to the `app:run_button_click` telemetry event so analytics can segment run button clicks by the user's current view context. ## Changes - **`types.ts`**: Added `view_mode?: string` and `is_app_mode?: boolean` to `RunButtonProperties` - **`PostHogTelemetryProvider.ts`**: Computes `view_mode` and `is_app_mode` from `useAppMode()` in `trackRunButton()` - **`MixpanelTelemetryProvider.ts`**: Same as PostHog (providers are mirrors) ## New Properties | Property | Type | Description | Example Values | |----------|------|-------------|----------------| | `view_mode` | `string` | Granular AppMode value | `'graph'`, `'app'`, `'builder:inputs'`, `'builder:outputs'`, `'builder:arrange'` | | `is_app_mode` | `boolean` | Simplified flag for app mode vs non-app mode | `true` when `mode === 'app' \|\| mode === 'builder:arrange'` | ## Design Decisions - **Both granular and simplified**: `view_mode` gives exact mode for detailed analysis; `is_app_mode` gives a quick boolean for simple segmentation - **Computed in providers**: View mode is read from `useAppMode()` at tracking time, same pattern as `getExecutionContext()` — no changes needed at call sites - **`trigger_source` unchanged**: `keybindingService.ts` already reports `trigger_source: 'keybinding'` regardless of view mode, satisfying the requirement that keybinding invocations are correctly identified even in app mode ## Testing - Typecheck passes (no new errors) - Format and lint pass (no new errors) - Manual verification: all pre-existing errors are in unrelated files (`draftCacheV2.property.test.ts`, `workflowDraftStoreV2.fsm.test.ts`) ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-9881-feat-telemetry-add-view_mode-and-is_app_mode-to-run_button_click-event-3226d73d36508101b3a8c7ff27706f81) by [Unito](https://www.unito.io) --- .../telemetry/providers/cloud/MixpanelTelemetryProvider.ts | 6 +++++- .../telemetry/providers/cloud/PostHogTelemetryProvider.ts | 6 +++++- src/platform/telemetry/types.ts | 2 ++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts b/src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts index 9c7f0a102f..b997c13167 100644 --- a/src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts +++ b/src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts @@ -1,6 +1,7 @@ import type { OverridedMixpanel } from 'mixpanel-browser' import { watch } from 'vue' +import { useAppMode } from '@/composables/useAppMode' import { useCurrentUser } from '@/composables/auth/useCurrentUser' import { checkForCompletedTopup as checkTopupUtil, @@ -278,6 +279,7 @@ export class MixpanelTelemetryProvider implements TelemetryProvider { trigger_source?: ExecutionTriggerSource }): void { const executionContext = getExecutionContext() + const { mode, isAppMode } = useAppMode() const runButtonProperties: RunButtonProperties = { subscribe_to_run: options?.subscribe_to_run || false, @@ -290,7 +292,9 @@ export class MixpanelTelemetryProvider implements TelemetryProvider { api_node_names: executionContext.api_node_names, has_toolkit_nodes: executionContext.has_toolkit_nodes, toolkit_node_names: executionContext.toolkit_node_names, - trigger_source: options?.trigger_source + trigger_source: options?.trigger_source, + view_mode: mode.value, + is_app_mode: isAppMode.value } this.lastTriggerSource = options?.trigger_source diff --git a/src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts b/src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts index e57dcbfbad..4a3be1c2a5 100644 --- a/src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts +++ b/src/platform/telemetry/providers/cloud/PostHogTelemetryProvider.ts @@ -1,6 +1,7 @@ import type { PostHog } from 'posthog-js' import { watch } from 'vue' +import { useAppMode } from '@/composables/useAppMode' import { useCurrentUser } from '@/composables/auth/useCurrentUser' import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription' import { remoteConfig } from '@/platform/remoteConfig/remoteConfig' @@ -277,6 +278,7 @@ export class PostHogTelemetryProvider implements TelemetryProvider { trigger_source?: ExecutionTriggerSource }): void { const executionContext = getExecutionContext() + const { mode, isAppMode } = useAppMode() const runButtonProperties: RunButtonProperties = { subscribe_to_run: options?.subscribe_to_run || false, @@ -289,7 +291,9 @@ export class PostHogTelemetryProvider implements TelemetryProvider { api_node_names: executionContext.api_node_names, has_toolkit_nodes: executionContext.has_toolkit_nodes, toolkit_node_names: executionContext.toolkit_node_names, - trigger_source: options?.trigger_source + trigger_source: options?.trigger_source, + view_mode: mode.value, + is_app_mode: isAppMode.value } this.lastTriggerSource = options?.trigger_source diff --git a/src/platform/telemetry/types.ts b/src/platform/telemetry/types.ts index d1da6f1730..f4a5607372 100644 --- a/src/platform/telemetry/types.ts +++ b/src/platform/telemetry/types.ts @@ -63,6 +63,8 @@ export interface RunButtonProperties { has_toolkit_nodes: boolean toolkit_node_names: string[] trigger_source?: ExecutionTriggerSource + view_mode?: string + is_app_mode?: boolean } /**