Tutorial

How to Build an SEO Dashboard with Retool and Scavio

Build a visual SEO dashboard in Retool powered by Scavio SERP data. Rank tracking, SERP features, and competitor analysis.

Retool lets you build internal dashboards without frontend code. This tutorial connects Scavio as the data source to build an SEO dashboard with rank tracking, SERP feature monitoring, and competitor comparison. Retool handles the UI while Scavio provides real-time SERP data at $0.005/query.

Prerequisites

  • A Retool account (free tier works)
  • A Scavio API key from scavio.dev
  • Basic SQL or JavaScript knowledge

Walkthrough

Step 1: Configure Scavio as a Retool REST API resource

Add Scavio as a REST API resource in Retool so queries can call it directly.

Python
// In Retool: Settings > Resources > Add Resource > REST API
// Name: Scavio Search API
// Base URL: https://api.scavio.dev/api/v1
// Headers:
//   x-api-key: {{SCAVIO_API_KEY}}
//   Content-Type: application/json

// Test query in Retool Query Editor:
// Method: POST
// URL: /search
// Body:
{
  "query": "{{ textInput1.value }}",
  "country_code": "us"
}

// Retool will show the response with organic_results, people_also_ask, etc.
// Map these to table and chart components.

// For server-side testing:
import os, requests
SH = {'x-api-key': os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'}
data = requests.post('https://api.scavio.dev/api/v1/search',
    headers=SH, json={'query': 'best search api 2026', 'country_code': 'us'}).json()
print(f'Organic results: {len(data.get("organic_results", []))}')
print(f'PAA questions: {len(data.get("people_also_ask", []))}')
print(f'Has featured snippet: {bool(data.get("featured_snippet"))}')

Step 2: Build the rank tracking view

Create a Retool table that shows keyword positions and trends over time.

Python
import os, requests, json
from datetime import datetime

API_KEY = os.environ['SCAVIO_API_KEY']
SH = {'x-api-key': API_KEY, 'Content-Type': 'application/json'}

def retool_rank_data(keywords, domain):
    """Generate data formatted for Retool table component."""
    rows = []
    for kw in keywords:
        data = requests.post('https://api.scavio.dev/api/v1/search',
            headers=SH, json={'query': kw, 'country_code': 'us'}, timeout=10).json()
        organic = data.get('organic_results', [])
        pos = next((i+1 for i, r in enumerate(organic) if domain in r.get('link', '')), None)
        featured = data.get('featured_snippet', {})
        rows.append({
            'keyword': kw,
            'position': pos,
            'in_top3': pos is not None and pos <= 3,
            'in_featured': domain in featured.get('displayed_link', ''),
            'competitor_1': organic[0].get('displayed_link', '') if organic else '',
            'paa_count': len(data.get('people_also_ask', [])),
            'date': datetime.now().strftime('%Y-%m-%d'),
        })
    return rows

keywords = ['search api python', 'mcp search tool', 'serp api pricing', 'web search api free tier']
rows = retool_rank_data(keywords, 'scavio.dev')
print(f'Retool table data: {len(rows)} rows')
for r in rows:
    pos = f'#{r["position"]}' if r['position'] else '-'
    print(f'  {r["keyword"]:35} | {pos:5} | Top 3: {r["in_top3"]}')
print(f'\nCost: ${len(keywords) * 0.005:.3f}')

Step 3: Add SERP feature monitoring

Track which SERP features appear for each keyword and how they change.

Python
def serp_features_data(keywords):
    """Extract SERP features for Retool chart components."""
    features = []
    for kw in keywords:
        data = requests.post('https://api.scavio.dev/api/v1/search',
            headers=SH, json={'query': kw, 'country_code': 'us'}, timeout=10).json()
        feat = {
            'keyword': kw,
            'has_ai_overview': bool(data.get('ai_overview', data.get('answer_box'))),
            'has_featured_snippet': bool(data.get('featured_snippet')),
            'has_paa': len(data.get('people_also_ask', [])) > 0,
            'paa_count': len(data.get('people_also_ask', [])),
            'organic_count': len(data.get('organic_results', [])),
            'has_knowledge_graph': bool(data.get('knowledge_graph')),
        }
        features.append(feat)
    # Summary for Retool pie chart
    ai_count = sum(1 for f in features if f['has_ai_overview'])
    fs_count = sum(1 for f in features if f['has_featured_snippet'])
    paa_count = sum(1 for f in features if f['has_paa'])
    print(f'\n=== SERP Features Summary (for Retool) ===')
    print(f'  Keywords scanned: {len(features)}')
    print(f'  AI Overview: {ai_count}/{len(features)} ({ai_count/len(features)*100:.0f}%)')
    print(f'  Featured Snippet: {fs_count}/{len(features)} ({fs_count/len(features)*100:.0f}%)')
    print(f'  People Also Ask: {paa_count}/{len(features)} ({paa_count/len(features)*100:.0f}%)')
    print(f'\n  Retool: Bind this data to a pie chart component')
    print(f'  Cost: ${len(keywords) * 0.005:.3f}/scan')
    return features

serp_features_data(keywords)

Python Example

Python
import os, requests
SH = {'x-api-key': os.environ['SCAVIO_API_KEY'], 'Content-Type': 'application/json'}

def retool_data(keyword):
    data = requests.post('https://api.scavio.dev/api/v1/search',
        headers=SH, json={'query': keyword, 'country_code': 'us'}, timeout=10).json()
    organic = data.get('organic_results', [])[:5]
    return [{'pos': i+1, 'domain': r.get('displayed_link', ''), 'title': r['title'][:40]} for i, r in enumerate(organic)]

for r in retool_data('best search api'):
    print(f'#{r["pos"]} {r["domain"]:25} {r["title"]}')

JavaScript Example

JavaScript
const SH = { 'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json' };
const data = await fetch('https://api.scavio.dev/api/v1/search', {
  method: 'POST', headers: SH,
  body: JSON.stringify({ query: 'best search api', country_code: 'us' })
}).then(r => r.json());
const rows = (data.organic_results || []).slice(0, 5).map((r, i) => ({
  position: i + 1, domain: r.displayed_link, title: r.title
}));
console.log(JSON.stringify(rows, null, 2));

Expected Output

JSON
Retool table data: 4 rows
  search api python                   | #3    | Top 3: True
  mcp search tool                     | #2    | Top 3: True
  serp api pricing                    | #5    | Top 3: False
  web search api free tier            | #4    | Top 3: False

Cost: $0.020

=== SERP Features Summary (for Retool) ===
  Keywords scanned: 4
  AI Overview: 3/4 (75%)
  Featured Snippet: 2/4 (50%)
  People Also Ask: 4/4 (100%)

  Cost: $0.020/scan

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.

A Retool account (free tier works). A Scavio API key from scavio.dev. Basic SQL or JavaScript knowledge. A Scavio API key gives you 250 free credits per month.

Yes. The free tier includes 250 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 visual SEO dashboard in Retool powered by Scavio SERP data. Rank tracking, SERP features, and competitor analysis.