How to Add and Check a Canonical Tag in HTML, WordPress and Shopify
A canonical tag is one line in the head of a page that tells search engines which address is the main version of that content. Without it, the same page reached through tracking parameters, filters, http and https or a trailing slash can look like several competing pages, and Google has to guess which one to show. Most sites need a self-referencing canonical on every indexable page and a cross-page canonical only on true duplicates. This guide shows the exact tag code, how to add it in plain HTML, WordPress with Yoast or Rank Math, and Shopify themes, and how to check the canonical a page actually outputs rather than the one you think you set.
- What a canonical tag is and what it does
- Canonical tag code and examples
- How to add a canonical tag in HTML
- How to add or fix the canonical URL in WordPress
- How to fix the canonical URL in Shopify
- How to check which canonical a page really outputs
- The fix, step by step
- Edge cases worth knowing
- Keeping canonicals correct
- Questions and answers
What a canonical tag is and what it does
A canonical tag is a <link> element with rel="canonical" placed in the <head> of a page. It names the preferred address for the content on that page. When Google finds several URLs showing the same or nearly the same content, it groups them together, picks one to index and show in results, and folds the signals from the others into it. Your canonical tag is your vote in that choice.
It is a strong hint, not an order. Google also weighs redirects, internal links, the sitemap, hreflang and whether the pages are truly duplicates. If your tag disagrees with everything else, Google may pick a different URL, and Search Console will say so. That is why adding the tag is only half the job; the other half is making the rest of the site agree with it.
There are two kinds of canonical you will use:
- Self-referencing. The page points to its own clean address. This is the normal case and belongs on every page you want indexed. It protects you when someone links to the page with
?utm_source=or other parameters. - Cross-page. A duplicate or near-duplicate points to a different, main page. Use this for printer versions, sorted or filtered listings, syndicated copies and product variants that do not deserve their own result.
A canonical tag is not a way to merge two different pages, and it does not hide a page from visitors. If an old page should never be visited again, a 301 redirect is the honest answer. The canonical fixes guide covers how canonicals fit alongside redirects and noindex.
Canonical tag code and examples
The tag itself is short. This is a self-referencing canonical for a service page:
<link rel="canonical" href="https://www.example.com/services/wedding-cakes/">
And this is a cross-page canonical on a filtered listing that should consolidate into the main category:
<!-- On https://www.example.com/cakes/?sort=price&flavour=lemon -->
<link rel="canonical" href="https://www.example.com/cakes/">
Five rules make the difference between a tag Google trusts and one it ignores:
| Rule | Right | Wrong |
|---|---|---|
| Use the full absolute address | https://www.example.com/cakes/ | /cakes/ or cakes/ |
| Match your live protocol and host | https and the host you actually serve | http, or www when the site redirects to non-www |
| Point to a page that returns 200 | A live, indexable page | A redirect, a 404 or a page with noindex |
| One canonical per page | A single tag in the head | Theme and plugin both printing one |
| Put it in the head | Inside <head> in the served HTML | In the body, or only added later by a script |
Relative addresses are allowed by the HTML specification, but they break easily when a page is copied, proxied or served on a staging host, so absolute addresses are the safer habit. Keep the trailing slash consistent with how your server actually answers, because /cakes and /cakes/ are different URLs.
Canonicals for files that are not HTML
A PDF cannot carry a head element, so you send the canonical as an HTTP response header instead. Google supports this for web search:
Link: <https://www.example.com/guides/cake-care.html>; rel="canonical"
How to add a canonical tag in HTML
On a hand-built or static site, open the template or each page file and add the tag inside the head, near the title and meta description:
<head>
<meta charset="UTF-8">
<title>Wedding Cakes in Leeds | Example Bakery</title>
<meta name="description" content="Tiered wedding cakes baked to order.">
<link rel="canonical" href="https://www.example.com/services/wedding-cakes/">
</head>
If you use a static site generator or a shared header include, add it once in the layout and build the address from the page's own path, so every page gets its own value. A common mistake is pasting the home page address into a shared header, which tells Google that every page is a copy of the home page. Pages then drop out of the index one by one.
For a server-side template, the pattern is the same: print the site's base address plus the clean path, without query strings. In PHP that might look like this:
<?php
$path = strtok($_SERVER['REQUEST_URI'], '?');
$canonical = 'https://www.example.com' . $path;
?>
<link rel="canonical" href="<?= htmlspecialchars($canonical) ?>">
That strips every parameter, which is right for tracking codes but wrong if a parameter genuinely changes the content, such as ?page=2 on a listing. Keep those parameters in the canonical, so page 2 points to page 2. The pagination guide explains why paginated pages should not all point to page 1.
How to add or fix the canonical URL in WordPress
WordPress core already prints a self-referencing canonical on single posts and pages through its rel_canonical() function. SEO plugins replace that output with their own and extend it to archives, categories and the home page. So on most WordPress sites you are not adding a canonical; you are checking and correcting the one the plugin prints.
Yoast SEO
Edit the post or page, open the Yoast SEO panel, choose the Advanced section and fill in Canonical URL. Leave it empty for a normal self-referencing canonical; only enter an address when this page is a duplicate of another. For template-wide changes, developers can use the wpseo_canonical filter:
add_filter( 'wpseo_canonical', function ( $url ) {
if ( is_page( 'cake-menu-print' ) ) {
return home_url( '/cake-menu/' );
}
return $url;
} );
Rank Math
Edit the post, open the Rank Math panel, go to the Advanced tab and use the Canonical URL field. The matching developer filter is rank_math/frontend/canonical.
Common WordPress canonical faults
- Two canonical tags. A theme hard-codes one in
header.phpwhile the plugin prints another. Remove the theme copy. - Two SEO plugins active. Yoast and Rank Math together, or an SEO plugin plus an all-in-one theme framework, often output duplicate tags. Keep one.
- Wrong host. The WordPress Address and Site Address settings still say http or the old domain after a move, so every canonical points to the wrong place. See the WordPress migration guide.
- Cached HTML. A page cache keeps serving the old tag after you change it. Purge the cache before you test.
How to fix the canonical URL in Shopify
Shopify themes print the canonical from the Liquid canonical_url object, normally in layout/theme.liquid. Open Online Store, then Themes, then Edit code, and search the layout for canonical. You should find one line like this:
<link rel="canonical" href="{{ canonical_url }}">
Shopify handles the common duplicates for you. A product reached through a collection, such as /collections/cakes/products/lemon-drizzle, gets a canonical to /products/lemon-drizzle. Leave that behaviour alone; it is correct.
The faults that do happen on Shopify are usually these:
- Missing tag. An older or heavily edited theme lost the line. Add it back inside the head of
theme.liquid. - Duplicate tag. An SEO app injects a second canonical. Check the rendered HTML and turn off the app's canonical option, or remove the theme line, so only one remains.
- Hard-coded address. A developer replaced
{{ canonical_url }}with a fixed domain, so every page claims to be the home page. - Wrong primary domain. If the store's primary domain in Settings, then Domains, is not the one you want indexed, canonicals follow it. Set the primary domain first.
Product and collection duplicates go deeper than the tag; the duplicate products guide covers variants, near-identical products and filtered collections.
How to check which canonical a page really outputs
The settings screen tells you what you asked for. The served HTML tells you what Google receives. Always check the second. From a terminal, fetch the page and pull out the tag:
curl -sL https://www.example.com/services/wedding-cakes/ | grep -io '<link[^>]*canonical[^>]*>'
More than one line in the result means more than one canonical. To check for a canonical sent as an HTTP header, look at the response headers:
curl -sI https://www.example.com/files/cake-care.pdf | grep -i '^link:'
In the browser, open Chrome DevTools, go to the Console and run:
[...document.querySelectorAll('link[rel="canonical"]')].map(l => l.href)
This shows the rendered page, after scripts have run. If curl shows one value and DevTools shows another, a script is rewriting the tag, and you should fix it at the source.
What Google decided
In Google Search Console, paste the address into URL Inspection and open the page indexing details. You will see the User-declared canonical, which is your tag, and the Google-selected canonical. When they match, you are done. When they differ, Google has overruled you, usually because internal links, the sitemap or a redirect point elsewhere, or because the content is a near-duplicate of another page. The canonical conflicts guide walks through that case.
Checking the whole website
To check a website for canonical tags at scale, run a crawl with the site crawler and sort pages by canonical status: missing, self-referencing, pointing elsewhere, pointing to a redirect or a 404, and pages with more than one tag. That list is your work queue.
The fix, step by step
Step 1
Decide the canonical address for each page
List your page types and write down the one address each page should be known by: https, your chosen host, the clean path and your usual trailing slash. Decide which pages are true duplicates, such as print versions, sorted listings or tracking links, and which page each should point to. Confirm each chosen address returns 200 by running curl -sI on it and reading the status line. You are finished when every template has a rule for its canonical address.
Step 2
Remove duplicate sources of the tag
Before adding anything, find every place that can print a canonical: the theme header, an SEO plugin, a Shopify app, a page builder or a CDN worker. Run curl -sL on a sample page and grep for canonical. If more than one tag appears, switch off all but one source. In WordPress keep the SEO plugin and remove any theme copy; in Shopify keep the theme line or the app, never both. Re-run the check until only one tag appears.
Step 3
Add the tag to the template head
Add a single <link rel="canonical"> inside the head of the shared layout, built from the page's own path rather than a fixed address. In plain HTML put it next to the title tag. In Shopify confirm theme.liquid contains {{ canonical_url }}. In WordPress leave the plugin's automatic canonical switched on. Save, purge any page cache, then fetch two different pages with curl and confirm each shows its own address.
Step 4
Set cross-page canonicals on true duplicates
For each real duplicate, point the canonical at the main page. In Yoast or Rank Math use the Canonical URL field in the Advanced section of that post. In custom code, map the duplicate path to the main address in the template. Do not do this for pages with distinct content. Fetch each changed page and confirm the tag now names the main page, and that the main page still names itself.
Step 5
Align redirects, links and sitemap
Make the other signals agree with your tags. Check that http and non-preferred host versions 301 redirect to the canonical address. Update menus and internal links that use parameter or old addresses. Regenerate the XML sitemap so it lists only canonical URLs that return 200. Spot check with curl -sI http://example.com/ and follow the Location header until it lands on the canonical address with a 200 status.
Step 6
Check the output across the site
Crawl the whole site and export each page's canonical. Filter for pages with no canonical, more than one canonical, a canonical that points to a redirect or 404, and a canonical that points to a different page unexpectedly. Fix each group at its template, not page by page. Run the crawl again after fixing. You are done when every indexable page either names itself or names a deliberate main page.
Step 7
Inspect key pages in Search Console
Open URL Inspection in Google Search Console for your most important pages, one per template. Run the live test to confirm Google can see the new tag in the rendered HTML. Then read the indexed result for the User-declared canonical and the Google-selected canonical. Where they now match, request indexing if the page is new or changed. Where they still differ, look for duplicate content or conflicting internal links.
Step 8
Monitor the indexing report
Over the next few weeks, watch the Page indexing report in Search Console. Duplicate and alternate page counts should settle to the URLs you expect, such as parameter and filtered addresses, while your main pages move into the indexed group. Google recrawls at its own pace, so allow days to weeks. If an important page stays under a duplicate reason, inspect it again and compare its content with the page Google chose.
Edge cases worth knowing
- Canonical plus noindex. Pointing a page's canonical at another URL while also marking it
noindexsends mixed signals. Pick one: canonical for a duplicate you want consolidated,noindexfor a page that should not appear at all. - Canonical to a different language. Each language version should canonicalise to itself and link to the others with hreflang. A French page canonicalising to the English one drops out of French results. See hreflang and canonical conflicts.
- Canonical chains. Page A points to B, and B points to C. Google may follow it, but point A directly at C.
- www and non-www. The canonical should use the same host your redirects settle on. Settle that first with the www canonicalisation guide.
- Very different content. If the two pages are not really duplicates, Google tends to ignore the tag. A canonical cannot make an unrelated page inherit another page's place in results.
- Syndicated articles. If a partner republishes your article, ask them to noindex their copy; Google no longer recommends cross-domain canonicals for syndication, and a link back to the original helps too.
Keeping canonicals correct
Canonicals break quietly. A theme update, a new plugin, a domain move or a caching layer can change every tag on the site at once, and nothing looks wrong to visitors. Build three habits:
- Check after every template change. After a theme update, a plugin install or a new page builder, run the curl check on one page of each template: home, category, product or post, and a static page.
- Crawl monthly. A scheduled crawl catches missing, duplicated and wrong canonicals before Google acts on them. Compare the count of self-referencing pages against last month.
- Keep signals aligned. Your sitemap should list only canonical addresses, menus should link to canonical addresses, and redirects should end on canonical addresses. When all four agree, Google almost always follows your tag.
1. How do I add a canonical tag to a page?
Add a single link element with rel set to canonical and the page's full address as href inside the head section of the HTML. On most sites you do this once in the shared template so every page outputs its own address, rather than editing pages one by one. WordPress SEO plugins and Shopify themes already print one, so on those platforms you normally check and correct the existing tag. After adding it, fetch the page with curl or view the source to confirm exactly one canonical appears with the right address.
2. What is an example of a canonical tag?
A typical self-referencing canonical looks like a link element with rel equal to canonical and an href of https://www.example.com/services/wedding-cakes/, placed in the head of that same page. A cross-page example is a filtered listing such as /cakes/?sort=price pointing its canonical at https://www.example.com/cakes/. Both use the full absolute address, the live https protocol and the same host the site redirects to. The code examples on this page show both forms ready to copy and adapt to your own addresses.
3. How do I add a canonical tag in WordPress?
WordPress already outputs a self-referencing canonical on posts and pages, and SEO plugins such as Yoast and Rank Math take over and extend it. To set a different canonical on one page, edit it, open the plugin panel, go to the Advanced section and enter the address in the Canonical URL field. Leave the field empty for the normal self-referencing tag. Then check the live page source, because a theme or second plugin can print a duplicate tag that confuses search engines.
4. How do I fix the canonical URL in Shopify?
Open the theme code editor, find layout/theme.liquid and make sure the head contains one canonical line that uses the canonical_url Liquid object rather than a fixed address. Shopify then sets sensible canonicals for products reached through collections. If an SEO app also adds a canonical, turn off one of them so only a single tag remains. Also confirm the primary domain in the store settings is the one you want indexed, because canonicals follow it.
5. How can I check a website for canonical tags?
For one page, view the page source and search for canonical, or run curl on the address and grep the output, which shows exactly what the server sends. In Search Console, URL Inspection shows both your declared canonical and the one Google selected. For a whole website, run a crawl that records the canonical of every page, then filter for pages with none, more than one, or a canonical pointing at a redirect, a 404 or an unexpected page.
6. Should every page have a self-referencing canonical?
Yes, every page you want indexed should normally carry a canonical pointing to its own clean address. It costs nothing and protects the page when people link to it with tracking parameters, mixed case or other variations, because those copies then consolidate into the main address. Google does not require it, and pages can be indexed without one, but a self-referencing tag removes guesswork. Pages you do not want indexed at all are better handled with noindex than with a canonical.
7. Why is Google ignoring my canonical tag?
Google treats the canonical as a strong hint, so it can overrule it when other signals disagree. The usual reasons are internal links or the sitemap pointing to a different version, redirects that land somewhere else, two canonical tags on the page, a canonical to a page that redirects or returns an error, or content that is not really a duplicate. Fix the conflicting signals, confirm a single correct tag in the served HTML, then request indexing and give Google time to recrawl.
The site audit crawls your pages and flags missing, duplicated and conflicting canonical tags, including canonicals that point to redirects or errors, so you can fix them template by template.
Open Site Audit Fixes โ