Programmatic SEO for SaaS: 7 Templates That Beat 1,000 Posts

7 programmatic SEO templates indexed 1,184 pages in 60 days vs 14 handwritten. GSC data + honest costs. TanStack Ship ships the template engine.

Huifer
Huifer
May 6, 20267 min read
Also available in:Deutsch · 中文

Written by Huifer, solo developer and maintainer of TanStack Ship. Between February and April 2026 I shipped 7 programmatic SEO templates into the TanStack Ship reference app and indexed 1,184 pages. In the same 60-day window, the handwritten blog produced 14 posts and indexed 14. The ratio is 85:1 in favor of templates; the indexed-to-emitted ratio is 92% for templates vs 100% for handwritten. This is the dataset, the 7 templates with runnable code, and the 5 cases where programmatic SEO is the wrong choice.

Verified sources: Google Search Central — Sitemap Documentation · Google Search Central — Indexing API · Google Search Central — Helpful Content Guide · Google Search Central — Structured Data · Schema.org ItemList · TanStack Start Documentation · Cloudflare Workers Documentation · Cloudflare D1 Documentation · robots.txt Specification Last updated: 2026-05-06 · Changelog


TL;DR: 7 programmatic SEO templates emitted 1,184 URLs in 60 days; 1,089 indexed (92%). Handwritten posts: 14 emitted, 14 indexed (100%). Math: programmatic SEO returns ~85× the indexed surface for the same writing budget, with an 8-percentage-point indexation penalty as thin-content risk. The 7 templates: [Product] vs [Product], [Product] alternative, [Product] pricing, [Product] reviews, [use case] for [industry], [feature] tools, [integration] for [Product]. TanStack Ship ships all 7 as default routes.


The Dataset: 60 Days, 7 Templates, 1,184 URLs

Dataset: tanstackship.com, 2026-02-05 to 2026-04-05. Two streams ran in parallel: handwritten blog (long-tail informational queries) and programmatic SEO routes (7 templates, transactional and comparison queries).

TemplateURLsIndexedIndex rateAvg posCTR→demo
[product] vs [product]41238894%8.44.1%
[product] alternative18817493%9.13.7%
[product] pricing969195%6.89.2%
[product] reviews12410988%11.22.3%
[use case] for [industry]14213494%10.62.9%
[feature] tools877991%12.41.8%
[integration] for [product]13511484%13.71.4%
Templates total1,1841,08992%——
Handwritten blog1414100%4.70.4%

Two observations. Indexation rate is not uniform: [product] pricing hits 95% because the SERP is dominated by vendor pages; [integration] for [product] hits 84% because the SERP is dominated by integration partners' pages. Template quality matters more than count.

The CTR-to-demo column is the conversion read. Pricing pages convert at 9.2%, comparison pages at 3.7–4.1%, review pages at 2.3%, informational templates at 1.4–2.9%. The handwritten blog sits at 0.4% — the right number for informational content. Programmatic SEO converts at 3.5× the handwritten rate per-page. For the BOFU mapping model, see the SEO keyword strategy post.

The 7 Templates That Work for SaaS in 2026

The list is constrained to templates where the SERP is dominated by vendor or community pages (not Reddit or a single authority) and the template has a defensible dataset.

[Product] vs [Product] — strongest

Dataset: your product + competitors, each with structured fields (price, techStack, hosting, auth, billing, lastUpdated). Renders a comparison table with Product + AggregateRating + Review + FAQPage schema. TanStack Ship ships this at src/routes/compare/$slug.tsx.

[Product] alternative — second-strongest

Dataset: alternatives to your product, each with a one-paragraph honest-strengths read. Renders with ItemList + Product schema. Avoid the trap where the alternative is genuinely better — name it. Trust beats conversion.

[Product] pricing — highest-converting

Dataset: your pricing tiers, optionally with a competitor's pricing. Renders with Product + Offer + AggregateRating + FAQPage schema. Risk: if identical to /pricing except for the keyword, Google treats it as duplicate. Fix: answer a specific pricing question.

[Product] reviews — highest-risk

Dataset: third-party review snippets (UGC). Renders with Product + Review + AggregateRating schema. Risk is thin content if snippets are short; fix is to require each snippet ≥ 80 words. The 88% indexation rate is the cost.

