seo101

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":

  1. 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.
  2. 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.
  3. 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.
  4. 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.

app/coworking/[city]/page.tsx
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 revalidate keeps 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, FAQPage with 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.