Frogpost
Guide

Programmatic SEO: a practical guide for headless CMS sites

Programmatic SEO means publishing many pages from one repeatable pattern, each aimed at a query people actually type. Done well, it is how a small team covers hundreds of real searches. Done badly, it is thousands of near-identical pages Google crawls once and never shows. This guide covers the two ways to do it, how to check demand first, and how to build it on a headless CMS like Contentful.

Updated

What programmatic SEO is

Most sites grow page by page: someone decides on a topic, writes it, and publishes it. Programmatic SEO starts from a pattern instead. You notice that people search a family of similar queries, like "[tool] Slack integration", "[city] coworking spaces", or "how to [task] in [product]", and you publish one page for each member of the family from a shared structure.

The pattern is what makes it efficient. The inputs are what make it work. Each page needs facts of its own that answer its query better than a generic page would. Without that, you have one page repeated a thousand times, and search engines treat it that way.

The two shapes: templates and article queues

Almost every programmatic SEO project is one of two things, and choosing the wrong one is the most expensive mistake you can make.

Template pages compared with an article queue
Template pagesArticle queue
Unit of workA row of dataA topic
Typical query"Stripe to Notion integration", "coworking in Lisbon""how to structure a blog content model", "headless CMS SEO checklist"
What makes each page uniqueIts own data: prices, specs, steps, locations, reviewsIts own explanation, examples and advice
Where the content comes fromA database or a CMS content typeA writer, human or AI, working from a brief
How many pagesHundreds to thousandsTens to hundreds
Main riskPages that differ by one wordPosts that are generic or off topic

A simple test decides it. Take one query from the family and imagine the best possible page for it. If that page is mostly structured facts that vary from row to row, it is a template. If it is mostly explanation that would have to be written differently each time, it is an article.

Common patterns, and what each page needs

Programmatic SEO patterns
PatternExample queryWhat each page needs to be worth opening
Integrations"[your product] + [tool]"What the integration does, the setup steps, the data that syncs, limits
Comparisons"[product A] vs [product B]"A real feature and pricing comparison, and who each one is for
Alternatives"[competitor] alternatives"Why people leave that product, and specific options for each reason
Locations"[service] in [city]"Local providers, prices, availability, and anything that differs by place
Templates"[document type] template"The template itself, a preview, and guidance on filling it in
Glossary"what is [term]"A clear definition, an example, and how the term is used in your field
How-to questions"how to [task] in [product]"Working steps for that exact task, with the settings named

Integrations, comparisons, locations and templates are almost always template pages. Glossaries sit in between. How-to questions and anything that needs judgment are usually better as articles.

Step 1: check demand before you build anything

A pattern is only worth building if people search it. This is where most projects should stop and do not, because the template is more fun to build than the spreadsheet is to fill.

Use Keyword Planner, and read the ranges correctly

Google Keyword Planner is free with a Google Ads account, and you do not have to run a campaign. Paste 10 to 20 real members of the family, not just the head term. Until an account has spent money, Planner shows buckets rather than exact numbers: 0, 50, 500, 5,000. A pattern where every variant shows 50 can still add up across hundreds of pages. A pattern where most variants come back blank has no demand, however logical it looks.

Check for searches that are really about something else

Some patterns look popular because a different meaning dominates. A query that shares a word with a technical term, a brand, or a famous product can show volume that has nothing to do with you. Search each head term yourself and read the first page of results. If none of them are the kind of page you plan to build, the volume belongs to someone else.

Use what you already rank for

If your site is live, the Performance report in Google Search Console shows the queries you already appear for. Families of queries you show up for with no dedicated page are the safest place to start, because Google already connects you with them.

Step 2: decide what makes each page worth opening

Google's spam policies name scaled content abuse: many pages generated primarily to manipulate search rankings instead of helping people, whether they are produced by automation, by people, or both. The method is not the problem. The sameness is.

Before you build, write down the fields that will differ on every page. For an integration page that might be the setup steps, the objects that sync, the trigger options and the plan it requires. If the only field that changes is the name in the heading, do not build the pattern. If you cannot get the data, do not build it yet.

  • Would this page still be useful if you deleted the keyword from the heading?
  • Does it answer the exact query better than your homepage does?
  • Would you link a customer to it?
  • Are at least half of the words on it specific to this page?

Step 3: model it in Contentful and render it in your front end

On a headless CMS, template pages split cleanly in two. Contentful holds the data, one entry per page. Your front end holds the template, one route for every entry.

For an integrations directory, the content type might be integration with a name, a slug, a logo, a short description, a list of use cases, setup steps as rich text, and references to related integrations. Those references matter later, because they become the links between pages.

app/integrations/[slug]/page.js in Next.js
import { createClient } from 'contentful';
import { notFound } from 'next/navigation';

