/ Redirect Checker Fixes / www Canonicalisation

How to Fix www vs Non-www Canonicalisation

When both www.example.com and example.com serve content as separate sites, Google sees two duplicate sites — ranking signals split, link equity diluted, indexing confused. The fix is picking one canonical hostname, 301-redirecting the other, then making the choice consistent across internal links, sitemaps, rel=canonical tags, and Search Console. Either www or non-www works for SEO; what matters is committing and being consistent.

1. Test the current state

Step 1
Both versions independently
curl -I https://www.example.com/
curl -I https://example.com/

# Expected (correctly canonicalised):
# One returns 200 OK
# The other returns 301 with Location: https://[canonical]/

# Problem state:
# Both return 200 OK (content served independently)
# Or chains exist
Step 2
Search results check
Search site:example.com and site:www.example.com separately in Google. If both return separate page sets, you have two indexed sites. If only one returns results, you're already canonicalised.
Step 3
Run Redirect Checker
Hostname mismatch findings list URLs where non-canonical version doesn't redirect. Audit the full set.

2. Pick a canonical

Either is fine for SEO. Decision factors:

Choose wwwChoose non-www
DNS flexibility (CNAME to CDN)Shorter, looks modern
Cookie scoping cleaner across subdomainsMarketing prefers brand without www
Existing backlinks point to wwwExisting backlinks point to non-www
Site has multiple subdomains (blog, app, api)Site has only the root domain

If existing backlinks heavily favour one version, pick that one to minimise migration impact. Use site: Google search or a backlink tool to check which has more.

3. 301 redirect the non-canonical version

nginx — non-www → www

server {
  listen 80;
  listen 443 ssl;
  server_name example.com;
  return 301 https://www.example.com$request_uri;
}

server {
  listen 80;
  listen 443 ssl;
  server_name www.example.com;
  # serves content
  root /var/www/html;
}

nginx — www → non-www

server {
  listen 80;
  listen 443 ssl;
  server_name www.example.com;
  return 301 https://example.com$request_uri;
}

server {
  listen 80;
  listen 443 ssl;
  server_name example.com;
  root /var/www/html;
}

Apache .htaccess — non-www → www

RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]

Apache .htaccess — www → non-www

RewriteEngine On
RewriteCond %{HTTP_HOST} ^www\.example\.com$ [NC]
RewriteRule ^(.*)$ https://example.com/$1 [R=301,L]

Cloudflare

Rules → Redirect Rules → Create rule
  When: Hostname equals "example.com" (or "www.example.com")
  Then: Static redirect
    URL: https://www.example.com${http.request.uri.path}${...}
    Status: 301
    Preserve query string: enabled

4. Update internal links

Hardcoded internal links to the non-canonical version cause unnecessary redirect hops on every navigation.

WordPress: search-replace

# WP-CLI search-replace (test with --dry-run first)
wp search-replace 'https://example.com' 'https://www.example.com' \
  --dry-run --skip-columns=guid

# After confirming, run live
wp search-replace 'https://example.com' 'https://www.example.com' \
  --skip-columns=guid

Static site: grep + sed

# Find affected files
grep -rl "https://example\.com" ./public

# Replace (test on one file first)
sed -i 's|https://example\.com|https://www.example.com|g' file.html

# Bulk
find ./public -name "*.html" -exec sed -i \
  's|https://example\.com|https://www.example.com|g' {} +

Database for dynamic sites

# MySQL
UPDATE wp_posts SET post_content = REPLACE(post_content,
  'https://example.com', 'https://www.example.com')
WHERE post_content LIKE '%https://example.com%';

# Backup database BEFORE running.

5. Update sitemap and rel=canonical

sitemap.xml

Every URL in sitemap.xml should use the canonical host. Regenerate from CMS or manually update.

<url>
  <loc>https://www.example.com/page</loc>
  <lastmod>2024-01-15</lastmod>
</url>

rel=canonical tags

<link rel="canonical" href="https://www.example.com/page" />

Canonical tags should match the actual served URL. CMS should output canonical based on the canonical host setting.

6. Update Google Search Console

Step 1
Verify both properties
Add both https://www.example.com and https://example.com as URL-prefix properties in Search Console. OR add a single Domain property example.com that covers all variants.
Step 2
Submit canonical sitemap
In the canonical property, submit sitemap.xml. The non-canonical property doesn't need its own sitemap (URLs redirect anyway).
Step 3
Use URL inspection on test pages
Inspect a non-canonical URL → "Test live URL" → confirm Google sees the 301 and the canonical URL. Inspect the canonical URL → confirm "Indexing allowed" and indexed status.

7. Update analytics and tracking

// Google Analytics 4
// Set "Hostname" as a custom dimension to spot stragglers
// Filter reports to canonical hostname only

// gtag.js setup
gtag('config', 'G-XXXX', {
  cookie_domain: 'www.example.com'  // or '.example.com' for shared
});

8. Verify the fix

Step 1
curl confirmation
curl -IL https://example.com/page
# Expected: 301 → https://www.example.com/page → 200

curl -IL https://www.example.com/page  
# Expected: 200 directly, no redirect
Step 2
Browser bar test
Type non-canonical URL in browser. Browser should resolve to canonical version. Address bar shows canonical URL after the redirect.
Step 3
Crawl with audit tool
Re-run the Redirect Checker site-wide. Zero hostname mismatch findings. All internal links use the canonical host.
💡 The most-forgotten part: internal links. Many sites correctly redirect external traffic but keep hardcoded internal URLs pointing at the non-canonical host. Every internal click then takes 2 hops. Use search-replace on the database AND on static template files. Audit afterwards by crawling your own site.

↪️ Re-run the Redirect Checker

Verify single-hostname canonicalisation site-wide.

Run Redirect Checker →
Related Guides: Redirect Checker Fixes  ·  Fix HTTPS Redirects  ·  Fix Trailing Slash  ·  Redirect Checker Guide
💬 Got a problem?