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

How to Build an Agency AEO Dashboard with a Search API

Build a client-facing AEO dashboard that tracks AI Overview citations, answer engine presence, and citation share across multiple clients.

Get Free API KeyAPI Docs

Answer Engine Optimization (AEO) is a growing service line for SEO agencies, but most rank tracking tools do not track AI Overview citations well or charge premium prices for it. Building a custom AEO dashboard with a search API gives agencies full control over the data, per-client views, and keeps costs predictable at $0.005 per keyword check. This tutorial builds a multi-client AEO dashboard backend that tracks citation presence, share of voice, and trend data, then outputs JSON ready for any frontend framework.

Prerequisites

  • Python 3.9+ installed
  • requests library installed
  • A Scavio API key from scavio.dev
  • Client keyword lists to monitor

Walkthrough

Step 1: Define the multi-client data structure

Set up a configuration that maps each client to their domain and target keywords. This is the input to the dashboard.

Python
clients = {
    'client_a': {
        'domain': 'clienta.com',
        'name': 'Client A - SaaS CRM',
        'keywords': [
            'best crm for small business',
            'crm software comparison 2026',
            'what is a crm system',
            'crm vs spreadsheet'
        ]
    },
    'client_b': {
        'domain': 'clientb.io',
        'name': 'Client B - Project Management',
        'keywords': [
            'best project management tools 2026',
            'how to manage remote teams',
            'project management software comparison',
            'agile vs waterfall 2026'
        ]
    }
}

total_keywords = sum(len(c['keywords']) for c in clients.values())
print(f'{len(clients)} clients, {total_keywords} total keywords')
print(f'Monthly cost (daily checks): ${total_keywords * 30 * 0.005:.2f}')

Step 2: Build the AEO data collection function

For each keyword, check the SERP for AI Overview presence and extract citation data. Record whether the client domain is cited.

Python
import requests, os, time

API_KEY = os.environ['SCAVIO_API_KEY']

def collect_aeo_data(keyword: str, client_domain: str) -> dict:
    resp = requests.post('https://api.scavio.dev/api/v1/search',
        headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
        json={'query': keyword, 'country_code': 'us'})
    data = resp.json()
    aio = data.get('ai_overview', {})
    has_overview = bool(aio and aio.get('text'))
    citations = aio.get('citations', []) if has_overview else []
    cited_domains = [c.get('domain', '') for c in citations]
    # Also check organic position
    organic_position = None
    for r in data.get('organic_results', []):
        if client_domain in r.get('link', ''):
            organic_position = r['position']
            break
    return {
        'keyword': keyword,
        'has_ai_overview': has_overview,
        'total_citations': len(citations),
        'client_cited': any(client_domain in d for d in cited_domains),
        'citation_position': next(
            (i + 1 for i, d in enumerate(cited_domains) if client_domain in d), None),
        'organic_position': organic_position,
        'competitor_domains': [d for d in cited_domains if client_domain not in d]
    }

Step 3: Generate per-client dashboard data

Aggregate keyword-level data into client-level metrics: citation rate, average citation position, organic overlap, and top competitor domains.

Python
from collections import Counter

def generate_client_dashboard(client_id: str, config: dict) -> dict:
    domain = config['domain']
    results = []
    competitor_counter = Counter()
    for kw in config['keywords']:
        data = collect_aeo_data(kw, domain)
        results.append(data)
        for d in data['competitor_domains']:
            competitor_counter[d] += 1
        time.sleep(0.3)
    total = len(results)
    with_aio = sum(1 for r in results if r['has_ai_overview'])
    cited = sum(1 for r in results if r['client_cited'])
    avg_cite_pos = 0
    cite_positions = [r['citation_position'] for r in results if r['citation_position']]
    if cite_positions:
        avg_cite_pos = sum(cite_positions) / len(cite_positions)
    return {
        'client_id': client_id,
        'client_name': config['name'],
        'domain': domain,
        'total_keywords': total,
        'keywords_with_aio': with_aio,
        'aio_rate': round(with_aio / max(total, 1) * 100, 1),
        'citations': cited,
        'citation_rate': round(cited / max(with_aio, 1) * 100, 1),
        'avg_citation_position': round(avg_cite_pos, 1),
        'top_competitors': competitor_counter.most_common(5),
        'keyword_details': results
    }

Step 4: Build the full agency dashboard output

Run the dashboard for all clients and output a JSON structure ready for a frontend. Include cost tracking per client.

Python
import json
from datetime import date

