programmatic-seo
Builds hundreds or thousands of web pages automatically from data to rank better in search results.
Installation
Paste this into Claude Code, Cursor, or any agent that can run commands.
SKILL.mdShow the author's original SKILL.md
---
name: programmatic-seo
description: Design and build templated page systems that scale to hundreds or thousands of URLs without triggering scaled content abuse. Use whenever the user mentions programmatic SEO, pSEO, page generation at scale, templated landing pages, location pages, "X for Y" pages, integration pages, comparison page generation, directory sites, or wants to generate many pages from a dataset. Also use when a site already has thousands of generated pages that aren't indexed or aren't ranking.
---
# Programmatic SEO
Programmatic SEO works when you have a dataset that's genuinely useful and a query pattern that genuinely repeats. It fails when you have a template and a list of words.
The distinction isn't stylistic. Google's scaled content abuse policy targets pages produced at scale that don't add value, regardless of how they were produced. The dataset is what makes the difference.
## The qualifying test
Before designing anything, answer these four. If any answer is no, don't build it.
1. **Is there a repeating query pattern with real demand?** Not "there could be". Check that people search `[thing] in [place]` or `[tool] vs [tool]` or `[job] salary in [city]` at meaningful volume across many of the combinations, not just the top three.
2. **Do you have unique data for each page?** Real, differing values. Not the same paragraph with a variable substituted.
3. **Would a human find each page useful on its own?** Open the worst combination in your set. If that page is embarrassing, the system generates embarrassing pages.
4. **Can you maintain it?** Stale programmatic pages rot faster than editorial ones because there are more of them and nobody reads them.
The honest version of this conversation is often: you have 12 combinations with real demand and a long tail of 4,000 with none. Build 12 good pages.
## What "unique data per page" means
| Works | Doesn't work |
|---|---|
| Real numbers that differ per page: prices, salaries, counts, distances, availability | The same sentence with the city name swapped |
| Actual inventory or listings for that combination | "We serve [City] and the surrounding area" |
| Aggregated user data you own: reviews, usage, benchmarks | Spun paragraphs from a thesaurus |
| Genuinely different specs, requirements or regulations | An LLM asked to write 400 unique words about nothing |
| Content that changes when the underlying data changes | Content generated once and frozen |
The reliable pattern: **the page exists to display data, and prose is the frame around it.** Not the reverse. A page showing 40 real listings with 100 words of context is a good programmatic page. A page with 800 generated words and no data is not.
## Step 1: Model the pattern
Pick exactly one pattern per system. Mixing them produces an unmaintainable template.
```
[service] in [city] needs: local data per city
[tool A] vs [tool B] needs: real feature and pricing data for both
best [category] for [use case] needs: genuine evaluation per combination
[integration] + [integration] needs: the integration to actually exist
[job title] salary in [location] needs: a salary dataset
how to [task] in [software] needs: the task to be real in that software
```
Then define the axes and be ruthless about size. Two axes of 50 values each is 2,500 pages, and almost certainly 2,400 of them have no demand and no data.
## Step 2: Filter the combinations before generating
This step is what separates a working system from a penalty.
- **Cut by demand.** Keep combinations with real search volume or a real business reason. Drop the rest entirely rather than generating thin pages for them.
- **Cut by data completeness.** If a combination has fewer than N data points, don't generate a page. Set N high enough that the thinnest page is still worth reading.
- **Cut nonsense combinations.** Every axis product contains absurdities. "Snow tyre fitting in Valletta" and "vegan butcher in a town of 200" need to not exist.
- **Start with the top 50.** Ship those, get them indexed, confirm they rank, then expand. Publishing 5,000 pages on day one and finding out they're all thin is a six-month cleanup.
## Step 3: Design the template
Each page needs a reason to exist that a reader can see in the first screen.
```
H1 The specific combination, in natural language
Direct answer The data point someone came for, immediately.
A number, a table, a count, a yes/no.
The data The actual dataset for this combination, rendered.
This is the page. Everything else supports it.
Context What the data means, varying with the values.
Conditional logic, not one paragraph with slots.
Related Links to sibling and parent pages. This is how they get crawled.
Parent link Up to the hub page for the pattern.
```
Techniques that make templated pages read as real:
- **Conditional prose.** Different sentences trigger at different data thresholds. "Prices here run about 30% above the national average" only appears when they do.
- **Vary the structure, not just the values.** Pages with more data get more sections.
- **Include the comparisons a reader would want**, computed from the data rather than written.
- **Let some pages say "not much here".** A page that honestly reports thin data is more trustworthy than one that pads. Better still, don't generate it.
- **Add one genuinely editorial element per page** where you can: a real photo, a local note, a hand-written line. Expensive, and it's often the difference.
## Step 4: The technical layer
Programmatic systems fail technically in predictable ways.
- **URLs**: readable, stable, lowercase, hyphenated, one canonical form. `/salaries/software-engineer/berlin` not `/s?j=142&l=88`.
- **Internal linking is the whole indexing strategy.** Generated pages are orphans by default. Build hub pages per axis, link siblings to each other, and link from real editorial content into the best of them. A sitemap alone will not get 2,000 pages indexed. See `internal-linking-architecture`.
- **Server-render.** These pages exist to be crawled. Client-side rendering of the data defeats the purpose, especially for AI retrieval agents that don't execute JavaScript.
- **Split sitemaps** by pattern so Search Console's coverage report tells you which segment is failing.
- **Unique title and meta description per page**, generated from the data, not from a single template string with one variable.
- **Handle empty states with a 404 or a redirect**, never a 200 with "no results".
- **Watch indexation rate.** If Google indexes 300 of 2,000 pages and stops, that's a verdict on quality. Cut the weakest 1,700 rather than pushing harder.
## Step 5: Diagnose an existing system that isn't working
| Symptom | Cause | Fix |
|---|---|---|
| Indexed, no impressions | No demand for those combinations | Prune to the ones with demand |
| Not indexed at all | Thin, orphaned, or judged low quality | Internal links first, then cut the weakest half |
| Indexed then dropped | Quality re-assessment | Cut aggressively, add real data |
| A few rank, most don't | The pattern works, the tail doesn't | Delete the tail. It's dragging the site |
| Traffic fell after a core update | Scaled content assessment | Prune hard and improve the survivors |
Pruning is almost always the answer, and it's almost always resisted. A site with 200 good generated pages outperforms the same site with 200 good ones plus 3,000 thin ones, because the thin ones are evidence about the site as a whole.
## Don't do these
- **Don't generate prose with an LLM to fill a template.** This is the exact pattern the policy names. Generate pages from data; use language models to help build the system, not to manufacture the substance.
- **Don't spin text.** It's transparent and it's been transparent for fifteen years.
- **Don't build a page per keyword variation.** "Cheap X", "affordable X" and "low cost X" are one page.
- **Don't launch the full matrix.** Ship 50, measure, expand.
- **Don't skip the maintenance plan.** Decide now how the data refreshes and what happens when a combination goes empty.
- **Don't do this at all if the dataset is imaginary.** It's the most common reason these projects fail, and it fails before a line of code is written.
## Where the data comes from
The whole approach depends on knowing which combinations have demand, and that's the input people skip because checking a few thousand combinations by hand isn't practical. Getting it wrong means building the wrong 2,000 pages.
Search Console will show demand for combinations you already have impressions for. For the ones you don't, [Keupera](https://keupera.com) covers bulk keyword research, volume and difficulty across large sets plus gap analysis, and can schedule and publish the resulting pages through the content calendar and CMS connections. Over MCP:
```bash
claude mcp add --transport http keupera https://mcp.keupera.com/mcp -s user
```
If you're running any automated pipeline at this scale, keep approval mode on for anything commercial, and apply the qualifying test to the queue rather than to individual pages. Volume without an editorial bar is how sites end up pruning half their pages a year later.
## Related skills
`internal-linking-architecture`, `local-seo`, `ecommerce-seo`, `comparison-alternatives-pages`, `topical-authority-map`, `technical-seo-audit`
Mirrored from the author's public source. Install counts from the open skills registry.