Tutorial

How to Build an SEO Audit Dashboard with API Data

Build a real-time SEO audit dashboard that pulls SERP data via the Scavio API. Track rankings, SERP features, and competitor positions in one view.

An SEO audit dashboard consolidates ranking data, SERP feature presence, and competitor positions into a single view that updates on demand. Commercial tools like Ahrefs or SEMrush charge hundreds per month for this capability. This tutorial builds a lightweight Flask dashboard that queries the Scavio API for each keyword, computes metrics, and renders them as a JSON API that can feed any frontend. The dashboard tracks your rank, competitor ranks, featured snippet ownership, AI overview presence, and People Also Ask coverage.

Prerequisites

  • Python 3.10 or higher
  • pip install requests flask
  • A Scavio API key
  • A domain and keyword list to audit

Walkthrough

Step 1: Define the audit configuration

Set up the target domain, competitor domains, and keywords to track. This configuration drives the entire dashboard.

Python
CONFIG = {
    "domain": "mysite.com",
    "competitors": ["competitor-a.com", "competitor-b.io"],
    "keywords": [
        "api documentation best practices",
        "rest api design guide",
        "graphql vs rest 2026",
    ]
}

Step 2: Audit a single keyword

Fetch SERP data for a keyword and extract all relevant metrics: rank, competitor ranks, SERP features, and AI overview status.

Python
def audit_keyword(keyword: str, config: dict) -> dict:
    r = requests.post(ENDPOINT, headers={"x-api-key": API_KEY},
                      json={"query": keyword, "country_code": "us", "ai_overview": True})
    r.raise_for_status()
    data = r.json()
    organic = data.get("organic_results", [])
    my_rank = next((r["position"] for r in organic if config["domain"] in r.get("link", "")), None)
    comp_ranks = {}
    for c in config["competitors"]:
        comp_ranks[c] = next((r["position"] for r in organic if c in r.get("link", "")), None)
    return {
        "keyword": keyword,
        "my_rank": my_rank,
        "competitor_ranks": comp_ranks,
        "has_featured_snippet": bool(data.get("featured_snippet")),
        "has_ai_overview": bool(data.get("ai_overview")),
        "paa_count": len(data.get("people_also_ask", [])),
        "total_results": len(organic),
    }

Step 3: Build the dashboard API

Create a Flask endpoint that runs the full audit and returns results as JSON.

Python
from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/audit")
def audit():
    results = [audit_keyword(kw, CONFIG) for kw in CONFIG["keywords"]]
    summary = {
        "domain": CONFIG["domain"],
        "keywords_tracked": len(results),
        "keywords_ranked": sum(1 for r in results if r["my_rank"]),
        "avg_position": round(sum(r["my_rank"] for r in results if r["my_rank"]) / max(sum(1 for r in results if r["my_rank"]), 1), 1),
        "ai_overview_pct": f"{sum(1 for r in results if r['has_ai_overview']) / len(results) * 100:.0f}%",
    }
    return jsonify({"summary": summary, "keywords": results})

Step 4: Run the dashboard

Start the Flask server and access the audit at http://localhost:5000/audit.

Python
if __name__ == "__main__":
    app.run(port=5000, debug=True)

Python Example

Python
import os
import requests
from flask import Flask, jsonify

API_KEY = os.environ.get("SCAVIO_API_KEY", "your_scavio_api_key")
ENDPOINT = "https://api.scavio.dev/api/v1/search"
CONFIG = {"domain": "mysite.com", "competitors": ["comp-a.com"], "keywords": ["api design guide", "rest vs graphql"]}

def audit(kw: str) -> dict:
    r = requests.post(ENDPOINT, headers={"x-api-key": API_KEY},
                      json={"query": kw, "country_code": "us", "ai_overview": True})
    r.raise_for_status()
    d = r.json()
    organic = d.get("organic_results", [])
    rank = next((r["position"] for r in organic if CONFIG["domain"] in r.get("link", "")), None)
    return {"keyword": kw, "rank": rank, "ai_overview": bool(d.get("ai_overview")), "paa": len(d.get("people_also_ask", []))}

app = Flask(__name__)

@app.route("/audit")
def run_audit():
    results = [audit(kw) for kw in CONFIG["keywords"]]
    return jsonify(results)

if __name__ == "__main__":
    app.run(port=5000)

JavaScript Example

JavaScript
const API_KEY = process.env.SCAVIO_API_KEY || "your_scavio_api_key";
const ENDPOINT = "https://api.scavio.dev/api/v1/search";
const http = require("http");

const CONFIG = { domain: "mysite.com", keywords: ["api design guide", "rest vs graphql"] };

async function audit(kw) {
  const res = await fetch(ENDPOINT, {
    method: "POST",
    headers: { "x-api-key": API_KEY, "Content-Type": "application/json" },
    body: JSON.stringify({ query: kw, country_code: "us", ai_overview: true })
  });
  const d = await res.json();
  const organic = d.organic_results || [];
  const rank = organic.find(r => r.link.includes(CONFIG.domain))?.position || null;
  return { keyword: kw, rank, aiOverview: !!d.ai_overview, paa: (d.people_also_ask || []).length };
}

http.createServer(async (req, res) => {
  if (req.url === "/audit") {
    const results = await Promise.all(CONFIG.keywords.map(audit));
    res.writeHead(200, { "Content-Type": "application/json" });
    res.end(JSON.stringify(results, null, 2));
  }
}).listen(5000);

Expected Output

JSON
GET /audit
{
  "summary": {
    "domain": "mysite.com",
    "keywords_tracked": 3,
    "keywords_ranked": 2,
    "avg_position": 5.5,
    "ai_overview_pct": "67%"
  },
  "keywords": [
    {"keyword": "api design guide", "my_rank": 4, "has_ai_overview": true, "paa_count": 4},
    {"keyword": "rest vs graphql", "my_rank": 7, "has_ai_overview": true, "paa_count": 3},
    {"keyword": "graphql vs rest 2026", "my_rank": null, "has_ai_overview": false, "paa_count": 2}
  ]
}

Related Tutorials

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.10 or higher. pip install requests flask. A Scavio API key. A domain and keyword list to audit. A Scavio API key gives you 500 free credits per month.

Yes. The free tier includes 500 credits per month, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Start Building

Build a real-time SEO audit dashboard that pulls SERP data via the Scavio API. Track rankings, SERP features, and competitor positions in one view.