Overview
Run daily SERP queries for your Surfer SEO target keywords to track ranking positions, AI Overview appearances, and competitor movements. Feed live SERP data into content optimization decisions.
Trigger
Daily cron at 06:00 UTC
Schedule
Daily at 06:00 UTC
Workflow Steps
Load keyword list
Read target keywords from a JSON file, database, or Google Sheet. Each keyword includes the target URL to track position for.
Query SERP for each keyword
Search Google via Scavio for each keyword with AI Overview enabled. Extract full organic rankings, AI Overview presence, and People Also Ask.
Find target position
Scan organic results for the target URL. Record its position, or mark as 'not found' if outside top 100.
Detect AI Overview changes
Check if the keyword triggers an AI Overview and whether the target domain is cited. Log changes from previous day.
Store and alert
Append daily snapshot to a time-series database or CSV. Send alerts on position drops greater than 3 or AI Overview citation changes.
Python Implementation
import requests, os, json
from datetime import date
H = {'x-api-key': os.environ['SCAVIO_API_KEY']}
def track_keyword(keyword, target_domain):
r = requests.post('https://api.scavio.dev/api/v1/search', headers=H,
json={'platform': 'google', 'query': keyword, 'ai_overview': True},
timeout=10).json()
organic = r.get('organic', [])
position = None
for o in organic:
if target_domain in o.get('link', ''):
position = o.get('position')
break
aio = r.get('ai_overview', {}) or {}
aio_text = aio.get('text', '')
return {
'date': str(date.today()),
'keyword': keyword,
'position': position,
'top_3': [{'domain': o.get('link', '').split('/')[2] if '/' in o.get('link', '') else '',
'title': o['title']} for o in organic[:3]],
'has_ai_overview': bool(r.get('ai_overview')),
'cited_in_aio': target_domain in aio_text.lower(),
'paa_count': len(r.get('people_also_ask', [])),
}
keywords = [
('best project management tool 2026', 'example.com'),
('project management software comparison', 'example.com'),
]
for kw, domain in keywords:
result = track_keyword(kw, domain)
pos = result['position'] or 'not found'
aio = 'CITED' if result['cited_in_aio'] else 'not cited'
print(f"{kw}: #{pos} | AIO: {result['has_ai_overview']} ({aio})")JavaScript Implementation
const H = {"x-api-key": process.env.SCAVIO_API_KEY, "Content-Type": "application/json"};
async function trackKeyword(keyword, targetDomain) {
const r = await fetch("https://api.scavio.dev/api/v1/search", {
method: "POST", headers: H,
body: JSON.stringify({platform: "google", query: keyword, ai_overview: true})
}).then(r => r.json());
const organic = r.organic || [];
const match = organic.find(o => (o.link || "").includes(targetDomain));
const aio = r.ai_overview || {};
return {
date: new Date().toISOString().split("T")[0],
keyword,
position: match ? match.position : null,
top3: organic.slice(0, 3).map(o => ({
domain: (o.link || "").split("/")[2] || "", title: o.title
})),
hasAiOverview: Boolean(r.ai_overview),
citedInAio: (aio.text || "").toLowerCase().includes(targetDomain),
paaCount: (r.people_also_ask || []).length,
};
}
(async () => {
const keywords = [
["best project management tool 2026", "example.com"],
["project management software comparison", "example.com"],
];
for (const [kw, domain] of keywords) {
const r = await trackKeyword(kw, domain);
const pos = r.position || "not found";
console.log(`${kw}: #${pos} | AIO: ${r.hasAiOverview} (${r.citedInAio ? "CITED" : "not cited"})`);
}
})();Platforms Used
Web search with knowledge graph, PAA, and AI overviews