SEO as an agent task
Why SEO is a strong fit for agent automation
Scale versus judgment
SEO splits into two different kinds of work: mechanical operations on data (rank tracking, link audits, report generation) and strategic judgment (priorities, brand voice, risk). The first kind fits agents β it is structured, repeatable, and scalable. The second needs business context and human expertise.
The numbers are blunt: an agent checks 10,000 URLs in a few minutes, while an experienced SEO specialist would spend days on the same pass. Mechanical check quality is not lower β the agent does not tire, skip spreadsheet rows, or mistype when copying data.
An agent does not replace SEO expertise. It amplifies it: it absorbs the routine volume so the specialist can spend time where understanding matters β strategy, brand, anomaly interpretation, incident response. That is the operating principle: the agent is a tool, not a substitute for the expert.
Three zones of automability
Not every SEO task automates equally. Split them into three zones:
Full automation
The agent runs the task end to end with no human in the loop.
- Rank tracking (position monitoring)
- Keyword data fetch (keyword metric pulls)
- Broken link checks
- Performance monitoring (speed / Core Web Vitals)
- Sitemap generation
- Automated reporting
Augmentation (agent + human)
The agent does the volume; a human makes the decisions.
- Writing content (LLM drafts β editor reviews)
- Link prospecting (agent finds candidates, human chooses)
- Technical audit (agent finds issues, human prioritizes)
Stays with the human
- SEO strategy β needs business goals, market, competitive position
- Brand voice β tone and style are set by the brand team
- Incident response β a sharp traffic drop needs contextual judgment
- E-E-A-T signals β authority and expertise need qualitative analysis
The chart below shows automation ROI for eight representative SEO tasks on a 0β10 scale:
Color coding: ▮ Green β high ROI, full automation; ▮ Yellow β medium ROI, augmentation (agent + human); ▮ Red β low ROI, the task stays with the human.
Types of SEO agents
Agent systems in SEO split into a few functional types β each owns a class of tasks:
- Data-collector β pulls data from APIs (Search Console, Ahrefs, Semrush, PageSpeed Insights), parses the SERP, aggregates metrics into tables. The basic building block of most SEO systems.
- Auditor β crawls the site, finds technical issues (404s, duplicates, missing meta, slow pages), builds a prioritized findings list for the SEO specialist.
- Content-generator β uses an LLM to draft copy, optimize title/description, and generate a keyword set. It works in tandem with an editor.
- Monitor β watches changes in near real time: rank drops, new competitors, algorithm shifts. Sends alerts on anomalies.
- Orchestrator β coordinates the other agents, manages the task queue, and rolls results into one report. The most complex type β it needs reliable planning and error handling.
Check yourself
The agent stack for SEO
Four layers: from data sources to a finished output
Stack architecture
Any SEO agent has four layers. Each layer owns a job β the boundaries matter when you pick tools.
1. Data Sources
- Google Search Console API β positions, CTR, clicks, impressions per query and page. The only official Google source for that data.
- SERP APIs (SerpAPI, DataForSEO, Bright Data) β live Google SERP: top 10, featured snippets, PAA.
- Ahrefs / Semrush API β backlinks, keyword difficulty, competitor organic traffic.
- Web crawlers β
requests + BeautifulSoupfor static sites,Scrapyfor scale,Playwrightfor JS sites (browser rendering).
2. Processing
- HTML parsing β extract title, h1, meta description, canonical, structured data.
- Data normalization β canonicalize URLs, clean text, strip HTML tags.
- Deduplication β find duplicate pages and keywords.
- Storage β
SQLitefor prototypes,PostgreSQLfor production load.
3. Agent Logic
- LLM β Claude API, GPT-4o, Ollama (local). The agent brain: analyzes, reasons, writes recommendations.
- Prompt engineering β a system prompt with site context, role, and output format.
- Tool use / function calling β the agent calls GSC API, SERP API, or the crawler when it needs them.
- Memory β persist prior state (old positions, change history) so you can compare movement.
4. Output
- Reports β Markdown or JSON with concrete recommendations and priorities.
- Tracker tickets β auto-create issues in Jira or Linear.
- CMS API β publish optimized content straight into WordPress, Strapi, Contentful.
- Alerts β WhatsApp, Telegram, or email when ranks drop sharply.
A minimal Python agent
Here is the skeleton of a simple SEO agent. In a real project each function grows; the structure stays the same:
import anthropic
import sqlite3
from datetime import datetime
# --- 1. Data Sources ---
def fetch_gsc_data(site_url: str, days: int = 28) -> list[dict]:
"""
Returns top pages from the Google Search Console API.
Requires: google-auth, google-api-python-client
Scope: googleapis.com/auth/webmasters.readonly
"""
# ... initialize credentials ...
# ... call searchanalytics.query(...) ...
return [
{"page": "/blog/seo-guide", "clicks": 320, "position": 4.2},
# ...
]
def fetch_serp(keyword: str) -> dict:
"""
Live SERP via SerpAPI / DataForSEO.
"""
# import serpapi; top-10 results
return {"organic_results": [...]}
# --- 2. Processing ---
def normalize_pages(raw_data: list[dict]) -> list[dict]:
"""Deduplicate URLs, normalize positions."""
seen = set()
result = []
for row in raw_data:
url = row["page"].rstrip("/")
if url not in seen:
seen.add(url)
result.append({**row, "page": url})
return result
def save_to_db(conn: sqlite3.Connection, rows: list[dict]) -> None:
conn.execute("""
CREATE TABLE IF NOT EXISTS pages
(page TEXT, clicks INT, position REAL, date TEXT)
""")
for row in rows:
conn.execute(
"INSERT INTO pages VALUES (?,?,?,?)",
(row["page"], row["clicks"], row["position"],
datetime.today().isoformat())
)
conn.commit()
# --- 3. Agent Logic ---
client = anthropic.Anthropic()
def analyze_pages(pages: list[dict]) -> str:
"""LLM analyzes the data and writes recommendations."""
data_str = "\n".join(
f"- {p['page']}: position {p['position']:.1f}, clicks {p['clicks']}"
for p in pages[:20] # top 20
)
message = client.messages.create(
model="claude-sonnet-4-6" # current ID: check docs.anthropic.com,
max_tokens=1024,
system=(
"You are an SEO analyst. Analyze page positions, "
"find growth opportunities, give concrete priorities."
),
messages=[{
"role": "user",
"content": f"GSC data for 28 days:\n{data_str}\n\n"
"Return the top 5 recommendations in Markdown."
}]
)
return message.content[0].text
# --- 4. Output ---
def save_report(text: str, path: str = "report.md") -> None:
with open(path, "w", encoding="utf-8") as f:
f.write(f"# SEO report {datetime.today().date()}\n\n{text}")
print(f"Report saved: {path}")
# --- Main ---
if __name__ == "__main__":
conn = sqlite3.connect("seo.db")
raw = fetch_gsc_data("example.com")
pages = normalize_pages(raw)
save_to_db(conn, pages)
report = analyze_pages(pages)
save_report(report)
fetch_gsc_data for a real API call, add logging β you already have a working agent. Add complexity later.
Choosing tools
SERP API: price and capability
SerpAPI
- Free tier: 100 queries/month β prototype only
- Paid plan: from $50/month for 5,000 queries
- Simple API, solid documentation
- Supports Google, Bing, YouTube, Maps
DataForSEO
- Pay-as-you-go: from $0.0006 per query
- Broad coverage: 50+ search engines
- Bulk API for high volume
- Fits production with unpredictable traffic
Bright Data
- Specialty: hard JS sites, anti-bot bypass
- Higher price, more reliable at scale
- Fits agents that work with dynamic content
LLM: picking a model for an SEO agent
Claude Sonnet β the default pick
GPT-4o β OpenAI alternative
Ollama β local run (no API fee)
Agent stack cost calculator
At 10,000 queries/month the full stack is about $30/month β less than one hour of specialist time. Run your scenario:
Check yourself
Technical site audit
Audit agent: find, prioritize, report
Technical SEO checklist
The audit agent checks each of these items as it crawls the site:
- robots.txt and sitemap.xml β files reachable, syntax valid, sitemap registered in GSC
- Index status β no unwanted
noindex;canonicalpoints at the right URLs - Broken links (4xx / 5xx) β every internal link returns 2xx
- Duplicate content β identical or near-identical pages without canonical cause cannibalization
- Core Web Vitals β LCP β€ 2.5s, CLS β€ 0.1, INP β€ 200ms (direct Google ranking factors)
- HTTPS and mixed content β all content loads over HTTPS, no HTTP assets on an HTTPS page
- Mobile layout β viewport meta present, content is not clipped on screens < 375 px
- Structured Data / Schema.org β markup is valid and covers the key entity types
- Image alt text β every meaningful image has a descriptive
alt - Meta tags β
title50β60 characters,description120β158 characters, unique on every page - Click depth β important pages are reachable in no more than 3 clicks from the homepage
- Orphan pages β no indexable page lacks inbound internal links
Audit agent architecture
crawl(url) β fetch_page(url) # download HTML, status, headers β check_all(page): [findings] # run all 12+ checks β prioritize(findings): # priority = severity Γ traffic_impact β generate_report(findings) # JSON / Markdown / HTML report β notify(report) # Slack / email / Jira ticket
Crawler tools
Baseline crawler for static HTML. Fast, no browser dependency.
JS rendering for SPA and React sites. Sees what a real browser sees.
Industrial crawler for large sites when a license is available.
Prioritizing findings
A raw list of hundreds of findings is useless. The audit agent applies:
- Severity (1β5): 5 = a direct Google ranking factor, 1 = cosmetic fix
- Traffic Impact (1β5): 5 = site-wide, 1 = a single page
- Final range: 1β25
Priority examples
| Finding | Severity | Traffic Impact | Priority |
|---|---|---|---|
| LCP > 4s (Core Web Vitals fail) | 5 | 5 | 25 |
| Mixed content (HTTP on HTTPS) | 4 | 5 | 20 |
| Duplicate pages without canonical | 4 | 4 | 16 |
| Broken links (4xx) | 3 | 3 | 9 |
| Missing H1 | 3 | 3 | 9 |
| Image alt text | 2 | 2 | 4 |
- 5 β direct Google ranking factor (Core Web Vitals, noindex, robots.txt block)
- 4 β meaningful technical signal (duplicate content, HTTPS/mixed content)
- 3 β moderate impact (broken links, missing H1, meta description)
- 2 β cosmetic with tiny SEO impact (alt text, minor schema errors)
- 1 β no ranking impact (style mismatches, extra tags)
Finding priority calculator
Check yourself
Keyword Intelligence
Clustering, intent mapping, and gap opportunities
Keyword classification
Before the agent works the keyword set, it needs a keyword taxonomy β one classification by length and by intent. Without it clustering is noise: the agent does not know which pages to assign the terms to.
By query length
Head keywords
1β2 words. High volume (>10,000 / month), difficulty KD > 70. Heavy competition β unrealistic as a primary target for a new site.
python, SEO, buy phone
Body keywords
3β4 words. Mid volume and difficulty. A workable balance, still competitive in most niches.
buy iPhone 15, SEO course
Long-tail keywords β the sweet spot for a new site
5+ words. Volume < 500 / month, KD < 30. Each query is small, but thousands of them add up past one head term β and they are far easier to rank for.
how to choose an SEO agency for an ecommerce store in 2025
By intent (Search Intent)
Search intent is the goal behind the query. An agent that mislabels intent assigns the keyword to the wrong page type, and the content never reaches the top β even if the technical quality is high.
Informational
The user wants to learn.
"how SEO works""what is PageRank"
β articles, guides, FAQ
Navigational
The user is looking for a specific site.
"ahrefs login""google search console"
β brand pages
Commercial
The user is comparing options.
"best SEO tool""ahrefs vs semrush"
β reviews, comparison tables
Transactional
The user is ready to buy.
"buy semrush""ahrefs subscription pricing"
β product pages, PLP
Semantic clustering
The agent collects thousands of keywords; without grouping they are noise. Clustering turns a flat list into a map of future site structure: each cluster is one page (or section).
Classic N-gram overlap
Groups keys that share the same words. Fast, no ML, runs on any hardware.
Downside: no synonyms. "notebook" and "laptop" land in different clusters.
Embeddings + k-means
sentence-transformers turns each query into a vector β cosine similarity β k-means clustering by semantic proximity.
Upside: catches synonyms and paraphrases. Downside: needs a GPU / cloud API.
Agent output after clustering β a cluster map with a site-structure proposal: 'Cluster "buy iPhone" (42 keywords, avg KD 35) β create /shop/iphone/ with 1 category page and 4 product pages'.
Keyword Gap Analysis
Gap analysis finds keywords where a competitor already ranks and you do not. Demand is proven, relevance is proven by the competitor; the job is to ship a stronger page.
Agent algorithm
- Fetch the competitor's domain keywords via Ahrefs / Semrush API
- Fetch your domain keywords
- Set difference:
competitor_kw - your_kwβ gap keyword list - Sort by the priority formula:
Volume / (KD + 1) - Filter by matching intent β pick the right page types
- Output top-N into a report with content recommendations
The gap-analysis sweet spot β keywords with high volume + low KD + matching intent for pages you already have or can create cheaply. The agent can flag this quadrant automatically.
Example Python pseudocode:
# gap_analysis.py β agent gap-analysis pseudocode
import requests
AHREFS_TOKEN = "..."
def fetch_domain_keywords(domain: str) -> set[str]:
"""Return the domain keyword set via Ahrefs API."""
# GET api.ahrefs.com/v3/site-explorer/organic-keywords
resp = requests.get(
AHREFS_TOKEN, # endpoint lives in config
params={"target": domain, "limit": 10000},
headers={"Authorization": f"Bearer {AHREFS_TOKEN}"}
)
resp.raise_for_status()
return {row["keyword"] for row in resp.json()["keywords"]}
def fetch_kw_metrics(keywords: list[str]) -> dict:
"""Fetch Volume and KD for a keyword list."""
# POST api.ahrefs.com/v3/keywords-explorer/overview
resp = requests.post(
AHREFS_TOKEN, # endpoint lives in config
json={"keywords": keywords},
headers={"Authorization": f"Bearer {AHREFS_TOKEN}"}
)
resp.raise_for_status()
return {r["keyword"]: r for r in resp.json()["keywords"]}
def gap_analysis(your_domain: str, competitor_domain: str, top_n: int = 50):
your_kws = fetch_domain_keywords(your_domain)
competitor_kws = fetch_domain_keywords(competitor_domain)
gap_kws = list(competitor_kws - your_kws) # set difference
metrics = fetch_kw_metrics(gap_kws)
# Sort: high volume, low difficulty first
ranked = sorted(
gap_kws,
key=lambda kw: metrics.get(kw, {}).get("volume", 0)
/ (metrics.get(kw, {}).get("kd", 100) + 1),
reverse=True
)
return [
{
"keyword": kw,
"volume": metrics[kw]["volume"],
"kd": metrics[kw]["kd"],
"intent": metrics[kw].get("intent", "unknown"),
"score": metrics[kw]["volume"] / (metrics[kw]["kd"] + 1),
}
for kw in ranked[:top_n]
if kw in metrics
]
if __name__ == "__main__":
results = gap_analysis("yoursite.com", "competitor.com", top_n=50)
for r in results:
print(f"{r['score']:6.1f} Vol={r['volume']:5d} KD={r['kd']:2d} "
f"[{r['intent'][:4]}] {r['keyword']}")
Keyword map
A Volume vs Difficulty scatter is the main visual for prioritization. Each point is a keyword; dashed lines split the space into quadrants.
Check yourself
Queries "buy iPhone 15 Pro Max", "iPhone 15 Pro Max price", "where to buy iPhone 15 Pro Max cheaper" β what is their search intent?
- A) Informational
- B) Navigational
- C) Transactional / commercial
- D) Educational
The content agent
From a keyword to a finished SEO article in one pipeline
A 6-stage pipeline
The content agent does not write an article in one call β it runs six sequential stages, each narrowing context and raising output quality.
Target keyword, a cluster of related queries, and search intent β informational, transactional, or navigational.
The agent writes a brief: topic, audience, H1/H2/H3 structure, tone, top-10 competitor analysis.
The agent generates a full outline and the key points of each section from the brief.
The agent writes the full article, following the approved outline. Each section is a separate call or one large prompt.
The agent checks: keyword in H1 and meta title, density 1β2%, title length 50β60 chars, meta description 120β158 chars.
A human checks facts, brand-voice fit, and publishes. The only mandatory manual step.
System prompt: what goes in
Content-agent quality is mostly the system prompt. Required pieces:
- Target keyword and LSI terms β as an explicit list so the agent knows which variants to use naturally.
- Search intent β what the user wants: learn (informational), buy (transactional), or find a site (navigational).
- Required structure β H1 with the keyword, 4β5 H2s, a required close/CTA.
- Hard limits β do NOT invent statistics without sources, do NOT use the keyword above 2% of the text.
- Target length β 1,000β1,500 words for informational, 500β800 for transactional.
System prompt template (pseudocode):
You are an SEO copywriter. Write the article strictly to spec.
TARGET QUERY: {target_keyword}
LSI TERMS: {lsi_list}
INTENT: {intent_type} # informational | transactional
STRUCTURE:
H1: must contain {target_keyword}
H2 x 4-5: {h2_list}
Close: short summary + call to action
CONSTRAINTS:
- Do NOT invent statistics without a source
- Keyword density: 1-2% of the text
- Length: {min_words}-{max_words} words
META:
title: 50-60 characters, contains {target_keyword}
description: 120-158 characters, reason to click
AUDIENCE: {audience_description}
TONE: {tone} # formal | conversational | expert
When the agent, when the editor
The agent can handle it
- Low-competition long-tail content
- Programmatic SEO β thousands of similar pages (cities, products, categories)
- Technical descriptions with a clear structure
- FAQ pages and glossaries
An editor is required
- YMYL content (health, finance, legal)
- E-E-A-T pieces that need first-hand author experience
- Expert articles with fresh data
- Brand voice with a distinctive tone
Content pipeline cost
Calculate the real cost of producing content at your scale.
Check yourself
What must you not put in a content-agent system prompt for an SEO article about smartphones?
SERP monitoring and link profile
The agent watches ranks and backlinks β and raises the alarm first
SERP monitoring
Search positions move every day. Tracking them by hand means you always learn late. A monitor agent makes this systematic.
What to track
Organic rank is the baseline signal. Track it daily on priority keywords.
Google Search Console gives real clicks and impressions. Rank is stable but CTR falls? The title or snippet needs work.
Featured Snippet, People Also Ask, Local Pack β they sit above organic. Losing a snippet drops CTR even at the same rank.
Anomaly thresholds
- Traffic drop > 20% in a day β diagnose immediately: algo update or a technical issue
- Rank drop > 10 places in a day on one keyword β check competitors and fresh content on the page
- Drop on all keywords at once β likely robots.txt / noindex or a Google algo update
Market-wide volatility is tracked by MozCast and SERPoscope β if those indexes spike, it is not just your site in the storm.
Monitor agent: pseudocode
# Rank-monitor agent (cron: every 24h)
def serp_monitor_agent(keywords: list, threshold_drop: int = 5):
state = load_state("serp_positions.json") # previous positions
alerts = []
for keyword in keywords:
current_pos = fetch_position(keyword) # GSC API / DataForSEO
prev_pos = state.get(keyword, current_pos)
drop = current_pos - prev_pos # positive = worse
if drop > threshold_drop:
alerts.append({
"keyword": keyword,
"prev": prev_pos,
"current": current_pos,
"drop": drop,
"severity": "HIGH" if drop > 15 else "MEDIUM"
})
state[keyword] = current_pos # update state
save_state("serp_positions.json", state)
if alerts:
# Extra context: check MozCast
volatility = fetch_mozcast_score()
context = "algo-update likely" if volatility > 80 else "site-specific issue"
send_alert(alerts, context=context)
return alerts
Rank movement over 30 days
On the chart below: the lower the line, the better the rank (position 1 beats position 25).
Link profile
Backlinks have been a core Google ranking factor since PageRank. Links pass "authority" (link equity) from one domain to another.
Link quality metrics
0β100, logarithmic
0β100, logarithmic
quality of the link path
unique referring domains
Toxic links and risk
Toxic-link tells:
- Domains with DR < 5 and irrelevant topics
- The same anchor text on hundreds of links (over-optimized anchors)
- Links from forum signatures, comments, low-quality directories
- A sudden burst of hundreds of links in a short window
Link Gap Analysis
Link gap β domains that link to competitors but not to you. A ready prospect list.
# Agent: link-profile analysis + link gap
def link_profile_agent(my_domain: str, competitors: list):
# 1. Fetch backlinks via API (Ahrefs / Semrush)
my_backlinks = fetch_backlinks(my_domain)
comp_backlinks = {c: fetch_backlinks(c) for c in competitors}
# 2. Score referring domains
scored = []
for link in my_backlinks:
score = compute_link_score(
dr=link["domain_rating"],
tf=link["trust_flow"],
relevance=link["topical_relevance"] # 0..1
)
scored.append({**link, "score": score})
# 3. Filter toxic (score < 0.2)
toxic = [l for l in scored if l["score"] < 0.2]
healthy = [l for l in scored if l["score"] >= 0.2]
if toxic:
build_disavow_file(toxic) # -> disavow.txt for Google
# 4. Link gap: competitor domains you do not have
my_domains = {l["domain"] for l in healthy}
gap_domains = set()
for comp, links in comp_backlinks.items():
for link in links:
if link["domain"] not in my_domains:
gap_domains.add(link["domain"])
# 5. Prioritize prospects by DR
prospects = sorted(gap_domains,
key=lambda d: get_dr(d), reverse=True)[:50]
return {
"healthy_links": len(healthy),
"toxic_links": len(toxic),
"prospects": prospects
}
Check yourself
Orchestrating SEO pipelines
How to assemble every worker into one system with reliable triggers
Orchestrator-worker pattern
In an agent SEO system the orchestrator is the central coordinator. It does not do the work itself: it takes a task, splits it, hands pieces to workers, and collects results. Workers are specialized agents; each owns a domain.
Running workers in parallel cuts wall-clock time: while KeywordWorker pulls data, AuditorWorker crawls the site.
class SEOOrchestrator:
def route_task(self, task_type, complexity):
"""Pick a model by task type (wired to M10)."""
if complexity == 'high' or task_type in ('strategy', 'eeat', 'competitive'):
return 'claude-opus-4' # frontier β deep analysis
elif task_type in ('content', 'audit', 'monitor'):
return 'claude-sonnet-4-6' # workhorse β content and audit
else:
return 'claude-haiku-4-5' # bulk β high-volume processing
async def run(self, task: SEOTask):
# Decompose the task
subtasks = self.decompose(task)
# Run workers in parallel
results = await asyncio.gather(
self.auditor.run(subtasks.audit),
self.keyword.run(subtasks.keywords),
self.monitor.run(subtasks.serp),
)
# Aggregate and decide
plan = self.aggregate(results)
# HITL check before irreversible actions
if plan.requires_human_approval:
await self.request_approval(plan)
else:
await self.execute(plan)
Trigger types
The pipeline starts three ways β each fits a different scenario:
- Daily SERP monitoring (06:00)
- Weekly audit (Monday)
- Monthly rollup report
0 6 * * * serp_monitor.py- New page published β keyword + audit check
- Ranks dropped 20% β alert + causal analysis
- Competitor hit top 3 β revisit the content
- On a manager request β one-off audit
- Urgent competitor analysis
- Check before launching a Google Ads campaign
Interactive pipeline
Click any block to see its role in the system.
Human-in-the-loop: when it is mandatory
Automation does not mean no humans. HITL is mandatory when an action is irreversible, reputationally risky, or can take the site down.
Error handling and state
Fault tolerance
delay = base * (2 ** attempt)
# 1s β 2s β 4s β 8s
# for API 429 / 503
What to persist between runs (State)
The pipeline must remember previous runs β otherwise anomalies and trends are invisible.
| What to store | Format | Why |
|---|---|---|
| Keyword positions | SQLite / JSON |
Trends, anomalies, drop alerts |
| List of indexed URLs | SQLite |
Incremental crawl, deduplication |
| Audit results | JSON |
Before/after comparison, progress tracking |
| Task status / DLQ | SQLite |
Retry logic, manual error review |
Check yourself
Evaluation and iteration
KPIs, anti-patterns, and the path from this course to a first working agent
KPIs for SEO agents
Metrics sit on two levels: operational (the system works correctly) and business (the system produces value).
Operational KPIs
| KPI | Formula | Target | Source |
|---|---|---|---|
Coverage |
% of pages audited | β₯ 95% | Crawler |
Error Rate |
# errors / # runs | < 2% | Logs |
Latency |
Workflow time | < 30 min | Orchestrator |
Cost/Action |
$ / unit of work | Trend down | API billing |
Business KPIs
| KPI | Formula | Target |
|---|---|---|
Organic Traffic Growth |
% growth MoM | β₯ 5% MoM |
Avg Position Improvement |
Δ avg_pos | Trend down |
Content Conversion Rate |
Conversions / SEO visits | β₯ 2% |
Indexed Pages Growth |
# indexed pages | Trend up |
Content A/B tests
What to test: meta title, H1, opening paragraph, CTA.
Process:
- The agent generates variant B (alternate title / H1).
- Publish side by side or on a schedule β two URLs or rotation.
- Wait 2β4 weeks while GSC collects CTR for each variant.
- The agent monitors CTR β detects a winner (ΔCTR > threshold) β recommends (or auto-applies) the stronger variant.
Anti-patterns β what kills the system
robots.txt or canonical tags on its own can drop the site from the index in hours. Any irreversible indexing action goes through Human-in-the-Loop.
- Hallucinated facts β the agent invents statistics and quotes. Google E-E-A-T penalizes sites with untrustworthy content β loss of trust and ranks.
- Keyword stuffing β packing the page with keywords. Google Panda filter β the whole site drops in the SERP.
- Duplicate content β the agent generates similar articles without a uniqueness check. Cannibalization β both URLs lose rank; Google does not know which to rank.
- Blind scaling β publishing 500 articles with no quality control. Mass low-quality content β possible Google Manual Action.
-
Missing HITL β the agent changes
robots.txt/ canonical with no human check. The site drops out of the index. Irreversible actions need confirmation.
SEO automation ROI
Calculate how much an agent system saves versus manual SEO.
5 steps to a first working agent
-
Pick ONE task.
A strong start is rank monitoring: no irreversible actions, fast feedback, easy to check by hand.
-
Assemble a minimum stack.
GSC API + Claude API β under $5/month to start. No heavy infrastructure on day one.
-
Run it on 50β100 keywords.
Check the first results by hand. Confirm the data is correct, the logic holds, and there are no hallucinations.
-
Add a second worker.
Page audit or keyword gap analysis β high ROI, low risk.
-
Iterate on the data.
What works in the top 15% β study the pattern β update prompts and topic lists β scale. Repeat every 4β6 weeks.
Check yourself
AI search and GEO
How to change SEO strategy when search moves into AI answers
What is happening to search
From 2024β2026 the SERP shifted structurally: an AI-generated answer sits above organic results, and users reach the blue links less often.
They appear on 40β60% of informational queries. The user gets a summary in the SERP and often does not click through.
Featured Snippet, PAA (People Also Ask), and AI Overview answer without a click. An organic click on an informational query became rare.
Perplexity cites sources. ChatGPT Search and Bing Copilot are standalone search surfaces with multi-million audiences.
GEO is still SEO
GEO (Generative Engine Optimization) is a label for optimizing not for a user click but for citation by an AI engine. The goal: become a source that Perplexity, Google AI Overview, or ChatGPT Search includes in the answer.
How AI actually picks sources (RAG + Query Fan-Out)
Google describes the mechanism directly β not a separate "AI ranking", but a layer on ordinary search:
- Retrieval (RAG). The same core ranking systems pull relevant fresh pages from the index. You enter an AI answer only if the page is indexed and snippet-eligible β you cannot skip ordinary SEO.
- Query Fan-Out. For one query the model spawns several related sub-queries (e.g. "how to get rid of weeds" β a set of follow-ups) and gathers results for each. Cover the topic and adjacent sub-questions, not one exact phrase.
- Generation. From retrieved pages the model takes concrete facts and forms an answer with clickable source links.
Signals that actually work are SEO fundamentals, not "AI tricks": E-E-A-T and expertise, domain authority and citability, crawler access, semantic HTML, solid page experience. Structured data is not a requirement for AI features (see the note below).
Content formats AI prefers
Answer the query in the first paragraph.
AI cites steps and lists easily.
Questionβanswer is a strong snippet format.
Statistics with a primary source raise trust-score.
- Do not spawn
llms.txtand "special" AI markup β it is not needed for visibility. - Do not shatter content into tiny chunks β the model understands multi-topic pages.
- Do not rewrite copy "for the machine" or chase keyword variations.
- Do not manufacture inauthentic mentions across the web.
- Do not make a separate page for every query variant β that is scaled content abuse.
- Do not overrate structured data as an AI requirement: useful, but an optional signal.
AI Overview probability by query type
Strategy by query type
Not every query is equally exposed to AI Overviews. The tactic depends on intent:
"how to choose", "what is", "why"
AIO risk: high (~47% on average, up to 77% in-niche). Strategy: GEO β FAQ structure, structured data, clear definitions, authority.
"course on", "guide", "training"
AIO risk: medium (40β50%). Strategy: hybrid β GEO + traditional SEO.
"best", "comparison", "ranking"
AIO risk: low (15β20%). Strategy: traditional SEO, conversion focus.
"buy", "price", "[brand] site"
AIO risk: minimal (5β10%). Strategy: traditional SEO at full strength. For AI-answer visibility Google points to Merchant Center feeds and Google Business Profile.
AI Overview monitoring agent
The agent's job is to watch whether an AI Overview appeared for your keywords and to change content strategy on the alert.
Tools
- DataForSEO SERP API β supports
ai_overviewin the response object (fielditems_types[]). - SerpAPI / Bright Data β alternatives with similar AIO detection.
- State store β SQLite/Redis: record the date AIO first appeared and the movement after.
Agent pseudocode
# AIO Monitor Agent β pseudocode
# Run: cron every 24h (or a webhook on rank change)
import serp_api, db, alerts
def run_aio_monitor(keywords: list[str]):
for kw in keywords:
result = serp_api.fetch(kw, features=["ai_overview", "featured_snippet"])
aio_present = result.has("ai_overview")
prev_state = db.get_aio_state(kw) # True/False/None
if aio_present and not prev_state:
# AIO appeared for the first time
db.set_aio_state(kw, True, date=today())
alerts.send(
channel="slack",
msg=f"[AIO ALERT] AI Overview appeared for '{kw}'. "
f"Current URL in position 1: {result.top_organic_url}. "
f"Recommendation: raise quality and the answer-first structure of the page."
)
content_pipeline.schedule_quality_review(kw)
elif not aio_present and prev_state:
# AIO gone β traditional SEO is the priority again
db.set_aio_state(kw, False, date=today())
alerts.send(
channel="slack",
msg=f"[AIO GONE] AI Overview disappeared for '{kw}'. "
f"Traditional SEO is the priority again."
)
# Log organic rank regardless of AIO
db.log_rank(kw, result.organic_position, result.url)
ai_overview flag. Cost: ~$0.002β0.005 per query. For 500 keywords a day β under $2.50/day.
Updating the content pipeline for GEO
Bridge to module M5: add a GEO layer on top of the existing content-generation pipeline.
1. Changes in the content-agent system prompt
# Add to the content-agent SYSTEM PROMPT (GEO mode):
CONTENT_RULES_GEO = """
- First paragraph = a clear definition: answer the query in 1β2 sentences.
- Add an FAQ section (at least 4 Q&A pairs) at the end of the article.
- For every claim with numbers β cite the primary source in parentheses.
- Use numbered lists for steps and instructions.
- The article author must be named with credentials (bio block).
- Avoid diluted intros β AI picks dense, factual content.
"""
2. Structured data β optional, not an "AI lever"
# Generate FAQ schema (add to the SEO Check pipeline step)
def generate_faq_schema(faq_items: list[dict]) -> str:
"""
faq_items: [{"question": "...", "answer": "..."}, ...]
Returns a JSON-LD string to insert in <head>.
"""
schema = {
"@context": "schema.org",
"@type": "FAQPage",
"mainEntity": [
{
"@type": "Question",
"name": item["question"],
"acceptedAnswer": {
"@type": "Answer",
"text": item["answer"]
}
}
for item in faq_items
]
}
return f'<script type="application/ld+json">{json.dumps(schema)}</script>'
# Likewise: HowTo schema for step-by-step instructions,
# Article schema with author.name + author.url for E-E-A-T
3. Intent detection as an SEO Check step
# Add to the SEO Check Agent before publish:
def check_aio_risk(keyword: str, content: str) -> dict:
intent = classify_intent(keyword) # 'informational'|'commercial'|...
aio_prob = AIO_RISK_MAP.get(intent, 0.5) # from the monitoring database
if aio_prob > 0.4:
geo_score = score_geo_readiness(content)
# geo_score: 0..1 (FAQ, definitions, structured data, authorship present)
if geo_score < 0.6:
return {
"status": "warn",
"msg": f"AIO risk {aio_prob:.0%}, GEO readiness {geo_score:.0%}. "
"Recommended: add FAQ, structured data, improve the definition."
}
return {"status": "ok", "aio_prob": aio_prob}
Quiz: check your understanding
Frontier models in SEO β routing them correctly
Sonnet does 95% of the work. Opus is needed less often than most teams think.
This is the final module of the course. Before practice β a mental-model correction, without which teams spend money on Opus where Sonnet already handles the job.
1. Rethinking "smart" tasks
Most SEO specialists inherit an outdated mental model of model tiers. Here is where it breaks:
Wrong
| Haiku | = cheap |
| Sonnet | = mid tier |
| Opus | = smart, for hard tasks |
This model leads to extra spend and the wrong expectations
Right
| Haiku | = bulk throughput (10k+ calls/day) |
| Sonnet | = strategy + content + analysis (95% of tasks) |
| Opus | = extended thinking, edge cases (<5%) |
The right question: "Can Sonnet handle this?" β almost always yes
The shift: Sonnet is not "mid tier", it is the default working tool. Opus is insurance for <5% of cases where extended thinking actually changes the answer.
2. Three real model-choice scenarios
Haiku β when you need SCALE on a fixed template
Use it when the task is templated and call volume is in the thousands:
- Check 50,000 meta tags for length and duplicates
- Classify 10,000 keywords by intent (informational/transactional/navigational)
- Generate short alt texts for 5,000 images from a template
- Export and structure GSC data into a table
Sonnet β almost everything else (including "smart" tasks)
The default model for anything that needs analysis, synthesis, or strategy:
- Competitive analysis of the top-10 SERP for a keyword
- Score a competitor page's E-E-A-T profile
- Strategic call: attack a head term or a long-tail cluster?
- Write a content brief, outline, article draft
- Technical SEO audit with interpreted priorities
- Analyze 50β100 site pages in one request (200k context)
- GEO optimization for AI Overviews
- "Which content gap should we fill next?"
Opus β only when Sonnet is actually insufficient
Not "a hard task" β a task where extended thinking changes the conclusion:
- Multi-step reasoning over 15+ steps with branching uncertainty
- A 500+ page document in one call with deep synthesis
- An irreversible decision (e.g. a full site-architecture redesign) where one error = months of work
- A task where extended thinking itself changes the final conclusion
3. Sonnet in action: patterns for "hard" tasks
Three tasks that look "smart" β all three are Sonnet jobs:
Pattern A β Competitive Intelligence
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=4096,
messages=[{"role": "user", "content": f"""
Analyze the Google top 10 for '{keyword}'.
For each: content type, length, H1-H3 structure, main topics.
Find: which topics are missing? Which format dominates?
Write a brief for an article that can take first place.
"""}]
)
Pattern B β E-E-A-T Assessment
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=2048,
messages=[{"role": "user", "content": f"""
Score this page's E-E-A-T profile on a 1-10 scale:
{page_content}
What to improve? Which authority signals to add?
"""}]
)
Pattern C β Strategic Decision
response = client.messages.create(
model="claude-sonnet-4-6",
max_tokens=3000,
messages=[{"role": "user", "content": f"""
GSC data: {gsc_summary}
Competitor profile: {competitor_data}
Question: should we compete on the head term '{head_term}'
or focus on the long-tail cluster '{longtail_cluster}'?
Argue from the data and name the risks of each option.
"""}]
)
claude-sonnet-4-6 β not as a budget compromise, but as the right choice for these tasks.4. An honest threshold for Opus
An example where Opus is justified in SEO:
- Find conflicting canonical errors across 200 pages
- Cluster them into typical issues
- Auto-generate a redirect plan
- Design a canonical strategy for the whole structure
An error in this plan = hundreds of hours of manual work β extended thinking changes output quality.
Note: this is not "a hard SEO task", it is a specific mix: huge input + multi-step logic + high cost of error. Competitive analysis on one keyword does not meet that bar.
5. Model routing in a real pipeline
A correct router makes Sonnet the default, not the exception:
def route_task(task_type, input_size, complexity):
# Rule 1: massive bulk -> Haiku
if task_type in ('bulk_classify', 'simple_check') and input_size > 1000:
return 'claude-haiku-4-5'
# Rule 2: Opus only for truly exceptional
if complexity == 'exceptional' and task_type in ('full_site_strategy', 'canonical_rebuild'):
return 'claude-opus-4-8'
# Rule 3: Sonnet -- default for everything else
return 'claude-sonnet-4-6'
return 'claude-sonnet-4-6' is not a fallback for "mid" tasks. It is the right choice for competitive analysis, E-E-A-T scoring, content strategy, and technical audits.
6. SEO pipeline cost calculator
Look at real numbers. Defaults match a typical split: Haiku takes volume, Sonnet takes value:
Formula: let Haiku do volume β Sonnet does value.
7. Check your understanding
Done!
10 modules complete. The full SEO-agent stack β from architecture to AI search and frontier analytics.
- Decompose an SEO workflow into agent tasks
- Assemble an agent stack: Data Sources β LLM β Output
- Build a technical-audit agent with prioritization
- Automate keyword research and intent mapping
- Set up a content pipeline with SEO checks
- Monitor SERP and the backlink profile with an agent
- Orchestrate a full SEO pipeline with human-in-the-loop
- Measure automation ROI and iterate the system
- Adapt SEO strategy to AI Overviews and GEO
- Apply frontier models to deep SEO analysis
What to read next
- Google Search Central Blog β official algorithm updates
- Anthropic API Docs β Claude API for content agents
- Screaming Frog Docs β advanced technical audit
- Ahrefs Academy β keyword research and backlink analysis