Programmatic SEO in WordPress: a step-by-step build guide

Build programmatic SEO pages in WordPress step by step using ACF, WP All Import and MPG — from data source to thousands of indexed, ranking pages.

R
Rohit Verma
Technical SEO and content lead; focuses on keyword research, on-page and AI search (GEO).
Published 17 Jun 2026·8 min read

Programmatic SEO in WordPress means generating hundreds or thousands of targeted pages from a single template plus a structured dataset — all inside the CMS you already run. The working stack is Advanced Custom Fields (ACF) for the data slots, WP All Import or Multi-Page Generator (MPG) to load the rows, and one PHP template that renders them. This guide walks the whole build, from spreadsheet to indexed pages, and shows where these projects usually break.

If you're new to the concept, start with what programmatic SEO is and browse real programmatic SEO examples before you touch WordPress. The strategy decisions matter far more than the plugin choice.

What you need: dataset, template, generation plugin

Every programmatic build has exactly three ingredients. Get these right and the WordPress mechanics are easy.

  1. A dataset — one row per page, one column per variable. A CSV or Google Sheet with columns like city, avg_price, provider_count, top_neighbourhood. This is the hard part and the part that decides whether you rank. See building database-driven pages for how to model this properly.
  2. A page template — the shared HTML/PHP layout with placeholders where the row data drops in. One template can power 10,000 pages.
  3. A generation plugin — the tool that marries rows to the template and publishes them: WP All Import, MPG, or a custom loop.

Here's how the two main plugin paths compare.

Factor ACF + WP All Import Multi-Page Generator (MPG)
Best for Messy data, scheduled re-imports Clean data, fast one-off generation
Data source CSV, XML, Google Sheet, API CSV, Google Sheet
Creates real posts Yes (custom post type) Virtual pages by default
Per-row meta title/desc Via ACF + SEO plugin Built in
Spintax / variation Manual Built in
Re-sync on data change Excellent Good
Learning curve Medium Low

A common, robust setup is ACF for the fields, a custom post type to hold them, and WP All Import to load the CSV. MPG is the faster route when your data is already clean and you don't need each page to be a full WordPress post.

Setting up custom post types and ACF fields

Don't dump programmatic pages into your normal Posts or Pages. Register a custom post type (CPT) so the generated content stays isolated — separate template, separate sitemap rules, one-click bulk cleanup if a batch flops.

Register a CPT called, say, location:

register_post_type('location', [
  'label' => 'Locations',
  'public' => true,
  'has_archive' => true,
  'rewrite' => ['slug' => 'seo/plumbers'],
  'supports' => ['title', 'editor', 'custom-fields'],
]);

Use the WordPress Custom Post Types handbook or a plugin like CPT UI if you'd rather not write code.

Next, create an ACF field group and attach it to that post type. Add one field per data point in your spreadsheet: avg_price (number), provider_count (number), top_neighbourhood (text), intro_paragraph (textarea). These field names must match the column mapping you'll set up during import. The ACF documentation covers field types in detail.

A quick rule: if a data point should appear on the page or influence its meta tags, it needs an ACF field. The more real fields you carry, the easier it is to make each page genuinely unique — which is the whole game in avoiding thin content.

Importing data with WP All Import (CSV or Google Sheets)

This is where WP All Import earns its place. Install it, choose your source, and map columns to fields.

Step by step:

  1. New Import → upload your CSV, or paste a published Google Sheet CSV URL (File → Share → Publish to web → CSV). The Google Sheet route lets non-technical teammates edit data in a spreadsheet and re-sync to the live site.
  2. Set the import target to New Items → your location post type.
  3. Map the title — drag your city column into the post title, e.g. Plumbers in {city}.
  4. Map ACF fields — in the Custom Fields / ACF section, drag each column to its matching field. {avg_price}avg_price, and so on. WP All Import's drag-and-drop uses {column_name} tokens.
  5. Set a unique identifier — this is critical. Point WP All Import at a stable unique column (an ID, or the slug). On re-import it updates existing posts instead of creating duplicates.
  6. Run the import. For large sets, WP All Import processes in chunks; a 5,000-row import typically completes in a few minutes on decent hosting.

Schedule re-imports (daily/weekly) so live pages reflect your source data. This turns your spreadsheet into a living CMS. For the wider tooling picture, see our roundup of programmatic SEO tools.

Building the template with dynamic fields

One template renders every imported row. Create single-location.php in your theme (or a child theme) and pull ACF values with get_field().

<h1>Plumbers in <?php the_title(); ?></h1>
<p><?php the_field('intro_paragraph'); ?></p>
<ul>
  <li>Average callout: ₹<?php the_field('avg_price'); ?></li>
  <li>Verified providers: <?php the_field('provider_count'); ?></li>
  <li>Busiest area: <?php the_field('top_neighbourhood'); ?></li>
</ul>

The template is also where you win or lose on quality. A page that only swaps the city name is thin content. Instead, surface 2-3 real, differentiating data points per page — pricing, counts, a location-specific paragraph — plus dynamic internal links to related rows. Our guide to template pages that actually rank goes deeper on this pattern.

Wire up meta tags too: if you use an SEO plugin (Rank Math, Yoast), set its title/description templates to read ACF fields so every page gets a unique, keyword-aligned title. This directly feeds your programmatic SEO keyword targeting.

