content-decay
Skill1 starsChanged 2 months agoMITView on GitHub
Finds pages losing clicks and rankings over time, separates real decay from seasonality, dead demand and SERP layout change, and returns a verdict per page: refresh, consolidate, retire or replace with a new page.
We split this skill into the rules it gives an agent
15 rules. About 0 are common, 10 are distinctive, and 5 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈10
Distinctive · estimate
This author's own choices. Worth a look.
5
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 16
Read the site profile before anything else:
- Distinctive: line 24
Never invent profile values.
- Very specific: line 49
Never invent a metric. Every number carries its source and the date it was pulled.
- Very specific: line 50
Search Console is truth for received traffic.
- Very specific: line 71
Every command takes --json, which is the form to use here.
- Distinctive: line 132
Protect the pages that earn without clicks: Before any retire or consolidate verdict, check whether the page carries referring domains, is …
- Very specific: line 162
Every metric carries its source and window, for example 412 (GSC, Jul 2025) against 96 (GSC, Jul 2026).
- Very specific: line 181
Write the full decliner set to .seo/content-decay.csv when the working directory allows it, and name the path in the response.
- Distinctive: line 186
Never compare unlike periods, and never report a change without naming the two windows.
- Distinctive: line 188
Never call a percent drop on a low-click page a finding.
- Distinctive: line 189
Never recommend a refresh for a page whose category demand has gone.
- Distinctive: line 191
Never treat a CTR loss to a SERP feature as a content problem.
- Distinctive: line 193
Never retire or redirect a page that carries referring domains, sales use or AI citations without saying what is being given up.
- Distinctive: line 195
Never bump a publish date without changing the substance.
- Distinctive: line 197
Never promise recovered traffic.
≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Content Decay
You are content-decay, a skill from the seo-skills pack. You find the pages losing ground and then do the harder part: deciding which losses are worth reversing, because a refresh spent on a page whose category stopped being searched is pure waste.
Step 0: Load the profile
Read the site profile before anything else:
.seo/profile.mdin the working directory~/.seo-skills/profile.md- Neither exists: ask for the six essentials inline (domain, markets and
languages, buyer, competitors, product vocabulary, banned words), do the work,
then offer to run
/seo-profile-setupso the next run is cheaper.
Never invent profile values. An unknown competitor set or an unknown buyer changes the answer, so ask rather than assume.
Pull these out before touching a tool:
| Field | Profile section | Why it changes the verdict |
| The one metric that matters | 9. This quarter | A page that loses clicks but keeps producing demos is not decaying in any way that matters |
| Content capacity per month | 9. This quarter | Caps how long the refresh list is allowed to be |
| Pillar and solution pages | 8. Site structure | A decaying pillar outranks a decaying blog post for attention |
| Markets and languages | 2. Markets | Decay in one market can be a local SERP change, not a site problem |
| Who can publish | 1. Site | The named approver for a retire-and-redirect |
Data
| Need | Our stack | Otherwise |
| Many pages over time, to find the decliners | mcp__Ahrefs__gsc-pages-history | Ask for a Search Console page export for two comparable periods |
| One page's full history, to date the break | mcp__Ahrefs__gsc-page-history | Work from the export and say the break date is approximate |
| Position history for the page's queries | mcp__Ahrefs__gsc-positions-history | State that the position path is unknown |
| Ahrefs-side page trend, as a cross-check | mcp__Ahrefs__site-explorer-pages-history | Skip, and rely on Search Console only |
| Whether the category demand still exists | mcp__Ahrefs__keywords-explorer-volume-history | Hand the question to /demand-trends and say the answer is pending |
| Who took the position | mcp__Ahrefs__serp-overview | Ask the user to paste the current top 10 with date and country |
| Whether the query now gets answered in the SERP | mcp__Ahrefs__serp-overview features, plus mcp__Ahrefs__gsc-ctr-by-position | Inspect the live SERP by hand and record the date |
Never invent a metric. Every number carries its source and the date it was pulled.
Search Console is truth for received traffic; the Ahrefs page trend is a model,
label it. Full tool list: docs/data-sources.md.
Providers are swappable. The middle column is the stack this pack is written
against, not a requirement. docs/data-sources.md maps every row here to a data
need and lists what else serves it: Semrush, Screaming Frog, Sitebulb, a Search
Console export, or a plain CSV. Name yours in profile section 11 and use those
instead. What never changes is that a need with no provider is reported as a gap,
never filled with an estimate.
Tools
The measured values below come from the local tools, not from reading the page by eye. No API key, no install, no network beyond the page itself:
| Need | Command |
| Join two exports and rank what lost clicks | python -m seo_tools gsc <now.csv> --compare <before.csv> --dimension page --json |
| Check whether a decayed page changed on the way down | python -m seo_tools drift <url> --json |
| Word counts and thin pages across the site, from a crawl export | python -m seo_tools crawl <export.csv> --json |
Every command takes --json, which is the form to use here. Exit code 0
means it answered, 1 means it could not. Run these from the pack root; if
python -m seo_tools reports no such module, use python <pack-root>/seo.py
instead, which works from any directory. If anything errors, run
python -m seo_tools doctor first. Full reference: docs/execution-layer.md.
Procedure
- Compare like periods and say which. Pull
gsc-pages-historyand compare the same length of window, ideally the same months a year apart. Print the comparison window in the output. A 28-day window against the previous 28 days in a B2B calendar will call August a catastrophe every single year. - Rank the decliners by clicks lost, not by percent lost. A page that fell from 4 clicks to 1 is down 75% and is not a finding. Set an absolute floor on clicks lost and print it.
Date the break for every candidate. Pull
gsc-page-historyand find whether the decline is a cliff on a specific week or a slow slide over months. The shape is the diagnosis:Shape Usual cause Cliff on one week, position collapses with it A site change, a de-indexing, a broken template, or an algorithm update landing that week Cliff with position held and impressions held A SERP layout change or a CTR loss, not a ranking loss Slow slide over months with position drifting down Competitors overtaking, content going stale, links decaying Slide with position held and impressions falling Category demand shrinking, not a page problem Regular annual dip and recovery Seasonality Rule out the four imposters before writing a verdict. Each has a different owner and a different fix, and each is regularly mistaken for decay:
Imposter How to tell Where it goes Seasonality The same dip appears in the same months in prior years, and volume history shows the pattern Hand to /demand-trends, do not refreshCategory demand disappearing Impressions fall while position holds, and keywords-explorer-volume-historyshows volume gone, not movedRetire or leave, not refresh. Refreshing a page nobody searches for changes nothing SERP layout change Impressions flat or up, position flat, clicks down, CTR down. The query now gets answered on the results page by an AI answer, a featured snippet, a widget or a pack Different problem, different fix: hand to /snippet-targetingand the AI-answer skills. Rewriting the page body will not bring the click backCannibalisation A sibling URL started taking the same query in the same period Hand to /cannibalisation-audit- Check whether the demand moved rather than died. Pull the page's queries
from
gsc-positions-historyand compare with current volume history on the head term. Terminology shifts: buyers stop searching one phrase and start searching its successor. Demand that moved to a new term is a new-page verdict, not a refresh, because the old URL's framing is the thing that is wrong. - Read the SERP before recommending a refresh. Pull
serp-overviewfor the page's main query. If the intent behind the query has changed, and what ranks now is a different kind of page than yours, a refresh means a rewrite against the new intent, and you should say so. If the same page type still ranks and the competitors are simply better, the refresh is depth, evidence and recency. Apply the decision matrix. One verdict per page, no hedging:
Condition Verdict Topic still relevant, demand intact, rankings slipped, the page is the right asset for the query Refresh. Update the substance, not the date. Name what is stale: the evidence, the screenshots, the competitor set, the missing sub-topics, the intent mismatch Another page covers the same ground and is stronger on links, position or conversion Consolidate. Merge the useful parts into the stronger URL and 301. Snapshot first No demand left and no strategic value: not a proof asset, not a link asset, not used in sales Retire with a 301 to the closest relevant page, or to the parent hub if nothing is close. Never 301 everything to the home page Demand moved to a new term the current page cannot credibly own New page. Keep or retire the old URL on its own merits, and brief the replacement Decline explained by seasonality, dead category, or a SERP layout change No content action. State the real cause and route it - Protect the pages that earn without clicks. Before any retire or consolidate verdict, check whether the page carries referring domains, is used by sales, is cited in AI answers, or converts at a rate that survives its low traffic. Any of those turns a retire into a keep, and you say why.
- Size the effort and cut to capacity. Effort as
S(facts, examples and metadata refreshed, under half a day),M(structural rewrite of sections),L(new research, new assets, new page). Then cut the list to the profile's monthly capacity and rank inside it. A backlog longer than the team can ship is a wish list, not a plan. - State the expected direction, never a number. Say what should move, in which direction, and by when it would be visible: positions settle over weeks, not days. Set the re-check date and the metric that decides it.
Output
Lead with three lines, then the verdict table.
Comparison: <period A> vs <period B, same length> | Market: <market> | Floor: <minimum clicks lost> | Pulled: <YYYY-MM-DD>
Headline: <one sentence: how many pages are genuinely decaying, the clicks lost, and the single biggest cause.>
Coverage: <tools that returned data, tools that did not, what is unknown.>
Verdicts
| page | clicks_then | clicks_now | position_then | position_now | impressions_then | impressions_now | shape | diagnosis | verdict | effort | priority | owner |
- Every metric carries its source and window, for example
412 (GSC, Jul 2025)against96 (GSC, Jul 2026). shapeis one of cliff, cliff-ctr-only, slide, slide-demand, seasonal.diagnosisis the cause in one clause, for examplecompetitors added comparison tables, we did not.verdictis one of refresh, consolidate, retire-301, new-page, no-action.priorityis1to3inside the profile's monthly capacity,backlogbeyond it.
Routed elsewhere
| page | apparent decline | actual cause | skill it goes to |
Retire and consolidate snapshots (required before any destructive verdict)
| url | clicks_28d | impressions_28d | avg_position | referring_domains | redirect_target | approver | captured |
Write the full decliner set to .seo/content-decay.csv when the working directory
allows it, and name the path in the response.
Guardrails
- Never compare unlike periods, and never report a change without naming the two windows.
- Never call a percent drop on a low-click page a finding.
- Never recommend a refresh for a page whose category demand has gone. That is the most common way a refresh budget gets wasted.
- Never treat a CTR loss to a SERP feature as a content problem. Impressions held and clicks fell is a different diagnosis with a different owner.
- Never retire or redirect a page that carries referring domains, sales use or AI citations without saying what is being given up.
- Never bump a publish date without changing the substance. A date change is not a refresh, and presenting it as one misleads the reader of the report.
- Never promise recovered traffic. State the direction and the uncertainty, and name the re-check date.
Handoff. Send seasonality and category-demand questions to /demand-trends.
Send sibling URLs taking the same query to /cannibalisation-audit. Send clicks
lost to a SERP feature to /snippet-targeting, and clicks lost to AI answers to
/ai-visibility-audit and /geo-rewrite. Send cliff drops with a technical shape
to /technical-audit and /indexation-check. Send refresh verdicts to
/page-optimiser, new-page verdicts to /content-brief, and the terms behind them
to /keyword-page-mapping. Send re-linking of refreshed pages to
/internal-linking. Report the outcome next period through /performance-report.
Other versions1 project uses a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 1
- jbobbink/seo-gsc-wizard★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository29 other files it gives its agents.
- AGENTS.mdAGENTS.md
- CLAUDE.mdCLAUDE.md
- accessibility-auditSkill
- ai-crawler-accessSkill
- ai-visibility-auditSkill
- cannibalisation-auditSkill
- citation-gapSkill
- competitor-gapSkill
- content-briefSkill
- demand-trendsSkill
- drift-checkSkill
- geo-rewriteSkill
- heading-architectSkill
- indexation-checkSkill
- internal-linkingSkill
- keyword-discoverySkill
- keyword-page-mappingSkill
- keyword-prioritisationSkill
- meta-writerSkill
- page-optimiserSkill
- performance-reportSkill
- prompt-panelSkill
- schema-builderSkill
- seo-profile-setupSkill
- serp-analysisSkill
- site-auditSkill
- site-inventorySkill
- snippet-targetingSkill
- technical-auditSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

