Programmatic SEO skill for Claude Code
Thousands of pages, each one worth indexing. Claude treats the dataset and the quality gate as the product, not the template. It validates that a page pattern matches real SERPs, measures per-page uniqueness instead of swapping variables into boilerplate, computes index, noindex, or skip per row at build time, and pilots a few hundred pages in their own sitemap segment before scaling, keeping clear of Google's scaled content abuse policy.
- name
programmatic-seo - size178 lines · ≈2,200 tokens
- files1
- licenseMIT
- updated
What Claude sees before loading it
This description is the only part of the skill that sits in context all the time. Claude reads it to decide when to load the full playbook below.
description: Designs and builds template-driven page sets at scale, such as location, integration, comparison, glossary, and "X for Y" pages, from structured data while avoiding thin and scaled-content-abuse patterns. Covers data sourcing, per-page uniqueness thresholds, quality gates that decide index vs. noindex, sitemap segmentation, internal linking, and staged rollout measured in Search Console. Use when generating hundreds or thousands of landing pages, when programmatic pages are stuck in "Discovered - currently not indexed", or when planning a pSEO project. Try asking
- Plan programmatic pages for every integration pair in our catalog without getting hit as thin content
- We launched 8,000 city pages and 90% are 'Discovered - currently not indexed'. What now?
- Build the Next.js template and index rules for our {role} salary in {city} pages
Use it when
- Generating hundreds or thousands of pages from structured data
- Programmatic pages are not getting indexed or are losing traffic
- Deciding whether a templated page pattern is worth building
- Setting index/noindex rules and sitemap segments for a large page set
Skip it when
- You are writing a handful of hand-crafted pages — use seo-content-briefs
- Indexing problems are site-wide, not template-specific — use technical-seo
How to check the result
Sampled sibling pages differ by more than half of their main content, gate rules are computed in code, and the pilot segment holds above 70% indexed in Search Console before scaling.
The common mistake it prevents
Launching every combination of city and service at once with identical boilerplate, which triggers scaled-content signals that can drag down the whole site.
Done well means every generated page answers a real query with data a visitor cannot get faster elsewhere, pages that lack enough data are never indexed, and the rollout is staged so indexation and traffic per template are measured before scaling. The template is the easy part; the dataset and the quality gate are the product.
Ground rules
- Google’s scaled content abuse policy targets pages generated at scale primarily to manipulate rankings with little value — regardless of whether humans, templates, or AI produce them. Variable-swapping (“Best plumber in {city}”) with identical body text is exactly that pattern.
- Only build a page type if (a) searchers use the pattern with measurable demand, and (b) you own or can license data that makes each page materially different.
- Every page must pass a quality gate before it is indexable. Failing pages get
noindexor are not generated — never “publish now, improve later” at scale. - Launch in batches. Never push 50,000 URLs live in one deploy on a site without established crawl demand.
- Generated AI text is filler unless grounded in per-page data. Do not use an LLM to paraphrase the same paragraph N ways to dodge duplicate detection.
Workflow
- [ ] 1. Validate the pattern (demand + SERP fit)
- [ ] 2. Audit the dataset (coverage, freshness, rights)
- [ ] 3. Design the page: unique modules per entity
- [ ] 4. Define the quality gate and index rules
- [ ] 5. Build URLs, internal links, and sitemaps
- [ ] 6. Pilot a batch and measure
- [ ] 7. Scale, monitor, prune
1. Validate the pattern
- Express the pattern as
{head term} {modifier}(e.g.{tool} integration with {tool},{role} salary in {city},{currency A} to {currency B}). - Pull volume for a sample of 30–50 concrete instances across head, mid, and long tail
(use
keyword-research). Many instances show zero volume individually; that is fine if the aggregate is real and the SERP for sampled instances shows template-style pages ranking. - Open 10 sampled SERPs. If they show forums, editorial guides, or a single dominant tool, a templated page will not fit the intent — stop or change the page type.
2. Audit the dataset
| Question | Minimum bar |
|---|---|
| What fraction of entities have enough fields to fill the unique modules? | Index only that fraction; target ≥ 60% coverage before building |
| Where does it come from? | Own product data, first-party usage stats, licensed APIs, public data with license that permits reuse |
| How fresh is it? | Update cadence stated on page; stale data is a quality issue |
| Is it proprietary? | Data only you have (usage counts, prices you observe, reviews you collect) is the moat |
| Legal | No scraped content from sites whose terms forbid it; no copied reviews or descriptions |
Store it in a typed table (DB, CSV in repo, or headless CMS) with a quality_score and
indexable flag computed per row, not decided in the template.
3. Design for per-page uniqueness
Each page needs modules whose content changes with the entity. Strong modules:
- Entity-specific numbers: prices, counts, rankings, distances, dates, comparisons with neighbours (“23% cheaper than the state median”).
- Tables or charts generated from real rows.
- Use-case content written per entity category by a human (not per page) and selected by attributes.
- First-party UGC: reviews, Q&A, templates, examples for that entity.
- Media: screenshots, maps, product images specific to the entity.
- Links to related entities chosen by similarity, not random.
Weak modules (do not count toward uniqueness): swapped name in a boilerplate paragraph, generic FAQ, the same “why choose us” block.
Rule of thumb to enforce in code: at least ~50% of the main-content text (excluding nav, header, footer) differs between any two sibling pages, and each page has at least 3 populated data modules. Measure it (step 6), do not assume it.
4. Quality gate and index rules
Compute per page at build time:
type PageData = { listings: number; reviews: number; fieldsFilled: number; fieldsTotal: number; updatedAt: Date };
export function indexDecision(d: PageData): "index" | "noindex" | "skip" {
const completeness = d.fieldsFilled / d.fieldsTotal;
const ageDays = (Date.now() - d.updatedAt.getTime()) / 86_400_000;
if (d.listings === 0 && d.reviews === 0) return "skip"; // do not generate
if (completeness < 0.6 || d.listings < 3 || ageDays > 180) return "noindex";
return "index";
}
skip→ no page, links point to the parent hub instead; requests return 404.noindex→ page may exist for users (e.g. internal navigation) with<meta name="robots" content="noindex,follow">, excluded from sitemaps.index→ self-canonical, in sitemap, linked from hubs.- Near-duplicates (e.g.
{A} vs {B}and{B} vs {A}): generate one, 301 the other to it. - Thresholds are project-specific; pick them from the pilot data, then write them down.
5. URLs, linking, sitemaps
- URL pattern stable and readable:
/integrations/slack/,/salaries/data-engineer/austin/. Never encode filters as query strings for indexable pages. - Hub hierarchy: root hub → category hubs → entity pages; every indexable page reachable in ≤ 3 clicks through HTML links. Hubs must be useful pages (sortable tables, maps), not link dumps.
- Cross-links between siblings by relevance (nearby cities, alternative tools), capped at ~10–20 per page.
- Segment sitemaps by template and batch (
sitemap-integrations-1.xml, …) so Search Console shows indexation per segment. Accuratelastmodfrom the data row’supdated_at. - Framework notes: Next.js
generateStaticParams+ ISR (revalidate) or on-demand rendering for long tails; AstrogetStaticPaths; ensure 404 for unknown slugs rather than rendering an empty template with 200 (soft 404).
6. Pilot and measure
-
Launch 200–1,000 pages (top-quality rows first) in their own sitemap segment.
-
Run the uniqueness check: sample 50 sibling pairs, extract main content, compare.
import difflib ratio = difflib.SequenceMatcher(None, text_a, text_b).ratio() # flag pairs with ratio > 0.5 -
Watch for 4–8 weeks in Search Console, filtered by sitemap segment and URL prefix:
Metric Healthy pilot Red flag Indexed / submitted > 70% < 30%, or mostly “Crawled – currently not indexed” Pages with impressions Rising weekly Flat at zero after 6 weeks Engagement (GA4 engaged sessions, scroll) Comparable to hand-written pages Bounce-level engagement Site-wide traffic Stable or up Hand-written pages lose rankings (site-level quality signal) -
If red flags: improve the data modules or tighten the gate. Do not add more pages.
7. Scale, monitor, prune
- Release in batches (e.g. 2–5x the previous batch) only while indexation ratio holds.
- Re-evaluate the gate on every data refresh: pages can move between index and noindex.
- Quarterly prune: pages with zero impressions over 6 months and no conversions →
improve, merge into hub, or
noindex/410. Confirm with the user before mass removal.
Gotchas
- A site-wide quality signal exists: thousands of thin pages can drag down rankings of the good pages too. The pilot must watch the rest of the site.
- “Discovered – currently not indexed” at scale means Google does not think the URLs are worth crawling yet. Fix internal linking and quality; resubmitting sitemaps does nothing.
- Combinatorial explosion (
{service} × {city} × {modifier}) creates millions of URLs with no data. Index the cross-product only where both dimensions have data and demand. - Hosting or buying pages on a strong third-party domain to exploit its ranking signals is site reputation abuse; do not propose it.
- Location pages for places without a real presence are doorway pages.
- Client-rendered templates that fetch data in the browser often index as empty shells. Render data into HTML on the server.
- Keep templates accessible and fast; INP and LCP problems multiply across every page.
Output: pSEO plan
## Pattern: {tool} integrations with {tool}
- Demand sample: 40 instances, aggregate ~18k/mo; SERP fit: 8/10 sampled SERPs show integration pages
- Dataset: product integration catalog (first-party), 1,240 pairs; 61% pass the gate
- Unique modules: setup steps (per pair), usage stats (first-party), trigger/action table, related pairs
- Gate: completeness ≥ 0.6 AND ≥ 3 documented triggers → index; else noindex; zero data → skip
- URLs: /integrations/{a}/{b}/ ; reverse pairs 301 to canonical order
- Pilot: top 300 pairs, sitemap-integrations-1.xml; success = ≥ 70% indexed and impressions growing by week 6
- Risks: thin long tail, reverse-pair duplicates, client-side data fetch About this skill
Written and maintained by the Claude Skills editors to the same editorial standard as every skill in the directory: a selective trigger, a real workflow, known pitfalls and a verification step. First published , last updated . MIT licensed.