Track daily changes to Google AI Overviews by querying target keywords through a search API and diffing the response against the previous day's snapshot. This approach surfaces new citations, removed sources, and rewritten summaries without manual SERP checking. The Scavio API returns structured AI Overview data including source URLs and summary text, making automated diffing straightforward. This tutorial builds a cron-friendly script that stores daily snapshots and reports deltas.
Prerequisites
- Python 3.8+ or Node.js 18+ installed
- requests library (Python) or built-in fetch (JS)
- A Scavio API key from scavio.dev
- A list of target keywords to monitor
Walkthrough
Step 1: Define keywords and storage
Set up the keyword list and a directory for daily snapshots.
import os, json, datetime
API_KEY = os.environ['SCAVIO_API_KEY']
KEYWORDS = ['best crm for startups', 'ai search api comparison', 'mcp server tutorial']
SNAPSHOT_DIR = 'aio_snapshots'
os.makedirs(SNAPSHOT_DIR, exist_ok=True)
TODAY = datetime.date.today().isoformat()Step 2: Fetch AI Overview for each keyword
Query the Scavio API and extract the AI Overview section, including sources and summary text.
import requests
def fetch_ai_overview(keyword: str) -> dict:
resp = requests.post('https://api.scavio.dev/api/v1/search',
headers={'x-api-key': API_KEY},
json={'platform': 'google', 'query': keyword}, timeout=15)
resp.raise_for_status()
data = resp.json()
aio = data.get('ai_overview', {})
return {
'keyword': keyword,
'summary': aio.get('text', ''),
'sources': [s.get('link', '') for s in aio.get('sources', [])],
}Step 3: Diff against yesterday's snapshot
Load the previous day's snapshot and compute added/removed sources and whether the summary text changed.
def diff_snapshots(today_data: dict, yesterday_data: dict) -> dict:
old_sources = set(yesterday_data.get('sources', []))
new_sources = set(today_data.get('sources', []))
return {
'keyword': today_data['keyword'],
'added_sources': list(new_sources - old_sources),
'removed_sources': list(old_sources - new_sources),
'summary_changed': today_data.get('summary', '') != yesterday_data.get('summary', ''),
}
def load_yesterday(keyword: str) -> dict:
yesterday = (datetime.date.today() - datetime.timedelta(days=1)).isoformat()
path = os.path.join(SNAPSHOT_DIR, f'{keyword}_{yesterday}.json')
if os.path.exists(path):
with open(path) as f: return json.load(f)
return {}Step 4: Run daily and save results
Iterate all keywords, fetch current data, diff against yesterday, save today's snapshot, and print a change report.
def run_daily():
changes = []
for kw in KEYWORDS:
current = fetch_ai_overview(kw)
previous = load_yesterday(kw)
path = os.path.join(SNAPSHOT_DIR, f'{kw}_{TODAY}.json')
with open(path, 'w') as f: json.dump(current, f, indent=2)
if previous:
delta = diff_snapshots(current, previous)
if delta['added_sources'] or delta['removed_sources'] or delta['summary_changed']:
changes.append(delta)
for c in changes:
print(f"[{c['keyword']}] +{len(c['added_sources'])} -{len(c['removed_sources'])} sources, summary_changed={c['summary_changed']}")
return changes
run_daily()Python Example
import requests, os, json, datetime
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
TODAY = datetime.date.today().isoformat()
def fetch_aio(kw):
data = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'platform': 'google', 'query': kw}, timeout=15).json()
aio = data.get('ai_overview', {})
return {'summary': aio.get('text', ''), 'sources': [s.get('link', '') for s in aio.get('sources', [])]}
def track(keywords):
for kw in keywords:
snapshot = fetch_aio(kw)
print(f'{kw}: {len(snapshot["sources"])} sources')
track(['best crm 2026', 'ai search api comparison'])JavaScript Example
const H = {'x-api-key': process.env.SCAVIO_API_KEY, 'Content-Type': 'application/json'};
async function fetchAIO(kw) {
const r = await fetch('https://api.scavio.dev/api/v1/search', {
method: 'POST', headers: H, body: JSON.stringify({platform: 'google', query: kw})
});
const data = await r.json();
const aio = data.ai_overview || {};
return {summary: aio.text || '', sources: (aio.sources || []).map(s => s.link)};
}
async function track(keywords) {
for (const kw of keywords) {
const snap = await fetchAIO(kw);
console.log(`${kw}: ${snap.sources.length} sources`);
}
}
track(['best crm 2026', 'ai search api comparison']);Expected Output
A daily change report showing which AI Overview sources were added or removed, and whether the summary text changed, for each tracked keyword.