diff --git a/src/platform/remoteConfig/types.ts b/src/platform/remoteConfig/types.ts index 43bfbd70fe..e33cde3095 100644 --- a/src/platform/remoteConfig/types.ts +++ b/src/platform/remoteConfig/types.ts @@ -1,3 +1,5 @@ +import type { TelemetryEventName } from '@/platform/telemetry/types' + /** * Server health alert configuration from the backend */ @@ -31,4 +33,5 @@ export type RemoteConfig = { comfy_api_base_url?: string comfy_platform_base_url?: string firebase_config?: FirebaseRuntimeConfig + telemetry_disabled_events?: TelemetryEventName[] } diff --git a/src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts b/src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts index 28ef060a69..d683288c41 100644 --- a/src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts +++ b/src/platform/telemetry/providers/cloud/MixpanelTelemetryProvider.ts @@ -1,4 +1,5 @@ import type { OverridedMixpanel } from 'mixpanel-browser' +import { watch } from 'vue' import { useCurrentUser } from '@/composables/auth/useCurrentUser' import { @@ -41,9 +42,30 @@ import type { WorkflowCreatedMetadata, WorkflowImportMetadata } from '../../types' +import { remoteConfig } from '@/platform/remoteConfig/remoteConfig' +import type { RemoteConfig } from '@/platform/remoteConfig/types' import { TelemetryEvents } from '../../types' import { normalizeSurveyResponses } from '../../utils/surveyNormalization' +const DEFAULT_DISABLED_EVENTS = [ + TelemetryEvents.WORKFLOW_OPENED, + TelemetryEvents.PAGE_VISIBILITY_CHANGED, + TelemetryEvents.TAB_COUNT_TRACKING, + TelemetryEvents.NODE_SEARCH, + TelemetryEvents.NODE_SEARCH_RESULT_SELECTED, + TelemetryEvents.TEMPLATE_FILTER_CHANGED, + TelemetryEvents.SETTING_CHANGED, + TelemetryEvents.HELP_CENTER_OPENED, + TelemetryEvents.HELP_RESOURCE_CLICKED, + TelemetryEvents.HELP_CENTER_CLOSED, + TelemetryEvents.WORKFLOW_CREATED, + TelemetryEvents.UI_BUTTON_CLICKED +] as const satisfies TelemetryEventName[] + +const TELEMETRY_EVENT_SET = new Set( + Object.values(TelemetryEvents) as TelemetryEventName[] +) + interface QueuedEvent { eventName: TelemetryEventName properties?: TelemetryEventProperties @@ -67,8 +89,19 @@ export class MixpanelTelemetryProvider implements TelemetryProvider { private eventQueue: QueuedEvent[] = [] private isInitialized = false private lastTriggerSource: ExecutionTriggerSource | undefined + private disabledEvents = new Set(DEFAULT_DISABLED_EVENTS) constructor() { + this.configureDisabledEvents( + (window.__CONFIG__ as Partial | undefined) ?? null + ) + watch( + remoteConfig, + (config) => { + this.configureDisabledEvents(config) + }, + { immediate: true } + ) const token = window.__CONFIG__?.mixpanel_token if (token) { @@ -131,6 +164,10 @@ export class MixpanelTelemetryProvider implements TelemetryProvider { return } + if (this.disabledEvents.has(eventName)) { + return + } + const event: QueuedEvent = { eventName, properties } if (this.isInitialized && this.mixpanel) { @@ -146,6 +183,27 @@ export class MixpanelTelemetryProvider implements TelemetryProvider { } } + private configureDisabledEvents(config: Partial | null): void { + const disabledSource = + config?.telemetry_disabled_events ?? DEFAULT_DISABLED_EVENTS + + this.disabledEvents = this.buildEventSet(disabledSource) + } + + private buildEventSet(values: TelemetryEventName[]): Set { + return new Set( + values.filter((value) => { + const isValid = TELEMETRY_EVENT_SET.has(value) + if (!isValid && import.meta.env.DEV) { + console.warn( + `Unknown telemetry event name in disabled list: ${value}` + ) + } + return isValid + }) + ) + } + trackSignupOpened(): void { this.trackEvent(TelemetryEvents.USER_SIGN_UP_OPENED) }