Google spam update 2026: how to check if it hit your site + Claude skills to fix it
Four checks with the exact commands, and what each one turns up. Copy the whole checklist at the bottom.
Clients we work withClients we
work with








Google shipped the August 2026 spam update on the 18th. The rollout finished on the 21st.
I don't know what to do.. my website also gone from Google.. while its classified website... Sudden fall in traffic and now website gone from Google, while some article was on top in Google.
— OwnPetz (@OwnPetz) August 24, 2026
August 2026 Spam Update rollout done #SEO
— Gagan Ghotra (@gaganghotra_) August 21, 2026
Within days the reports started — sites dropping out of Google search and AI Overviews on the same day. Four checks tell you whether yours is one of them.
What it enforces
| Policy | Trigger |
|---|---|
| Scaled content abuse | Many pages on one template that add little of their own |
| Deceptive freshness & hidden text | dateModified bumped with no real change; text served only to crawlers |
| Site reputation abuse | Unrelated topics hosted on a trusted domain for ranking reasons |
Not spam signals: losing AI Overview citations (separate system, different inputs), or a -2026 in the slug.
Four checks, with the commands
The commands are in the checklist at the bottom — copy it or download the .md.
Fake freshness
If the only diff is a date string, that is date manipulation, not an update. Check what your last “refresh” commit actually changed: git show --stat <commit>.
Hidden text
If it is good enough for the crawler it is good enough for the reader. Surface it as a visible summary or delete it — your JSON-LD already carries the entity facts.
Stale hardcoded claims
Worse when combined with check 1: those pages claim they were verified this week. Fix the numbers — that is a real update, and it earns a new date honestly.
Templated families — measure before deleting
Repeating structure is not duplication. Mass-deleting a templated family is the confident, decisive, usually wrong move — and it is the one most panic audits make.
The Claude skill that audits and fixes it
Download SKILL.md, then in Claude open Customize → Skills → Add and upload it. Point Claude at your repo and it runs every check, reports what trips a red flag, and works the fix queue.
It asks before deleting, redirecting, or rewriting anything — and it will tell you when a drop looks like falling demand rather than a penalty.
---
name: spam-update-audit
description: Audit a website's source against the Google spam update — deceptive freshness, hidden text, stale hardcoded claims, templated near-duplicates, dead pages — then fix what fails. Use when a site loses Google or AI Overviews traffic, or before a large content push.
---
# Spam-update audit and fix
Run the checks in order, report findings as a table, then work the fix queue.
Nothing is deleted or rewritten without asking first.
Three policies cause most damage. Ranked by how often the cause is automation
rather than a person:
| Policy | Trigger |
|---|---|
| Deceptive freshness / hidden text | A date bumped with no real change; text served only to crawlers |
| Scaled content abuse | Many pages on one template that add little of their own |
| Site reputation abuse | Unrelated topics hosted on a trusted domain for ranking reasons |
Not spam signals, and commonly confused for them: losing AI Overview citations
(a separate retrieval system), a year in the slug, or a page simply being old.
## Step 0 — orient
Find where pages live and how many there are. Adjust the paths in every command
below to match.
# framework guesses, in order of likelihood
ls src/app src/pages content posts _posts 2>/dev/null
find . -name "page.jsx" -o -name "page.tsx" -o -name "*.mdx" | grep -v node_modules | wc -l
Record the page count. Percentages matter more than raw numbers from here on.
## Check 1 — deceptive freshness
The single most common automated offence. Look for dates clustered on a handful
of recent days.
grep -rhoE "dateModified: '[0-9-]+'" --include=page.jsx src \
| sort | uniq -c | sort -rn | head -20
# frontmatter variants
grep -rhoE "^(date|updated|lastmod|modifiedTime):.*" content posts \
| sort | uniq -c | sort -rn | head -20
**Red flag:** more than 20% of pages sharing a date inside any 7-day window, or
any single date covering more than 10% of the site.
Confirm the cause before concluding anything. Find the commit that set them:
git log --oneline -S"dateModified: '<the-clustered-date>'" -- src | head -5
git show --stat <commit> | tail -3
git show <commit> -- src | grep -E "^[+-]" | grep -v "^[+-][+-]" | head -40
**Verdict rule:** if the diff for a page contains only a date string, a
timestamp field, or a sentence like "Updated <Month> <Year>", that page was not
updated. Count how many of the commit's files match that shape. Also check for a
scheduler that does this on a cadence:
ls .github/workflows/ && grep -rl "schedule:" .github/workflows/
grep -rn "dateModified\|modifiedTime\|lastmod" .github/workflows/ scripts/ | head
## Check 2 — hidden text
Text present for crawlers and invisible to readers.
grep -rl 'aria-hidden="false"' src | wc -l
grep -rn 'sr-only\|visually-hidden\|screen-reader-text' src | head -20
grep -rn 'display:\s*none\|visibility:\s*hidden\|font-size:\s*0\|text-indent:\s*-9999' src | head -20
Then test whether the block is real accessibility markup or a keyword payload.
Pull one instance and read it. Ask three questions:
1. Does it repeat near-verbatim across many pages? Count it:
`grep -rl '<a distinctive sentence from the block>' src | wc -l`
2. Does it contain marketing claims, statistics, or brand names rather than
navigational help ("skip to content", a chart's text alternative)?
3. Would you be comfortable showing it to a reader as written?
**Red flag:** yes, yes, no. Legitimate `sr-only` use is short, per-page, and
describes an interface element. A repeated paragraph of company facts is not.
## Check 3 — stale hardcoded claims
grep -rhoE '\$[0-9,]+(\.[0-9]{2})?(/mo|/month|/yr| per month)?' src \
| sort | uniq -c | sort -rn | head -20
grep -rhoE '[0-9,]+\+? (customers|users|clients|marketers|reviews)' src \
| sort | uniq -c | sort -rn | head -20
**Red flag:** any figure repeated on more than ~50 pages, because one change
makes it wrong everywhere at once. Compounds badly with check 1: a page that
claims a fresh timestamp while quoting a stale price is asserting a reliability
it does not have.
For each repeated figure, verify the current value against the source before
touching anything. Report figures you could not verify separately from ones you
confirmed wrong — do not guess.
## Check 4 — templated families
Cluster the slugs first:
ls src/app/\(site\)/blog | sed -E 's/^(.*)-(alternatives|pricing|review|vs-.*)$/\2/' \
| sort | uniq -c | sort -rn | head
Structure repeating is normal. Duplicated prose is not — so measure the prose,
never judge by the slug pattern:
python3 - <<'PY'
import re, os, itertools, sys
base = sys.argv[1] if len(sys.argv) > 1 else "."
def sents(d):
txt = ""
for f in os.listdir(d):
if f.endswith((".jsx", ".js", ".mdx", ".md")):
txt += open(os.path.join(d, f), errors="ignore").read()
return set(s.strip() for s in re.findall(r'["\'>]([^"\'<]{40,})["\'<]', txt))
dirs = [os.path.join(base, d) for d in sorted(os.listdir(base))
if os.path.isdir(os.path.join(base, d))]
for a, b in itertools.combinations(dirs[:40], 2):
A, B = sents(a), sents(b)
if not A or not B: continue
o = len(A & B) / min(len(A), len(B))
if o > 0.30:
print(f"{o:.0%} {os.path.basename(a)} vs {os.path.basename(b)}")
PY
**Verdict rule:** under 10% overlap means the pages are genuinely distinct —
leave them alone. 30%+ across many pairs is real duplication; consolidate into
one strong page and 301 the rest to it. Between the two, read a pair yourself
before deciding.
Do not mass-delete a templated family on pattern alone. This is the most common
and most expensive mistake in a post-update panic.
## Check 5 — dead weight
Pages older than 30 days with effectively no traffic and no AI-assistant
sessions. This needs analytics, not grep — pull Search Console clicks and
impressions per URL over 90 days, plus referral sessions from ChatGPT,
Perplexity, Claude, Gemini and Copilot.
**Red flag:** 30+ days old, ≤3 clicks in 90 days, zero AI sessions. Protect any
page that earns AI citations even when clicks are near zero — those are two
different kinds of value.
## Report first
Before changing anything, output one table:
| Check | Pages affected | % of site | Red flag? | Cause |
|---|---|---|---|---|
Then state plainly which findings are risk signals versus proven damage. A grep
result is a risk signal. Proven damage needs a step change in Search Console on
a specific date, with positions holding while clicks fall. Positions flat and
impressions falling is a demand drop, not a penalty — say so rather than letting
someone rewrite a site that was never hit.
## Fix queue, in order
Work top to bottom. The first two stop new signal from being created; the rest
clean up what exists.
1. **Turn off any scheduled job that bumps dates.** Disable the workflow. Nothing
else matters while it is still running nightly.
2. **Gate the date bump on a real diff.** If the only change is a date string,
skip the page and log it. Keep the staleness ceiling — pages that genuinely
go stale get rewritten, not restamped.
3. **Reset the false timestamps.** For each page whose only recent change was the
date, restore `dateModified` from the last commit that touched visible
content: `git log --format=%cI --name-only -- <path>`, skipping the refresh
commits. Regenerate the sitemap afterwards so `lastmod` agrees.
4. **Surface or delete the hidden block.** Either promote it to a visible summary
at the top of the page, or remove it and let JSON-LD carry the entity facts.
Drop `aria-hidden="false"` either way.
5. **De-duplicate boilerplate.** Keep the claim where it is evidence — pricing,
about, case studies. Remove it from articles where it is filler.
6. **Correct the hardcoded figures.** This is a genuine content change, so these
pages earn a new `dateModified` honestly.
7. **Consolidate confirmed duplicates.** Lift anything unique out of the loser
into the keeper first, then 301. Redirect to a topically matching target —
a mismatched redirect is treated as a soft 404 and the equity is discarded.
8. **Prune dead weight.** Only after 1–3, so freshness noise is not polluting the
traffic data.
9. **Write the rule down** in the repo's contributor guide: a date bump requires
a content change, and hidden text is not an AI-visibility tactic.
## Rules for the agent
- Ask before deleting, redirecting, or bulk-rewriting. Show the list first.
- Never fix a freshness problem by editing dates in bulk — that is the offence.
- Never add hidden text to satisfy a check.
- Change one category at a time and commit separately, so a regression is
traceable to a single pass.
- Report what you could not verify. An unverified figure stays unverified in the
report; it does not become a confident claim.
Frequently asked questions
What does the Google spam update actually penalise?
Scaled content abuse, deceptive freshness and hidden text, and site reputation abuse. Losing AI Overview citations is not one of them — that is a separate system.
Is bumping the “last updated” date a spam signal?
Yes, when nothing else changes. A scheduled job doing it nightly turns a one-off into a pattern.
Is screen-reader-only text a safe way to feed AI assistants?
No. If it is good enough for the crawler it is good enough for the reader — make it a visible summary, or delete it.
Should I delete templated pages like brand-alternatives?
Not automatically. Measure sentence overlap first: low overlap means only the structure repeats, which is fine.
Can Claude run these checks and fix what it finds?
Yes. Hand it the SKILL.md and point it at your repo — it runs each check, reports the red flags, then works the fix queue.
How do I install it as a Claude skill?
Customize → Skills → Add, upload the .md. Trigger it by name on any repo.