const client = createClient({
  space: process.env.CONTENTFUL_SPACE_ID,
  accessToken: process.env.CONTENTFUL_DELIVERY_TOKEN,
});

const getIntegration = async (slug) => {
  const { items } = await client.getEntries({
    content_type: 'integration',
    'fields.slug': slug,
    limit: 1,
  });
  return items[0] ?? null;
};

export async function generateStaticParams() {
  const { items } = await client.getEntries({
    content_type: 'integration',
    select: ['fields.slug'],
    limit: 1000,
  });
  return items.map(item => ({ slug: item.fields.slug }));
}

export async function generateMetadata({ params }) {
  const { slug } = await params;
  const integration = await getIntegration(slug);
  if (!integration) return {};
  return {
    title: `${integration.fields.name} integration`,
    description: integration.fields.description,
  };
}

export default async function IntegrationPage({ params }) {
  const { slug } = await params;
  const integration = await getIntegration(slug);
  if (!integration) notFound();
  // Render name, use cases, setup steps and related integrations here.
}

Add a webhook in Contentful on Entry publish that revalidates the route, and a new entry becomes a live page without a deploy. Include every route in your sitemap, generated from the same query.

Step 5: launch small and watch indexing

Publish your strongest 20 to 50 pages first, with the richest data and the clearest demand. Submit the sitemap in Search Console and watch the Page indexing report for the next few weeks.

Search Console statuses worth knowing
StatusWhat it usually means
Discovered, currently not indexedGoogle knows the URL but has not crawled it yet. Common on new sites. Better internal links and patience help.
Crawled, currently not indexedGoogle read the page and chose not to index it. On programmatic pages this is usually a quality signal: the pages are too similar or too thin.
Duplicate without user-selected canonicalGoogle considers the page a copy of another one. Pages differ too little, or canonicals are missing.

If most of the first batch lands in "crawled, currently not indexed", publishing the next thousand will not help. Fix the template or the data first.

Step 6: measure, then improve or prune

In the Performance report, filter by URL prefix, such as /integrations/, to see the whole pattern at once. Give it eight to twelve weeks. Pages with impressions but few clicks usually need a better title and meta description. Pages with no impressions at all either target a query nobody searches, or are not indexed. Improve them, merge them into a stronger page, or remove them. A smaller set of pages that all earn impressions beats a large set that mostly does not.

Where Frogpost fits

Frogpost is the article queue, for Contentful. You add topics, and each one becomes a post of at least 1,500 words with its own headings, SEO title and meta description, written from what your website says about your product. It is created as a Contentful entry in your blog content type, with images uploaded as assets and links to your earlier posts. You can keep posts as drafts, or publish a queue on a schedule.

It does not build template pages from a dataset. If your pattern is integrations, locations or comparisons, build the template in your front end as above, and use Frogpost for the articles that sit around it: the guides and how-to posts that link into those pages and give them context.

Mistakes that sink programmatic SEO projects

  • Building the template before checking that the pattern is searched.
  • Launching thousands of pages at once, so a quality problem affects all of them.
  • Pages that differ only by the keyword in the heading and the title tag.
  • No hub pages and no links between neighbours, so most pages are orphans.
  • Leaving pages with no impressions live for a year instead of improving or removing them.
  • Using a data template for queries that need an explanation, or articles for queries that need data.

Questions

What is programmatic SEO?
Publishing many pages from one repeatable pattern, each aimed at its own search query. The pattern is usually a template filled from a dataset, such as one page per integration or per city, or a queue of articles written from a list of topics.
Is programmatic SEO against Google guidelines?
Not in itself. Google targets scaled content abuse, meaning many pages produced mainly to manipulate rankings rather than to help people, whether they are made by automation, by people, or both. Pages that each answer their query with facts of their own are ordinary content published at scale.
How many pages should I launch with?
Start with the 20 to 50 pages with the clearest demand and the richest data. Watch how many get indexed and whether they earn impressions in Search Console before you publish the rest. Launching thousands of thin pages at once is the most common way to get most of them ignored.
Can I do programmatic SEO with Contentful?
Yes. Model each entity as a content type, keep one entry per page, and let your front end generate a route for every entry. Contentful holds the data and your framework renders the template.
Is a blog queue programmatic SEO?
It is the article form of it. Each topic becomes its own post with its own structure, published on a schedule. It suits queries that need explanation, where a data template would produce the same paragraph with one word swapped.
Can Frogpost generate programmatic landing pages?
No. Frogpost writes SEO blog posts and publishes them to Contentful. Template pages built from a dataset belong in your front end, with the data in Contentful.

Connect Contentful and publish the first post free

Free includes 3 posts a month. Pro is $10 a month.