Overview
Monitor a set of target keywords daily to track which pages appear in Google AI Overviews. Compare your citation rate against competitors, detect when you gain or lose AI Overview citations, and track the overall AEO landscape for your keyword cluster.
Trigger
Daily cron at 05:00 UTC
Schedule
Daily at 05:00 UTC
Workflow Steps
Load keyword tracking list
Read the target keywords and your domain from config. Each keyword tracks which domains were cited in yesterday's AI Overview.
Search with AI Overview enabled
For each keyword, query Google with AI Overview extraction enabled. Parse the AI Overview response for cited URLs.
Extract citations
Pull all URLs cited in the AI Overview. Record domain, page path, and citation position.
Compare to previous day
Diff today's citations against yesterday's. Flag new citations gained, citations lost, and position changes.
Generate AEO report
Output daily AEO visibility metrics: total keywords with AI Overviews, your citation rate, competitor citation rates, and changes.
Python Implementation
import requests, os, json
from urllib.parse import urlparse
from datetime import date
H = {"x-api-key": os.environ["SCAVIO_API_KEY"], "Content-Type": "application/json"}
STATE_FILE = "aeo_state.json"
def track_aeo(keywords, my_domain):
state = {}
try:
with open(STATE_FILE) as f: state = json.load(f)
except FileNotFoundError: pass
today = str(date.today())
results = {"date": today, "keywords": {}}
for kw in keywords:
resp = requests.post("https://api.scavio.dev/api/v1/search",
headers=H, json={"query": kw, "country_code": "us",
"include_ai_overview": True}).json()
aio = resp.get("ai_overview")
citations = []
if aio and aio.get("sources"):
for src in aio["sources"]:
domain = urlparse(src.get("link", "")).netloc
citations.append({"domain": domain, "url": src["link"], "title": src.get("title", "")})
prev_domains = set(state.get(kw, {}).get("domains", []))
curr_domains = set(c["domain"] for c in citations)
my_cited = my_domain in curr_domains
results["keywords"][kw] = {
"has_aio": bool(aio),
"my_cited": my_cited,
"citations": len(citations),
"gained": list(curr_domains - prev_domains),
"lost": list(prev_domains - curr_domains),
}
state[kw] = {"domains": list(curr_domains), "date": today}
with open(STATE_FILE, "w") as f: json.dump(state, f)
cited_count = sum(1 for k in results["keywords"].values() if k["my_cited"])
print(f"AEO Report {today}: cited in {cited_count}/{len(keywords)} AI Overviews")
return results
track_aeo(["serp api pricing", "best search api 2026", "mcp search tools"], "scavio.dev")JavaScript Implementation
const H = { "x-api-key": process.env.SCAVIO_API_KEY, "Content-Type": "application/json" };
async function trackAEO(keyword, myDomain) {
const resp = await fetch("https://api.scavio.dev/api/v1/search", {
method: "POST", headers: H,
body: JSON.stringify({ query: keyword, country_code: "us", include_ai_overview: true })
}).then(r => r.json());
const sources = resp.ai_overview?.sources || [];
const cited = sources.some(s => s.link?.includes(myDomain));
console.log(`"${keyword}": AI Overview ${resp.ai_overview ? "present" : "absent"}, ${cited ? "CITED" : "not cited"} (${sources.length} sources)`);
}
trackAEO("serp api pricing", "scavio.dev");Platforms Used
Web search with knowledge graph, PAA, and AI overviews