Generating pages at scale with Multi-Page Generator

If your data is clean and you want speed over full post objects, Multi-Page Generator (MPG) is the lighter path. You attach a dataset (CSV or Google Sheet) to a single WordPress page marked as a template, then use {{column}} shortcodes anywhere in that page — content, meta title, meta description, even the URL slug.

MPG generates URLs like /plumbers/mumbai/, /plumbers/pune/ from one template page. Its built-in spintax lets you vary sentence structure per row ({fast|quick|rapid}) so pages don't read identically — useful, but no substitute for real per-row data.

When to pick MPG over WP All Import:

  • You want generation live in minutes, not an import job.
  • You don't need each page to be a queryable WordPress post.
  • Your dataset is already tidy and stable.

When to stick with ACF + WP All Import:

  • You need real posts for archives, related-post loops, or WooCommerce.
  • Your data is messy and needs field-level cleanup on import.
  • You want scheduled re-syncs from an external source.

For a strategy-level view of pushing volume responsibly, read scaled content creation and AI content for SEO — automation multiplies both quality and mistakes.

Sitemaps, indexing and avoiding thin-content flags

Generating pages is half the job. Getting them crawled, indexed and kept is the other half, and it's where most WordPress programmatic projects quietly fail.

Sitemaps. Your SEO plugin auto-generates an XML sitemap, but a 20,000-URL dump in one file is a red flag. Split into files of 50,000 URLs max (Google's limit), ideally far smaller and grouped by post type. See Google's guidance on splitting large sitemaps. Submit the sitemap index in Search Console.

Drip-publish, don't dump. Publishing 15,000 pages overnight looks unnatural and burns crawl budget. Release in batches of a few hundred to a couple thousand, watch indexing, then continue. WP All Import can set posts to draft, so you stage publishing.

Beat thin-content flags. Google's scaled content abuse policy targets pages made mainly to manipulate rankings with little value. Protect yourself with a per-page checklist:

Do Don't
Include 2-3 unique data points per page Swap only the city/product name
Write a unique meta title and description Reuse one meta template verbatim
Add dynamic internal links to related rows Leave pages orphaned
Set noindex on pages with missing data Publish empty-field pages
Prune rows that never earn impressions Keep dead pages forever

That last point matters. Conditionally noindex any page where key ACF fields are empty — a stub page with no data is a liability. After 60-90 days, prune rows that earn zero impressions in Search Console.

Track from day one. Programmatic sets move as a group, so a template or indexing problem hits thousands of pages at once. Monitor rankings and indexed-page counts continuously — a tool like DeployFlare's rank tracker lets you segment by page group and catch a batch-wide drop before it spreads. Watch the Search Console Pages report for the ratio of submitted-to-indexed URLs; if indexing stalls below ~50%, your content is likely too thin or your internal linking too sparse.

Build it in this order — clean data, isolated post type, honest per-page value, staged publishing, constant monitoring — and programmatic SEO on WordPress behaves like any other content that earns its rankings. For the full strategic picture, circle back to the programmatic SEO pillar guide.

Frequently asked questions

Which is the best programmatic SEO WordPress plugin?

There's no single winner — it depends on your data. Use Advanced Custom Fields (ACF) plus WP All Import when your source is a messy CSV or Google Sheet that needs per-field mapping and scheduled re-imports. Use Multi-Page Generator (MPG) when your dataset is clean and you want fast row-to-page generation, spintax, and per-row meta titles without touching post types. Most serious builds use ACF alongside one of the two.

How do I create programmatic pages in WordPress in bulk?

Register a custom post type, attach ACF fields for each data point, then import rows from a CSV or Google Sheet with WP All Import — mapping each column to a field. Build one PHP template that pulls those fields dynamically, so every imported row renders as a full page. WP All Import can create thousands of posts in a single run and re-sync when your source data updates.

Will Google penalise programmatic SEO pages in WordPress?

Google doesn't penalise programmatic pages for being generated — it demotes them for being thin or duplicative. Pages that only swap a city or product name with no unique data get flagged as scaled content abuse. Give each page 2-3 real, differentiating data points, a unique title and meta description, and useful internal links. Done right, programmatic pages rank exactly like hand-written ones.

Do I need custom post types for programmatic SEO?

You don't strictly need them, but you should use them. A dedicated custom post type keeps thousands of generated pages out of your normal Posts and Pages, so you can apply separate templates, sitemap rules, and indexing controls. It also makes bulk cleanup trivial — if a batch underperforms, you delete one post type's entries instead of hunting through your whole site.

How many programmatic pages can WordPress handle?

WordPress itself can hold hundreds of thousands of posts, but performance depends on hosting and caching. The practical bottleneck is usually your sitemap and crawl budget, not the database. Use full-page caching, split sitemaps into files of 50,000 URLs or fewer, and publish in batches rather than dumping 20,000 pages at once, which spooks crawlers and slows indexing.

Can I use Google Sheets as the data source for programmatic pages?

Yes. WP All Import can pull directly from a published Google Sheet CSV URL and re-import on a schedule, so editing a row in Sheets updates the live page. This is ideal for teams that maintain data in a spreadsheet. Keep one row per page, one column per ACF field, and a stable unique-ID column so re-imports update existing pages instead of creating duplicates.

Keep reading