WordPress already generates a basic canonical tag for single posts and pages automatically, but if you need control over archives, categories, or custom setups, you can add your own canonical tags directly through your theme’s functions.php file — no SEO plugin required. Here’s exactly how to do it.
What a Canonical Tag Does
A canonical tag is a meta tag that specifies the primary URL pointing to the original web page containing content that may be duplicated on other webpages elsewhere. If duplicate or near-duplicate content exists across multiple URLs, the canonical tag tells search engines which version is the “real” one to index.
Where WordPress Already Handles This — And Where It Doesn’t
Most WordPress themes generate a canonical tag automatically, especially for single posts and the front page, though themes differ in how they generate meta tags. The gap shows up elsewhere. Most themes don’t generate canonical tags for different archives, such as categories and tags. More specifically, archive pages — categories, tags, custom taxonomies, and authors — are generated without a canonical tag by default.
Step 1: Remove the Default Canonical Function
Before adding your own, you need to disable WordPress’s built-in canonical output to avoid duplicate tags. Add this to your theme’s functions.php:
remove_action('wp_head', 'rel_canonical');
This removes the built-in canonical tag to make sure it’s not duplicated with your new custom code.
Step 2: Add a Custom Function for Common Page Types
Here’s a version that covers single posts, the homepage, and category and tag archives:
function add_canonical_link() {
global $post;
if (is_singular()) {
$canonical_url = get_permalink($post->ID);
} elseif (is_home() || is_front_page()) {
$canonical_url = home_url('/');
} elseif (is_category()) {
$canonical_url = get_category_link(get_query_var('cat'));
} elseif (is_tag()) {
$canonical_url = get_tag_link(get_query_var('tag_id'));
} elseif (is_archive()) {
$canonical_url = get_permalink();
} else {
$canonical_url = get_permalink();
}
echo '<link rel="canonical" href="' . esc_url($canonical_url) . '" />' . "\n";
}
add_action('wp_head', 'add_canonical_link');
This function checks whether you’re on a single post or page, the homepage, a category archive, a tag archive, or another archive type, and outputs the appropriate canonical URL for each case, hooked into wp_head.
A More Thorough Version That Handles Pagination and Search
If your site has paginated archives or search results pages, a more complete function accounts for those cases too:
function custom_canonical_tag() {
$canonical_url = '';
if (is_front_page() || is_singular()) {
$canonical_url = get_permalink();
} elseif (is_home() || is_archive()) {
if (is_paged()) {
$canonical_url = get_pagenum_link(get_query_var('paged'));
} else {
$canonical_url = get_pagenum_link();
}
} elseif (is_search()) {
$canonical_url = home_url('/?s=' . urlencode(get_search_query()));
}
$canonical_url = strtok($canonical_url, '?');
$canonical_url = preg_replace('#(?<!https:|http:)/+#', '/', $canonical_url);
echo '<link rel="canonical" href="' . esc_url($canonical_url) . '" />' . "\n";
}
add_action('wp_head', 'custom_canonical_tag');
This approach cleans query strings and normalizes slashes in the resulting URL before outputting the tag, handling paginated pages and search result URLs alongside the standard single-post and archive cases.
How to Apply This to Your Site
- Log in to your WordPress dashboard.
- Go to Appearance > Theme Editor (or better, edit functions.php through a child theme or via FTP/SFTP for safety).
- Locate and open functions.php.
- Paste in the remove_action call and your chosen custom function.
- Save the file and verify the change on the live site.
It’s crucial to create a child theme before making changes directly to functions.php, since editing a parent theme’s files means your changes get wiped out on the next theme update.
How to Verify It’s Working
Once you’ve made the change, confirm it took effect properly. You can check whether your canonical tag is working by viewing the page source in your browser, using Google Search Console’s URL Inspection tool, or running an SEO crawler like Screaming Frog to confirm correct implementation.
Common Mistakes to Avoid
- Duplicate canonical tags. If you have an SEO plugin and your theme also outputs a canonical tag, you’ll end up with two competing canonicals, and search engines may end up ignoring both — always disable one before adding the other.
- Canonical pointing to a broken page. If the canonical URL returns a 404 error, search engines will ignore it entirely, so always verify the canonical target is a live, accessible page.
- Canonical pointing to a redirected URL. If your canonical points to a URL that 301-redirects elsewhere, search engines may get confused — the canonical should always point to the final destination URL, not an intermediate redirect.
- Missing self-referencing canonicals. Every page should have a self-referencing canonical tag pointing to its own URL, even without known duplicates, since this protects against URL parameter variations you might not be aware of.
Join The Discussion
Have you implemented canonical tags manually on a WordPress site instead of relying on an SEO plugin, and how did it affect your indexing or crawl behavior? Share what your functions.php setup looks like, whether you’ve had to account for multilingual or multi-domain configurations, and if you’ve run into any conflicts between theme-generated and plugin-generated canonicals along the way.