SEO AutopilotAug 19, 2026Claim-checked

WordPress blog SEO optimization: the publish-time system

A working system for WordPress blog SEO optimization: index-bloat arithmetic, a nine-check publish gate, template-tax measurement, and a plugin portability test.

Article proof

GEO score
91
Claim gate
Passed
Pipeline
Published
Read time
19 min
WordPress blog SEO optimization: the publish-time system

Short answer: WordPress blog SEO optimization means two jobs: Controlling which URLs WordPress publishes on your behalf, and enforcing a fixed set of on-page checks before each post goes live. Prune the archive URLs first — plugins only help with the second job.

Most guides describe job two only. Job one is stopping WordPress from publishing URLs you never decided to publish: Tag archives, author archives, date archives, paginated indexes. In the worked example below, a 200-post blog ends up with 206 real pages sitting alongside 245 pieces of scaffolding — and it happens quietly, without anyone choosing it. An SEO plugin gives you fields to fill in for job two; the URL inventory in job one is a decision nobody can make for you.

What follows is the system rather than the tour: The URL arithmetic to run first, a nine-check publish gate with explicit pass conditions, a way to measure how much of your article page is actually the article, a portability test that decides the plugin question without a leaderboard, and a triage table for choosing which published posts to touch.

Run the index arithmetic before you install a plugin

Five things do the measuring in this article, and it is worth being precise about what each one is:

  • Search Console Pages report — Google's own record of which URLs on your domain are indexed and which reasons it gives for the rest.
  • URL Inspection — the Search Console tool that shows the HTML Google actually crawled for a single URL.
  • WordPress core sitemap — the XML sitemap current WordPress versions publish at `/wp-sitemap.xml`, independent of any plugin.
  • `srcset` / `sizes` — the HTML attributes that together decide which image candidate a browser downloads.
  • Core Web Vitals — Google's page-experience metrics, including LCP (largest contentful paint) and INP (interaction to next paint).

Now the arithmetic. The table below is an illustrative worked example, not measured data: A blog with 200 published posts, 8 categories, 140 tags, 3 authors, three years of history, and the WordPress Reading setting left at its default of 10 posts per archive page.

URL typeHow WordPress generates itExample count
ArticlesPublished posts200
Static pagesAbout, contact, privacy, blog index, and two more6
Blog index pagination200 posts ÷ 10 per page20
Category archives8 categories, ~25 posts each, 3 pages each24
Tag archives140 tags, most holding 1–3 posts140
Author archives3 authors × 7 paginated pages21
Date archives36 monthly + 4 yearly40
Non-article total245

Two hundred and forty-five scaffolding URLs against 206 real ones — in this example, roughly 54% of the site's index surface is machinery rather than content. And that figure excludes RSS feeds, per-category feeds, `?replytocom=` comment-reply links, internal search results at `/?s=`, and attachment pages if your install still renders them.

The decision rule is blunt: When non-article indexable URLs outnumber your articles, pruning outranks everything else on your list, including the plugin choice. Adding a plugin to a site in that state gives you better control over a problem you have not decided to solve yet.

To measure your own site, do not rely on a `site:` search — those counts are approximations and they move. Open the Search Console Pages report and read the indexed and not-indexed counts, then crawl your own domain with any crawler and group the results by URL pattern. Two ratios tell you most of it: Tags divided by posts, and non-article URLs divided by articles. The Posts → Tags screen already shows a post count per term, so the first ratio takes a couple of minutes.

The taxonomy rule that ends the argument

This is an editorial threshold, not a search-engine requirement — but holding a line beats arguing term by term. A taxonomy term earns an indexable archive when it meets all three conditions: It holds at least 8 posts, someone actually searches for the term, and you are willing to write 150 words of intro copy for that archive. Two out of three means keep the term for navigation but set the archive to noindex. One or none means delete the term and redirect its archive to the closest category that survives.

In the example above, 140 tags against 200 posts is a tags-to-posts ratio of 0.7, and almost every tag clearing the 8-post floor will be one you would have created deliberately. Treat any ratio much above 0.5 as a signal to schedule a pruning pass, then confirm against your own term counts before deleting anything.

The failure mode here is half-doing it. Teams set tag archives to noindex, then leave forty tag links in the post footer, so crawlers keep walking a path that leads nowhere useful. Or they bulk-delete terms and leave 404s at URLs that older posts still link to. Prune the terms, remove the links from the template, and map the deleted archives to a redirect target in the same pass — three actions, one afternoon.

Permalinks: Change them now, or accept them

The `/%postname%/` structure is the working default for a blog, and the interesting question is not which structure to pick but whether a change is worth its cost on a site that already has posts.

