An AI writer that drafts from training data alone produces generic posts that AI Overviews already answer, so they never get clicked or cited. The fix is grounding: before the model writes, pull the live Google SERP for the topic and feed it the People Also Ask questions, related searches, and the pages currently ranking. The draft then answers the exact sub-questions Google is surfacing today, structured the way cited pages are. This tutorial builds that loop with Scavio's Google endpoint in about 30 lines. It is the same pattern Reddit marketers describe running daily through MCP to auto-publish brand-voice posts.
Prerequisites
- Python 3.9+ and the requests library
- A Scavio API key (50 free credits at signup)
- Any LLM you can call for the writing step (Claude, GPT, a local model)
Walkthrough
Step 1: Set your API key
Keep the key in an environment variable, not in source. Scavio uses Bearer auth for all REST endpoints.
export SCAVIO_API_KEY=sk_your_key_hereStep 2: Pull the full SERP for your topic
Set light_request to false (2 credits) so the response includes the questions (People Also Ask) and related_searches blocks alongside the ranking pages. Those are the sub-questions your draft must answer to be cited.
import os, requests
H = {"Authorization": f"Bearer {os.environ['SCAVIO_API_KEY']}",
"Content-Type": "application/json"}
def serp_brief(topic):
# full SERP (2 credits) gives related_searches + People Also Ask to mine subtopics
r = requests.post("https://api.scavio.dev/api/v1/google",
headers=H, json={"query": topic, "light_request": False}).json()
paa = [q["question"] for q in r.get("questions", [])]
related = r.get("related_searches", [])
top = [{"title": x["title"], "link": x["link"], "snippet": x.get("snippet","")}
for x in r.get("results", [])[:8]]
return {"people_also_ask": paa, "related": related, "ranking_pages": top}
brief = serp_brief("how to clean a cast iron skillet")
# Feed brief into your writer prompt so the draft answers the questions
# Google is actually surfacing and cites the pages currently ranking.Step 3: Build the writer prompt from the brief
You are handing the model the real demand curve for the topic, not asking it to imagine one. The PAA list becomes your H2 structure, which is also how answer engines chunk a page.
brief = serp_brief("how to clean a cast iron skillet")
h2s = "\n".join("- " + q for q in brief["people_also_ask"])
prompt = f"""Write a 900-word guide on: how to clean a cast iron skillet.
Answer the title question in the first sentence (no intro).
Then answer each of these real questions, each as its own H2:
{h2s}
Cover these related angles where relevant: {', '.join(brief['related'])}
Match the depth of the pages currently ranking; do not pad."""Step 4: Generate, then re-check before publishing
Grounding is not one-and-done. Re-pulling the SERP on a schedule tells you when a post has drifted from what people now ask, which is your refresh trigger.
draft = your_llm(prompt) # call whatever model you use
# Re-pull the SERP weekly and diff the PAA list.
# New questions appearing = a content-refresh signal for that post.
fresh = serp_brief("how to clean a cast iron skillet")
new_qs = set(fresh["people_also_ask"]) - set(brief["people_also_ask"])
if new_qs:
print("Refresh with:", new_qs)Python Example
import os, requests
H = {"Authorization": f"Bearer {os.environ['SCAVIO_API_KEY']}",
"Content-Type": "application/json"}
def serp_brief(topic):
# full SERP (2 credits) gives related_searches + People Also Ask to mine subtopics
r = requests.post("https://api.scavio.dev/api/v1/google",
headers=H, json={"query": topic, "light_request": False}).json()
paa = [q["question"] for q in r.get("questions", [])]
related = r.get("related_searches", [])
top = [{"title": x["title"], "link": x["link"], "snippet": x.get("snippet","")}
for x in r.get("results", [])[:8]]
return {"people_also_ask": paa, "related": related, "ranking_pages": top}
brief = serp_brief("how to clean a cast iron skillet")
# Feed brief into your writer prompt so the draft answers the questions
# Google is actually surfacing and cites the pages currently ranking.JavaScript Example
const H = { Authorization: `Bearer ${process.env.SCAVIO_API_KEY}`, "Content-Type": "application/json" };
async function serpBrief(topic) {
const r = await fetch("https://api.scavio.dev/api/v1/google", {
method: "POST", headers: H,
body: JSON.stringify({ query: topic, light_request: false })
}).then(r => r.json());
return {
peopleAlsoAsk: (r.questions || []).map(q => q.question),
related: r.related_searches || [],
ranking: (r.results || []).slice(0, 8).map(x => ({ title: x.title, link: x.link }))
};
}Expected Output
{
"people_also_ask": [
"Can you use soap on a cast iron skillet?",
"How do you clean cast iron after cooking?",
"Why is my cast iron sticky after seasoning?"
],
"related": ["cast iron cleaning rust", "cast iron seasoning oil"],
"ranking_pages": [ { "title": "How to Clean Cast Iron...", "link": "https://..." } ]
}