mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-02 22:37:32 +00:00
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 <action@github.com>
This commit is contained in:
@@ -185,6 +185,14 @@ export class MixpanelTelemetryProvider implements TelemetryProvider {
|
||||
this.trackEvent(TelemetryEvents.RUN_BUTTON_CLICKED, runButtonProperties)
|
||||
}
|
||||
|
||||
trackRunTriggeredViaKeybinding(): void {
|
||||
this.trackEvent(TelemetryEvents.RUN_TRIGGERED_KEYBINDING)
|
||||
}
|
||||
|
||||
trackRunTriggeredViaMenu(): void {
|
||||
this.trackEvent(TelemetryEvents.RUN_TRIGGERED_MENU)
|
||||
}
|
||||
|
||||
trackSurvey(
|
||||
stage: 'opened' | 'submitted',
|
||||
responses?: SurveyResponses
|
||||
|
||||
@@ -206,6 +206,8 @@ export interface TelemetryProvider {
|
||||
trackAddApiCreditButtonClicked(): void
|
||||
trackApiCreditTopupButtonPurchaseClicked(amount: number): void
|
||||
trackRunButton(options?: { subscribe_to_run?: boolean }): void
|
||||
trackRunTriggeredViaKeybinding(): void
|
||||
trackRunTriggeredViaMenu(): void
|
||||
|
||||
// Survey flow events
|
||||
trackSurvey(stage: 'opened' | 'submitted', responses?: SurveyResponses): void
|
||||
@@ -255,6 +257,8 @@ export const TelemetryEvents = {
|
||||
|
||||
// Subscription Flow
|
||||
RUN_BUTTON_CLICKED: 'app:run_button_click',
|
||||
RUN_TRIGGERED_KEYBINDING: 'app:run_triggered_keybinding',
|
||||
RUN_TRIGGERED_MENU: 'app:run_triggered_menu',
|
||||
SUBSCRIPTION_REQUIRED_MODAL_OPENED: 'app:subscription_required_modal_opened',
|
||||
SUBSCRIBE_NOW_BUTTON_CLICKED: 'app:subscribe_now_button_clicked',
|
||||
MONTHLY_SUBSCRIPTION_SUCCEEDED: 'app:monthly_subscription_succeeded',
|
||||
|
||||
@@ -2,6 +2,8 @@ import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import { WORKFLOW_ACCEPT_STRING } from '@/platform/workflow/core/types/formats'
|
||||
import { type StatusWsMessageStatus, type TaskItem } from '@/schemas/apiSchema'
|
||||
import { useDialogService } from '@/services/dialogService'
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
import { useLitegraphService } from '@/services/litegraphService'
|
||||
import { useCommandStore } from '@/stores/commandStore'
|
||||
import { useWorkspaceStore } from '@/stores/workspaceStore'
|
||||
@@ -470,7 +472,12 @@ export class ComfyUI {
|
||||
$el('button.comfy-queue-btn', {
|
||||
id: 'queue-button',
|
||||
textContent: 'Queue Prompt',
|
||||
onclick: () => app.queuePrompt(0, this.batchCount)
|
||||
onclick: () => {
|
||||
if (isCloud) {
|
||||
useTelemetry()?.trackRunTriggeredViaMenu()
|
||||
}
|
||||
app.queuePrompt(0, this.batchCount)
|
||||
}
|
||||
}),
|
||||
$el('div', {}, [
|
||||
$el('label', { innerHTML: 'Extra options' }, [
|
||||
@@ -572,7 +579,12 @@ export class ComfyUI {
|
||||
$el('button', {
|
||||
id: 'queue-front-button',
|
||||
textContent: 'Queue Front',
|
||||
onclick: () => app.queuePrompt(-1, this.batchCount)
|
||||
onclick: () => {
|
||||
if (isCloud) {
|
||||
useTelemetry()?.trackRunTriggeredViaMenu()
|
||||
}
|
||||
app.queuePrompt(-1, this.batchCount)
|
||||
}
|
||||
}),
|
||||
$el('button', {
|
||||
$: (b) => (this.queue.button = b as HTMLButtonElement),
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { CORE_KEYBINDINGS } from '@/constants/coreKeybindings'
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { useSettingStore } from '@/platform/settings/settingStore'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
import { app } from '@/scripts/app'
|
||||
import { useCommandStore } from '@/stores/commandStore'
|
||||
import { useDialogStore } from '@/stores/dialogStore'
|
||||
@@ -64,6 +66,14 @@ export const useKeybindingService = () => {
|
||||
|
||||
// Prevent default browser behavior first, then execute the command
|
||||
event.preventDefault()
|
||||
if (
|
||||
isCloud &&
|
||||
(keybinding.commandId === 'Comfy.QueuePrompt' ||
|
||||
keybinding.commandId === 'Comfy.QueuePromptFront' ||
|
||||
keybinding.commandId === 'Comfy.QueueSelectedOutputNodes')
|
||||
) {
|
||||
useTelemetry()?.trackRunTriggeredViaKeybinding()
|
||||
}
|
||||
await commandStore.execute(keybinding.commandId)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ import type { MenuItem } from 'primevue/menuitem'
|
||||
import { ref } from 'vue'
|
||||
|
||||
import { CORE_MENU_COMMANDS } from '@/constants/coreMenuCommands'
|
||||
import { isCloud } from '@/platform/distribution/types'
|
||||
import { useTelemetry } from '@/platform/telemetry'
|
||||
import type { ComfyExtension } from '@/types/comfy'
|
||||
|
||||
import { useCommandStore } from './commandStore'
|
||||
@@ -62,7 +64,17 @@ export const useMenuItemStore = defineStore('menuItem', () => {
|
||||
.map(
|
||||
(command) =>
|
||||
({
|
||||
command: () => commandStore.execute(command.id),
|
||||
command: () => {
|
||||
if (
|
||||
isCloud &&
|
||||
(command.id === 'Comfy.QueuePrompt' ||
|
||||
command.id === 'Comfy.QueuePromptFront' ||
|
||||
command.id === 'Comfy.QueueSelectedOutputNodes')
|
||||
) {
|
||||
useTelemetry()?.trackRunTriggeredViaMenu()
|
||||
}
|
||||
return commandStore.execute(command.id)
|
||||
},
|
||||
label: command.menubarLabel,
|
||||
icon: command.icon,
|
||||
tooltip: command.tooltip,
|
||||
|
||||
Reference in New Issue
Block a user