Programmatic SEO That Is Not Just Doorway Pages
I run a system that publishes 530 pages from a CMS. The difference between the version that works and the version that gets ignored is not technical.
UKUgur KelleciogluIndependent Product EngineerProgrammatic SEO has a bad reputation and it earns most of it. Generate a page per city, change the city name, publish five hundred of them, and you have built exactly what Google's doorway policy describes.
I run a system that publishes 530 pages from a CMS. This is what I have learned about the difference between the version that works and the version that gets ignored, and the honest answer is that the difference is not technical.
The generation is the easy part
The pipeline itself is unremarkable. Content lives in Sanity as structured documents. A single dynamic route calls generateStaticParams, gets every slug, and prerenders them. Add a document, the page exists. Nothing about that is difficult, and nothing about it is the interesting problem.
The interesting problem is that a page which exists is not a page that deserves to.
The test that matters
Take two of your generated pages and put them side by side. Delete the variable, the city name or the technology or whatever it is. Is what remains different?
If the answer is no, you have not built five hundred pages. You have built one page and five hundred URLs pointing at it, and search engines have been able to see that for years.
On the system I run, the honest assessment is mixed. The service and comparison pages pass: each answers a genuinely different question. The city pages largely do not, because they came from six templates crossed with a list of place names. I know which half is which, and knowing is the point, because it tells you where the next hour of work goes.
What makes a generated page defensible
Something on it that could not have been generated.
The mechanism I use is proof injection. Each page declares which technologies it is about, and the template queries the real project database for work that matches, then renders those products with their real numbers. The prose is written per page. The evidence is pulled per page. A competitor can copy the template in an afternoon and cannot copy the twenty five products behind it.
That is the difference in one sentence: the page should assemble something you have rather than restate something you claimed.
The technical parts that are actually load bearing
Three, and only three matter more than the rest.
Structured data, because a page that declares itself as an article with an author and a set of questions is legible in a way a wall of divs is not. FAQPage in particular earns its place, since it maps to how people phrase queries.
Correct hreflang, which is where most multilingual programmatic systems quietly break. Mine did: pages declared a Turkish alternate that served English content, because the fallback logic filled the gap instead of admitting it was empty. Declaring a translation that does not exist is worse than declaring nothing.
A sitemap that is actually current. Mine was generated once at deploy and frozen, so seven new pages existed and were announced nowhere. That was a one line fix and it had been silently wrong for weeks.
Scale is a multiplier, not a strategy
The instinct after the first hundred pages is to find the next axis and multiply again. Country by service. Technology by industry. It is the obvious move and it is usually the wrong one, because the risk multiplies at the same rate as the page count while the quality per page falls.
The better question is what you have that cannot be templated. Real projects, real numbers, a genuine opinion about a tradeoff. Those do not scale linearly, which is exactly why they are worth something.
Five hundred pages built on one idea is one idea. Thirty pages built on thirty is thirty.
Frequently asked questions
How do I know if my generated pages are doorway pages?
Put two of them side by side and delete the variable, the city name or the technology. If what remains is the same, you have not built five hundred pages. You have built one page and five hundred URLs pointing at it.
What makes a programmatically generated page defensible?
Something on it that could not have been generated. The mechanism I use is proof injection: each page declares its subject and the template queries a real project database for matching work and renders it with real numbers. A competitor can copy the template and cannot copy what sits behind it.
Which technical pieces matter most at scale?
Structured data, correct hreflang and a sitemap that is actually current. Mine declared a Turkish alternate that served English content and the sitemap was frozen at deploy so new pages were announced nowhere. Both were silent for weeks.
More writing
Browse all articles