Overview
This workflow audits your brand's visibility in Google AI Overviews every week by checking 20 target keywords and recording whether your domain is cited in AI-generated answers. The output is a weekly GEO scorecard that tracks citation rates over time, flags new citations, and alerts when your brand drops out of AI answers. Teams use it to measure the ROI of GEO optimization efforts.
Trigger
Cron schedule (every Monday at 8:00 AM UTC)
Schedule
Runs every Monday at 8:00 AM UTC
Workflow Steps
Load brand keyword list
Read the 20 brand-related keywords from a local config file or database.
Query each keyword with AI Overview enabled
Call the Scavio API for each keyword with ai_overview: true to capture AI-generated answer content.
Parse AI Overview for brand citations
Check each AI Overview response for mentions of your domain or brand name in the cited sources.
Compare against previous week
Load last week's results and compute changes: new citations gained, citations lost, and stable citations.
Generate GEO scorecard
Output a weekly scorecard with citation rate, week-over-week changes, and keyword-level detail.
Python Implementation
import requests
import json
from pathlib import Path
from datetime import datetime
API_KEY = "your_scavio_api_key"
BRAND_DOMAIN = "yourdomain.com"
KEYWORDS = [
"best search API for AI agents",
"SERP API comparison 2026",
"structured search data API",
"web search API for LLMs",
"search API pricing comparison",
]
def check_geo_citation(keyword: str) -> dict:
res = requests.post(
"https://api.scavio.dev/api/v1/search",
headers={"x-api-key": API_KEY},
json={"platform": "google", "query": keyword, "ai_overview": True},
timeout=15,
)
res.raise_for_status()
data = res.json()
aio = data.get("ai_overview") or {}
aio_text = aio.get("text", "")
aio_sources = aio.get("sources", [])
cited = any(BRAND_DOMAIN in (s.get("link", "") or s.get("url", "")) for s in aio_sources)
mentioned = BRAND_DOMAIN.split(".")[0].lower() in aio_text.lower()
return {
"keyword": keyword,
"has_ai_overview": bool(aio_text),
"brand_cited": cited,
"brand_mentioned": mentioned,
"aio_sources_count": len(aio_sources),
"aio_preview": aio_text[:200],
}
def run():
date = datetime.utcnow().strftime("%Y-%m-%d")
results = [check_geo_citation(kw) for kw in KEYWORDS]
cited_count = sum(1 for r in results if r["brand_cited"])
mentioned_count = sum(1 for r in results if r["brand_mentioned"])
aio_count = sum(1 for r in results if r["has_ai_overview"])
# Load previous week for comparison
archive_dir = Path("geo_reports")
archive_dir.mkdir(exist_ok=True)
previous_files = sorted(archive_dir.glob("geo_*.json"))
previous = {}
if previous_files:
prev_data = json.loads(previous_files[-1].read_text())
previous = {r["keyword"]: r["brand_cited"] for r in prev_data.get("results", [])}
gained = [r["keyword"] for r in results if r["brand_cited"] and not previous.get(r["keyword"])]
lost = [kw for kw, was_cited in previous.items() if was_cited and not any(r["keyword"] == kw and r["brand_cited"] for r in results)]
report = {
"date": date,
"keywords_checked": len(KEYWORDS),
"ai_overviews_present": aio_count,
"brand_cited": cited_count,
"brand_mentioned": mentioned_count,
"citation_rate": f"{cited_count}/{aio_count}" if aio_count else "0/0",
"citations_gained": gained,
"citations_lost": lost,
"results": results,
}
archive_dir.joinpath(f"geo_{date}.json").write_text(json.dumps(report, indent=2))
print(f"GEO Report {date}: {cited_count}/{aio_count} AI Overviews cite {BRAND_DOMAIN}")
if gained:
print(f" Gained: {', '.join(gained)}")
if lost:
print(f" Lost: {', '.join(lost)}")
if __name__ == "__main__":
run()JavaScript Implementation
const API_KEY = "your_scavio_api_key";
const BRAND_DOMAIN = "yourdomain.com";
const KEYWORDS = ["best search API for AI agents", "SERP API comparison 2026", "structured search data API"];
async function checkGeoCitation(keyword) {
const res = await fetch("https://api.scavio.dev/api/v1/search", {
method: "POST",
headers: { "x-api-key": API_KEY, "content-type": "application/json" },
body: JSON.stringify({ platform: "google", query: keyword, ai_overview: true }),
});
if (!res.ok) throw new Error(`scavio ${res.status}`);
const data = await res.json();
const aio = data.ai_overview ?? {};
const sources = aio.sources ?? [];
const cited = sources.some((s) => (s.link ?? s.url ?? "").includes(BRAND_DOMAIN));
return { keyword, hasAio: !!aio.text, cited, sourcesCount: sources.length };
}
const results = [];
for (const kw of KEYWORDS) results.push(await checkGeoCitation(kw));
const cited = results.filter((r) => r.cited).length;
const withAio = results.filter((r) => r.hasAio).length;
console.log(`GEO Report: ${cited}/${withAio} AI Overviews cite ${BRAND_DOMAIN}`);Platforms Used
Web search with knowledge graph, PAA, and AI overviews