ScavioScavio
ProductPricingDocs
Sign InGet Started
  1. Home
  2. Tutorials
  3. How to Build a Custom SEO Dashboard with a Search API
Tutorial

How to Build a Custom SEO Dashboard with a Search API

Build a rank tracking dashboard replacing $500/mo enterprise tools. Python backend with daily SERP checks and SQLite history for under $30/mo.

Get Free API KeyAPI Docs

Enterprise SEO tools charge $200-500/month for dashboards you cannot customize. A SERP API feeding your own dashboard gives you exactly the metrics you need at a fraction of the cost. This tutorial builds a Python rank tracking backend that checks keyword positions daily, stores history in SQLite, and exports CSV for any frontend. Tracking 200 keywords daily costs about $1/day on Scavio.

Prerequisites

  • Python 3.8+ installed
  • requests and sqlite3 (built-in)
  • A Scavio API key from scavio.dev
  • Keywords and your target domain

Walkthrough

Step 1: Set up the database and configuration

Create a SQLite database for daily rank snapshots. Define your target domain and keyword list.

Python
import os, sqlite3, requests, json
from datetime import date

API_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
DOMAIN = 'mysite.com'
KEYWORDS = ['serp api python', 'web scraping api', 'tiktok data api', 'seo rank tracking api']

def init_db(path='seo_dashboard.db'):
    conn = sqlite3.connect(path)
    conn.execute('''CREATE TABLE IF NOT EXISTS rankings (
        id INTEGER PRIMARY KEY, date TEXT, keyword TEXT,
        position INTEGER, url TEXT, title TEXT)''')
    conn.commit()
    return conn

db = init_db()

Step 2: Fetch rankings for each keyword

Query Google for each keyword and find your domain's position in the organic results.

Python
def check_keyword(keyword):
    resp = requests.post('https://api.scavio.dev/api/v1/search',
        headers=H, json={'query': keyword, 'country_code': 'us'})
    for r in resp.json().get('organic_results', []):
        if DOMAIN in r.get('link', ''):
            return {'position': r['position'], 'url': r['link'], 'title': r.get('title', '')}
    return {'position': None, 'url': '', 'title': ''}

def run_daily_check():
    today = date.today().isoformat()
    for kw in KEYWORDS:
        r = check_keyword(kw)
        db.execute('INSERT INTO rankings (date,keyword,position,url,title) VALUES (?,?,?,?,?)',
            (today, kw, r['position'], r['url'], r['title']))
        status = f"#{r['position']}" if r['position'] else 'NOT FOUND'
        print(f'  {kw}: {status}')
    db.commit()
    print(f'Cost: ${len(KEYWORDS) * 0.005:.3f}')

run_daily_check()

Step 3: Query history and detect rank changes

Pull rank history from SQLite to identify trends, drops, and improvements.

Python
def get_movers(days=7):
    cursor = db.execute('''
        WITH recent AS (
            SELECT keyword, position, date,
                ROW_NUMBER() OVER (PARTITION BY keyword ORDER BY date DESC) as rn
            FROM rankings WHERE position IS NOT NULL
        )
        SELECT a.keyword, a.position as current_pos, b.position as prev_pos,
            b.position - a.position as change
        FROM recent a JOIN recent b ON a.keyword = b.keyword
        WHERE a.rn = 1 AND b.rn = ? AND a.position != b.position
        ORDER BY change DESC
    ''', (min(days, 30),))
    for kw, curr, prev, change in cursor.fetchall():
        d = 'UP' if change > 0 else 'DOWN'
        print(f'  [{d}] {kw}: #{prev} -> #{curr} ({change:+d})')

def export_csv(output='dashboard.csv'):
    import csv
    rows = db.execute('SELECT date, keyword, position, url FROM rankings ORDER BY date DESC, keyword').fetchall()
    with open(output, 'w', newline='') as f:
        w = csv.writer(f)
        w.writerow(['date', 'keyword', 'position', 'url'])
        w.writerows(rows)
    print(f'Exported {len(rows)} rows to {output}')

get_movers(7)
export_csv()

Step 4: Schedule daily checks

Add a cron job to run the checker daily with duplicate prevention.

Python
def already_checked_today():
    today = date.today().isoformat()
    return db.execute('SELECT COUNT(*) FROM rankings WHERE date = ?', (today,)).fetchone()[0] > 0

