WordPress SEO

A technical SEO practitioner's guide to WordPress — the default settings that hurt you, how the core sitemap and canonical handling actually work, why you run exactly one SEO plugin, and the duplicate-content sources WordPress creates on its own.

First published: Jun 27, 2026 · Last updated: Jul 25, 2026 · Advanced
demand #1 in CMS#5 in Platform SEO#33 in Technical SEO#45 on the site

WordPress is SEO-capable, not SEO-finished. It self-canonicalizes posts since version 2.9 and ships a native XML sitemap since 5.5 — but its defaults also leave ?p=123 permalinks, attachment pages, date/tag/author archives, feeds, and internal search results all indexable, and a single Settings → Reading checkbox can silently block the whole site. The fixes that actually matter: set /%postname%/ before publishing, run exactly one SEO plugin (Yoast, Rank Math, or AIOSEO — never two, the wp_head conflict produces duplicate metadata), noindex thin archives instead of disallowing them, and keep the sitemap to canonical indexable URLs only. WordPress 6.4+ disables attachment pages on new installs by default — redirecting straight to the file, not the parent post — but existing sites keep them on and must migrate manually. Google has never said WordPress ranks better or worse than any other CMS — content and links decide that, not the platform.

TL;DR — WordPress is SEO-capable, not SEO-finished. It self-canonicalizes singular posts since version 2.9 and ships a native XML sitemapAn XML sitemap is a UTF-8 file listing the canonical URLs on your site (with optional lastmod) so search engines can discover and prioritize them. It's a discovery and diagnostic aid, not a guarantee of indexing — and Google ignores its priority and changefreq tags. since 5.5 — but defaults leave ?p=123 permalinks, attachment pages, date/tag/author archives, feeds, and ?s= search pages all indexable, and the Settings → Reading checkbox can silently block the whole site. The fixes that move the needle: /%postname%/ before publishing, exactly one SEO plugin (the wp_head conflict from two is real), noindexNoindex is a directive that tells search engines to keep a page out of their index, so it won't appear in search results. It works only on pages a crawler can actually fetch — a page blocked in robots.txt can never be noindexed. thin archives rather than disallowing them, and a sitemapA sitemap is a file that lists the pages, images, videos, and other files on your site so search engines can discover them. It helps discovery, but submitting a sitemap doesn't guarantee crawling or indexing. of canonical indexable URLs only. WordPress 6.4+ disables attachment pages by default on new installs — redirecting to the file itself, not the parent post; existing sites keep them enabled and migrate by hand. Google has never said WordPress is better or worse for SEO than any other CMSA content management system (CMS) is software that lets users create, manage, and publish digital content — like blog posts and pages — without writing raw code. WordPress, Drupal, and Joomla are the most common open-source CMS platforms.. Evidence for this claim WordPress added core XML sitemaps in 5.5 and attachment-page redirects for new sites in 6.4. Scope: Core version history; existing sites can retain prior attachment behavior. Confidence: high · Verified: WordPress 5.5 XML sitemaps WordPress 6.4 attachment pages

WordPress is SEO-capable, not SEO-finished

The honest framing is somewhere between the two marketing claims you usually hear. WordPress is not “SEO-friendly out of the box” in any complete sense — but it also isn’t bad for SEO. It gives you a strong, controllable foundation and then leaves a pile of indexable cruft turned on by default. The whole job is knowing which defaults to change and which auto-generated URLs to suppress.

And to be clear up front: Google has never said WordPress ranks better or worse than any other CMS. As Google’s documentation puts it, “if you’re using a CMS such as WordPress, Wix, or Blogger, it’s likely that your CMS has already made a sitemapA sitemap is a file that lists the pages, images, videos, and other files on your site so search engines can discover them. It helps discovery, but submitting a sitemap doesn't guarantee crawling or indexing. available to search engines” — the platform is treated like any other. Rankings come from content and links, not from the logo in your admin bar. Evidence for this claim Google says common CMS platforms often generate sitemaps and does not prescribe a CMS-specific ranking advantage. Scope: Google sitemap guidance; absence of a CMS ranking advantage is an editorial inference from platform-neutral requirements. Confidence: medium · Verified: Google: Build and submit a sitemap

