Programmatic SEO
Programmatic SEO (pSEO) generates large numbers of pages from structured data + templates: every city × service, every integration pair ("Connect X to Y"), every comparison, every entity in a dataset. Done right it captures long-tail demand no hand-written content could economically reach (Zapier, Tripadvisor, Zillow are the canonical examples). Done wrong, it's the textbook definition of what Google's scaled content abuse policy targets.
The qualifying questions#
Before building, all four must be "yes":
- Does query demand exist at the pattern level?
weather in {city},{tool} vs {tool}- validate with keyword research that the pattern has volume across many values, even if each page's volume is tiny. - Do you have unique data per page? Real values per entity - prices, specs, reviews, availability, measurements. If every page is the same sentence with a swapped noun, stop.
- Does each page satisfy its query alone? A user landing on "best coworking spaces in Lisbon" must get a genuinely useful answer, not a template skeleton.
- Can you maintain it? Stale programmatic data at scale (closed businesses, old prices) becomes a quality liability.
Architecture in Next.js#
The standard build: a data source, a dynamic route, generateStaticParams for pregeneration, and per-page metadata.
import type { Metadata } from "next";
import { notFound } from "next/navigation";
import { getCities, getCityData } from "@/lib/coworking";
export async function generateStaticParams() {
const cities = await getCities();
return cities.map((city) => ({ city: city.slug }));
}
export async function generateMetadata({
params,
}: PageProps<"/coworking/[city]">): Promise<Metadata> {
const { city } = await params;
const data = await getCityData(city);
if (!data) return {};
return {
title: `${data.spaceCount} Best Coworking Spaces in ${data.name} (${data.year})`,
description: `Compared on price, wifi speed and amenities - day passes from ${data.minPrice}.`,
alternates: { canonical: `https://example.com/coworking/${city}` },
};
}
export default async function CityPage({ params }: PageProps<"/coworking/[city]">) {
const { city } = await params;
const data = await getCityData(city);
if (!data || data.spaceCount < 3) notFound(); // quality gate: thin pages don't ship
return <CityGuide data={data} />;
}Implementation notes:
- Quality-gate in code. The
notFound()on insufficient data is the most important line - it enforces "no thin pages" structurally rather than editorially. - SSG/ISR over SSR - pregenerated pages give the TTFB and LCP profile thousands of pages need, and
revalidatekeeps data fresh. - Vary the template genuinely: conditional sections based on what data exists per entity, so pages differ in structure, not just nouns.
Template design for value density#
Each page should lead with the unique data, not boilerplate:
- Above the fold: the entity-specific answer - the table, the map, the number
- Comparative context: how this entity ranks among its siblings ("3rd cheapest of 41")
- Structured data matching the entity type (
Product,LocalBusiness,FAQPagewith entity-specific questions) - Hand-written framing where it counts: intro paragraphs for the top-traffic pages; the head of the long tail deserves human attention
Internal linking at scale#
Thousands of pages need systematic discovery paths (architecture principles):
- Hub indexes with pagination (country → cities; category → entities)
- Sibling links ("nearby cities", "similar tools") - algorithmic but capped and relevant
- Breadcrumbs everywhere
- Sitemaps segmented by section (
/sitemaps/coworking.xml) so you can monitor indexation per pattern in GSC
Rollout and monitoring#
Launch in tranches, not all at once: ship a few hundred pages, watch GSC indexation ("Crawled - currently not indexed" at scale = quality verdict), iterate on the template, then expand. Track per-pattern: indexation rate, impressions/clicks, and engagement. Patterns that never index or never earn clicks get improved or pruned - maintenance discipline applies double at scale.
Next: Site Migrations - the highest-stakes operation in technical SEO.
