SEO, AEO and GEO Are Three Different Jobs: What Each Optimizes and How to Measure It

One search team, three different jobs
For CMOs and SEO leads who now get asked about AI search every week: what SEO, answer engine optimization and generative engine optimization each win, and the Python to measure all three.
Most marketing teams have folded generative engine optimization into the SEO budget, as if being cited by ChatGPT were page one with a new coat of paint. It isn’t. SEO, answer engine optimization (AEO) and generative engine optimization (GEO) each win a different thing, pay off through a different mechanism, and need a different metric. Score all three on organic clicks and two of them will always look like failures.
The pressure behind the question is real. Ahrefs compared the same 300,000 keywords in December 2023 and December 2025 and found that when an AI Overview appears, the top-ranking page earns about 58% fewer clicks than its trend predicted. A Pew Research Center panel of 900 U.S. adults clicked a traditional result on 8% of searches that showed an AI summary, against 15% when none appeared. Meanwhile AI assistants still send only 1.08% of web traffic across Conductor’s sample of 13,770 domains. Clicks are falling faster than the replacement channel is growing, and leadership wants to know where the effort should go.
This piece gives you a frame for the three jobs, one value equation that shows when each one pays, and three scripts you can run this week: a Search Console pull that finds where answer features are eating your clicks, a GA4 split for AI referrals, and a citation panel for generative engines with honest confidence intervals.
The frame: retrieval, extraction, synthesis
Every answer a person gets from a search box now passes through up to three steps. A system retrieves candidate pages and ranks them. It may extract one passage and show it as the answer. It may synthesize a new answer from several sources and cite some of them. SEO competes at retrieval, AEO competes at extraction, and GEO competes at synthesis. Same content, three different contests.