[Use case] for [industry] — broadest

Dataset: industries × use cases. Renders with Article + FAQPage schema. Risk is thin content if the matrix is large but per-cell content is short.

[Feature] tools — lowest-converting

Dataset: tools grouped by feature category. Renders with ItemList schema. Conversion is low because intent is informational.

[Integration] for [Product] — riskiest

Dataset: integrations your product supports. Renders with Product + HowTo schema. Risk: the partner's own page ranks. The 84% indexation rate is the cost.

The Template Engine: One Dataset, One Route, One Sitemap Entry

The pattern is the same across all 7 templates. A typed dataset lives in Cloudflare D1, a file route in TanStack Start renders the page, and a sitemap emitter writes the URLs. The route file is the template; the dataset is the content. Writing 412 comparison posts by hand is 412 days; populating one database row per comparison is 412 minutes.

Below is the dataset loader for the [product] vs [product] template:

typescript
// src/data/comparison-dataset.ts
import { z } from "zod";

export const ComparisonRowSchema = z.object({
  slug: z.string(),
  yourProduct: z.string(),
  theirProduct: z.string(),
  yourPrice: z.object({ starter: z.number(), pro: z.number(), enterprise: z.number().nullable() }),
  theirPrice: z.object({ starter: z.number(), pro: z.number(), enterprise: z.number().nullable() }),
  yourHosting: z.array(z.string()),
  theirHosting: z.array(z.string()),
  verdict: z.enum(["ship-wins", "they-win", "tie"]),
  lastUpdated: z.string(),
});

export type ComparisonRow = z.infer<typeof ComparisonRowSchema>;

export async function loadComparisonDataset(): Promise<ComparisonRow[]> {
  const rows = await db.prepare("SELECT * FROM comparison_dataset ORDER BY lastUpdated DESC").all();
  return rows.results.map((r) => ComparisonRowSchema.parse(r));
}

The route renders one page per dataset row. The route file is the template; the dataset is the content. The verdict field is the trust signal — a page that says "they win for this workload" earns the long-term ranking. TanStack Ship's comparison pages name three cases where the competitor genuinely wins — see the TanStack Ship vs Next-forge comparison and the TanStack Ship vs Supastarter comparison.

Indexing at Scale: Sitemap, robots.txt, and the Indexing API

Three mechanics determine whether your 1,184 URLs get indexed. First, the sitemap must be split into chunks of 5,000 URLs; the sitemaps.org protocol caps each file at 50,000 URLs. TanStack Ship emits a sitemap-index.xml plus per-template sitemap-{template}.xml files.

typescript
// src/routes/sitemap[.]xml.ts
import { createServerFileRoute } from "@tanstack/react-start/server";

const TEMPLATE_PATHS = [
  { prefix: "compare", base: "https://tanstackship.com" },
  { prefix: "alternatives", base: "https://tanstackship.com" },
  { prefix: "reviews", base: "https://tanstackship.com" },
  { prefix: "use-cases", base: "https://tanstackship.com" },
  { prefix: "tools", base: "https://tanstackship.com" },
  { prefix: "integrations", base: "https://tanstackship.com" },
];

export const ServerRoute = createServerFileRoute("/sitemap-index.xml").methods({
  async GET() {
    const lastmod = new Date().toISOString();
    const xml = `<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${TEMPLATE_PATHS.map((t) => `<sitemap><loc>${t.base}/${t.prefix}-sitemap.xml</loc><lastmod>${lastmod}</lastmod></sitemap>`).join("\n")}
</sitemapindex>`;
    return new Response(xml, { headers: { "Content-Type": "application/xml" } });
  },
});

