Skip to content

field note

Programmatic SEO in WordPress: the gates I run before generating a single page

WordPress

Shahid AliSeptember 13, 2026all posts

Programmatic SEO in WordPress: the gates I run before generating a single page

On 7 September, John Mueller answered a site owner on Bluesky whose site iterated through “a large list of domain names, technologies, and attributes - finding all possible combinations”. His verdict on the pattern: programmatic SEO like this “often leads to a site that’s either spam, borderline spam, or low quality”, and “our systems have possibly lost faith in your site providing good value to users based on the old pages.”

Read that last sentence again, because it is the expensive one. The generated pages you shipped last year are the evidence Google is judging your new pages by. I wrote about whether programmatic SEO is bad in general; this post is the WordPress-specific version, because WordPress is where most of these rollouts happen and where every tutorial stops one step too early.

Search “programmatic SEO WordPress” and the ranking guides will teach you the machinery: a custom post type, ACF fields, WP All Import, a template, a CSV, generate. I read the top guides for this post and not one of them tells you what to check in Search Console afterwards, or what has to be true of the data before you press generate. They teach generation. Indexing is treated as something that happens by itself. On generated page sets, it is the part that fails.

Gate 1: every row earns its page

Before anything is generated, the question is not “how many pages can the spreadsheet make” but “how many rows contain a fact a searcher cannot get from the template alone”. A page for each city you genuinely serve, with real coverage details, can clear that bar; I did the maths on a 90-page rollout in the service area post. City times service times adjective combinations do not clear it, and that pattern has a name in Google’s spam policies: doorway abuse when it targets near-identical queries, scaled content abuse when volume is the strategy. Mueller’s thread described exactly this failure: pages with “some” value, where “the overall picture is not that exciting”.

The practical rule I use: if two rows would produce pages whose only difference is the value swapped into the title and H1, delete one of them. Repeat until deleting hurts. Whatever count survives is your set, and it is usually a tenth of the spreadsheet.

Gate 2: the section gets its own sitemap

The one WordPress-specific decision that pays for itself all rollout long: register the generated post type with its own sitemap. Yoast, Rank Math and core’s wp-sitemap.xml all split sitemaps by post type, so this mostly means not fighting the default. Submit that sitemap separately in Search Console.

Now the Page indexing report can be filtered to the generated section alone, and the sitemap report shows discovered versus indexed for just those URLs. Without this you are reading blended numbers, and a generated section can rot for months inside a healthy-looking site total. Blended reporting is how sites end up with the index bloat I keep finding in audits: nobody was watching the one section that needed watching.

Gate 3: release in tranches, and watch two statuses

Publish a slice, not the set. Then watch two numbers weekly in the filtered report: Discovered, currently not indexed and Crawled, currently not indexed. They are different verdicts. Discovered rising means Google is not spending crawl on the section, which on a new set is often just queue time. Crawled rising is the one that should stop the rollout: Google fetched the pages and declined them. Generating more of a declined template is how the “old pages” in Mueller’s sentence get written.

The loop the tutorials skip

Gate 1 Cull the data: a page only for rows that hold a fact the template cannot fake Gate 2 Own sitemap for the generated post type, submitted on its own Gate 3 Publish one tranche, then read the filtered Page indexing report weekly

Discovered, currently not indexed climbing queue time; wait before judging Crawled, currently not indexed climbing stop generating; the template was declined Section still unindexed after the fix noindex or remove; old pages testify against new ones

Rollout loop from my own audits. The "lost faith" framing is from John Mueller's Bluesky thread of 7 September 2026, linked below.

The exit rule nobody writes down

Tutorials never include a deletion step, and it is the step Mueller’s thread makes unavoidable. If a tranche has sat crawled-and-declined through a fix cycle, the section does not get to stay published while you hope. Noindex it or remove it, and if it never earned crawling at all, removal with a 410 also stops it burning crawl budget that the rest of the site needs. Recovery from a devalued generated section, Mueller said plainly, “tends to take time & significant effort”, on the scale of recovering from spam and core updates. The cheap version of that effort is not shipping the section, or unshipping it early.

One honest caution about the location-page flavour of this, since that is the version WordPress agencies build most: the line between a real service area page and a doorway is the substance on the page, not the plugin that made it. I keep both halves of that argument in are location pages doorway pages.

If you are mid-rollout and the generated section’s numbers are going the wrong way, I audit exactly this pattern on WordPress sites. Send me the section’s sitemap URL, and the filtered report will tell us within a day whether you have a queue problem or a verdict.

Sources