import React, { useState, useEffect } from 'react' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@core/components/ui/card' import { Badge } from '@core/components/ui/badge' import { Button } from '@core/components/ui/button' import { Progress } from '@core/components/ui/progress' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@core/components/ui/tabs' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@core/components/ui/table' import { useApi } from '@core/hooks/useApi' import { formatDistanceToNow } from 'date-fns' import { Download, TrendingUp, Users, Package } from 'lucide-react' interface InstallMetrics { total_downloads: number unique_installers: number active_instances: number conversion_funnel: { downloads: number installations: number first_use: number claimed: number } install_trends: Array<{ date: string downloads: number installations: number }> recent_installs: Array<{ id: string serial: string app_version: string environment: string first_seen_at: string last_signal_at: string claimed_by?: string claimed_at?: string account_name?: string }> top_versions: Array<{ version: string count: number percentage: number }> } export default function InstallFunnelPage() { const [metrics, setMetrics] = useState(null) const [loading, setLoading] = useState(true) const { apiFetch } = useApi() useEffect(() => { loadMetrics() }, []) const loadMetrics = async () => { try { const data = await apiFetch('/admin/install-funnel/metrics') setMetrics(data) } catch (error) { console.error('Failed to load install metrics:', error) } finally { setLoading(false) } } const exportData = async () => { try { const response = await apiFetch('/admin/install-funnel/exportData') // Create download link const blob = new Blob([JSON.stringify(response, null, 2)], { type: 'application/json' }) const url = window.URL.createObjectURL(blob) const a = document.createElement('a') a.href = url a.download = `install-funnel-${new Date().toISOString().split('T')[0]}.json` document.body.appendChild(a) a.click() window.URL.revokeObjectURL(url) document.body.removeChild(a) } catch (error) { console.error('Failed to export data:', error) } } if (loading) { return
Loading install funnel data...
} const conversionRates = metrics ? { download_to_install: (metrics.conversion_funnel.installations / metrics.conversion_funnel.downloads * 100) || 0, install_to_use: (metrics.conversion_funnel.first_use / metrics.conversion_funnel.installations * 100) || 0, use_to_claim: (metrics.conversion_funnel.claimed / metrics.conversion_funnel.first_use * 100) || 0 } : { download_to_install: 0, install_to_use: 0, use_to_claim: 0 } return (

Install Funnel

Track downloads, installations, and adoption metrics

{/* Key Metrics */}
Total Downloads
{metrics?.total_downloads || 0}

All-time downloads

Unique Installers
{metrics?.unique_installers || 0}

Distinct installations

Active Instances
{metrics?.active_instances || 0}

Used in last 7 days

Overall Conversion
{conversionRates.download_to_install.toFixed(1)}%

Download → Install

Conversion Funnel Instance Details Installation Trends Version Analytics
Conversion Funnel User progression from download to claim
{metrics?.conversion_funnel && ( <>
Downloads {metrics.conversion_funnel.downloads}
Installations {metrics.conversion_funnel.installations}

{conversionRates.download_to_install.toFixed(1)}% conversion

First Use {metrics.conversion_funnel.first_use}

{conversionRates.install_to_use.toFixed(1)}% conversion

Claimed {metrics.conversion_funnel.claimed}

{conversionRates.use_to_claim.toFixed(1)}% conversion

)}
Conversion Insights Key metrics and drop-off points
Download to Install
{conversionRates.download_to_install.toFixed(1)}% conversion
50 ? 'default' : 'destructive'}> {conversionRates.download_to_install > 50 ? 'Good' : 'Needs Attention'}
Install to Use
{conversionRates.install_to_use.toFixed(1)}% conversion
70 ? 'default' : 'destructive'}> {conversionRates.install_to_use > 70 ? 'Good' : 'Needs Attention'}
Use to Claim
{conversionRates.use_to_claim.toFixed(1)}% conversion
30 ? 'default' : 'destructive'}> {conversionRates.use_to_claim > 30 ? 'Good' : 'Needs Attention'}
Recent Installations Latest instance installations and their status Instance ID Version Environment First Seen Last Activity Status Owner {metrics?.recent_installs?.map((instance) => ( {instance.serial.slice(0, 12)}... {instance.app_version} {instance.environment}
{formatDistanceToNow(new Date(instance.first_seen_at), { addSuffix: true })}
{formatDistanceToNow(new Date(instance.last_signal_at), { addSuffix: true })}
{instance.claimed_by ? 'Claimed' : 'Unclaimed'} {instance.account_name ? (
{instance.account_name}
{instance.claimed_by}
) : ( Unclaimed )}
))}
Installation Trends Daily download and installation activity

Chart visualization would be implemented here

Showing {metrics?.install_trends?.length || 0} days of data

Version Distribution Active instances by version
{metrics?.top_versions?.map((version) => (
{version.version} {version.count} instances
{version.percentage.toFixed(1)}%
))}
) }