/* Page: Single client SEO Overview */
function OverviewView({ client, range }) {
const rangeParam = range === 'Last 7 days' ? '7d'
: range === 'Last 90 days' ? '90d'
: range === 'YTD' ? 'ytd'
: '30d';
const { data: D, loading, error } = useApi(
`/api/clients/${client.id}/overview?range=${rangeParam}`,
[client.id, rangeParam]
);
if (loading) return
Loading overview...
;
if (error) return Failed to load overview: {error}
;
const traffic90 = D.traffic90 || [];
const trafficPrev = D.trafficPrev || [];
const totalSessions = traffic90.reduce((a,b) => a+b, 0);
const prevSessions = trafficPrev.reduce((a,b) => a+b, 0);
const delta = prevSessions > 0 ? ((totalSessions - prevSessions) / prevSessions) * 100 : 0;
return (
<>
SEO · Q2 2026 in progress
Foundation set. Rank stabilising. Content investment unblocked.
Cannibalisation resolved on 3 priority clusters. Crawl budget recovered. Organic sessions +18% MoM in March.
Organic sessions
{(totalSessions/1000).toFixed(1)}k
+{delta.toFixed(1)}% vs prev 90d
GA4 · last 90 days
Conversions
{D.conversions}
+{D.convDelta}%
GA4 · key events
Avg position
{D.avgPosition}
−2.7
GSC · 142 tracked
CTR
{D.ctr}%
+0.6pp
GSC · last 28 days
Top-3 keywords
{D.top3Keywords}
+11
Semrush · tracked set
Organic traffic
Daily sessions · 90 days
Current 90d
{totalSessions.toLocaleString()}
Previous 90d
{prevSessions.toLocaleString()}
Best day
{(traffic90.length ? Math.max(...traffic90) : 0).toLocaleString()}
GA4 · property 287654032Synced 14m ago
Top movers
Last 7 days
Climbing
{(D.topMovers?.up || []).map((m, i) => (
))}
Slipping
{(D.topMovers?.down || []).map((m, i) => (
))}
Channel mix
GA4 · 30d
a + c.value, 0)}/>
{(D.channels || []).map((c, i) => (
{c.name}
{c.share.toFixed(1)}%
))}
This cycle's findings
{[
{ p: 'High', t: 'Cannibalisation across 14 pages', d: 'Core service terms split rank between competing pages. Highest-leverage fix this cycle.' },
{ p: 'High', t: '340 parameterised URLs wasting crawl budget', d: 'Faceted-nav URLs indexed without intent. Block in robots.txt.' },
{ p: 'Med', t: 'Cluster architecture missing for 3 service lines', d: 'No pillar pages anchor mid-funnel intent. Briefs queued for Q2 execution.' },
].map((f, i) => (
))}
Data sources
Last sync
{(D.dataSources || []).map((s, i) => (
{s.name.toUpperCase()}
{s.prop}
STATUS {s.status.toUpperCase()}
))}
>
);
}
window.OverviewView = OverviewView;