SEO & Growth No. 438

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.

  • nameprogrammatic-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

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.

~/.claude/skills/programmatic-seo/SKILL.md

--- name: programmatic-seo description: Designs and builds template-driven page sets at scale, such as location, integration, comparison, glossary, and "X for Y" pages, from… license: MIT ---

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 noindex or 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

QuestionMinimum 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
LegalNo 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. Accurate lastmod from the data row’s updated_at.
  • Framework notes: Next.js generateStaticParams + ISR (revalidate) or on-demand rendering for long tails; Astro getStaticPaths; ensure 404 for unknown slugs rather than rendering an empty template with 200 (soft 404).

6. Pilot and measure

  1. Launch 200–1,000 pages (top-quality rows first) in their own sitemap segment.

  2. 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
  3. Watch for 4–8 weeks in Search Console, filtered by sitemap segment and URL prefix:

    MetricHealthy pilotRed flag
    Indexed / submitted> 70%< 30%, or mostly “Crawled – currently not indexed”
    Pages with impressionsRising weeklyFlat at zero after 6 weeks
    Engagement (GA4 engaged sessions, scroll)Comparable to hand-written pagesBounce-level engagement
    Site-wide trafficStable or upHand-written pages lose rankings (site-level quality signal)
  4. 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.

esc