If your site can be reached at both yourdomain.com and www.yourdomain.com, you do not have one website. You have two, and Google has to guess which one you meant. Add a shop with color and size filters, a staging copy someone forgot to lock down, and a few hundred URLs with tracking parameters, and one website can present itself to a search engine as several thousand — most of them saying the same thing.

Advertisement. We earn a commission if you sign up through this link, at no extra cost to you.
This is duplicate content. It is the least dramatic problem in technical SEO and one of the most common, and almost nobody notices it until rankings quietly stop improving.
First, a myth worth killing
You have probably read that duplicate content carries a Google penalty. It does not. Google has said so repeatedly and directly: there is no duplicate content penalty for ordinary sites. Penalties are reserved for deliberate deception — scraped content republished at scale, doorway pages, that kind of thing.
What actually happens is duller and, for most sites, more expensive. When Google finds several URLs with the same content, it picks one to show and files the rest away. That choice is Google’s, not yours, and it does not always match what you would have chosen. Everything that made the page worth ranking — the links pointing at it, the engagement signals, the relevance — gets attributed to whichever version Google settled on, and the others sit in the index doing nothing.
So the cost is not punishment. It is dilution and loss of control. Ten links to your product page split five and five across two URLs give you two mediocre pages instead of one strong one.
What it actually costs you
Split ranking signals. This is the real damage. Links, mentions and internal links all point at whichever URL the linker happened to copy. Half your authority lands on a version Google may not even be showing.
The wrong page in results. Google picks a canonical for you. Sometimes it picks the parameterised URL, or the staging copy, or the print stylesheet version. Users land on something you never intended to be the front door.
Muddled analytics. When the same page reports under four URLs, every page-level report you look at understates its traffic. You end up deprioritizing pages that are actually working.
Crawl waste — but only if you are big. Crawl budget gets cited constantly in articles like this one, and for most sites it is irrelevant. Google has been clear that sites under a few thousand URLs generally do not need to think about it. If you run a shop with 40,000 filter combinations, it matters a great deal. If you run a 60-page business site, it does not, and anyone telling you otherwise is padding.
Where duplicates actually come from
In practice, nearly every case traces back to one of seven sources.
www and non-www
The classic. Both versions resolve, neither redirects to the other, and every inbound link is a coin flip. This one is free to fix and is usually worth doing before anything else.
HTTP and HTTPS
Same problem, one layer down. A certificate was installed but the old HTTP URLs were never redirected, so both schemes serve the site. Combined with the www issue, you now have four addresses for every page: http, https, http+www, https+www.
URL parameters
Sorting, filtering, session IDs, and campaign tags all append query strings. /shoes/?sort=price and /shoes/?sort=newest hold the same twelve products in a different order. UTM parameters are the quiet one here — every campaign link you have ever sent creates a distinct URL, and if any of them get linked or shared, they can get indexed.
Product variations
WooCommerce and most other e-commerce platforms generate a URL per variation. A t-shirt in five colors and four sizes is twenty URLs sharing one description, one gallery and one set of reviews. The variation URLs are useful for customers and cart links; they are not pages you want competing in search.
Pagination
Category and archive pages split across /blog/, /blog/page/2/, /blog/page/3/. These are not duplicates in the strict sense — each holds different posts — but they are routinely mishandled in a way that creates the same effect.
Staging and development copies
Someone spins up staging.yourdomain.com, forgets to lock it, and a full second copy of the site enters the index. This is the most damaging version of the problem because the duplicate is not a variant of a page — it is the entire site, often with placeholder text and half-finished layouts attached to your brand name in search results.
The small stuff
Trailing slash versus no trailing slash. Uppercase versus lowercase paths. /index.php/about/ alongside /about/. Individually trivial, collectively responsible for a surprising share of what a crawler reports.
Finding your duplicates in twenty minutes
Type both versions into a browser
Start here. Enter all four variants of your homepage — with and without www, http and https — and watch the address bar. Every one should end up at the same URL. If any of them stays where it is, you have found your first problem in under a minute.
Use the site: operator
Search Google for site:yourdomain.com and then site:www.yourdomain.com. If both return substantial results, both versions are indexed. Do the same for any subdomain you suspect: site:staging.yourdomain.com is the fastest way to find a staging site that got loose.
The result counts Google shows are estimates and should not be treated as inventory. They are perfectly good for answering the yes-or-no question of whether something is indexed.
Read the Pages report in Search Console
This is the authoritative source, and it is where most people should start. Under Indexing, open the Pages report and look at the “Not indexed” reasons. Three of them are about canonicalization:
- Duplicate, Google chose different canonical than user — you specified a canonical and Google overrode it. Worth investigating; it usually means your canonical points somewhere that contradicts other signals.
- Duplicate, submitted URL not selected as canonical — you put the URL in your sitemap, Google decided another URL is the real one.
- Alternate page with proper canonical tag — this one is good news. It means your canonical is being respected and the duplicate is correctly filed away.
The URL Inspection tool answers the same question for one page at a time, and shows both your declared canonical and the one Google actually selected. When those two disagree, you have your answer.
Crawl the site
A crawler — Screaming Frog is the standard, and free up to 500 URLs — gives you the whole picture at once. The reports worth opening are the canonical report, the duplicate page titles report, and the near-duplicates analysis. Titles are a good proxy: if forty URLs share one title, they are usually the same page wearing forty hats.
Look at the source
On any page, view source and search for rel=”canonical”. Check three things: that it exists, that it is an absolute URL including the protocol and domain, and that it points where you expect. A canonical pointing at the wrong page is worse than no canonical at all, because Google is more likely to act on it.
What a canonical tag does — and what it does not
The tag itself is unremarkable:
<link rel="canonical" href="https://example.com/preferred-url/">
It goes in the <head>, and it tells search engines which URL you consider the master copy.
Two things about it are consistently misunderstood.
It is a hint, not an instruction. Google treats the canonical tag as one signal among several — alongside internal links, sitemap inclusion, redirects and which version is more frequently linked. If your canonical contradicts everything else on the site, Google will often ignore it. This is why the tag alone rarely fixes anything; it works when it agrees with the rest of your signals.
It does not stop crawling. The duplicate still gets fetched. If your goal is to keep something out of the index entirely, canonical is the wrong tool — you want noindex or authentication.
Every page should carry a self-referencing canonical pointing at itself. It costs nothing, and it means that when someone links to your page with a tracking parameter attached, the signal still lands where it belongs.
Fixing it: choose one version and enforce it everywhere
The principle behind every fix below is the same. Decide what the real URL is, redirect everything else to it permanently, and make sure your canonicals, internal links and sitemap all tell the same story.
Redirect at the server
Server-level redirects run before WordPress loads, which makes them the fastest and most reliable option. Always take a backup of the config file first — a syntax error in .htaccess takes the whole site down.
Apache, forcing HTTPS and non-www together in one rule:
RewriteEngine On
RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTP_HOST} ^www\. [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]
Nginx, doing the same thing:
server {
listen 80;
listen 443 ssl;
server_name www.example.com example.com;
return 301 https://example.com$request_uri;
}
Use 301, not 302. A 301 is permanent and passes ranking signals; a 302 tells Google the move is temporary and to keep the old URL indexed. Getting this backwards is one of the more common ways to make the problem worse.
Set WordPress straight
In Settings → General, both the WordPress Address and Site Address should be your chosen version, with the protocol you actually serve. WordPress uses these to build every internal link and every canonical tag it generates, so getting them right fixes a great deal at once.
If those fields are greyed out, they are being set in wp-config.php, and that is where to change them.
Let your SEO plugin handle canonicals
Rank Math, Yoast and SEOPress all output self-referencing canonicals automatically and strip query parameters by default. In almost every case the right move is to leave that alone and only override the canonical on individual pages where you have a specific reason — a syndicated article that should credit the original, for instance.
Writing your own canonical logic in functions.php is a common suggestion and usually a mistake. It duplicates what the plugin already does, and two canonical tags on one page is worse than none: Google ignores both.
Product variations
Variation URLs should canonicalize to the parent product. WooCommerce handles this correctly out of the box — the variation is served as a state of the product page rather than a separate page, and the canonical points at the parent. Where it breaks is when a theme or a filtering plugin generates real, crawlable URLs per variation.
Check it the direct way: open a variation URL, view source, and confirm the canonical points at the plain product URL with no parameters. If it does, there is nothing to fix.
If you genuinely want variations to rank independently — different sizes of a technical part with distinct part numbers and distinct search demand — then they need to be separate products with genuinely different descriptions, not variations. Half-measures here produce the worst outcome: pages too similar to rank separately and too separate to consolidate.
Pagination
Google stopped using rel=”next” and rel=”prev” in 2019 and announced it publicly after having quietly dropped support years earlier. You can leave the tags in for other crawlers, but do not expect anything from Google.
What Google wants now is simple: each paginated page carries a self-referencing canonical. Page two canonicalizes to page two, not to page one. Canonicalizing every page back to page one is a genuinely harmful pattern — it tells Google the content on pages two onward does not exist, and those posts can fall out of the index entirely.
Parameters
The parameter handling tool in Search Console was retired in 2022, so this is now handled entirely on your side. Self-referencing canonicals that exclude parameters cover the ordinary cases. For faceted navigation that generates large numbers of combinations, the stronger tools are noindex on filter results and robots.txt rules that stop crawling of the parameter patterns you never want visited.
Keeping staging out of the index
This deserves its own treatment because it is the one that embarrasses people, and because the usual advice is half wrong.
Password protection is the only complete answer. HTTP authentication at the server means crawlers cannot fetch anything, so nothing can be indexed, and your unfinished work is not visible to anyone who guesses the subdomain. On Apache:
AuthType Basic
AuthName "Staging - authorised access only"
AuthUserFile /path/to/.htpasswd
Require valid-user
Most managed hosts offer this as a toggle in the control panel, which is easier and harder to get wrong.
noindex is the second-best answer. A robots meta tag on every staging page keeps them out of the index while leaving the site reachable:
<meta name="robots" content="noindex, nofollow">
In WordPress, Settings → Reading → Discourage search engines does this for you. It is a request rather than a guarantee, but Google honours it.
robots.txt alone does not work, and this trips people up constantly. Blocking crawling with Disallow: / prevents Google from fetching the page — which also prevents it from seeing your noindex tag. A URL that is blocked but linked from elsewhere can still appear in results, listed by URL alone. If pages are already indexed and you want them out, you must allow crawling long enough for the noindex to be read, then block it afterwards if you like.
For a staging site already in the index, the fastest route is noindex on every page, then the Removals tool in Search Console for anything urgent, then password protection once it has cleared.
Verifying that it worked
Changes here are easy to make and easy to get subtly wrong, so check.
- Test every variant. All four combinations of protocol and www should land on the same final URL, in a single hop. Two hops — http to https to https+www — is a redirect chain and worth flattening.
- Confirm the status code. Use any HTTP header checker and look for 301, not 302 and not 200.
- Re-inspect in Search Console. URL Inspection will show whether Google’s selected canonical now matches yours. It takes days to weeks to update, so do not expect an instant answer.
- Update internal links. Redirects handle visitors, but every internal link still pointing at the old URL forces an unnecessary hop and keeps sending a contradictory signal. A search-and-replace across the database, done carefully and with a backup, is the usual fix.
- Check the sitemap. It should contain canonical URLs only. A sitemap listing URLs that redirect is a direct contradiction of everything else you just set up.
What canonicalization will not fix
Worth being clear about the limits, because duplicate content gets blamed for a lot of things it did not do.
It will not help if your pages are near-identical because the content is thin. Twenty product pages with two sentences each are not a canonicalization problem; they are a content problem, and consolidating them changes nothing about why they do not rank.
It will not consolidate pages that genuinely serve different intents. If two articles overlap enough to compete for the same query, the answer is to merge them into one better article with a 301, not to canonicalize one to the other and leave both live.
And it will not produce a visible ranking change on a small site with a handful of duplicates. The fix is worth doing because it is cheap, permanent, and removes a source of confusion. It is not a growth lever. If you are looking for one of those, look at what your pages actually say.
The short version
Pick one version of your domain. Redirect the other three with a 301. Let your SEO plugin write self-referencing canonicals and do not write your own. Point variation URLs at the parent product. Give every paginated page its own canonical. Password-protect staging. Then open the Pages report in Search Console in a month and see what changed.
Most sites can do all of this in an afternoon, and most sites never do.
Working through this list on your own site and would rather not? That is what an Expert Web Audit is for.

Advertisement. We earn a commission if you sign up through this link, at no extra cost to you.





