feat: add Search panel to dashboard and enrich Search tab

Dashboard: compact Search Performance panel showing top 5 queries,
clicks, impressions, and avg position alongside Campaigns.

Search tab: clicks/impressions trend chart, top query position
tracker cards, and new queries badge.
This commit is contained in:
Usman Baig
2026-03-14 18:05:05 +01:00
parent af29bb77cd
commit 8f00193e0f
7 changed files with 392 additions and 3 deletions

View File

@@ -77,3 +77,22 @@ export async function getGSCQueryPages(siteId: string, query: string, startDate:
export async function getGSCPageQueries(siteId: string, page: string, startDate: string, endDate: string): Promise<GSCQueryResponse> {
return apiRequest<GSCQueryResponse>(`/sites/${siteId}/gsc/page-queries?page=${encodeURIComponent(page)}&start_date=${startDate}&end_date=${endDate}`)
}
export interface GSCDailyTotal {
date: string
clicks: number
impressions: number
}
export interface GSCNewQueries {
count: number
queries: string[]
}
export async function getGSCDailyTotals(siteId: string, startDate: string, endDate: string): Promise<{ daily_totals: GSCDailyTotal[] }> {
return apiRequest<{ daily_totals: GSCDailyTotal[] }>(`/sites/${siteId}/gsc/daily-totals?start_date=${startDate}&end_date=${endDate}`)
}
export async function getGSCNewQueries(siteId: string, startDate: string, endDate: string): Promise<GSCNewQueries> {
return apiRequest<GSCNewQueries>(`/sites/${siteId}/gsc/new-queries?start_date=${startDate}&end_date=${endDate}`)
}

View File

@@ -33,8 +33,8 @@ import { listFunnels, type Funnel } from '@/lib/api/funnels'
import { getUptimeStatus, type UptimeStatusResponse } from '@/lib/api/uptime'
import { listGoals, type Goal } from '@/lib/api/goals'
import { listReportSchedules, type ReportSchedule } from '@/lib/api/report-schedules'
import { getGSCStatus, getGSCOverview, getGSCTopQueries, getGSCTopPages } from '@/lib/api/gsc'
import type { GSCStatus, GSCOverview, GSCQueryResponse, GSCPageResponse } from '@/lib/api/gsc'
import { getGSCStatus, getGSCOverview, getGSCTopQueries, getGSCTopPages, getGSCDailyTotals, getGSCNewQueries } from '@/lib/api/gsc'
import type { GSCStatus, GSCOverview, GSCQueryResponse, GSCPageResponse, GSCDailyTotal, GSCNewQueries } from '@/lib/api/gsc'
import { getSubscription, type SubscriptionDetails } from '@/lib/api/billing'
import type {
Stats,
@@ -84,6 +84,8 @@ const fetchers = {
gscOverview: (siteId: string, start: string, end: string) => getGSCOverview(siteId, start, end),
gscTopQueries: (siteId: string, start: string, end: string, limit: number, offset: number) => getGSCTopQueries(siteId, start, end, limit, offset),
gscTopPages: (siteId: string, start: string, end: string, limit: number, offset: number) => getGSCTopPages(siteId, start, end, limit, offset),
gscDailyTotals: (siteId: string, start: string, end: string) => getGSCDailyTotals(siteId, start, end),
gscNewQueries: (siteId: string, start: string, end: string) => getGSCNewQueries(siteId, start, end),
subscription: () => getSubscription(),
}
@@ -449,6 +451,24 @@ export function useGSCTopPages(siteId: string, start: string, end: string, limit
)
}
// * Hook for GSC daily totals (clicks & impressions per day)
export function useGSCDailyTotals(siteId: string, start: string, end: string) {
return useSWR<{ daily_totals: GSCDailyTotal[] }>(
siteId && start && end ? ['gscDailyTotals', siteId, start, end] : null,
() => fetchers.gscDailyTotals(siteId, start, end),
dashboardSWRConfig
)
}
// * Hook for GSC new queries (queries that appeared in the current period)
export function useGSCNewQueries(siteId: string, start: string, end: string) {
return useSWR<GSCNewQueries>(
siteId && start && end ? ['gscNewQueries', siteId, start, end] : null,
() => fetchers.gscNewQueries(siteId, start, end),
dashboardSWRConfig
)
}
// * Hook for subscription details (changes rarely)
export function useSubscription() {
return useSWR<SubscriptionDetails>(