Under roughly 30 published posts with no meaningful external links, change it today and move on. Above that, change only when the current structure is doing concrete damage: Dates in the URL that make evergreen posts look stale in the SERP, an `/index.php/` prefix left over from a bad host, or numeric `?p=123` URLs that carry no meaning. "It would be tidier" is not damage.

When you do migrate, the order matters more than the tool:

  1. Crawl and export the current URL list *before* you touch the permalink setting. After you save, the old URLs exist only in your export and in Google's index.
  2. Build the map as a spreadsheet, one old URL per row, one target per row, no wildcards you have not tested.
  3. Implement the redirects at the server or edge layer if you have access. A redirect that lives in a plugin's database table can disappear the day someone deactivates the plugin during troubleshooting.
  4. Re-crawl the old list and confirm every row returns a single 301 to a 200. Chains and trailing-slash duplicates are the two that survive casual testing.

Separately, and independent of structure: The slug is not the headline. Make it three to five words, drop stop words, and match the query rather than the title. A post titled "We rebuilt our onboarding email sequence — here's what changed" ships with the slug `onboarding-email-sequence`. Leave the year out unless the post is genuinely reissued every year, because a year in the slug commits you to either an annual migration or a permanently stale URL.

The nine-check publish gate

This is the part that decides whether the rest of the work compounds. Every post passes these nine checks before it goes live, and each pass condition is checked against the *rendered HTML*, not against the plugin's preview panel. Those two disagree more often than people expect, usually because a theme, a page builder, or a caching layer rewrites the head.

#CheckPass conditionCommon failure
1Single H1Exactly one `<h1>` in the rendered sourceEditor sets the first block to Heading 1, duplicating the theme's title output
2Title tagDistinct from the H1, query language in the first 40 charactersSEO title left empty, so the plugin falls back to the headline
3Meta descriptionWritten by hand, one sentence of substance plus one of specificityAuto-generated from the opening lines of the intro
4Slug3–5 words, no stop words, no date, matches the querySlug inherited from a working headline nobody updated
5Heading hierarchyNo skipped levels; each H2 answers a question a reader would typeH3s used for visual size, not structure
6Links outAt least two contextual links to existing posts, in body copyLinks added only in a "related reading" block at the end
7Links inAt least three older posts edited to link to this oneSkipped entirely — see the next section
8Canonical + robotsSelf-referencing absolute canonical matching the live permalink exactly; robots meta reads `index, follow`Category-level noindex rule silently applied to the post
9Lead imageAlt text describing the image, correct dimensions, no `loading="lazy"` on the LCP elementOptimization plugin re-adds lazy loading after the theme removed it

Check 8 deserves its own paragraph because the mismatch is invisible in the editor. The canonical should match the permalink character for character — protocol, `www` or bare host, trailing slash. A site serving `https://example.com/post/` while emitting a canonical of `http://www.example.com/post` has told Google that its own page is a copy of a URL that redirects. Curl the page or use view-source; the plugin's field will look perfect either way.

Check 9 has a version-dependent trap. WordPress core applies heuristics that skip lazy-loading for the first in-content image, but page builders and image-optimization plugins can re-add the attribute afterwards. Confirm in the rendered markup that the largest above-the-fold image carries no `loading="lazy"`, and consider `fetchpriority="high"` on it.

Internal links: The direction everyone gets backwards

Every new post gets links *out*. Almost nothing gets links *in*, because adding inbound links means editing old posts, and editing old posts is not part of anyone's publishing routine. That asymmetry is why an archive of 200 posts can behave like an archive of 40.

Two numbers make it operational. Both thresholds are operating defaults you choose, not search-engine rules — the value is in tracking them consistently:

  • Link debt: The count of posts older than 30 days with fewer than three inbound internal links from other posts. Set the age and link floor to whatever fits your publishing cadence, then track the result as a single number and let it drive the backlog. Run the crawl once before arguing about where the floor should sit.
  • The 7-day rule: Within a week of publishing, the three highest-impression pages that are topically adjacent to the new post should link to it. Pull those from the Search Console Pages report, sorted by impressions, not from memory.

Getting inbound links right also addresses drift that a "related posts" widget cannot fix, because widget links are template output — every post gets the same six, chosen by recency or by taxonomy, with no anchor text you control. Contextual body links carry the anchor text, and the anchor text is the part that describes what the target page is about. If you are auditing a provider's work rather than doing it yourself, this is the line item worth checking first; the same logic applies to how you would evaluate an on-page SEO service before signing anything.

Template tax: How much of your article page is the article?

Open a published post and count the visible words that belong to the post, then count the visible words that belong to the theme. Header nav, sidebar widgets, tag cloud, author box, related posts, comment prompt, footer menu, cookie notice. The counts below are example values from an ordinary-looking setup, meant as a template for your own audit rather than a benchmark:

