/** * Ajax Search Analytics Tab * View search analytics and insights */ import { useState } from 'react'; import { Label } from '@/components/ui/label'; import { Switch } from '@/components/ui/switch'; import { Button } from '@/components/ui/button'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Badge } from '@/components/ui/badge'; import { Skeleton } from '@/components/ui/skeleton'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { BarChart3, TrendingUp, TrendingDown, Search, MousePointerClick, AlertCircle, RefreshCcw, Download, Trash2, } from 'lucide-react'; import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from '@/components/ui/alert-dialog'; import { AjaxSearchSettings, SearchAnalytics } from '../config'; interface AnalyticsTabProps { analytics: SearchAnalytics | null; settings: AjaxSearchSettings; setSettings: React.Dispatch>; isLoading: boolean; isPro: boolean; onRefresh: (period: string) => void; onClear: () => void; onExport: (format: string) => void; } export function AjaxSearchAnalyticsTab({ analytics, settings, setSettings, isLoading, onRefresh, onClear, onExport, }: AnalyticsTabProps) { const [period, setPeriod] = useState('30days'); // Loading state if (isLoading) { return (
); } // No data state if (!analytics) { return (

No Analytics Data

Analytics data will appear here once customers start using your search.

); } const data = analytics!; return (
{/* Header Actions */}
Clear Analytics Data? This will permanently delete all search analytics data. This action cannot be undone. Cancel Clear Data
Analytics Collection Choose which storefront search events are recorded locally.
setSettings((previous) => ({ ...previous, enableAnalytics: checked }))} />
{settings.enableAnalytics && ( <>
setSettings((previous) => ({ ...previous, trackSearches: checked }))} />
setSettings((previous) => ({ ...previous, trackClicks: checked }))} />
)}
{/* Stats Overview */}
Total Searches
{data.totalSearches.toLocaleString()}
{data.uniqueSearches.toLocaleString()} unique terms
Click-through Rate
{data.clickThroughRate.toFixed(1)}% {data.clickThroughRate >= 40 ? ( Good ) : ( Needs Work )}
Successful Searches
{data.totalSearches > 0 ? ((data.searchesWithResults / data.totalSearches) * 100).toFixed(1) : 0} %
{data.searchesWithResults.toLocaleString()} found results
Zero Results Rate
{data.totalSearches > 0 ? ((data.searchesWithoutResults / data.totalSearches) * 100).toFixed(1) : 0} % {data.searchesWithoutResults / data.totalSearches > 0.15 && ( High )}
{/* Top Search Terms */} Top Search Terms Most frequently searched terms by customers. {data.topSearchTerms.length > 0 ? ( Search Term Searches Clicks CTR {data.topSearchTerms.map((term, index) => ( {term.term} {term.count.toLocaleString()} {term.clicks.toLocaleString()} = 40 ? 'secondary' : 'outline'} className={term.ctr >= 40 ? 'text-green-600' : ''} > {term.ctr.toFixed(1)}% ))}
) : (

No search terms recorded yet.

)}
{/* No Results Searches */} Searches With No Results These searches returned no results. Consider adding products or synonyms. {data.noResultSearches.length > 0 ? (
{data.noResultSearches.map((term, index) => (
{term.term} {term.count} searches
))}
) : (
All searches are returning results!
)}
{/* Popular Products */} Most Clicked Products Products that customers click on most from search results. {data.popularProducts.length > 0 ? (
{data.popularProducts.map((product, index) => (
{index + 1} {product.image && ( {product.name} )}
{product.name}
{product.clickCount} clicks
))}
) : (

No product clicks recorded yet.

)}
); }