What does a technical SEO health dashboard show in Metabase?
A technical SEO health dashboard turns one-off site audits into a trend: health score over time, issues by severity and type, new vs. resolved issues between crawls, and crawl coverage. Audit tools show you the latest crawl; the warehouse keeps every crawl, which is what makes "are we getting cleaner?" answerable. It runs on audit snapshots from SE Ranking and page-level crawl issues from DataForSEO OnPage, as part of SEO analytics.
Which cards belong on a technical SEO health dashboard?
- Health score over time (line)
- Errors, warnings, and notices per audit (stacked bar)
- Issues by type, latest crawl (bar)
- New vs. resolved issues between the last two crawls (table)
- Pages crawled per audit — scope watch (line)
- Pages with the most issues, latest crawl (table)
- Issue age — how many crawls each open issue has survived (table)
- Speed and page-weight flags — Core-Web-Vitals-adjacent checks per crawl (line)
What data does the dashboard need?
seranking_audit_snapshots— domain, audit_date, health_score, errors, warnings, notices, pages_crawled — one row per audit run.onpage_crawl_issues— crawl_id, crawl_date, page_url, issue_type, severity — one row per issue per page per crawl, from DataForSEO OnPage or your auditor's issue export.- Optional: Search Console page-level clicks, to rank issues by traffic at stake rather than severity alone.
How do you build it?
- Schedule recurring audits in SE Ranking (or post DataForSEO OnPage crawl tasks) with frozen settings, weekly or per release.
- Sync audit summaries and per-page issues to the warehouse via the API — one table for snapshots, one for issue rows keyed by crawl_id.
- Model crawl-over-crawl issue diffs (the FULL OUTER JOIN pattern below) to separate genuinely new issues from persisting ones.
- Assemble the cards with severity and issue-type filters, and a drill-through from issue types to the affected pages.
Example card SQL
SELECT
audit_date,
health_score,
errors,
warnings,
notices,
pages_crawled
FROM seranking_audit_snapshots
WHERE domain = 'yourdomain.com'
ORDER BY audit_date;WITH latest AS (
SELECT page_url, issue_type
FROM onpage_crawl_issues
WHERE crawl_id = (
SELECT crawl_id FROM onpage_crawl_issues
ORDER BY crawl_date DESC LIMIT 1
)
),
previous AS (
SELECT page_url, issue_type
FROM onpage_crawl_issues
WHERE crawl_id = (
SELECT crawl_id FROM onpage_crawl_issues
WHERE crawl_date < (
SELECT MAX(crawl_date) FROM onpage_crawl_issues
)
ORDER BY crawl_date DESC LIMIT 1
)
)
SELECT
COALESCE(l.issue_type, p.issue_type) AS issue_type,
COUNT(*) FILTER (WHERE p.page_url IS NULL) AS new_issues,
COUNT(*) FILTER (WHERE l.page_url IS NULL) AS resolved_issues
FROM latest l
FULL OUTER JOIN previous p
ON p.page_url = l.page_url
AND p.issue_type = l.issue_type
GROUP BY 1
ORDER BY new_issues DESC;Related
Metrics
Integrations
Dashboards
FAQ
Is a health score of 85 good?
The score jumped 10 points overnight — what happened?
pages_crawled next to the score — a score change with a big pages_crawled change is a scope change until proven otherwise. Keep audit settings frozen and annotate any deliberate change.How do I verify that a fix actually worked?
Does this dashboard cover Core Web Vitals?
Which issues should be fixed first?
onpage_crawl_issues to Search Console page data on URL and sort by severity × organic clicks at stake, the same join that powers the content performance dashboard. Fixing template-level issues also collapses hundreds of page-rows at once, which is where health scores actually move.