Template elementWords (example)Internal links (example)
Header navigation128
"Recent posts" widget (10 items)8010
Category list widget88
Tag cloud (45 terms)9045
Author box601
Related posts (6 items)486
Comment prompt250
Footer menu + legal10030
Chrome total423108

Run two posts through those figures. An 1,800-word article with six contextual links: The article is about 81% of the page's visible words, and 6 of 114 internal links — roughly 5% — are unique to the page. A 700-word article: The article drops to about 62% of visible words. A 400-word news note: Around 49%. The template did not change; the dilution is a function of how short your posts are.

A working budget: Keep template chrome under about 25% of your median post length. Median post 900 words means a chrome budget near 225 words. The example above blows it by nearly double, and the cheapest fixes are the tag cloud (delete it), the recent-posts widget (cut to three, or delete), and the footer menu (nav links, not a second sitemap).

This is also the quiet reason platform comparisons mislead. A hosted platform hands you a template you cannot easily bloat; WordPress hands you one you can. If you have run the same content strategy on a hosted store blog, the contrast with Shopify blog SEO is mostly this: Fewer knobs, fewer ways to dilute a page, and correspondingly fewer ways to fix it.

Speed work that changes what gets measured

On most blog templates, the LCP element is the featured image or the first in-content image — confirm it in your own field data rather than assuming. Where that holds, most of the useful work is image work rather than cache-plugin work; the cache helps TTFB, which is upstream of LCP but often not the failing part.

A practical sizing rule: Content column width × 2 as an upper bound for uploaded image width, which covers typical 2× device pixel ratios. A 760px column lands around 1,520px, and pixels beyond that are mostly bytes the visitor pays for and never sees. Adjust upward if you serve full-bleed images or explicitly support higher-DPR layouts.

The failure mode is subtler than oversized uploads. WordPress generates a `srcset` from its registered image sizes, but the `sizes` attribute — the part that tells the browser which candidate to pick — comes from the theme, and themes frequently emit `sizes="100vw"` on a layout that is nothing like full width. The browser then dutifully downloads the 2,400px candidate for a 760px slot. To check: Open DevTools, select the image, and compare `currentSrc` against the rendered CSS width. If the downloaded file is more than twice the rendered width, the `sizes` attribute is lying and the fix is a template edit, not a bigger cache.

On thresholds: Read the current "good" values off your own Search Console Core Web Vitals report rather than off any article, including this one. The metric set itself has changed in recent years — INP superseded FID — so a remembered number has a real chance of being the wrong number.

Choosing a plugin without a leaderboard

The major SEO plugins converge on the same core fields: Title, description, canonical, robots directives, sitemap, basic schema, and a redirect manager in the paid tiers. Feature availability and pricing change release to release, so verify anything specific against the vendor's own documentation rather than a comparison post. The question that actually separates them for a blog you intend to run for years is what happens to your data when you leave.

The portability test. On staging, install the candidate, publish three posts with every field filled in, then deactivate the plugin and diff the rendered `<head>` before and after. Count how many of your title, description, canonical, robots, and schema values survive the deactivation. Pick your own tolerance before you run it — if fewer than half the values survive, the plugin holds a meaningful share of your on-page configuration, and that is a migration cost you should price now rather than discover later.

Beyond that, a weighted scorecard keeps the decision honest:

CriterionWeightWhat to check
Field portability25Are values stored in exportable post meta, or in a proprietary table?
Per-taxonomy indexing control20Can you noindex tag archives without touching every term?
Redirect storage15Exportable table, and does the plugin document the export path?
Bulk editing15Can you edit 50 titles without opening 50 posts?
Schema override10Can you replace generated schema, or only accept it?
Sitemap granularity10Per-post-type inclusion, and does it disable the core sitemap?
Admin weight5Queries and admin-page load added per screen

Score each candidate 0–5 per row, multiply by the weight, and let the total decide. If two candidates land close together, the difference probably does not justify another week of evaluation — pick the one your team has already used. The same weighting logic scales to the rest of your stack, which is the argument in this SEO automation tool selection framework.

One configuration detail that catches people: Current WordPress versions ship an XML sitemap at `/wp-sitemap.xml`, and most SEO plugins publish their own at a different path. Open both URLs on your install. If both exist and both are submitted in Search Console, you are maintaining two inventories with different contents, and the one you forget will be the one with the stale entries.

Post-publish verification, and what to check the next day

Publishing is not the end of the gate; it is the middle. Two checks close it.

The same day, fetch the live URL and confirm three things in the response: A 200 status, the canonical you intended, and the robots meta you intended. Caching layers and CDN rules are perfectly capable of serving a cached `noindex` from a draft state.

The next day, run the URL through Search Console's URL Inspection tool and read the rendered page it reports — not the "indexed / not indexed" verdict, which is slow and noisy, but the crawled HTML. If your article body is missing from that rendering, you have a JavaScript delivery problem that no amount of on-page work will offset.

