Define Canonical URL in a Hugo Theme

Hugo is a static site generator, but links to your site may contain optional params like ref=... which may produce duplicate content for search engines. You can use canonical URL to define, which URL should be used by Google and co.

Google has a very detailed description how to consolidate duplicate URLs.

If you know Hugo and want just a copy a paste solution, just add this to your head:

<head>
  ...
  <link rel="canonical" href="{{ .Permalink }}">
  ...
</head>

This will result in an URL like:

<head>
  <link rel="canonical" href="https://qameta.com/posts/your-blog-post/">
</head>

Using relative URLs may be wrong

According to Google documentation for content. It is important to use absolute URL in your canonical URL definition. Some online sources say, that you should use relative permalink:

<head>
  <link rel="canonical" href="{{ .RelPermalink }}">
</head>

This would result to this:

<head>
  <link rel="canonical" href="/posts/your-blog-post/">
</head>

The missing Domain is considered to be wrong.

Use absolute URLs

Using absolute URLs is an important part for canonical URLs, as you may cross post content on your other sites or external media site (like medium), which may have the same link structure, but a different domain.

Lookup in your project folder my-website/themes/ for your Hugo Theme. There should be a folder layouts/ where the base structure of your HTML site is defined. There find the part, where <head> is defined. For my themes it is in /layouts/partials/head.html.

Just a hint, you can grep for it in your project:

$ grep -R "<head>" .
./thems/your-theme/layouts/partials/head.html:<head>

Open the file where your <head> part of the website defined and add it:

<head>
  ...
  <link rel="canonical" href="{{ .Permalink }}">
  ...
</head>

This will result in an URL like:

<head>
  <link rel="canonical" href="https://qameta.com/posts/your-blog-post/">
</head>

Summary

This is a simple solution to add canonical URLs to every page through Hugo Theme of your choice. A lot of themes have already this or a similar line included. If your theme does not, you should add it, to reduce the chance of content marked as duplicate due to URL parameters.

This solution does not handle internationalization. You may also want to define, where the content is cross posted, what is according to moz.com: Using the Cross Domain Rel=Canonical to Maximize the SEO Value of Cross-Posted Content an import part.