Canonical points to the wrong domain: staging and old-domain URLs left in your head tags

If the live site's canonical tags name another host, such as staging.example.com or a domain you moved away from, every page tells Google its real home is elsewhere. Google may index the other host or ignore the tags. Find where the old hostname is stored in WordPress and replace it.

This is a migration fault, and it tends to affect the whole site at once. It deserves a check on the day of every launch, domain change or staging push.

What it looks like

Before

html
<!-- served from https://example.com/pricing/ -->
<link rel="canonical" href="https://staging.example.com/pricing/">

After

html
<link rel="canonical" href="https://example.com/pricing/">

Check in ten seconds

code
curl -s https://example.com/ | grep -ioE '<link[^>]*rel=.canonical.[^>]*>|property=.og:url.[^>]*>'
curl -s https://example.com/ | grep -oE 'https?://[a-z0-9.-]+' | sort | uniq -c | sort -rn | head

The first command prints the canonical and og:url. The second counts every hostname mentioned in the homepage HTML, which exposes stray references in scripts, images and schema as well. Repeat on one post and one archive page. A canonical is a problem when its host, including www and the protocol, is not exactly the host you want indexed.

Cross-domain canonicals are legitimate when you republish someone else's article and credit the original. That is a deliberate, per-page choice. A different host on every page is not.

Where WordPress keeps the wrong host

Canonical URLs are built from permalinks, and permalinks are built from the site address. Check these in order:

  1. Constants in wp-config.php. WP_HOME and WP_SITEURL override the database. A staging value left in the file wins over anything you set in the dashboard, and the fields under Settings → General appear greyed out.
  2. The home and siteurl options. Under Settings → General, WordPress Address and Site Address. From the command line: wp option get home.
  3. Stored canonical overrides. A custom canonical typed into an SEO plugin is saved as a full URL in post meta. A site-address change does not touch it.
  4. Content and settings containing absolute URLs. Internal links, image URLs, menu items and page-builder data often embed the host.
  5. A page cache or CDN still serving HTML generated before the switch.
  6. Environment-aware hosts. Some managed hosts rewrite the site URL per environment; a misconfigured "primary domain" setting there produces the same symptom.

Replace the hostname properly

Back up the database first. Then, with WP-CLI:

code
wp option update home 'https://example.com'
wp option update siteurl 'https://example.com'
wp search-replace 'https://staging.example.com' 'https://example.com' --skip-columns=guid --dry-run

Read the dry-run report, then run it again without --dry-run. Use WP-CLI or a migration tool that understands serialized data. A plain SQL REPLACE changes string lengths inside serialized arrays and corrupts widget, theme and page-builder settings. Run the replacement for each variant that occurs: http://, https://, with and without www, and the JSON-escaped form https:\/\/staging.example.com that block and builder data use.

Remove or correct WP_HOME and WP_SITEURL in wp-config.php. Then flush the object cache, purge the page cache and CDN, and re-save permalinks.

In Hydrogen SEO, the default canonical is derived from the current permalink, so it corrects itself as soon as the site address is right. Only posts with a value in the Canonical URL field of the SEO Settings sheet keep an old host, and the search-replace covers those.

Other tags that carry the same mistake

The canonical is rarely alone. Check the same pages for the old host in:

  • og:url and og:image
  • JSON-LD @id, url and logo values
  • hreflang alternates
  • the XML sitemap's <loc> entries, and the Sitemap: line in robots.txt
  • RSS feed links

Paste a sitemap file into our XML sitemap validator to catch URLs on an unexpected host, and a page's head into the Open Graph preview to see which URL and image a share would use.

Deal with the other host

Fixing the tags stops the damage; the old host should also stop competing.

  • Staging or development site: put it behind HTTP authentication so nothing can crawl it. See staging site indexed if its URLs are already in Google.
  • Previous domain: it should 301 every URL to the same path on the new domain. Our guide to moving WordPress to a new domain covers the redirect map and the Change of Address step in Search Console.

Verify across templates

Run the first curl command against the homepage, a post, a page, a category, a product and a paginated archive. Every canonical should start with your live origin. In Search Console, inspect a key URL with a live test and confirm the user-declared canonical. The free SEO audit confirms that each URL you test has a canonical tag; the curl check above is what shows you the host inside it.

Common questions

Will Google deindex my live site because of this?

It can favour the other host if that host is crawlable and serves the same content, or it may ignore the tags because they conflict with other signals. Either way, fix it quickly; the outcome is not something to leave to chance.

Why are Settings → General URL fields greyed out?

WP_HOME or WP_SITEURL is defined in wp-config.php, which overrides the database values. Edit or remove the constants there.

Is it safe to run search-replace on the whole database?

With WP-CLI's search-replace, yes, because it handles serialized data. Take a backup, do a dry run first and skip the guid column.

I fixed it but view-source still shows the old domain. Why?

A cache is serving old HTML. Purge the page cache, any server-level cache and the CDN, then check in a private window.