Dashboard

What does a keyword rank tracking dashboard show in Metabase?

A keyword rank tracking dashboard turns daily position checks into an operational view: position trends by keyword group, the week's biggest gains and losses, newly ranking keywords, striking-distance opportunities, and rank volatility. It runs on daily snapshots synced from SE Ranking, Semrush position tracking, or raw DataForSEO SERP data — the day-to-day working layer of SEO analytics.

For: SEO practitioners watching movement and catching drops early. Grain: one row per keyword × search engine × location × day, in seo_keyword_positions.

Which cards belong on a keyword rank tracking dashboard?

  • Average position by keyword group over time (line)
  • Biggest gains week-over-week, in positions (table)
  • Biggest losses week-over-week, in positions (table)
  • Newly ranking keywords, trailing 28 days (table)
  • Striking distance — positions 11–20 by search volume (table)
  • Rank volatility — position standard deviation, trailing 30 days (table)
  • SERP features on tracked keywords — who owns the snippet (table)
  • Tracking coverage — keywords tracked by engine and location (bar)

What data does the dashboard need?

  • seo_keyword_positions with search_engine and location columns — keyword, project, search_engine, location, stat_date, position, previous_position, search_volume, url — from SE Ranking or Semrush position tracking.
  • Or raw serp_snapshots from DataForSEO — one row per keyword per result position per crawl — reduced to your domain's best rank per keyword in a view.
  • A keyword grouping table (topic, intent, funnel stage) so trend cards aggregate something more useful than the all-keyword average.
Keep engines, locations, and devices in separate rows and filter explicitly — a trend that silently averages US desktop with German mobile isn't a trend. And adopt one convention (best rank per keyword) everywhere, so cards agree with each other.

How do you build it?

  1. Sync daily positions to the warehouse via the SE Ranking or Semrush API, or schedule DataForSEO SERP tasks and land the results — there is no managed connector for any of the three.
  2. Model best-rank-per-keyword per day, plus a weekly rollup with LAG() deltas for the movers tables.
  3. Add the keyword grouping table and compute per-group averages and 30-day position standard deviation for volatility.
  4. Assemble the cards with engine, location, and group filters, and a drill-through from mover rows to the keyword's full position history.

Example card SQL

Biggest gains week-over-weekPostgreSQL
WITH weekly AS (
  SELECT
    keyword,
    date_trunc('week', stat_date) AS week,
    MIN(position) AS best_position
  FROM seo_keyword_positions
  WHERE search_engine = 'google'
    AND location = 'United States'
  GROUP BY 1, 2
),
deltas AS (
  SELECT
    keyword,
    week,
    best_position,
    LAG(best_position)
      OVER (PARTITION BY keyword ORDER BY week) AS prev_position
  FROM weekly
)
SELECT
  keyword,
  prev_position,
  best_position,
  prev_position - best_position AS positions_gained
FROM deltas
WHERE week = date_trunc('week', CURRENT_DATE)
  AND prev_position IS NOT NULL
ORDER BY positions_gained DESC
LIMIT 20;
Newly ranking keywords, trailing 28 daysPostgreSQL
WITH ranked_days AS (
  SELECT
    keyword,
    stat_date,
    MIN(position) AS best_position
  FROM seo_keyword_positions
  WHERE search_engine = 'google'
    AND position <= 20
  GROUP BY 1, 2
)
SELECT
  keyword,
  MIN(stat_date) AS first_ranked_on,
  MIN(best_position) AS best_position_since
FROM ranked_days
GROUP BY 1
HAVING MIN(stat_date) >= CURRENT_DATE - 28
ORDER BY first_ranked_on DESC;

Metrics

Integrations

Dashboards

FAQ

Why track locations, devices, and engines separately?
Because "the ranking" doesn't exist — a keyword can sit at #3 on Google desktop in the US and #14 on mobile in Germany. Trackers like SE Ranking store one row per keyword per search engine per location, so averaging across them produces a number no user ever saw. Give every card an explicit engine and location filter (or defaults), and treat each engine × location pair as its own trend.
What if one keyword ranks with several URLs?
Pick a convention and encode it in the model, not per card. The common one is best rank per keyword: MIN(position) per keyword per snapshot, which is what the example SQL uses. The alternative — tracking a designated target URL and treating other pages as cannibalization — is stricter but needs a keyword-to-URL mapping table. Either works; mixing them across cards makes the dashboard contradict itself.
How often should positions be checked?
Crawl cadence sets the resolution of every trend on this page: daily checks give you week-over-week movers and volatility, weekly checks give you monthly direction and nothing finer. Daily tracking is standard in SE Ranking and Semrush position-tracking campaigns; with DataForSEO you set the cadence yourself by scheduling SERP tasks — and pay per check, so match frequency to how fast you can actually react.
How does this differ from Search Console average position?
GSC average position is impression-weighted across every search where you appeared — it blends countries, devices, and personalization into one decimal. A rank tracker asks the same question the same way every day: fixed keyword, fixed location, fixed device. That controlled measurement is what makes day-over-day deltas meaningful. Use tracked positions for movement detection and the measured organic search performance dashboard for whether movement turned into clicks.
What counts as a newly ranking keyword?
Define it as a keyword whose first appearance at or above a threshold (top 20 in the example SQL) falls inside the window — not merely one that improved. Two caveats keep the card honest: a keyword added to tracking last week will show up as "new" even if it ranked for months untracked, so consider excluding keywords first tracked inside the window; and keywords bouncing around position 19–21 will enter and leave repeatedly, which the volatility card is there to expose.