def build_agency_dashboard(clients: dict) -> dict:
    dashboard = {
        'generated': date.today().isoformat(),
        'clients': [],
        'summary': {}
    }
    total_credits = 0
    for client_id, config in clients.items():
        print(f'Processing {config["name"]}...')
        client_data = generate_client_dashboard(client_id, config)
        dashboard['clients'].append(client_data)
        total_credits += len(config['keywords'])
    # Agency summary
    all_clients = dashboard['clients']
    dashboard['summary'] = {
        'total_clients': len(all_clients),
        'total_keywords': sum(c['total_keywords'] for c in all_clients),
        'avg_citation_rate': round(
            sum(c['citation_rate'] for c in all_clients) / max(len(all_clients), 1), 1),
        'total_credits': total_credits,
        'cost': f'${total_credits * 0.005:.2f}'
    }
    with open(f'aeo_dashboard_{date.today()}.json', 'w') as f:
        json.dump(dashboard, f, indent=2)
    return dashboard

dashboard = build_agency_dashboard(clients)
for c in dashboard['clients']:
    print(f'{c["client_name"]}: {c["citation_rate"]}% citation rate, {c["citations"]}/{c["keywords_with_aio"]} cited')

Python Example

Python
import os, requests, time, json
from datetime import date
from collections import Counter

API_KEY = os.environ['SCAVIO_API_KEY']

def check_aeo(keyword, domain):
    resp = requests.post('https://api.scavio.dev/api/v1/search',
        headers={'x-api-key': API_KEY, 'Content-Type': 'application/json'},
        json={'query': keyword, 'country_code': 'us'})
    aio = resp.json().get('ai_overview', {})
    citations = aio.get('citations', []) if aio.get('text') else []
    domains = [c.get('domain', '') for c in citations]
    return {'keyword': keyword, 'has_aio': bool(aio.get('text')),
            'cited': any(domain in d for d in domains), 'domains': domains}

def client_report(name, domain, keywords):
    results = [check_aeo(kw, domain) for kw in keywords]
    cited = sum(1 for r in results if r['cited'])
    with_aio = sum(1 for r in results if r['has_aio'])
    print(f'{name}: {cited}/{with_aio} cited ({len(keywords)} keywords, ${len(keywords)*0.005:.3f})')

client_report('Demo Client', 'example.com', ['best crm 2026', 'crm comparison'])

JavaScript Example

JavaScript
const API_KEY = process.env.SCAVIO_API_KEY;

async function checkAeo(keyword, domain) {
  const resp = await fetch('https://api.scavio.dev/api/v1/search', {
    method: 'POST',
    headers: { 'x-api-key': API_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify({ query: keyword, country_code: 'us' })
  });
  const data = await resp.json();
  const aio = data.ai_overview || {};
  const domains = (aio.citations || []).map(c => c.domain || '');
  return { keyword, hasAio: Boolean(aio.text), cited: domains.some(d => d.includes(domain)) };
}

async function main() {
  const keywords = ['best crm 2026', 'crm comparison'];
  let cited = 0;
  for (const kw of keywords) {
    const r = await checkAeo(kw, 'example.com');
    if (r.cited) cited++;
    console.log(`${r.hasAio ? '+' : '-'}AIO ${r.cited ? '+CITED' : ''} ${kw}`);
  }
  console.log(`Citation rate: ${(cited/keywords.length*100).toFixed(0)}%`);
}

main().catch(console.error);

Expected Output

JSON
2 clients, 8 total keywords
Monthly cost (daily checks): $1.20

Processing Client A - SaaS CRM...
Processing Client B - Project Management...

Client A - SaaS CRM: 50.0% citation rate, 1/2 cited
Client B - Project Management: 33.3% citation rate, 1/3 cited

Agency summary:
  Total clients: 2
  Total keywords: 8
  Avg citation rate: 41.7%
  Cost: $0.04

Related Tutorials

  • How to Track AI Overview Citations on a Budget
  • How to Batch SEO Rank Checks Overnight with an API
  • How to Build an Ops Dashboard with Search Data

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.9+ installed. requests library installed. A Scavio API key from scavio.dev. Client keyword lists to monitor. 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 AEO Tracking APIs on a Budget in 2026

Read more
Best Of

Best AI Overview Tools for Small Agencies in 2026

Read more
Solution

Track AI Overview Citations for Agency Clients

Read more
Use Case

GEO/AEO Metric Tracking Dashboard

Read more
Use Case

AI Overview Agency Dashboard

Read more
Glossary

AEO for Agencies

Read more

Start Building

Build a client-facing AEO dashboard that tracks AI Overview citations, answer engine presence, and citation share across multiple clients.

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