diff --git a/apps/web/src/analytics/events.ts b/apps/web/src/analytics/events.ts index 91f8496b2..525aff845 100644 --- a/apps/web/src/analytics/events.ts +++ b/apps/web/src/analytics/events.ts @@ -36,6 +36,8 @@ import type { PluginsTemplatesDropdownClickProps, PluginsAvailableTabClickProps, PluginsSourcesTabClickProps, + PluginDetailClickProps, + PluginLoopClickProps, DesignSystemsTopClickProps, DesignSystemsTemplateCardClickProps, DesignSystemsTemplatesModalClickProps, @@ -326,6 +328,20 @@ export function trackPluginsSourcesTabClick( send(track, 'ui_click', props); } +export function trackPluginDetailClick( + track: Track, + props: PluginDetailClickProps, +): void { + send(track, 'ui_click', props); +} + +export function trackPluginLoopClick( + track: Track, + props: PluginLoopClickProps, +): void { + send(track, 'ui_click', props); +} + export function trackDesignSystemsTopClick( track: Track, props: DesignSystemsTopClickProps, diff --git a/apps/web/src/components/PluginDetailView.tsx b/apps/web/src/components/PluginDetailView.tsx index b9845346f..33157063b 100644 --- a/apps/web/src/components/PluginDetailView.tsx +++ b/apps/web/src/components/PluginDetailView.tsx @@ -12,6 +12,8 @@ import type { ApplyResult, InstalledPluginRecord } from '@open-design/contracts' import { applyPlugin } from '../state/projects'; import { navigate } from '../router'; import { useI18n } from '../i18n'; +import { useAnalytics } from '../analytics/provider'; +import { trackPluginDetailClick } from '../analytics/events'; interface Props { pluginId: string; @@ -19,11 +21,17 @@ interface Props { export function PluginDetailView(props: Props) { const { locale } = useI18n(); + const analytics = useAnalytics(); const [plugin, setPlugin] = useState(null); const [error, setError] = useState(null); const [applying, setApplying] = useState(false); const [applied, setApplied] = useState(null); + const onBack = () => { + trackPluginDetailClick(analytics.track, { page_name: 'plugins', area: 'plugin_detail', element: 'back', plugin_id: props.pluginId }); + navigate({ kind: 'marketplace' }); + }; + useEffect(() => { let cancelled = false; void fetch(`/api/plugins/${encodeURIComponent(props.pluginId)}`) @@ -47,7 +55,7 @@ export function PluginDetailView(props: Props) { if (error) { return (
-
Failed to load plugin: {error}
@@ -80,6 +88,7 @@ export function PluginDetailView(props: Props) { }>; const onUse = async () => { + trackPluginDetailClick(analytics.track, { page_name: 'plugins', area: 'plugin_detail', element: 'use_plugin', plugin_id: plugin.id }); setApplying(true); setError(null); const result = await applyPlugin(plugin.id, { locale }); @@ -100,7 +109,7 @@ export function PluginDetailView(props: Props) { diff --git a/apps/web/src/components/PluginLoopHome.tsx b/apps/web/src/components/PluginLoopHome.tsx index f6e76c320..8f8b61732 100644 --- a/apps/web/src/components/PluginLoopHome.tsx +++ b/apps/web/src/components/PluginLoopHome.tsx @@ -15,6 +15,8 @@ import { Icon } from './Icon'; import { PluginDetailsModal } from './PluginDetailsModal'; import { TrustBadge } from './TrustBadge'; import { authorInitials, derivePluginSourceLinks } from '../runtime/plugin-source'; +import { useAnalytics } from '../analytics/provider'; +import { trackPluginLoopClick } from '../analytics/events'; export interface PluginLoopSubmit { prompt: string; @@ -56,6 +58,7 @@ interface ActivePlugin { export function PluginLoopHome({ onSubmit }: Props) { const { locale } = useI18n(); + const analytics = useAnalytics(); const [plugins, setPlugins] = useState([]); const [loading, setLoading] = useState(true); const [pendingApplyId, setPendingApplyId] = useState(null); @@ -128,6 +131,7 @@ export function PluginLoopHome({ onSubmit }: Props) { function submit() { const trimmed = prompt.trim(); if (!trimmed) return; + trackPluginLoopClick(analytics.track, { page_name: 'plugins', area: 'plugin_loop', element: 'submit', plugin_id: active?.record.id }); onSubmit({ prompt: trimmed, pluginId: active?.record.id ?? null, @@ -168,7 +172,7 @@ export function PluginLoopHome({ onSubmit }: Props) {