Skip to content

Commit dad2d80

Browse files
feat(telemetry): add unified run_triggered event for all run initiations (#6499)
Summary - Add new telemetry event: `app:run_triggered` with `{ trigger_source: 'button' | 'keybinding' | 'menu' }`. - Instrument all run initiation paths: - UI Queue button emits `run_triggered` (source `button`) and keeps emitting `run_button_click` for UI-only tracking. - Keybindings (Ctrl+Enter / Ctrl+Shift+Enter) emit `run_triggered` (source `keybinding`). - Menus (menubar + legacy menu buttons) emit `run_triggered` (source `menu`). - Mixpanel provider now supports `trackRunTriggered` and forwards `run_triggered`. - `execution_start` tracking remains unchanged. Motivation GTM observed more `execution_start` events than `run_button_click`. This change clarifies attribution by adding a unified event across all triggers while preserving the UI-only `run_button_click` metric. Files - src/platform/telemetry/types.ts: Add `RunTriggeredMetadata`, `RUN_TRIGGERED`, provider method signature. - src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts: Implement `trackRunTriggered`. - src/components/actionbar/ComfyRunButton/ComfyQueueButton.vue: Emit `run_triggered` on button path. - src/services/keybindingService.ts: Emit `run_triggered` when queue commands are invoked via keybindings. - src/stores/menuItemStore.ts: Emit `run_triggered` for queue commands invoked via menubar. - src/scripts/ui.ts: Emit `run_triggered` for legacy menu queue buttons. Notes - `run_button_click` continues to represent UI button presses only. - `run_triggered` now represents all user-initiated runs with clear source attribution. QA - Cloud build: verify `app:run_triggered` appears with the correct `trigger_source` for button, keybinding, and menu triggers. - Verify `app:run_button_click` only fires for the button path. - Confirm `execution_start` still tracks as before. If preferred, we can extend `run_triggered` with additional fields (e.g., queue mode, batchCount) in a follow-up. ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6499-feat-telemetry-add-unified-run_triggered-event-for-all-run-initiations-29e6d73d3650819fb481d3e0e925c50f) by [Unito](https://www.unito.io) --------- Co-authored-by: GitHub Action <[email protected]>
1 parent f2aea9c commit dad2d80

File tree

5 files changed

+49
-3
lines changed

5 files changed

+49
-3
lines changed

src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,14 @@ export class MixpanelTelemetryProvider implements TelemetryProvider {
185185
this.trackEvent(TelemetryEvents.RUN_BUTTON_CLICKED, runButtonProperties)
186186
}
187187

188+
trackRunTriggeredViaKeybinding(): void {
189+
this.trackEvent(TelemetryEvents.RUN_TRIGGERED_KEYBINDING)
190+
}
191+
192+
trackRunTriggeredViaMenu(): void {
193+
this.trackEvent(TelemetryEvents.RUN_TRIGGERED_MENU)
194+
}
195+
188196
trackSurvey(
189197
stage: 'opened' | 'submitted',
190198
responses?: SurveyResponses

src/platform/telemetry/types.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ export interface TelemetryProvider {
206206
trackAddApiCreditButtonClicked(): void
207207
trackApiCreditTopupButtonPurchaseClicked(amount: number): void
208208
trackRunButton(options?: { subscribe_to_run?: boolean }): void
209+
trackRunTriggeredViaKeybinding(): void
210+
trackRunTriggeredViaMenu(): void
209211

210212
// Survey flow events
211213
trackSurvey(stage: 'opened' | 'submitted', responses?: SurveyResponses): void
@@ -255,6 +257,8 @@ export const TelemetryEvents = {
255257

256258
// Subscription Flow
257259
RUN_BUTTON_CLICKED: 'app:run_button_click',
260+
RUN_TRIGGERED_KEYBINDING: 'app:run_triggered_keybinding',
261+
RUN_TRIGGERED_MENU: 'app:run_triggered_menu',
258262
SUBSCRIPTION_REQUIRED_MODAL_OPENED: 'app:subscription_required_modal_opened',
259263
SUBSCRIBE_NOW_BUTTON_CLICKED: 'app:subscribe_now_button_clicked',
260264
MONTHLY_SUBSCRIPTION_SUCCEEDED: 'app:monthly_subscription_succeeded',

src/scripts/ui.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { useSettingStore } from '@/platform/settings/settingStore'
22
import { WORKFLOW_ACCEPT_STRING } from '@/platform/workflow/core/types/formats'
33
import { type StatusWsMessageStatus, type TaskItem } from '@/schemas/apiSchema'
44
import { useDialogService } from '@/services/dialogService'
5+
import { isCloud } from '@/platform/distribution/types'
6+
import { useTelemetry } from '@/platform/telemetry'
57
import { useLitegraphService } from '@/services/litegraphService'
68
import { useCommandStore } from '@/stores/commandStore'
79
import { useWorkspaceStore } from '@/stores/workspaceStore'
@@ -470,7 +472,12 @@ export class ComfyUI {
470472
$el('button.comfy-queue-btn', {
471473
id: 'queue-button',
472474
textContent: 'Queue Prompt',
473-
onclick: () => app.queuePrompt(0, this.batchCount)
475+
onclick: () => {
476+
if (isCloud) {
477+
useTelemetry()?.trackRunTriggeredViaMenu()
478+
}
479+
app.queuePrompt(0, this.batchCount)
480+
}
474481
}),
475482
$el('div', {}, [
476483
$el('label', { innerHTML: 'Extra options' }, [
@@ -572,7 +579,12 @@ export class ComfyUI {
572579
$el('button', {
573580
id: 'queue-front-button',
574581
textContent: 'Queue Front',
575-
onclick: () => app.queuePrompt(-1, this.batchCount)
582+
onclick: () => {
583+
if (isCloud) {
584+
useTelemetry()?.trackRunTriggeredViaMenu()
585+
}
586+
app.queuePrompt(-1, this.batchCount)
587+
}
576588
}),
577589
$el('button', {
578590
$: (b) => (this.queue.button = b as HTMLButtonElement),

src/services/keybindingService.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { CORE_KEYBINDINGS } from '@/constants/coreKeybindings'
2+
import { isCloud } from '@/platform/distribution/types'
23
import { useSettingStore } from '@/platform/settings/settingStore'
4+
import { useTelemetry } from '@/platform/telemetry'
35
import { app } from '@/scripts/app'
46
import { useCommandStore } from '@/stores/commandStore'
57
import { useDialogStore } from '@/stores/dialogStore'
@@ -64,6 +66,14 @@ export const useKeybindingService = () => {
6466

6567
// Prevent default browser behavior first, then execute the command
6668
event.preventDefault()
69+
if (
70+
isCloud &&
71+
(keybinding.commandId === 'Comfy.QueuePrompt' ||
72+
keybinding.commandId === 'Comfy.QueuePromptFront' ||
73+
keybinding.commandId === 'Comfy.QueueSelectedOutputNodes')
74+
) {
75+
useTelemetry()?.trackRunTriggeredViaKeybinding()
76+
}
6777
await commandStore.execute(keybinding.commandId)
6878
return
6979
}

src/stores/menuItemStore.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import type { MenuItem } from 'primevue/menuitem'
33
import { ref } from 'vue'
44

55
import { CORE_MENU_COMMANDS } from '@/constants/coreMenuCommands'
6+
import { isCloud } from '@/platform/distribution/types'
7+
import { useTelemetry } from '@/platform/telemetry'
68
import type { ComfyExtension } from '@/types/comfy'
79

810
import { useCommandStore } from './commandStore'
@@ -62,7 +64,17 @@ export const useMenuItemStore = defineStore('menuItem', () => {
6264
.map(
6365
(command) =>
6466
({
65-
command: () => commandStore.execute(command.id),
67+
command: () => {
68+
if (
69+
isCloud &&
70+
(command.id === 'Comfy.QueuePrompt' ||
71+
command.id === 'Comfy.QueuePromptFront' ||
72+
command.id === 'Comfy.QueueSelectedOutputNodes')
73+
) {
74+
useTelemetry()?.trackRunTriggeredViaMenu()
75+
}
76+
return commandStore.execute(command.id)
77+
},
6678
label: command.menubarLabel,
6779
icon: command.icon,
6880
tooltip: command.tooltip,

0 commit comments

Comments
 (0)