The defaults that hurt — and why

The “Discourage search engines from indexingStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. this site” checkbox (Settings → Reading) writes a site-wide noindex and a restrictive virtual robots.txtA plain-text file at the root of a host that tells crawlers which URLs they may and may not request. It controls crawling, not indexing — a blocked URL can still be indexed if it's linked from elsewhere.. It’s the first thing I check on any WordPress audit, because it’s the single setting that can silently zero out an entire site’s indexingStoring a crawled page in the search index so it can appear in results. Crawled is not the same as indexed — Google selects what to keep, and indexing isn't guaranteed. — usually left on from staging.

The ?p=123 default permalink gives no topical signal and isn’t a clean URL. Switch to /%postname%/ — and do it before publishing. On an established site, changing the permalink structure means URL changes; WordPress will auto-301 the old numeric URLs for standard post types, but custom post types and pages don’t always redirectA redirect sends browsers and crawlers from a requested URL to a different one. An HTTP redirect specifically is a 3xx status code paired with a Location header; meta refresh and JavaScript redirects achieve a similar navigation without being a 3xx response themselves. Permanent redirects (301/308) are Google's signal the target should be canonical; temporary ones (302/303/307) aren't. cleanly, so test. I’d avoid baking the category into the permalink (/%category%/%postname%/): the day you reorganize taxonomy you trigger a mass URL change and throw away ranking history for no proportional benefit.

Attachment pages are the WordPress-specific gotcha people forget. Every media upload historically spawned a standalone URL containing just the file and some auto-metadata — thin pagesThin content is web content that provides little or no value to users. Google's spam policies name it 'thin content with little or no added value' — and it's about value per page, not word count. that can cannibalize the real ones. WordPress 6.4 changed the default so new installs disable attachment pages entirely — a request to one now redirects straight to the file itself, not the parent post. Existing (upgraded) sites keep attachment pages enabled; there’s no Settings-screen toggle for this, only wp option set wp_attachment_pages_enabled 0 via WP-CLI or editing the option directly on wp-admin/options.php. In practice most site owners never touch that option and instead handle it the plugin way: noindexNoindex is a directive that tells search engines to keep a page out of their index, so it won't appear in search results. It works only on pages a crawler can actually fetch — a page blocked in robots.txt can never be noindexed. the attachment page, or better, redirect it to the parent post via your SEO plugin. Don’t assume an older site inherited the WordPress 6.4 default; it didn’t.

Archives, feeds, and search pages. By default WordPress generates indexable category archives, tag archives, date archives, author archives, paginated archive pages (?page=2), feed URLs (/feed/), attachment pages, and internal search result pages (/page=search, i.e. ?s=). That’s the canonical list of WordPress duplicate-content sources, and almost none of it was a decision you made.

Duplicate content WordPress creates on its own

Worth stating plainly because it surprises people: WordPress manufactures structural duplicate contentThe same or very similar primary content reachable at more than one URL. There's no general duplicate content penalty — the real costs are possible signal dilution, the wrong URL getting chosen, and less-efficient crawling. by default. The recurring sources:

SourceExampleTypical fix
Category archives/category/news/Keep, or noindex if thin
Tag archives/tag/wordpress/Usually noindex (thin, overlapping)
Author archives/author/admin/Noindex on single-author sites
Date archives/2023/04/Noindex (almost always thin)
PaginationPagination splits a large set of content — product listings, blog archives, search results — across multiple sequentially numbered URLs. For SEO, each paginated page should be crawlable, indexable, and self-canonical; Google no longer uses rel=prev/next, but Bing still does./page/2/Self-referential canonical (not page 1)
Feed URLs/feed/Noindex feeds
Attachment pages/photo-of-cat/Redirect to parent via SEO plugin (WP 6.4+ redirects new installs to the file itself instead)
Search results/?s=keywordNoindex

