export interface ISeoGoogleStatus { connected: boolean; email: string | null; site_url: string | null; ga4_property: string | null; last_synced_at: string | null; syncing: boolean; rows: number; error: string | null; } export interface ISeoGoogleProperties { sites: { site_url: string; permission_level: string }[]; ga4: { property: string; display_name: string }[]; } export interface ISeoAnalyticsTotals { clicks: number; impressions: number; ctr: number; /** Impression-weighted; null when nothing was shown. */ position: number | null; } export interface ISeoAnalyticsPeriod { from: string; to: string; } interface ISeoAnalyticsEnvelope { period: ISeoAnalyticsPeriod; previous: ISeoAnalyticsPeriod; stale: boolean; syncing: boolean; last_synced_at: string | null; } export interface ISeoAnalyticsOverview extends ISeoAnalyticsEnvelope { totals: ISeoAnalyticsTotals; previous_totals: ISeoAnalyticsTotals; daily: (ISeoAnalyticsTotals & { date: string })[]; } export interface ISeoAnalyticsRow extends ISeoAnalyticsTotals { key: string; previous: ISeoAnalyticsTotals | null; } export interface ISeoAnalyticsList extends ISeoAnalyticsEnvelope { rows: ISeoAnalyticsRow[]; total: number; page: number; per_page: number; total_pages: number; } /** A keyword or page row as the API sends it, before the page flattens it. */ export interface ISeoAnalyticsApiRow { query?: string; page?: string; current: ISeoAnalyticsTotals; previous: ISeoAnalyticsTotals | null; } export type SeoAnalyticsSort = keyof ISeoAnalyticsTotals; export interface ISeoAnalyticsListQuery { from: string; to: string; sort: SeoAnalyticsSort; order: 'asc' | 'desc'; page: number; per_page: number; search?: string; }