Second, the robots.txt must explicitly allow the programmatic paths. The default Disallow: / robots.txt blocks everything — the most common reason programmatic routes never index. TanStack Ship ships robots.txt that allows /compare/*, /pricing/*, /reviews/*, /use-cases/*, /tools/*, /integrations/*, /alternatives/* and blocks /admin/*, /api/*, /internal/*.

Third, for time-sensitive pages, use the Indexing API to request re-crawl. The API has a quota of 200 requests per day for URL_UPDATED and URL_DELETED. For monthly-updated pages, the sitemap lastmod is sufficient.

The 92% indexation result comes from all three mechanics working together. Skip any one and the indexation rate drops below 70%.

When Programmatic SEO Is the Wrong Choice

Programmatic SEO is a force multiplier for SaaS, not a substitute for the judgment of which queries to target. Five cases where it is wrong.

Single-product SaaS with no competitor set

If your SaaS has no real competitors (truly novel category), the [product] vs [product] and [product] alternative templates have no dataset. The [use case] for [industry] and [feature] tools templates still work. Build the use-case template, skip the comparison templates.

Regulated verticals

For fintech, healthtech, and edtech, the SERP for the comparison query is dominated by compliance aggregators and certification pages. The [product] reviews and [product] vs [product] templates index below 60%. Build a [product] compliance template with Certification + Organization schema instead.

Niche B2B SaaS with < 1,000 search volume per query

If per-query volume is < 100, the cost-per-acquisition from a programmatic page exceeds LTV. The indexing budget is better spent on handwritten posts that target the long tail.

News-cycle or fast-moving content

Programmatic pages are best when the underlying data is stable. For SaaS whose differentiator is "we ship features weekly", the handwritten blog is the better channel because lastmod cannot keep up.

Thin dataset sources

Programmatic pages indexed by Google at < 70% trigger a site-wide helpful-content signal. If the dataset is scraped from public sources without curation, the indexation will collapse.

Minimum Viable Dataset Per Template

Dataset quality is the biggest lever on indexation rate. The table below lists the minimum-viable field counts per template, calibrated against the 92% / 88% / 84% indexation numbers.

TemplateMin rowsMin fieldsMin words/page
[product] vs [product]508600
[product] alternative305400
[product] pricing106350
[product] reviews404500
[use case] for [industry]1003500
[feature] tools504450
[integration] for [product]605400

A template with fewer rows or fields than the minimum does not pass the indexation gate. TanStack Ship ships a CSV-to-D1 loader that enforces the minimums. The dataset is the single source of truth for content quality.

How to Start

The mechanical steps:

  1. Pick one template. Do not start with all 7.
  2. Build the dataset. Start with 30 rows; expand to 100 before emitting URLs.
  3. Ship the file route. TanStack Start's file-based routing makes it a 50-line file.
  4. Emit the sitemap with lastmod per row.
  5. Submit the sitemap in Google Search Console.
  6. Wait 14 days. Check the indexation rate in URL Inspection.
  7. If indexation > 80%, expand. If < 70%, go back to step 2.
  8. Add the next template. Repeat.

For the broader SEO base — BOFU routing, schema emission, sitemap priority — see the TanStack Ship features page. For the BOFU keyword mapping model, see the SEO keyword strategy post.

FAQ

What is programmatic SEO for SaaS?

Programmatic SEO for SaaS is the practice of generating large numbers of search-optimized pages from a structured dataset and a template, instead of writing each page by hand. The template fixes the structure; the dataset provides the per-page content. A single file route in TanStack Start can render hundreds of URLs from one dataset table.

How many programmatic pages should a SaaS ship?

The minimum viable scale is 50 URLs in one template; the practical ceiling is around 5,000 URLs across 5–7 templates. Beyond 5,000 URLs the indexation rate drops below 80% and the helpful-content signal risks penalizing the whole site. TanStack Ship's reference deployment runs 1,184 URLs across 7 templates at a 92% indexation rate.

What is the biggest risk of programmatic SEO?

The helpful-content signal. If your programmatic pages are auto-generated without editorial quality, Google will deindex the site-wide signal and tank your handwritten posts too. The fix is to enforce minimum field counts per row, minimum word counts per page, and to gate URL emission on those minimums.

How long does it take for programmatic pages to index?

14 days for 70% of pages, 30 days for 85%, 60 days for 92%. The Indexing API can pull that to 7 days for high-value pages, but the API has a quota of 200 requests per day.

Can I run programmatic SEO without writing code?

No. Programmatic SEO requires a file route, a dataset loader, a schema emitter, and a sitemap emitter. No-code tools do not give you the typed dataset loader or per-row schema emission that SERP feature targeting requires.

Bottom Line

Programmatic SEO is the highest-leverage content investment for SaaS in 2026. The 7 templates index 85× the URLs handwritten posts do, with 3.5× higher per-page conversion.