The fix is almost never to panic about a penalty — Google consolidates duplicates to a canonical rather than penalizing structural duplication. The fix is to noindex the thin stuff and keep the sitemap clean. And a critical distinction: noindex ≠ no-crawl. A noindexed page must stay crawlable so Google can actually read the noindex. If you disallow it in robots.txtA plain-text file at the root of a host that tells crawlers which URLs they may and may not request. It controls crawling, not indexing — a blocked URL can still be indexed if it's linked from elsewhere. instead, Google can’t see the directive — which is why you noindex thin archives rather than blocking them.

The XML sitemap: core vs. plugin

WordPress 5.5 (August 2020) added a native XML sitemapAn XML sitemap is a UTF-8 file listing the canonical URLs on your site (with optional lastmod) so search engines can discover and prioritize them. It's a discovery and diagnostic aid, not a guarantee of indexing — and Google ignores its priority and changefreq tags. at /wp-sitemap.xml. It’s real, but barebones. It dumps in all public post types, all public taxonomies, and author archives — meaning it happily lists exactly the thin pages you want out of the index. It has no image-sitemap support and limited control. So in practice most sites use the sitemap from Yoast or Rank Math instead, which lets you include/exclude specific post types and taxonomies and keep the file to canonical, indexable URLs. Yoast disables the core sitemap and replaces it; that’s expected.

Two things the sitemap won’t do for you: Google ignores <priority> and <changefreq> entirely (per Google’s own docs), and WordPress does not submit the sitemap to Google for you — you submit it in Search ConsoleGoogle's free tool for monitoring crawling, indexing, and search performance. and Bing Webmaster Tools, and you can list it via a Sitemap: directive in robots.txt for passive discovery. The 50,000-URL / 50MB limit from the spec still applies; split into a sitemap indexA sitemap index is a sitemap of sitemaps — a single file that lists your other sitemap files instead of listing URLs directly. It's how large sites stay under the 50,000-URL / 50MB-per-sitemap limit while submitting just one file. past that.

Canonical handling: core, plugin, and the conflict trap