if __name__ == '__main__':
    db = init_db()
    if already_checked_today():
        print('Already checked today.')
    else:
        print(f'{date.today()}: Running daily check...')
        run_daily_check()
        get_movers(7)

# crontab -e
# 0 6 * * * cd /path/to && python seo_dashboard.py >> dashboard.log 2>&1

Python Example

Python
import os, sqlite3, requests
from datetime import date

API_KEY = os.environ['SCAVIO_API_KEY']
H = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}
DOMAIN = 'mysite.com'
KEYWORDS = ['serp api python', 'web scraping api']

db = sqlite3.connect('seo.db')
db.execute('CREATE TABLE IF NOT EXISTS ranks (date TEXT, keyword TEXT, position INT)')

for kw in KEYWORDS:
    data = requests.post('https://api.scavio.dev/api/v1/search',
        headers=H, json={'query': kw, 'country_code': 'us'}).json()
    pos = next((r['position'] for r in data.get('organic_results', []) if DOMAIN in r.get('link', '')), None)
    db.execute('INSERT INTO ranks VALUES (?,?,?)', (date.today().isoformat(), kw, pos))
    print(f'{kw}: #{pos}' if pos else f'{kw}: not found')
db.commit()

JavaScript Example

JavaScript
const Database = require('better-sqlite3');
const API_KEY = process.env.SCAVIO_API_KEY;
const H = { 'x-api-key': API_KEY, 'Content-Type': 'application/json' };
const DOMAIN = 'mysite.com';
const KEYWORDS = ['serp api python', 'web scraping api'];

const db = new Database('seo.db');
db.exec('CREATE TABLE IF NOT EXISTS ranks (date TEXT, keyword TEXT, position INT)');

async function run() {
  const today = new Date().toISOString().slice(0, 10);
  const insert = db.prepare('INSERT INTO ranks VALUES (?, ?, ?)');
  for (const kw of KEYWORDS) {
    const data = await fetch('https://api.scavio.dev/api/v1/search', {
      method: 'POST', headers: H, body: JSON.stringify({ query: kw, country_code: 'us' })
    }).then(r => r.json());
    const match = (data.organic_results || []).find(r => r.link.includes(DOMAIN));
    insert.run(today, kw, match ? match.position : null);
    console.log(match ? `${kw}: #${match.position}` : `${kw}: not found`);
  }
}
run().catch(console.error);

Expected Output

JSON
2026-05-18: Running daily check...
  serp api python: #4
  web scraping api: #7
  tiktok data api: #2
  seo rank tracking api: #11
Cost: $0.020

  [UP] tiktok data api: #5 -> #2 (+3)
  [DOWN] seo rank tracking api: #8 -> #11 (-3)
Exported 28 rows to dashboard.csv

Related Tutorials

  • How to Track SEO Rankings Daily with the Scavio API
  • How to Fetch Google Search Results in Python
  • How to Build a Competitive SERP Monitor

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.8+ installed. requests and sqlite3 (built-in). A Scavio API key from scavio.dev. Keywords and your target domain. A Scavio API key gives you 50 free credits on signup.

Yes. The free tier includes 50 credits on signup, 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.

Related Resources

Best Of

Best API for Custom SEO Dashboards in 2026

Read more
Best Of

Best SEO Rank Tracking APIs in 2026

Read more
Solution

Build Reliable Local Rank Tracking with Scavio API

Read more
Use Case

SEO Dashboard Raw API

Read more
Solution

Build a Custom SEO Dashboard From Raw SERP Data

Read more
Use Case

AppSumo SEO Tool to API Migration

Read more

Start Building

Build a rank tracking dashboard replacing $500/mo enterprise tools. Python backend with daily SERP checks and SQLite history for under $30/mo.

Get Free API KeyRead the Docs
ScavioScavio

Real-time search API for AI agents. Search every platform, not just Google.

Product

  • Features
  • Pricing
  • Dashboard
  • Affiliates

Developers

  • Documentation
  • API Reference
  • Quickstart
  • MCP Integration
  • Python SDK

Alternatives

  • Tavily Alternative
  • SerpAPI Alternative
  • Firecrawl Alternative
  • Exa Alternative

Tools

  • JSON Formatter
  • cURL to Code
  • Token Counter
  • All Tools

© 2026 Scavio. All rights reserved.

Featured on TAAFT
Terms of ServicePrivacy Policy