What you get from this article
A running skill for your Codex install that checks one page for content quality and the four E-E-A-T signals: Experience, Expertise, Authoritativeness, Trustworthiness. You feed it a URL, it fetches the page, collects the evidence (word count, readability, keyword placement, links, quotes, author meta, dates, trust signals), and you get back two scores and a list of fixes ranked by priority.
This is the skill I wish we had six months ago. The painful part of content audits was never the judgment, it was the grunt work: counting words, hunting for the byline, checking whether the author meta tag exists, guessing if a paragraph is actually quotable. The skill does the grunt work in about a second and leaves the judgment to you in plain language, with weights anchored to what Google actually documents.
Who this is for: anyone who publishes content and needs to answer "does this page actually deserve to rank, and if not, what do I change?" in about five minutes. Site owners, content leads, solo operators, new SEOs who want to see what a real E-E-A-T check looks like.
Time: about 7 minutes to install and verify, then about 1 minute per page.
Definition of done: you type $codex-seo-content <url> in Codex (or just paste a URL and ask "check the content quality") and get a report with a Content Quality Score, an E-E-A-T breakdown by factor, and an AI-citation-readiness score. No paid tools, no API keys, one small script.
Why content quality is the ranking lever you can actually pull
Rankings have always been a bundle of signals: crawlability, speed, links, schema, and the messy business of whether the content itself is any good. The good news in 2026 is that the content side is the one you can improve without waiting on anyone, and the quality bar has moved twice in a way that makes it more important, not less.
First: helpfulness signals are now always-on. Google merged the Helpful Content System into its core ranking system during the March 2024 update, so the "people-first content" checks no longer wait for a named update. And since the December 2025 changelog Google says it runs smaller, unannounced core updates continuously. The practical implication: improving content quality lifts rankings slowly but steadily, without needing a big update to land.
Second: the low-quality bar now names the thing you're most tempted to do with an AI assistant. The spam policy update in May 2026 explicitly calls out "using generative AI tools to generate many pages without adding value" as scaled content abuse. It also covers synonyms-and-translations automation. Nothing here says AI content is banned: the September 2025 Quality Rater Guidelines say AI-assisted content is fine when it shows genuine E-E-A-T, unique value, and human oversight. It says "trustworthy" is what matters, not the production method.
Third: the AI answer engines now sit on top of all this. ChatGPT, Perplexity, and Google AI Overviews pick sources the same way they always test for: clean structure, quotable claims, first-person experience, evidence. A page that passes the E-E-A-T questions is the page an assistant can quote.
One more thing worth admitting up front: word count is not a ranking factor. Google has said this plainly. The word-count floors in this skill are topical coverage floors, not targets, and the skill says so. A 500-word page that answers the query will beat a 2,000-word page that doesn't.
How the skill works, in three layers
The original claude-seo project, which this series adapts to Codex, organizes content quality around three things: Google's own Who/How/Why heuristic, the four E-E-A-T factors, and content mechanics. Its curated E-E-A-T framework (checked against the September 2025 QRG, re-checked June 2026) is dense, so the Codex version keeps the anchors and drops the fluff.
Layer 1: the Who/How/Why test
Before scoring anything, every page gets checked against Google's own three-question heuristic from the helpful-content guide:
Question | What to look for |
|---|---|
Who created it? | Visible byline, author bio page, credentials. Non-negotiable for YMYL. |
How was it created? | Process disclosure where readers would reasonably ask, especially for AI-assisted content. Original research or lived experience where possible. |
Why does it exist? | "To help people" rather than "to attract clicks." Watch for niche entry without expertise, churn to chase freshness, word-count targets. |
When all three answers are weak, the page is at risk under the core ranking system's helpfulness signals. That's the quick version of the test in Google's own words, and it comes from developers.google.com's creating-helpful-content guide.
Layer 2: the E-E-A-T matrix with weights
E-E-A-T is a concept from the Quality Rater Guidelines, not a scoring module that Google publishes. The main fact worth remembering is Google's own wording: trust is the most important member of the family, and the other three support the assessment of trust. So it's wrong to score all four at 25 points each. The framework in this skill uses a non-equal split that respects that hierarchy:
Factor | Weight | What you look at |
|---|---|---|
Experience | 20% | First-hand signals: original research, case studies, before/after results, personal anecdotes, original screenshots, "I tested this" process documentation |
Expertise | 25% | Credentials and demonstrated knowledge, accuracy, claims backed by sources, field-specific vocabulary used correctly |
Authoritativeness | 25% | Recognition by others: citations from authoritative sources, industry awards, consistent publication history, media coverage |
Trustworthiness | 30% | Contact info, privacy policy and terms, HTTPS, transparent authorship, visible corrections, no deceptive patterns |
The weights are this skill's internal model, ordered to match Google's stated hierarchy, and the skill says so. It also says the split is not Google's. Honest every time.
Layer 3: content mechanics thresholds
Beyond E-E-A-T, the mechanics that make a page comfortable to read and link to:
Check | Target | Note |
|---|---|---|
Word count vs page type | Blog 1,500+, service 800+, product 300+ | Coverage floor, not a ranking target |
Flesch reading ease | 60-70 for general audience | Estimated by the scanner; a usability signal, not a ranking score |
Sentence length | 15-20 words avg | Scanner reports it |
Paragraph length | 2-4 sentences | Scanner reports avg words/paragraph |
Primary keyword | In title, H1, first 100 words | 1-3% natural density, semantic variations, no stuffing |
Internal links | 3-5 per 1,000 words | Descriptive anchors, no orphan pages |
Freshness | datePublished visible, dateModified if revised | Flag anything older than 12 months without an update in fast-changing topics |
What the scanner actually measures
The companion script is a single file, standard library only, no dependencies to install. Here's what it extracts from a URL:
- Content: words, sentences, words-per-sentence, average paragraph length, an estimated Flesch reading ease, plus H1/H2 counts
- Keyword guess: it takes the first two non-generic words from the title as a stand-in for your primary keyword, then checks whether they appear in the first 100 words. Before you comment on this: the skill treats it as a guess and asks you to supply the real keyword.
- Quotable sentences: sentences containing numbers, percentages, currency, or attributed claims. That's your AI-citation-readiness raw material.
- Links: internal, external, and internal per 1,000 words
- Multimedia: image count, video/iframe count, table-of-contents or anchor-nav presence
- E-E-A-T: author meta tags, Person schema, byline text presence, datePublished/dateModified, and trust signals (privacy policy, contact, email/phone, address)
Two honest limitations the skill explains: Flesch is estimated from visible HTML text (it strips code blocks and script tags), and anything rendered client-side or behind a login can't be judged from raw HTML. The skill says to say so, and to analyze only what the HTML proves.
The full SKILL.md
Copy this exact file to ~/.codex/skills/codex-seo-content/SKILL.md.
---
name: codex-seo-content
description: Use when the user gives a URL or article and asks to evaluate content quality, E-E-A-T, readability, thin content, AI-citation readiness, who-how-why authority signals, byline trust, or whether a page justifies its rankings. Triggers on "content quality check", "is this content authoritative", "which page should I refresh", "E-E-A-T audit", "is this AI slop".
---
# Content Quality & E-E-A-T Analysis
One URL, two reports. The scanner fetches the page and collects the evidence;
you score the four E-E-A-T factors and the content mechanics against the
anchors below, then write the recommendations.
## Run
```bash
python3 ~/.codex/skills/codex-seo-content/scripts/content_scan.py <url> [--json]
```
The scanner reports words, sentences, words-per-sentence, average paragraph
length, an estimated Flesch reading ease score, primary-keyword guess
(two first non-generic title words) and whether it appears in the first 100
words, H1/H2 counts, internal/external link counts, quotable sentences with
numbers or attributed claims, images/videos/table-of-contents presence,
author meta, Person schema, byline text, datePublished, and trust signals
(contact, privacy policy, email/phone, address).
Content behind login or client-side-rendered shells cannot be judged from
raw HTML. Say so and analyze only what the HTML proves.
## Google's "Who / How / Why" test
Every page passes Google's own three-question heuristic first (helpful-content
guide):
| Question | What to look for |
|---|---|
| **Who** created it? | Visible byline, author bio page, credentials. Required where readers expect it; non-negotiable for YMYL. |
| **How** was it created? | Process disclosure where readers would reasonably ask, especially for AI-assisted content. Original research, first-hand evidence, lived experience. |
| **Why** does it exist? | "To help people" rather than "to attract clicks". Watch for niche entry without expertise, churn for freshness signals, content written to a word-count target. |
When all three answers are weak, the page is at risk under the core ranking
system's helpfulness signals (merged into core during the March 2024 update).
## E-E-A-T framework (Sept 2025 QRG; currency-checked 2026)
E-E-A-T is a concept in the Quality Rater Guidelines, not a direct ranking
score. Trust is the most important member of the family; Experience,
Expertise, and Authoritativeness support the assessment of Trust.
### Experience (20% of this skill's score) - first-hand signals
- Original research, case studies, before/after results
- Personal anecdotes, process documentation, "I tested this"
- Unique data, proprietary insights
- Photos/screenshots from direct experience (not stock)
Strong: multiple first-hand signals. Moderate: some evident. Weak: generic,
no personal touch. None: clearly AI-generated or scraped.
### Expertise (25%) - demonstrated knowledge
- Author credentials, certifications, bio
- Technical accuracy and depth appropriate for the audience
- Claims supported by evidence or sources
- Specialized vocabulary used correctly; up to date with the field
Strong: verified credentials, deep accuracy. Moderate: demonstrable
knowledge. Weak: surface-level, no credentials. None: factual errors.
### Authoritativeness (25%) - recognition by others
- Site and author recognized in the niche
- Content cited by other authoritative sources
- Industry awards, consistent publication history, media coverage
Strong: widely cited. Moderate: some external validation. Weak: no external
recognition. None: known for misinformation.
### Trustworthiness (30%) - most important
- Clear contact info (address, phone, email)
- Privacy policy, terms of service, return/refund policy
- HTTPS with valid certificate
- Transparent about who creates content and why
- Visible corrections and update history
- No deceptive practices (hidden ads, clickbait, back-button hijacking)
Strong: full transparency. Moderate: good signals, minor gaps. Weak: missing
key signals. None: deceptive practices, scam indicators.
The weight split (20/25/25/30) is this skill's own scoring model. Google
publishes no numbers, only that trust is most important - so do not use an
equal 25/25/25/25 split. Overall bands: 90+ exceptional, 70-89 strong,
50-69 moderate, 30-49 weak, 0-29 very low with trust issues.
## Content metrics
### Word count floors (coverage floors, not targets)
| Page type | Floor |
|---|---|
| Homepage | 500 |
| Service page | 800 |
| Blog post | 1,500 |
| Product page | 300+ (400+ for complex products) |
| Location page | 500-600 |
Word count is NOT a direct ranking factor. These are topical-coverage floors:
a 500-word page that completely answers the query outranks a 2,000-word page
that doesn't. Flag thin pages, never recommend padding to hit a number.
### Readability
- Flesch reading ease 60-70 for a general audience (scanner estimates it)
- Average sentence 15-20 words; paragraphs 2-4 sentences
- Flesch is NOT a direct ranking factor either (Google confirms it doesn't
use basic readability scores). It is a content-quality indicator: a page at
20 (dense legalese) or 90 (sentence fragments) for a general audience is a
usability concern, not an SEO emergency.
### Keyword and structure
- Primary keyword in title, H1, first 100 words; natural 1-3% density plus
semantic variations; no stuffing
- Logical heading hierarchy, descriptive headings, bullets where appropriate,
table of contents for long-form content
### Links and multimedia
- 3-5 relevant internal links per 1,000 words, descriptive anchors, no
orphans
- Cite authoritative external sources; reasonable count
## Low-quality AI content markers (QRG, Sept 2025)
AI authorship itself is not penalized. Raters assess patterns:
- Generic phrasing without specificity
- No original insight or unique perspective
- No first-hand experience signals
- Factual inaccuracies
- Repetitive structure across pages
- No author attribution
"Using generative AI tools to generate many pages without adding value" is
explicitly named under scaled content abuse (spam policy, 2026-05-15). Human
oversight and unique value are the difference.
## AI citation readiness
For ChatGPT, Perplexity, Google AI Overviews, and AI Mode:
- Clear, quotable statements with statistics or facts (the scanner lists
sentences containing digits, percentages, or attributed claims)
- Answer-first formatting for key questions; strong H1->H2->H3 flow
- Tables and lists for comparative data, structured data for data points
- First-party research is the most-cited material
Per Google's official AI optimization guide (2026-06-29), AEO/GEO is a
rebranded label for SEO grounded in the same quality systems, and you do not
need new AI files, markup, or AI-specific rewrites. Never claim a structured
data change "earns AI citations" - that is not a documented guarantee.
## Freshness
- Publication date visible; date modified if revised (scanner reports it)
- Flag content older than 12 months without an update in fast-changing topics
## Output contract
```
Content Quality Score: XX/100
AI Citation Readiness: XX/100
E-E-A-T Breakdown
| Factor | Score | Key signals |
|-------------------|-------|-------------|
| Experience | XX/20 | ... |
| Expertise | XX/25 | ... |
| Authoritativeness | XX/25 | ... |
| Trustworthiness | XX/30 | ... |
Issues (with priority) -> Recommendations
```
Every recommendation gets the prove-it check. Examples: "add a byline, then
verify it appears in the rendered article on the live URL"; "add dateModified,
then check the JSON-LD - if Google's crawler shows the old date, say so and
re-request indexing"; "add author credentials to the bio page, then confirm
that page links from the post and the bio is linked in the footer".
## Errors
| Scenario | Action |
|---|---|
| URL unreachable | Report the error, never guess content |
| 402/403 or login wall | Analyze only visible meta and headers, note the limitation |
| Under ~100 words retrievable | Report as-is, flag possible JS rendering, ask for the full text |
| Keyword guess off | Say the guess is heuristic and ask for the real primary keyword |The scanner script
Copy this exact file to ~/.codex/skills/codex-seo-content/scripts/content_scan.py.
#!/usr/bin/env python3
"""Content quality and E-E-A-T signal collector. Standard library only."""
import html as htmlmod
import json
import re
import sys
import urllib.error
import urllib.request
TIMEOUT = 15
UA = ("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0 Safari/537.36 "
"codex-seo-content/1.0")
def fetch(url):
req = urllib.request.Request(url, headers={"User-Agent": UA})
try:
resp = urllib.request.urlopen(req, timeout=TIMEOUT)
return resp.status, resp.geturl(), resp.read().decode("utf-8", "replace")
except urllib.error.HTTPError as e:
return e.code, url, ""
except Exception as e:
return "ERR:" + str(e), url, ""
def syllables(word):
w = re.sub(r"[^a-z]", "", word.lower())
if not w:
return 0
groups = len(re.findall(r"[aeiouy]+", w))
if w.endswith("e") and groups > 1 and not w.endswith("le"):
groups -= 1
return max(groups, 1)
def main():
url = sys.argv[1] if len(sys.argv) > 1 else ""
if not url:
print("usage: python3 content_scan.py <url> [--json]")
sys.exit(1)
want_json = "--json" in sys.argv
if not url.startswith("http"):
url = "https://" + url
status, final, html = fetch(url)
r = {"url": url, "status": status, "final_url": final}
if not html:
r["error"] = "no HTML body; status=" + str(status)
print(json.dumps(r, indent=2) if want_json else r["error"])
sys.exit(0 if status == 200 else 1)
def m(p):
return re.findall(p, html, re.I)
text = re.sub(r"(?is)<script.*?</script>|<style.*?</style>|<pre.*?</pre>|<code.*?</code>|<[^>]+>", " ", html)
text = htmlmod.unescape(re.sub(r"\s+", " ", text).strip())
words = text.split()
sentences = [s for s in re.split(r"(?<=[.!?])\s+", text) if len(s.strip()) > 8]
syl = sum(syllables(w) for w in words)
wc, sc, words_per_sent = len(words), max(len(sentences), 1), len(words) / max(len(sentences), 1)
flesch = 206.835 - 1.015 * words_per_sent - 84.6 * (syl / wc) if wc else 0
paras = [p for p in m(r"(?is)<p[^>]*>(.*?)</p>") if len(re.sub(r"<[^>]+>", " ", p).split()) > 3]
para_words = [len(re.sub(r"<[^>]+>", " ", p).split()) for p in paras]
# keyword: assume primary phrase = first two non-generic title words
title = (m(r"<title[^>]*>([^<]+)</title>") or [""])[0]
tkw = title.split()
kw = " ".join([w for w in tkw if w.lower() not in ("a", "an", "the", "how", "to", "in", "of", "&", "and")][:2])
first100 = " ".join(words[:100]).lower()
quotes = [s.strip() for s in sentences if re.search(r"\d|%|£|\$|€| from | by ", s)]
quotes = [q for q in quotes if len(q) < 240][:6]
domain = re.search(r"https?://([^/]+)", final)
dom = domain.group(1) if domain else ""
links = m(r'<a\s[^>]*href=["\']([^"\']+)["\']')
internal = [l for l in links if l.startswith("/") or dom in l]
external = [l for l in links if l not in internal and l.startswith("http")]
trust = {
"privacy_policy": bool(re.search(r"(?i)\bprivacy\s*policy\b", text) or
re.search(r"privacy", " ".join(links))),
"contact": bool(re.search(r"(?i)\bcontact\b", text)),
"email_or_phone": bool(re.search(r"[\w.+-]+@[\w-]+\.[\w.-]+|\+?\d[\d\s()-]{6,}\d", text[:3000])),
"address": bool(re.search(r"(?i)\b(addr(ess)?|street|suite)\b", text[:3000])),
}
dates = m(r'(?i)(?:datePublished|pub_date|published_time|dateModified|modified_time)\s*["\']?\s*[:>]?\s*["\']?([\d-]{4,10})')
h1 = m(r"<h1[^>]*>")
h2 = m(r"<h2[^>]*>")
toc = bool(re.search(r"(?i)\b(table of contents|toc|contents)\b", text[:2000])) or \
bool(re.search(r'href=["\']#[\w-]+["\']', html))
r["content"] = {
"words": wc,
"sentences": len(sentences),
"words_per_sentence": round(words_per_sent, 1),
"avg_paragraph_words": round(sum(para_words) / len(para_words), 1) if para_words else 0,
"flesch_reading_ease": round(flesch, 1),
"primary_keyword_guess": kw,
"keyword_in_first_100": kw.lower() in first100 if kw else False,
"h1_count": len(h1), "h2_count": len(h2),
"quotable_sentences": quotes,
}
r["links"] = {
"internal": len(internal),
"external": len(external),
"internal_per_1000_words": round(1000 * len(internal) / wc, 2) if wc else 0,
}
r["multimedia"] = {"images": len(m(r"<img\b")), "videos": len(m(r"<video\b|<iframe\b")),
"toc_or_anchor_nav": toc}
r["eeeat"] = {
"author_meta": m(r'<meta[^>]+name=["\']author["\'][^>]+content=["\']([^"\']{1,120})["\']'),
"person_schema": [t for t in m(r'"@type"\s*:\s*"([A-Za-z]+)"') if t in ("Person", "Author")],
"byline_present": bool(re.search(r"(?i)\b(autho?red by|written by)\b", text)),
"date_published": dates[0] if dates else None,
"trust_signals": trust,
}
if want_json:
print(json.dumps(r, indent=2))
else:
c = r["content"]
print("content_scan %s" % r["url"])
print(" words %d sentences %d %.1f w/s para %d w flesch %s" %
(c["words"], c["sentences"], c["words_per_sentence"],
c["avg_paragraph_words"], c["flesch_reading_ease"]))
print(" kw guess: %r in first 100: %s h1 x%d h2 x%d" %
(c["primary_keyword_guess"], c["keyword_in_first_100"],
c["h1_count"], c["h2_count"]))
print(" links: %d internal (%.1f/1000w), %d external" %
(r["links"]["internal"], r["links"]["internal_per_1000_words"], r["links"]["external"]))
print(" media: img %d video %d toc %s | date %s | author %s" %
(r["multimedia"]["images"], r["multimedia"]["videos"],
r["multimedia"]["toc_or_anchor_nav"], r["eeeat"]["date_published"],
r["eeeat"]["author_meta"] or r["eeeat"]["person_schema"] or "-"))
print(" trust: " + ", ".join(k for k, v in r["eeeat"]["trust_signals"].items() if v) or " none of privacy/contact detected")
if __name__ == "__main__":
main()Install it in three commands
mkdir -p ~/.codex/skills/codex-seo-content/scripts
# save the two files above at:
# ~/.codex/skills/codex-seo-content/SKILL.md
# ~/.codex/skills/codex-seo-content/scripts/content_scan.py
python3 ~/.codex/skills/codex-seo-content/scripts/content_scan.py https://example.comThe last command is the sanity check. You should see content_scan <url> followed by word count, sentences, words-per-sentence, Flesch, keyword guess, link counts, media counts, date, and trust signals. If it errors, check the troubleshooting table below before blaming your site.
Then in Codex, restart the session and either run $codex-seo-content <url> explicitly or paste a URL and say: "Run a content quality and E-E-A-T check on this page." The skill triggers on terms like content quality, E-E-A-T, readability, thin content, or authority.
A real run, and how to read it
Here is the actual output from running the scanner on the article about technical audits earlier in this series, https://auspia.ai/blog/codex-seo-technical-audit:
content_scan https://auspia.ai/blog/codex-seo-technical-audit
words 2409 sentences 108 22.3 w/s para 55 w flesch 50.9
kw guess: 'Audit Technical' in first 100: True h1 x1 h2 x27
links: 61 internal (25.3/1000w), 2 external
media: img 16 video 0 toc False | date 2026-08-28 | author -
trust: privacy_policy, contactReading it line by line:
- 2,409 words clears the blog post floor of 1,500 with room to spare. No padding needed.
- 22.3 words per sentence is on the long side, and the estimated Flesch is 50.9, under the 60-70 band. The piece explains a technical audit, so some dense sentences are fair, but a Flesch in the 50s on a general-audience page is the kind of thing the skill flags as a usability note, not a scandal.
- The keyword guess lands on "Audit Technical" because the page title starts with "How to Audit Technical SEO..." That's a limitation of the guess. The real keywords here are "technical SEO audit" and "Codex", and the first 100 words do carry them.
- 61 internal links and 25 per 1,000 words. That's high because this article is the hub page of a series, so it links out heavily. The skill calls out density but the report should read it against page intent.
- No author meta tag in the HTML, and the byline text on the page is "Author: ..." so the scanner reports
author -. That is a real E-E-A-T gap worth naming: a technical blog without a structured byline is a page Google has to figure out at runtime. - Trust comes from site-wide signals: privacy policy and contact page are present. Email and physical address are not, which for a software site is normal.
Then the agent writes the report. A filled-in version looks like this:
Content Quality Score: 76/100
AI Citation Readiness: 71/100
E-E-A-T Breakdown
| Factor | Score | Key signals |
|-------------------|-------|-------------|
| Experience | 15/20 | First-person walkthrough, real scan output shown |
| Expertise | 21/25 | Technical threshold details, primary-source citations |
| Authoritativeness | 16/25 | Series context, no external recognition signals |
| Trustworthiness | 24/30 | Privacy + contact site-wide, date present; no structured byline |
Priority fixes:
High - add author meta + Person schema to article pages
Medium - trim longest sentences, target Flesch 60+
Low - add last-updated date under the headlineScores like 76/100 are the agent's judgment against the anchored bands, not a tool output, and they will differ from run to run. What stays stable is the evidence underneath.
Troubleshooting
Scenario | Action |
|---|---|
| Install Python 3 (python.org or your package manager), or use |
Page returns 401/403 | It's behind auth. Ask for a public URL or paste the full text into Codex |
Word count near zero, many scripts | Likely client-side rendering. Say what the raw HTML proves, and offer a pasted full text or a headless-browser tool as next step |
Keyword guess looks wrong | It's a heuristic. Tell the agent what the real primary keyword is |
Windows paths | The same |
Codex doesn't auto-trigger | Run |
URL unreachable | Report the error, never fabricate content. Re-check the URL |
Paste this article into Codex
If you'd rather have Codex do the installation, paste the entire article up to this line into a new Codex conversation and say this:
Read the two code fences marked "The full SKILL.md" and "The scanner script" above.
1. Create ~/.codex/skills/codex-seo-content/SKILL.md with the full content of the SKILL.md fence.
2. Create ~/.codex/skills/codex-seo-content/scripts/content_scan.py with the full content of the script fence.
3. Run: python3 ~/.codex/skills/codex-seo-content/scripts/content_scan.py https://example.com
4. If that works, run the same scan on my own site and produce the full Content Quality + E-E-A-T report with scores and prioritized fixes.
Do not install or modify any other files.Codex will create the skill, run the self-test, and report what it found on your site. If you want the rest of the series first, start with the setup guide and the technical audit skill.
FAQ
Is E-E-A-T a ranking factor? Not a direct score. It's a concept in Google's Quality Rater Guidelines that informs the core ranking and helpful-content systems. The skill treats it as a checklist for quality, not as a measurement of Google's internal math.
Is a Flesch score of 50 a disaster? No. Google has confirmed it doesn't use basic readability scores for ranking, and the skill says so. Use it as a usability signal: hard-to-read pages get bounced, especially on mobile. Aim for 60-70 for general audiences and don't touch heavily technical copy.
Can AI-generated content rank? Yes, when it shows genuine E-E-A-T and unique value, per the September 2025 QRG. What gets penalized is generic, scaled, unoriginal content, and the May 2026 spam policy explicitly names mass AI generation without added value.
How do I make a page more AI-citable? The signals that get quoted: clear answer-first structure, sentences with numbers or attributed claims, first-party data, tables for comparisons, and accurate schema. Google's own AI optimization guide says AEO/GEO is just SEO, and you don't need special AI files or Markdown. The scanner's quotable-sentences list is where you'd look.
How much does this cost? Nothing. One Python script, standard library only, no keys, no calls to paid APIs.
Next in the series (post 04 of 20): [How to Build an SEO Content Brief with Codex (Full SKILL.md Included)](https://auspia.ai/blog/codex-seo-content-brief) - seo content brief generator (intent, competitors, gaps).
Previous in the series: How to Diagnose a Single Page's SEO Problems with Codex (Full SKILL.md Included). The full series roadmap lists all 20 posts.
Author: Elise Morgan, 15-Year Editorial SEO Strategist at Auspia. Elise writes about refreshes, rewrites, and content quality, and edits the practices the Auspia growth desk uses across its own editorial programs.
Based on the open-source claude-seo project by AgriciDaniel (MIT license, GitHub). This series adapts it for the Codex runtime: rewritten methodology, a Codex-native SKILL.md, and new evidence collectors written from scratch for this series.