Do not request indexing for every post as a reflex. Reserve it for posts where the sitemap has not been fetched recently, and check the sitemap's last-read date in the Sitemaps report before you decide.

Refresh triage: Which published posts to touch

Give a post a few weeks of Search Console data before judging it — a 28-day window is convenient because it maps to a common reporting range. Average position is a rough routing signal, not a diagnosis: A page averaging deep in the results usually has a retrieval or intent problem that rewriting the body copy will not solve, so check which queries it receives impressions for before you touch the text. The bands below are heuristics for choosing an intervention, not predictions of outcome.

Average positionWhat it usually meansAction
1–3The page matches the queryLeave it alone; add internal links from it to weaker pages
4–10Relevance is fine, the click is notRewrite title and description only, then hold for 28 days
11–20A subtopic competitors cover is missingAdd the missing section, then re-fetch the sitemap
21–50Intent mismatch, or the wrong page is rankingCheck which query it ranks for; often a different page should own it
50+The page is not in the runningConsolidate into a stronger post and redirect, or leave it

The 11–20 band is usually where refresh work pays best, because the page has already demonstrated it can be retrieved for the query. Find the missing subtopic by pulling the queries that page receives impressions for, then reading which of them the page does not actually answer with a heading. That is a ten-minute exercise per page and it produces a specific edit rather than a vague "improve the content" ticket.

The band nobody acts on is 21–50 with rising impressions. Those are often two of your own posts splitting the same query, and the fix is consolidation, not optimization.

Running the gate as a release process

Once the routine is stable, expect the nine checks to take roughly a quarter of an hour per post. An illustrative budget:

StepMinutes (target)
Diff the rendered `<head>` against intent2
Title, description, slug3
Heading structure and links out3
Edit three older posts to link in4
Lead image: Dimensions, alt, lazy-load state2
Next-day index verification1
Total15

If a check regularly runs over its budget, it belongs in the template or in automation — not on the checklist. A step that takes eight minutes every time is a step your team will quietly skip in week six. Canonical correctness, robots directives, image dimensions, and schema output are all template-level concerns; solving them once at that layer removes them from the per-post ritual. What remains — the title, the slug, the inbound links, the judgment about intent — is the part that genuinely needs a person.

That is the argument for treating a WordPress blog like a deploy pipeline rather than a publishing habit: The checks that can be enforced automatically should fail loudly and block, and the checks that require judgment should be short enough that nobody rationalizes skipping them.

When this system is the wrong system

A news site publishing eight times a day cannot run a 15-minute manual gate, and its archives genuinely benefit from date-based URLs that this article treats as a liability. A large multi-author site needs author archives that a three-person blog does not. A WooCommerce store's blog sits inside a URL architecture with different constraints — product and category pages come first, and the blog's job is often internal linking rather than acquisition.

The parts that survive those exceptions are the arithmetic and the portability test. Count your non-article URLs before you optimize anything; know what your plugin is holding before you commit years of metadata to it.

FAQ

How do I optimize a WordPress blog for SEO without a plugin? Further than most people assume. Core publishes an XML sitemap at `/wp-sitemap.xml`, permalink structure is a core setting, and title and canonical output can be handled in a child theme with a modest amount of code. What you lose is per-post editing convenience for non-technical authors, bulk editing, and a redirect UI. For a single-author blog where every post passes through the same person, going plugin-free is a reasonable choice. For a team, the editing interface is the feature you are actually buying.

Which SEO plugin should I use for WordPress? There is no portable answer, because the fit depends on who edits posts, whether you need bulk operations, and how much metadata you are willing to lock into one vendor. Run the portability test above on two candidates, score them against the weighted table, verify current features and pricing on the vendor's own site, and pick the higher total. When the totals are close, the choice is not load-bearing.

What is the 80/20 rule in SEO? It is a prioritization habit borrowed from the Pareto principle, not a documented property of search engines — treat any specific percentage claim about it with suspicion. For a WordPress blog, the short list worth front-loading is: The post is indexable and in the submitted sitemap, the title and slug match the query language, at least three existing posts link to it, and the first sixty words answer the question directly rather than introducing the topic.

How often should I re-optimize existing posts? Trigger the work from data, not the calendar. Review positions monthly, act mainly on the 4–10 and 11–20 bands, and give each change a full 28 days before you judge it. Changing a title and the body copy in the same week means you learn nothing from either.

Do categories and tags help or hurt? Both, depending on how many you have. A category structure that mirrors how you would organize a navigation menu helps readers and gives you a plausible hub page. A tag for every noun in every article generates archives with one post each. The 8-post floor in the taxonomy rule above is an editorial line worth holding.

Analytics consent

We use Google Analytics only after consent to understand reach and product usage.

WordPress blog SEO optimization: the publish-time system