Skip to content

Commit de53526

Browse files
arjansinghtrevorreznik05christian-byrneclaude
authored
feat(telemetry): help center and workflow creation (#6505)
## Summary For Cloud distribution: 1. Track help center usage 2. Track workflow creation ┆Issue is synchronized with this [Notion page](https://www.notion.so/PR-6505-feat-telemetry-help-center-and-workflow-creation-29e6d73d36508185af8ccbf19d5af9e7) by [Unito](https://www.unito.io) --------- Co-authored-by: Christian Byrne <[email protected]> Co-authored-by: Christian Byrne <[email protected]> Co-authored-by: Claude <[email protected]>
1 parent dad2d80 commit de53526

File tree

9 files changed

+190
-18
lines changed

9 files changed

+190
-18
lines changed

src/components/actionbar/ComfyRunButton/ComfyQueueButton.vue

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,7 @@ const queuePrompt = async (e: Event) => {
158158
? 'Comfy.QueuePromptFront'
159159
: 'Comfy.QueuePrompt'
160160
161-
if (isCloud) {
162-
useTelemetry()?.trackRunButton({ subscribe_to_run: false })
163-
}
161+
useTelemetry()?.trackRunButton({ subscribe_to_run: false })
164162
165163
await commandStore.execute(commandId)
166164
}

src/components/dialog/content/ErrorDialogContent.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ import { useI18n } from 'vue-i18n'
6161
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
6262
import FindIssueButton from '@/components/dialog/content/error/FindIssueButton.vue'
6363
import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
64+
import { useTelemetry } from '@/platform/telemetry'
6465
import { api } from '@/scripts/api'
6566
import { app } from '@/scripts/app'
6667
import { useCommandStore } from '@/stores/commandStore'
@@ -92,12 +93,18 @@ const showReport = () => {
9293
const toast = useToast()
9394
const { t } = useI18n()
9495
const systemStatsStore = useSystemStatsStore()
96+
const telemetry = useTelemetry()
9597
9698
const title = computed<string>(
9799
() => error.nodeType ?? error.exceptionType ?? t('errorDialog.defaultTitle')
98100
)
99101
100102
const showContactSupport = async () => {
103+
telemetry?.trackHelpResourceClicked({
104+
resource_type: 'help_feedback',
105+
is_external: true,
106+
source: 'error_dialog'
107+
})
101108
await useCommandStore().execute('Comfy.ContactSupport')
102109
}
103110

src/components/dialog/content/setting/CreditsPanel.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ import UserCredit from '@/components/common/UserCredit.vue'
124124
import UsageLogsTable from '@/components/dialog/content/setting/UsageLogsTable.vue'
125125
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
126126
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
127+
import { useTelemetry } from '@/platform/telemetry'
127128
import { useDialogService } from '@/services/dialogService'
128129
import { useCommandStore } from '@/stores/commandStore'
129130
import { useFirebaseAuthStore } from '@/stores/firebaseAuthStore'
@@ -140,6 +141,7 @@ const dialogService = useDialogService()
140141
const authStore = useFirebaseAuthStore()
141142
const authActions = useFirebaseAuthActions()
142143
const commandStore = useCommandStore()
144+
const telemetry = useTelemetry()
143145
const { isActiveSubscription } = useSubscription()
144146
const loading = computed(() => authStore.loading)
145147
const balanceLoading = computed(() => authStore.isFetchingBalance)
@@ -170,6 +172,11 @@ const handleCreditsHistoryClick = async () => {
170172
}
171173
172174
const handleMessageSupport = async () => {
175+
telemetry?.trackHelpResourceClicked({
176+
resource_type: 'help_feedback',
177+
is_external: true,
178+
source: 'credits_panel'
179+
})
173180
await commandStore.execute('Comfy.ContactSupport')
174181
}
175182

src/components/helpcenter/HelpCenterMenuContent.vue

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,13 +138,14 @@
138138

139139
<script setup lang="ts">
140140
import Button from 'primevue/button'
141-
import { computed, nextTick, onMounted, ref } from 'vue'
141+
import { computed, nextTick, onBeforeUnmount, onMounted, ref } from 'vue'
142142
import type { CSSProperties, Component } from 'vue'
143143
import { useI18n } from 'vue-i18n'
144144
145145
import PuzzleIcon from '@/components/icons/PuzzleIcon.vue'
146146
import { isCloud } from '@/platform/distribution/types'
147147
import { useSettingStore } from '@/platform/settings/settingStore'
148+
import { useTelemetry } from '@/platform/telemetry'
148149
import type { ReleaseNote } from '@/platform/updates/common/releaseService'
149150
import { useReleaseStore } from '@/platform/updates/common/releaseStore'
150151
import { useCommandStore } from '@/stores/commandStore'
@@ -196,6 +197,7 @@ const { t, locale } = useI18n()
196197
const releaseStore = useReleaseStore()
197198
const commandStore = useCommandStore()
198199
const settingStore = useSettingStore()
200+
const telemetry = useTelemetry()
199201
200202
// Emits
201203
const emit = defineEmits<{
@@ -207,6 +209,7 @@ const isSubmenuVisible = ref(false)
207209
const submenuRef = ref<HTMLElement | null>(null)
208210
const submenuStyle = ref<CSSProperties>({})
209211
let hoverTimeout: number | null = null
212+
const openedAt = ref<number>(Date.now())
210213
211214
// Computed
212215
const hasReleases = computed(() => releaseStore.releases.length > 0)
@@ -226,6 +229,7 @@ const moreItems = computed<MenuItem[]>(() => {
226229
label: t('helpCenter.desktopUserGuide'),
227230
visible: isElectron(),
228231
action: () => {
232+
trackResourceClick('docs', true)
229233
const docsUrl =
230234
electronAPI().getPlatform() === 'darwin'
231235
? EXTERNAL_LINKS.DESKTOP_GUIDE_MACOS
@@ -281,6 +285,7 @@ const menuItems = computed<MenuItem[]>(() => {
281285
icon: 'pi pi-book',
282286
label: t('helpCenter.docs'),
283287
action: () => {
288+
trackResourceClick('docs', true)
284289
openExternalLink(EXTERNAL_LINKS.DOCS)
285290
emit('close')
286291
}
@@ -291,6 +296,7 @@ const menuItems = computed<MenuItem[]>(() => {
291296
icon: 'pi pi-discord',
292297
label: 'Discord',
293298
action: () => {
299+
trackResourceClick('discord', true)
294300
openExternalLink(EXTERNAL_LINKS.DISCORD)
295301
emit('close')
296302
}
@@ -301,6 +307,7 @@ const menuItems = computed<MenuItem[]>(() => {
301307
icon: 'pi pi-github',
302308
label: t('helpCenter.github'),
303309
action: () => {
310+
trackResourceClick('github', true)
304311
openExternalLink(EXTERNAL_LINKS.GITHUB)
305312
emit('close')
306313
}
@@ -311,6 +318,7 @@ const menuItems = computed<MenuItem[]>(() => {
311318
icon: 'pi pi-question-circle',
312319
label: t('helpCenter.helpFeedback'),
313320
action: () => {
321+
trackResourceClick('help_feedback', false)
314322
void commandStore.execute('Comfy.ContactSupport')
315323
emit('close')
316324
}
@@ -326,6 +334,7 @@ const menuItems = computed<MenuItem[]>(() => {
326334
label: t('helpCenter.managerExtension'),
327335
showRedDot: shouldShowManagerRedDot.value,
328336
action: async () => {
337+
trackResourceClick('manager', false)
329338
await useManagerState().openManager({
330339
initialTab: ManagerTab.All,
331340
showToastOnLegacyError: false
@@ -349,6 +358,23 @@ const menuItems = computed<MenuItem[]>(() => {
349358
})
350359
351360
// Utility Functions
361+
const trackResourceClick = (
362+
resourceType:
363+
| 'docs'
364+
| 'discord'
365+
| 'github'
366+
| 'help_feedback'
367+
| 'manager'
368+
| 'release_notes',
369+
isExternal: boolean
370+
): void => {
371+
telemetry?.trackHelpResourceClicked({
372+
resource_type: resourceType,
373+
is_external: isExternal,
374+
source: 'help_center'
375+
})
376+
}
377+
352378
const openExternalLink = (url: string): void => {
353379
window.open(url, '_blank', 'noopener,noreferrer')
354380
}
@@ -504,6 +530,7 @@ const onReinstall = (): void => {
504530
}
505531
506532
const onReleaseClick = (release: ReleaseNote): void => {
533+
trackResourceClick('release_notes', true)
507534
void releaseStore.handleShowChangelog(release.version)
508535
const versionAnchor = formatVersionAnchor(release.version)
509536
const changelogUrl = `${getChangelogUrl()}#${versionAnchor}`
@@ -512,6 +539,7 @@ const onReleaseClick = (release: ReleaseNote): void => {
512539
}
513540
514541
const onUpdate = (_: ReleaseNote): void => {
542+
trackResourceClick('docs', true)
515543
openExternalLink(EXTERNAL_LINKS.UPDATE_GUIDE)
516544
emit('close')
517545
}
@@ -526,10 +554,16 @@ const getChangelogUrl = (): string => {
526554
527555
// Lifecycle
528556
onMounted(async () => {
557+
telemetry?.trackHelpCenterOpened({ source: 'sidebar' })
529558
if (!hasReleases.value) {
530559
await releaseStore.fetchReleases()
531560
}
532561
})
562+
563+
onBeforeUnmount(() => {
564+
const timeSpentSeconds = Math.round((Date.now() - openedAt.value) / 1000)
565+
telemetry?.trackHelpCenterClosed({ time_spent_seconds: timeSpentSeconds })
566+
})
533567
</script>
534568

535569
<style scoped>

src/composables/useCoreCommands.ts

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import type { Point } from '@/lib/litegraph/src/litegraph'
1919
import { useAssetBrowserDialog } from '@/platform/assets/composables/useAssetBrowserDialog'
2020
import { createModelNodeFromAsset } from '@/platform/assets/utils/createModelNodeFromAsset'
2121
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
22-
import { isCloud } from '@/platform/distribution/types'
2322
import { useSettingStore } from '@/platform/settings/settingStore'
2423
import { SUPPORT_URL } from '@/platform/support/config'
2524
import { useTelemetry } from '@/platform/telemetry'
@@ -74,6 +73,7 @@ export function useCoreCommands(): ComfyCommand[] {
7473
const toastStore = useToastStore()
7574
const canvasStore = useCanvasStore()
7675
const executionStore = useExecutionStore()
76+
const telemetry = useTelemetry()
7777

7878
const bottomPanelStore = useBottomPanelStore()
7979

@@ -102,7 +102,14 @@ export function useCoreCommands(): ComfyCommand[] {
102102
label: 'New Blank Workflow',
103103
menubarLabel: 'New',
104104
category: 'essentials' as const,
105-
function: () => workflowService.loadBlankWorkflow()
105+
function: async () => {
106+
const previousWorkflowHadNodes = app.graph._nodes.length > 0
107+
await workflowService.loadBlankWorkflow()
108+
telemetry?.trackWorkflowCreated({
109+
workflow_type: 'blank',
110+
previous_workflow_had_nodes: previousWorkflowHadNodes
111+
})
112+
}
106113
},
107114
{
108115
id: 'Comfy.OpenWorkflow',
@@ -118,7 +125,14 @@ export function useCoreCommands(): ComfyCommand[] {
118125
id: 'Comfy.LoadDefaultWorkflow',
119126
icon: 'pi pi-code',
120127
label: 'Load Default Workflow',
121-
function: () => workflowService.loadDefaultWorkflow()
128+
function: async () => {
129+
const previousWorkflowHadNodes = app.graph._nodes.length > 0
130+
await workflowService.loadDefaultWorkflow()
131+
telemetry?.trackWorkflowCreated({
132+
workflow_type: 'default',
133+
previous_workflow_had_nodes: previousWorkflowHadNodes
134+
})
135+
}
122136
},
123137
{
124138
id: 'Comfy.SaveWorkflow',
@@ -460,9 +474,7 @@ export function useCoreCommands(): ComfyCommand[] {
460474

461475
const batchCount = useQueueSettingsStore().batchCount
462476

463-
if (isCloud) {
464-
useTelemetry()?.trackWorkflowExecution()
465-
}
477+
useTelemetry()?.trackWorkflowExecution()
466478

467479
await app.queuePrompt(0, batchCount)
468480
}
@@ -481,9 +493,7 @@ export function useCoreCommands(): ComfyCommand[] {
481493

482494
const batchCount = useQueueSettingsStore().batchCount
483495

484-
if (isCloud) {
485-
useTelemetry()?.trackWorkflowExecution()
486-
}
496+
useTelemetry()?.trackWorkflowExecution()
487497

488498
await app.queuePrompt(-1, batchCount)
489499
}
@@ -721,6 +731,11 @@ export function useCoreCommands(): ComfyCommand[] {
721731
menubarLabel: 'ComfyUI Issues',
722732
versionAdded: '1.5.5',
723733
function: () => {
734+
telemetry?.trackHelpResourceClicked({
735+
resource_type: 'github',
736+
is_external: true,
737+
source: 'menu'
738+
})
724739
window.open(
725740
'https://github.com/comfyanonymous/ComfyUI/issues',
726741
'_blank'
@@ -734,6 +749,11 @@ export function useCoreCommands(): ComfyCommand[] {
734749
menubarLabel: 'ComfyUI Docs',
735750
versionAdded: '1.5.5',
736751
function: () => {
752+
telemetry?.trackHelpResourceClicked({
753+
resource_type: 'docs',
754+
is_external: true,
755+
source: 'menu'
756+
})
737757
window.open('https://docs.comfy.org/', '_blank')
738758
}
739759
},
@@ -744,6 +764,11 @@ export function useCoreCommands(): ComfyCommand[] {
744764
menubarLabel: 'Comfy-Org Discord',
745765
versionAdded: '1.5.5',
746766
function: () => {
767+
telemetry?.trackHelpResourceClicked({
768+
resource_type: 'discord',
769+
is_external: true,
770+
source: 'menu'
771+
})
747772
window.open('https://www.comfy.org/discord', '_blank')
748773
}
749774
},
@@ -801,6 +826,11 @@ export function useCoreCommands(): ComfyCommand[] {
801826
menubarLabel: 'ComfyUI Forum',
802827
versionAdded: '1.8.2',
803828
function: () => {
829+
telemetry?.trackHelpResourceClicked({
830+
resource_type: 'help_feedback',
831+
is_external: true,
832+
source: 'menu'
833+
})
804834
window.open('https://forum.comfy.org/', '_blank')
805835
}
806836
},

src/platform/cloud/subscription/composables/useSubscriptionActions.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { useI18n } from 'vue-i18n'
33

44
import { useFirebaseAuthActions } from '@/composables/auth/useFirebaseAuthActions'
55
import { useSubscription } from '@/platform/cloud/subscription/composables/useSubscription'
6+
import { isCloud } from '@/platform/distribution/types'
7+
import { useTelemetry } from '@/platform/telemetry'
68
import { useDialogService } from '@/services/dialogService'
79
import { useCommandStore } from '@/stores/commandStore'
810

@@ -14,6 +16,7 @@ export function useSubscriptionActions() {
1416
const dialogService = useDialogService()
1517
const authActions = useFirebaseAuthActions()
1618
const commandStore = useCommandStore()
19+
const telemetry = useTelemetry()
1720
const { fetchStatus, formattedRenewalDate } = useSubscription()
1821

1922
const isLoadingSupport = ref(false)
@@ -35,6 +38,13 @@ export function useSubscriptionActions() {
3538
const handleMessageSupport = async () => {
3639
try {
3740
isLoadingSupport.value = true
41+
if (isCloud) {
42+
telemetry?.trackHelpResourceClicked({
43+
resource_type: 'help_feedback',
44+
is_external: true,
45+
source: 'subscription'
46+
})
47+
}
3848
await commandStore.execute('Comfy.ContactSupport')
3949
} catch (error) {
4050
console.error('[useSubscriptionActions] Error contacting support:', error)

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ import type {
1515
ExecutionContext,
1616
ExecutionErrorMetadata,
1717
ExecutionSuccessMetadata,
18+
HelpCenterClosedMetadata,
19+
HelpCenterOpenedMetadata,
20+
HelpResourceClickedMetadata,
1821
NodeSearchMetadata,
1922
NodeSearchResultMetadata,
2023
PageVisibilityMetadata,
@@ -28,6 +31,7 @@ import type {
2831
TemplateLibraryMetadata,
2932
TemplateLibraryClosedMetadata,
3033
TemplateMetadata,
34+
WorkflowCreatedMetadata,
3135
WorkflowImportMetadata
3236
} from '../../types'
3337
import { TelemetryEvents } from '../../types'
@@ -277,6 +281,22 @@ export class MixpanelTelemetryProvider implements TelemetryProvider {
277281
this.trackEvent(TelemetryEvents.TEMPLATE_FILTER_CHANGED, metadata)
278282
}
279283

284+
trackHelpCenterOpened(metadata: HelpCenterOpenedMetadata): void {
285+
this.trackEvent(TelemetryEvents.HELP_CENTER_OPENED, metadata)
286+
}
287+
288+
trackHelpResourceClicked(metadata: HelpResourceClickedMetadata): void {
289+
this.trackEvent(TelemetryEvents.HELP_RESOURCE_CLICKED, metadata)
290+
}
291+
292+
trackHelpCenterClosed(metadata: HelpCenterClosedMetadata): void {
293+
this.trackEvent(TelemetryEvents.HELP_CENTER_CLOSED, metadata)
294+
}
295+
296+
trackWorkflowCreated(metadata: WorkflowCreatedMetadata): void {
297+
this.trackEvent(TelemetryEvents.WORKFLOW_CREATED, metadata)
298+
}
299+
280300
trackWorkflowExecution(): void {
281301
const context = this.getExecutionContext()
282302
this.trackEvent(TelemetryEvents.EXECUTION_START, context)

0 commit comments

Comments
 (0)