AEO (AI Engine Optimization) tracking is becoming essential as Google AI Overviews reshape organic search traffic. Most AEO monitoring tools charge $100-500 per month for basic tracking. You can build your own AEO report API using Scavio at $0.005 per search credit, making it possible to track hundreds of keywords for under $5 per month. This tutorial shows how to build a lightweight AEO report endpoint that checks whether your site appears in AI Overviews, tracks citation sources, and generates weekly comparison reports.
Prerequisites
- Python 3.8+ with Flask or FastAPI installed
- requests library installed
- A Scavio API key from scavio.dev
- A list of target keywords to monitor
Walkthrough
Step 1: Define your keyword list
Set up the keywords and domains you want to track for AI Overview presence.
import os, requests, json
from datetime import date
API_KEY = os.environ["SCAVIO_API_KEY"]
MY_DOMAIN = "example.com"
KEYWORDS = [
"best crm for startups",
"how to automate lead generation",
"cold email tools 2026",
]Step 2: Check AI Overview presence
Query each keyword and check if the AI Overview cites your domain.
def check_aeo(keyword):
resp = requests.post("https://api.scavio.dev/api/v1/search",
headers={"x-api-key": API_KEY},
json={"platform": "google", "query": keyword})
data = resp.json()
aio = data.get("ai_overview", {})
sources = aio.get("sources", []) if aio else []
cited = any(MY_DOMAIN in s.get("link", "") for s in sources)
return {
"keyword": keyword,
"has_ai_overview": bool(aio),
"cited": cited,
"source_count": len(sources),
"date": date.today().isoformat(),
}
result = check_aeo(KEYWORDS[0])
print(json.dumps(result, indent=2))Step 3: Build the report
Run AEO checks across all keywords and aggregate into a report.
def build_aeo_report(keywords):
results = [check_aeo(kw) for kw in keywords]
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["cited"])
return {
"date": date.today().isoformat(),
"domain": MY_DOMAIN,
"total_keywords": total,
"keywords_with_ai_overview": with_aio,
"domain_cited": cited,
"citation_rate": round(cited / total * 100, 1) if total else 0,
"details": results,
}
report = build_aeo_report(KEYWORDS)
print(f"AEO citation rate: {report['citation_rate']}%")Step 4: Save and compare reports
Store reports as JSON files and compare week-over-week changes.
REPORT_DIR = "aeo_reports"
os.makedirs(REPORT_DIR, exist_ok=True)
def save_report(report):
path = f"{REPORT_DIR}/{report['date']}.json"
with open(path, "w") as f:
json.dump(report, f, indent=2)
print(f"Saved report to {path}")
def compare_reports(current, previous_path):
with open(previous_path) as f:
prev = json.load(f)
return {
"citation_rate_change": current["citation_rate"] - prev["citation_rate"],
"new_citations": current["domain_cited"] - prev["domain_cited"],
}
save_report(report)Python Example
import os, requests
API_KEY = os.environ["SCAVIO_API_KEY"]
def check_aeo(keyword):
resp = requests.post("https://api.scavio.dev/api/v1/search",
headers={"x-api-key": API_KEY},
json={"platform": "google", "query": keyword})
aio = resp.json().get("ai_overview", {})
return {"keyword": keyword, "has_aio": bool(aio), "sources": len(aio.get("sources", []))}
for kw in ["best crm 2026", "cold email tools"]:
print(check_aeo(kw))JavaScript Example
const H = {"x-api-key": process.env.SCAVIO_API_KEY, "Content-Type": "application/json"};
async function checkAeo(keyword) {
const r = await fetch("https://api.scavio.dev/api/v1/search", {
method: "POST", headers: H,
body: JSON.stringify({platform: "google", query: keyword})
});
const aio = (await r.json()).ai_overview || {};
return {keyword, hasAio: !!aio.sources, sources: (aio.sources || []).length};
}
checkAeo("best crm 2026").then(console.log);Expected Output
A JSON report showing AI Overview presence, citation rate, and source counts for each tracked keyword, stored for week-over-week comparison.