Dashboard

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.

For: SEO and web-engineering teams tracking site quality over releases. Grain: one row per audit run for scores, plus one row per issue × page × crawl for the detail.

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.
Comparability is everything: keep crawl scope, page caps, and settings identical between audits, or the trend measures your configuration instead of your site. Watch the pages_crawled card for silent scope drift.

How do you build it?

  1. Schedule recurring audits in SE Ranking (or post DataForSEO OnPage crawl tasks) with frozen settings, weekly or per release.
  2. 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.
  3. Model crawl-over-crawl issue diffs (the FULL OUTER JOIN pattern below) to separate genuinely new issues from persisting ones.
  4. Assemble the cards with severity and issue-type filters, and a drill-through from issue types to the affected pages.

Example card SQL

Health score and issue counts by auditPostgreSQL
SELECT
  audit_date,
  health_score,
  errors,
  warnings,
  notices,
  pages_crawled
FROM seranking_audit_snapshots
WHERE domain = 'yourdomain.com'
ORDER BY audit_date;
New vs. resolved issues between the last two crawlsPostgreSQL
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;

Metrics

Integrations

Dashboards

FAQ

Is a health score of 85 good?
Only relative to your own history. Health scores are vendor-relative: each tool weights its own issue catalog with its own formula, so 85 in SE Ranking means something different from 85 in another auditor, and neither is a number Google computes. The score works as a trend line — is this site getting cleaner or messier? — not as a benchmark. For cross-team reporting, pair it with absolute counts (errors on indexable pages) that don't depend on a formula.
The score jumped 10 points overnight — what happened?
Check the crawl before celebrating: scores are only comparable between audits with the same scope and settings. A crawl that hit a page cap, was blocked from a section by robots.txt changes, or ran after a subdomain was added is scoring a different site. That is why the dashboard keeps 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?
Audit data is snapshot-based, so a fix only "counts" after the next crawl re-checks the page — deploying it changes nothing on this dashboard. The workflow: fix, trigger a recrawl (or wait for the scheduled one), then confirm the issue moved to the resolved column in the new-vs-resolved card. With DataForSEO OnPage you can post a targeted crawl task for just the fixed URLs to verify sooner, without burning a full-site crawl.
Does this dashboard cover Core Web Vitals?
Partially. Site auditors run lab checks that are CWV-adjacent — slow-responding pages, oversized payloads, render-blocking resources — and those belong on this dashboard as a per-crawl trend. But real Core Web Vitals are field data from Chrome users (CrUX), which an audit crawler cannot observe. If CWV is a goal, land CrUX or RUM data as a separate source and give it its own cards; treat audit-tool speed flags as leading indicators, not the metric.
Which issues should be fixed first?
Severity alone over-prioritizes noise — a warning on your highest-traffic template beats an error on ten orphan pages. Because the issues table is in the warehouse, you can rank properly: join 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.