The value of any of them comes down to one proposed model, which I use to keep budget conversations honest:
V = E × (c × v + b)
E is the number of times a person sees your brand or page for a query, c is the probability that a sighting becomes a click, v is the value of a click (conversion rate times value per conversion), and b is the value of a sighting that never becomes a click, the brand effect. SEO mostly works on c, because rank sets the click rate. AEO works on E inside answer features, where c collapses: Pew found people clicked a link inside the AI summary itself on 1% of visits. GEO works on E in places with no ranked list at all, where nearly everything rides on b.
A worked example shows why the distinction matters. Take a B2B query with 10,000 monthly impressions, a 2% conversion rate and $2,000 per lead, so v = $40. Ahrefs puts the December 2025 position-one CTR for AI Overview keywords at 1.6%, against a projected 3.7% without the overview. At 3.7% the page earns 370 clicks worth $14,800 a month. At 1.6% it earns 160 clicks worth $6,400. The $8,400 gap only closes if each no-click exposure is worth b = (0.037 − 0.016) × $40 = $0.84. Display impressions trade at a few dollars per thousand. An 84-cent impression is a premium placement by any media plan, which tells you AEO is mostly a defensive job: you hold the answer slot so a competitor doesn’t, and you put your click budget into the queries that still click.
SEO: win the click on the queries that still click
SEO’s unit of success is still the click, and its job has narrowed rather than disappeared. Ahrefs’ position data shows the AI Overview penalty shrinking down the page, from −58% at position one to −19.4% at position ten, and plenty of queries never trigger an overview at all: in Conductor’s four-week sample, overviews appeared on 48.7% of health care queries but only 4.4% of real estate queries. Commercial, local, navigational and comparison queries still send buyers. The SEO job is to find them and win them.
The right yardstick is your own click curve, not an industry average. Your brand, your SERP layout and your audience set what position three is worth. Build the curve from 90 days of Search Console data, then rank every query by the clicks it is missing against that curve. A query sitting at position two with a third of your normal position-two CTR is the signature of an answer feature taking the click, and it belongs on the AEO list rather than the SEO list.
"""Build your own CTR-by-position curve from Search Console and find queries
that click far below it (the queries where an answer feature is likely eating the click)."""
import datetime as dt
import pandas as pd
SITE = "sc-domain:vector1.ai" # your property
KEY_FILE = "service-account.json" # service account with read access to the property
SCOPES = ["https://www.googleapis.com/auth/webmasters.readonly"]
def fetch(site, start, end, dims=("query", "page"), row_limit=25000):
from google.oauth2 import service_account
from googleapiclient.discovery import build
creds = service_account.Credentials.from_service_account_file(KEY_FILE, scopes=SCOPES)
svc = build("searchconsole", "v1", credentials=creds, cache_discovery=False)
rows, start_row = [], 0
while True:
body = {"startDate": start, "endDate": end, "dimensions": list(dims),
"type": "web", "rowLimit": row_limit, "startRow": start_row}
batch = svc.searchanalytics().query(siteUrl=site, body=body).execute().get("rows", [])
for r in batch:
rows.append({**dict(zip(dims, r["keys"])), "clicks": r["clicks"],
"impressions": r["impressions"], "position": r["position"]})
if len(batch) < row_limit:
break
start_row += row_limit
return pd.DataFrame(rows)
def ctr_curve(df, min_impr=50, max_pos=20):
d = df[df.impressions >= min_impr].copy()
d["pos"] = d.position.round().clip(1, max_pos).astype(int)
g = d.groupby("pos").agg(clicks=("clicks", "sum"), impressions=("impressions", "sum"))
g["ctr"] = g.clicks / g.impressions
return g
def ctr_gap(df, curve, min_impr=200, max_pos=20):
d = df[df.impressions >= min_impr].copy()
d["pos"] = d.position.round().clip(1, max_pos).astype(int)
d = d.join(curve["ctr"].rename("expected_ctr"), on="pos")
d["ctr"] = d.clicks / d.impressions
d["missing_clicks"] = (d.expected_ctr - d.ctr) * d.impressions
return d.sort_values("missing_clicks", ascending=False)
if __name__ == "__main__":
end = dt.date.today() - dt.timedelta(days=3) # Search Console data lags a few days
start = end - dt.timedelta(days=90)
df = fetch(SITE, start.isoformat(), end.isoformat())
curve = ctr_curve(df)
print(curve.head(10).round(4))
cols = ["query", "page", "position", "impressions", "ctr", "expected_ctr", "missing_clicks"]
print(ctr_gap(df, curve)[cols].head(25).round(3).to_string(index=False))Install google-api-python-client, google-auth and pandas, and add the service account’s email as a user on the Search Console property. The curve pools clicks and impressions by rounded position instead of averaging per-query CTRs, so a few tiny queries with 100% CTR can’t bend it. The 50-impression floor for the curve and the 200 floor for the gap list keep noise out of both; raise them on a large site. One caveat stated once: position in this report is an average across impressions, so a query that bounces between one and five shows up as three, and its gap is an estimate, not a measurement.
What to report to leadership: organic clicks and revenue on queries without answer features, and the missing-click total on the gap list. That is the SEO scoreboard.
Answer engine optimization: be the passage that gets extracted
AEO’s unit of success is selection: your passage, your fact or your page is the one the system lifts into the answer slot. That slot is a featured snippet, a People Also Ask box, a voice assistant reply or a cited source inside an AI Overview or AI Mode answer. The reader often gets what they need without leaving. Pew found that 26% of searches with an AI summary ended the browsing session on the results page, against 16% without one. AEO is the job of being the source of that answer anyway.
The content work differs from classic SEO in its grain. SEO optimizes a page for a query. AEO optimizes a passage for a question: a heading phrased the way people ask, a direct answer in the first one or two sentences under it, the number or definition stated plainly, and supporting detail after. These are practitioner conventions rather than published ranking rules, so test them on your own query set before rewriting a library.
Measurement finally has first-party data, with gaps. Google began rolling out generative AI performance reports in Search Console on June 3, 2026, to a subset of sites. They show impressions in AI Overviews, AI Mode and Discover’s generative features, by page, country, device and date; Google has not said they include clicks, and the same impressions still sit inside the main performance report. Bing Webmaster Tools added an AI Performance report in public preview on February 10, 2026, covering Copilot, Bing’s AI summaries and some partner surfaces. It counts total citations, average cited pages per day and a sample of grounding queries, and it reports no clicks.
So the AEO scoreboard is exposure, not traffic: answer-feature impressions and citations on a fixed list of target questions, tracked weekly, plus the gap list from the SEO script for queries where you rank but lose the click. The value side, b, has to be estimated the way marketing mix modeling estimates any upper-funnel channel: put answer-feature impressions in the model as a channel and let branded search and conversions tell you what they are worth. An illustrative read: if 50,000 extra answer impressions in a quarter line up with 150 extra branded clicks at v = $40, then b ≈ 150 × $40 / 50,000 = $0.12 per exposure. That is real money, and still well short of the $0.84 break-even from the worked example, which is why AEO protects a position more often than it replaces lost clicks.
Generative engine optimization: get cited in the synthesized answer
GEO’s unit of success is inclusion: across the many ways people ask an assistant about your category, how often are you cited or named, how much of the answer leans on you, and is what it says about you correct? There is no position one. ChatGPT, Perplexity, Gemini and Copilot write a new answer each time, and the same prompt can cite different sources on the next run.
The term comes from a 2024 KDD paper by Aggarwal and colleagues at Princeton and IIT Delhi, who built GEO-bench, 10,000 queries across 25 domains, and tested content edits against a generative engine. Adding quotations from credible sources raised their position-adjusted visibility by about 41%, adding statistics by about 31%, and citing sources by about 28%. Keyword stuffing, the reflex from old SEO, scored about 8% below baseline. On Perplexity itself they report gains of up to 37%. The lesson for content teams is that evidence density, not keyword density, is what synthesis rewards.
The paper’s visibility metric is worth borrowing, because it measures how much of the answer you own rather than whether a link appears:
PAWC(c, r) = [ Σ over s in S_c of |s| × e^(−pos(s) / |S|) ] / [ Σ over s in S_r of |s| ]
S_c is the set of sentences in answer r that cite source c, |s| is a sentence’s word count, pos(s) is its place in the answer, |S| is the number of sentences, and the denominator is every word in the answer. A citation in the opening sentence counts more than the same citation at the end.
Measuring GEO means sampling, because answers vary. Build a panel of 100 to 200 prompts that real buyers would type, run each one several times per engine every week, and report the citation rate with a confidence interval. The interval is the part most GEO dashboards leave out. Cited in 40 of 200 runs, your rate is 20% with a 95% Wilson interval of 15.0% to 26.1%. Next week you are cited in 48 of 200, or 24%, with an interval of 18.6% to 30.4%. The intervals overlap; that four-point gain may be noise. To reliably detect a move from 20% to 30% at a 5% significance level and 80% power, you need about 294 runs in each period.
"""A vendor-neutral citation panel for generative engine optimization.
Plug any answer engine into `Engine`: a function that takes a prompt and returns
the answer text (with [n] citation markers) and the cited URLs in marker order."""
import math
import random
import re
from collections import Counter
from dataclasses import dataclass
from typing import Callable, List
from urllib.parse import urlparse
@dataclass
class Answer:
text: str
citations: List[str] # citations[0] is marker [1], and so on
Engine = Callable[[str], Answer]
def domain(url):
host = urlparse(url).netloc.lower()
return host[4:] if host.startswith("www.") else host
def sentences(text):
return [s for s in re.split(r"(?<=[.!?])\s+", text.strip()) if s]
def pawc(answer, target):
"""Position-adjusted word count (Aggarwal et al., KDD 2024): words in sentences that
cite the target, discounted by e^(-pos/|S|), over all words in the answer."""
sents = sentences(answer.text)
total = sum(len(s.split()) for s in sents)
marks = {i + 1 for i, u in enumerate(answer.citations) if domain(u) == target}
score = 0.0
for pos, s in enumerate(sents, start=1):
cited = {int(m) for m in re.findall(r"\[(\d+)\]", s)}
if cited & marks:
score += len(s.split()) * math.exp(-pos / len(sents))
return score / total if total else 0.0
def wilson(k, n, z=1.96):
if n == 0:
return 0.0, 0.0
p = k / n
d = 1 + z * z / n
centre = (p + z * z / (2 * n)) / d
half = z * math.sqrt(p * (1 - p) / n + z * z / (4 * n * n)) / d
return centre - half, centre + half
def run_panel(engine, prompts, target, runs_per_prompt=3):
cited_runs, n, pawc_sum, domains = 0, 0, 0.0, Counter()
for prompt in prompts:
for _ in range(runs_per_prompt): # answers vary run to run, so sample each prompt
a = engine(prompt)
ds = [domain(u) for u in a.citations]
domains.update(set(ds))
cited_runs += target in ds
pawc_sum += pawc(a, target)
n += 1
lo, hi = wilson(cited_runs, n)
sov = domains[target] / sum(domains.values()) if domains else 0.0
return {"runs": n, "citation_rate": cited_runs / n, "ci95": (round(lo, 3), round(hi, 3)),
"share_of_voice": sov, "mean_pawc": pawc_sum / n, "top_domains": domains.most_common(5)}
def runs_needed(p1, p2, z_alpha=1.959964, z_beta=0.841621):
"""Runs per arm to detect a move in citation rate from p1 to p2 (alpha 0.05, power 0.8)."""
pb = (p1 + p2) / 2
num = z_alpha * math.sqrt(2 * pb * (1 - pb)) + z_beta * math.sqrt(p1 * (1 - p1) + p2 * (1 - p2))
return math.ceil(num ** 2 / (p1 - p2) ** 2)
if __name__ == "__main__":
rng = random.Random(7)
pool = ["https://vector1.ai/mmm-guide", "https://en.wikipedia.org/wiki/Marketing_mix_modeling",
"https://www.reddit.com/r/marketing/x", "https://example-agency.com/blog/mmm",
"https://www.youtube.com/watch?v=abc"]
def demo_engine(prompt): # stand-in so the file runs; replace with a real API call
cites = rng.sample(pool, 3)
text = (f"{prompt.capitalize()} depends on the data you have [1]. "
f"Most teams start with a Bayesian model [2]. Validation matters more than the tool [3].")
return Answer(text, cites)
prompts = ["best marketing mix modeling tools", "how to build an MMM in python",
"robyn vs pymc-marketing", "is MMM better than attribution"]
print(run_panel(demo_engine, prompts, "vector1.ai", runs_per_prompt=50))
print("runs per arm to see 20% -> 30%:", runs_needed(0.20, 0.30))The harness is vendor-neutral on purpose. Each engine’s API returns citations in its own shape, and those shapes change, so write one small adapter per engine that returns an Answer and keep the scoring code untouched. The demo engine makes the file run as written; swap it out before you trust a number. Share of voice counts each domain once per run, so a site cited three times in one answer doesn’t inflate its share. Keep the panel fixed for a quarter. Changing prompts mid-stream breaks the trend line the same way changing a survey’s questions does.
Then measure the clicks GEO does produce, small as they are. Conductor’s benchmark found ChatGPT behind 87.4% of AI referrals. Adobe’s July 2026 data shows AI-referred retail visitors converting at a 60% higher rate than other traffic, with 53% more revenue per visit. Since May 13, 2026, GA4 groups recognized assistants such as ChatGPT, Gemini and Claude into a default AI Assistant channel, though Google hasn’t published the full source list. This script does the same split on an export, with a source list you control, and puts conversion rate and revenue per session next to organic search:
"""Split AI assistant referrals out of GA4 traffic and compare them with organic search.
Input: a CSV exported from a GA4 exploration with columns
session_source, session_medium, sessions, key_events, revenue."""
import re
import sys
import pandas as pd
AI_SOURCES = {
"ChatGPT": r"(^|\.)(chatgpt\.com|chat\.openai\.com)$",
"Perplexity": r"(^|\.)perplexity\.ai$",
"Gemini": r"(^|\.)gemini\.google\.com$",
"Copilot": r"(^|\.)copilot\.microsoft\.com$",
"Claude": r"(^|\.)claude\.ai$",
}
def channel(source, medium):
s = str(source).lower().strip()
for name, pattern in AI_SOURCES.items():
if re.search(pattern, s):
return f"AI: {name}"
if str(medium).lower() == "organic":
return "Organic search"
return "Other"
def summarize(df):
df = df.assign(channel=[channel(s, m) for s, m in zip(df.session_source, df.session_medium)])
g = df.groupby("channel")[["sessions", "key_events", "revenue"]].sum()
g["share_of_sessions"] = g.sessions / g.sessions.sum()
g["conv_rate"] = g.key_events / g.sessions
g["rev_per_session"] = g.revenue / g.sessions
if "Organic search" in g.index:
g["conv_vs_organic"] = g.conv_rate / g.loc["Organic search", "conv_rate"]
return g.sort_values("sessions", ascending=False)
if __name__ == "__main__":
if len(sys.argv) > 1:
data = pd.read_csv(sys.argv[1])
else: # small demo so the script runs as written
data = pd.DataFrame({
"session_source": ["google", "chatgpt.com", "perplexity.ai", "(direct)", "gemini.google.com"],
"session_medium": ["organic", "referral", "referral", "(none)", "referral"],
"sessions": [35000, 900, 120, 40000, 60],
"key_events": [700, 29, 4, 600, 2],
"revenue": [28000.0, 1150.0, 160.0, 24000.0, 80.0],
})
print(summarize(data).round(4).to_string())Run the numbers for a typical site and the scale problem is plain. At 100,000 monthly sessions, Conductor’s 1.08% share means about 1,080 AI sessions. If organic converts at 2% and AI visitors convert 1.6 times better (Adobe’s retail ratio, borrowed here as an illustration), those sessions produce about 35 conversions, against 700 from 35,000 organic sessions. Clicks are a lagging indicator for GEO. Citations are the leading one, so the GEO scoreboard is citation rate, share of voice and PAWC on the panel, with AI-referred conversions reported beside them.
One scorecard for three jobs
Put the three jobs on one page, each graded on its own line, and stop asking any one metric to grade all of them.
- SEO competes at retrieval and ranking, and its unit of success is a click. Report organic clicks and revenue on queries without answer features, plus missing clicks on the gap list, weekly, from the Search Console API and GA4.
- AEO competes at extraction, and its unit of success is being the selected answer. Report answer-feature impressions and citations on a fixed question list weekly, from Search Console’s generative AI reports and Bing’s AI Performance report, and estimate b quarterly from branded search lift in your mix model.
- GEO competes at synthesis, and its unit of success is being cited and described correctly. Report citation rate with its 95% interval, share of voice and PAWC from the weekly prompt panel, with AI-referred conversions from GA4 beside them and a monthly trend.
Budget follows the value equation. A query on the SEO list earns content and technical work while c × v stays above your cost per page. A query on the gap list moves to AEO when its impressions are large enough that holding the answer slot matters, even at a b well below break-even. A prompt goes on the GEO panel when it is a question buyers ask before they shortlist, because that is where being absent costs the most.
What changes as AI moves toward super intelligence
The direction of travel matters more than this quarter’s numbers. Each generation of models does more of the reading, comparing and shortlisting that used to happen across ten browser tabs. As artificial intelligence/super intelligence systems take on more of that research step, and agents begin to complete purchases on a person’s behalf, a smaller share of buying journeys will include a visit to your site at all. In the value equation, c keeps falling and b carries more of the weight. The teams that already measure exposure, inclusion and accuracy will be able to see that shift as it happens; the teams that only measure clicks will see a decline and not know why.
Where it breaks
The click studies are observational. Ahrefs’ 58% compares AI Overview keywords against a projection built from keywords without overviews, using desktop CTR from aggregated Search Console data; it shows a strong association, not a controlled effect. Pew’s panel is 900 people browsing in March 2025, and Google called the study’s method flawed. Both point the same way, which is why I use them, but neither tells you what will happen on your queries. Your own gap list does.
The GEO evidence comes from a lab. GEO-bench edits were tested against a generative engine the authors controlled plus Perplexity in 2023 and 2024, and engines have changed since. The paper itself reports that what works varies by domain. Treat its findings as hypotheses to test on your panel, not as a playbook.
The first-party tools are partial. Google’s generative AI reports are reaching a subset of sites and describe impressions, not clicks or position inside the answer. Bing’s report counts citations and samples grounding queries; it also shows no clicks. Neither covers ChatGPT, Claude or Perplexity, which is why the prompt panel exists.
The panel has its own weak point: the prompts. A citation rate is only as representative as the questions behind it, and assistants personalize answers by location, history and account, which an API call doesn’t reproduce. Build the panel from your sales calls, site search and Search Console questions, not from what your team guesses buyers ask. And a citation is not an endorsement. An assistant can cite you while describing your product wrongly, so read a sample of answers every week instead of trusting the rate alone.
Finally, referral data undercounts. Visits from AI mobile apps and some embedded browsers arrive with no referrer and land in Direct, so GA4’s AI Assistant channel and the script above both measure a floor, not a total. Tags help but break too: one analytics vendor tracked a stretch in October 2026 when links in ChatGPT’s answers arrived with neither a tag nor a referrer.
The path forward this quarter
Start with the data you already own. Run the Search Console script, build your click curve, and split the top 100 queries by missing clicks into an SEO list and an AEO list. That one exercise usually ends the argument about whether organic is “down”: some of it is down because answers took the click, and some of it is down because rankings slipped, and those need different fixes.
Next, set up the AI referral split in GA4 and report it monthly next to organic, with conversion rate and revenue per session. The volumes will be small. Report them anyway, because the trend is the point and you want a baseline from before the next model release, not after.
Then build the prompt panel. Take 100 to 200 real buyer questions, run them through two or three assistants every week, and report citation rate with its interval, share of voice and PAWC. Read 20 answers by hand each week for accuracy. Before you rewrite your content library around GEO advice, including the quotation and statistics findings above, test a change on half the pages behind a fixed panel and see whether the citation rate moves beyond its interval.
Last, give leadership one page with three rows. SEO answers for clicks, AEO for answer exposure, GEO for citations. Graded separately, each one can show whether it is working.
Brian Curry writes about artificial intelligence/super intelligence in Kansas City: agentic AI, applied machine learning, causal inference and forecasting for healthcare, energy, seo, geo, aeo, commodities and marketing at Vector1 Research. Read more on Medium and Substack.
Get the next piece free by email: subscribe on Substack.
Sources
- AI Overviews Reduce Clicks (2026 update), Ahrefs, February 4, 2026
- Google users are less likely to click on links when an AI summary appears in the results, Pew Research Center, July 22, 2025
- GEO: Generative Engine Optimization, Aggarwal et al., KDD 2024
- AI sends 1% of website traffic, Search Engine Land on Conductor’s 2026 AEO/GEO Benchmarks Report
- Introducing AI Performance in Bing Webmaster Tools Public Preview, Microsoft Bing, February 10, 2026
- Google gives Search Console its own generative AI visibility reports, PPC Land, June 2026
- AI Traffic Trends Report, August 2026, Adobe Digital Insights
- Google Analytics adds native AI Assistant channel to GA4’s default channel group, TechWyse, May 2026
- Why ChatGPT traffic shows as Direct in GA4, Clickport, updated October 22, 2026