Core has output rel=canonical via rel_canonical() since WordPress 2.9 (2009) — singular posts and pages self-canonicalize. WordPress 4.6 didn’t add the tag; it refactored the function to use the filterable wp_get_canonical_url(), which is what people usually mean when they say “canonical since 4.6.” That’s a good baseline, but core doesn’t handle custom post types consistently across themes, doesn’t add canonicals on 404s, and doesn’t resolve URL-variation duplicates (?utm_source=, www vs. non-wwwWWW vs. non-WWW is the choice between serving a site from www.example.com (the www subdomain) or example.com (the bare/apex/root domain). Both point to the same content, so it's a canonicalization and consistency decision, not a ranking factor., trailing slashes) on its own. SEO plugins replace the core output with more comprehensive handling: custom post type canonicals, self-referential paginationPagination splits a large set of content — product listings, blog archives, search results — across multiple sequentially numbered URLs. For SEO, each paginated page should be crawlable, indexable, and self-canonical; Google no longer uses rel=prev/next, but Bing still does. canonicals (not pointing page 2+ at page 1 — a mistake that deindexes your deeper pages), cross-domain canonical for syndication, and per-page overrides.

Here’s the trap that ties the whole plugin question together: the canonical tagA rel=\"canonical\" annotation — in the HTML <head> or an HTTP Link header — that tells search engines which URL is the preferred version of duplicate or near-duplicate content. set by your SEO plugin is the authoritative signal — but if your theme also injects a title tagThe title tag is the HTML title element in a page's head that specifies the document's title. It's the primary source for the SERP title link and a confirmed light ranking factor — but since August 2021 Google doesn't always show it verbatim. or its own SEO meta, you get a conflict. Some theme frameworks (Genesis, Thesis) emit their own SEO tags. When you activate an SEO plugin, disable the theme-level SEO, and inspect the rendered <head> to confirm exactly one canonical, one title, one meta descriptionThe meta description is an HTML head tag — `<meta name=\"description\" content=\"…\">` — that suggests a short summary of the page for the search snippet. It's not a Google ranking factor, and Google rewrites it the majority of the time, but a good one can still lift click-through..

One SEO plugin. Never two.

This deserves its own heading because it’s the most common self-inflicted WordPress SEO wound. Never run two SEO plugins simultaneously. Yoast, Rank Math, and AIOSEO all hook into wp_head() to write the title, meta description, canonical, Open Graph/Twitter tags, robots meta, and JSON-LDJSON-LD (JavaScript Object Notation for Linked Data) is a script-based structured data format, typically paired with the schema.org vocabulary to describe page content for search engines and AI systems. Google recommends it over Microdata and RDFa because it's the easiest format to implement and maintain at scale — but all three work, and structured data isn't a ranking signal.. Run two and they both fire — duplicate meta descriptions, duplicate (and contradictory) canonical tags, conflicting Open Graph, and conflicting sitemaps. Search Console will flag the duplicate metadata. Pick one and fully uninstall the other (deactivating leaves database entries behind).

As for which one — they all cover the core tasks; the choice is use-case and budget:

  • Yoast SEO — the largest install base, the familiar traffic-light scoring, great for beginners and content teams that want a guided workflow. (WooCommerce schema is a paid add-on.)
  • Rank Math — the most generous free tier: unlimited focus keywords, redirect manager, 404 monitoring, GSC + GA4 integration, and a strong schema builder (16+ types free). My pick for developers and power users.
  • All in One SEO (AIOSEO) — strong WooCommerce integration, internal-link assistant, good local SEO. Suits agencies and large stores.

One caution on Yoast’s green lights: a higher Yoast score doesn’t mean better rankings. It’s a heuristic for basic on-page formatting — keyword presence, title length, readability proxies. A red-light post routinely outranks an all-green one. Content quality, intent match, authority, and links matter far more.

Schema: what WordPress does and doesn’t output

Core WordPress outputs essentially nothing useful for rich resultsRich results (formerly 'rich snippets') are enhanced search listings — stars, images, prices, breadcrumbs, video thumbnails, and more — that Google and Bing build from structured data. They're a display feature, not a ranking factor, and eligibility never guarantees they'll show. — clean HTML Google can parse, but no JSON-LD. As Google notes, “if you use a CMS, such as Wix, WordPress, or Shopify, you might not be able to edit your HTML directly… you may be able to install a plugin that allows you to specify structured dataStructured data is a standardized way of labeling page content (using the schema.org vocabulary in JSON-LD, Microdata, or RDFa) so search engines can understand its meaning. It's not a direct ranking factor — its value is rich results and entity understanding..” That’s the path:

  • Yoast auto-adds Organization/Person, WebSite (with SearchAction), WebPage, BreadcrumbList, and Article schemaArticle schema (Article, NewsArticle, or BlogPosting) is structured data marking up a written piece's headline, author, and dates — Google labels it the \"Article rich result,\" but it's a better-displayed existing result, not a distinct new card, and it isn't required for Top Stories or Discover eligibility. in JSON-LD.
  • Rank Math adds those plus 16+ schema types in the free tier (FAQ, HowTo, Product, Review, Event…) and a builder for custom types.
  • WooCommerce alone outputs basic Open GraphOpen Graph (OG) tags are `<meta>` elements in a page's head, defined by the Open Graph protocol (ogp.me, created by Facebook), that describe a page as a shareable object — its title, description, image, URL, and type. They control how a link preview card looks when the page is shared on Facebook, LinkedIn, Slack, Discord, WhatsApp, and iMessage. They are not a direct Google ranking factor, though Google reads og:title, og:image, and og:site_name as inputs to how a result appears. product metadata but no Product JSON-LD — you need Yoast WooCommerce SEOWooCommerce SEO is optimizing a WooCommerce store — which runs as a free plugin on WordPress, not as a standalone platform — to rank in organic search. Because you control the whole stack (templates, URLs, plugins, server), the ceiling is high and the ways to misconfigure it are many. (paid) or Rank Math Pro for full Product schema with price, availability, and review aggregate.

WooCommerce, briefly

WooCommerce stacks more SEO surface on top of standard WordPress. The recurring issues: the /product/ and /product-category/ URL bases (removable, with redirects on existing sites), product variations creating near-duplicates, and — the big one — faceted navigationFaceted navigation (faceted search, product filtering) lets visitors refine a list of products or content by attribute — price, color, size, brand, rating. The SEO problem: each filter combination can spawn a distinct crawlable URL, turning a small catalog into millions of near-duplicate pages that waste crawl budget and dilute ranking signals. generating thousands of thin filter-combination URLs. Handle facets the same way you’d handle them anywhere: ideally JS-based filtering with no URL change, otherwise rel=canonical to the base category and/or noindex, follow on filter pages (with crawlingCrawling is how search engines use automated bots (like Googlebot and Bingbot) to discover URLs and download pages. A page has to be crawlable to be indexed, but crawling on its own isn't a ranking factor. allowed so the directive is seen). Shop and category pagination wants self-referential canonicals, and Google deprecated rel=prev/next back in 2019 — harmless if present, but don’t rely on it. Faceted nav has its own deep treatment in the Ecommerce SEOEcommerce SEO is the practice of optimizing an online store so its product and category pages rank in organic search and attract purchase-intent visitors. It uses the same Google algorithm as any other site, but compounds the usual SEO work with commerce-specific challenges like faceted navigation, product variants, and platform-imposed URLs. pillar.

robots.txt and Core Web Vitals — two quick notes

WordPress serves a virtual robots.txt (it’s not a file on disk) defaulting to disallowing /wp-admin/ while allowing admin-ajax.php. Drop a physical file at the root and it overrides the virtual one entirely; SEO plugins let you edit the virtual version from the dashboard. The classic mistake is disallowing /wp-content/, which blocks CSS/JS/images and breaks renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. — don’t.

On performance: the “WordPress is slow” complaint is a configuration problem, not a core problem. LCPLargest Contentful Paint — render time of the largest visible image or text block, relative to when the page started loading. ≤2.5 s (at the 75th percentile) is good. issues trace mostly to TTFBTime to First Byte — the time from the start of a request to when the first byte of the response arrives. It's a diagnostic metric (not a Core Web Vital) and a major input to FCP and LCP; ≤0.8 s is good. (cheap shared hosting, no opcode cache) and unoptimized hero images; INPInteraction to Next Paint — the input-to-paint latency at the 75th percentile of a page's interactions. ≤200 ms is good. issues to JavaScript bloat from page builders (Elementor, Divi); CLSCumulative Layout Shift — a unitless score for unexpected visual movement, taken from the largest burst (session window) of layout shifts, not the lifetime sum. ≤0.1 is good. to images without dimensions and web fonts without font-display: swap. Lightweight themes (GeneratePress, Kadence, Astra) plus a caching plugin, a CDN, and modern image formatsThe file encoding used to store an image (JPEG, PNG, WebP, AVIF, SVG, GIF) — it drives file size and Core Web Vitals, but carries no direct ranking weight. get a well-built WordPress site through Core Web VitalsGoogle's three real-user UX metrics — LCP (loading), INP (responsiveness), and CLS (visual stability) — used by Google's ranking systems, with no official weight attached, measured on field data. comfortably. The detail lives in the Web Performance cluster.

TIP Crawl the combined WordPress theme and plugin output

This raw-HTML baseline catches repeatable template findings and states what it did not evaluate. Rendered JavaScript and Search Console remain separate checks.

Run a scoped WordPress crawl with my free Scout Site Audit Free Free

  1. Crawl representative posts, pages, archives, and special routes.
  2. Group metadata, canonical, indexability, and heading findings by template owner.
  3. Fix the theme or plugin source, rerun the same scope, and verify priority URLs in Search Console.
The useful output is the template pattern plus its coverage and blind spots, not the score alone.

The report scores 82 out of 100, crawls 24 of 31 discovered URLs, reports two missing-title warnings, and says rendered JavaScript and AI checks were not evaluated.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.