On our page we use the Metatag module to show a canonical meta tag. In the configuration we use the [current-page:url:absolute] token. This works fine, but the problem is, that whether the page gets accessed by HTTP or HTTPS this protocol is used in the canonical URL.

For SEO purposes we want the canonical URL to be the same and use HTTP for both protocols.

How can we achieve this?

  • 2
    Instead of doing that in Drupal I would simply force all traffic to HTTPS by default via .htaccess or Apache config. Problem solved.
    – leymannx
    Aug 23, 2018 at 13:31

4 Answers 4


Drupal 7

You can implement hook_html_head_alter() to change head tags; the following is untested but should do the trick:

function MYMODULE_html_head_alter(&$head_elements) {
  foreach ($head_elements as $key => &$tag) {
    if (strpos($key, 'drupal_add_html_head_link:canonical:') === 0) {
      if (strpos('https://', $tag['#attributes']['href']) === 0) {
        $tag['#attributes']['href'] = str_replace('https://', 'http://', $tag['#attributes']['href']);

With the metatag module you can use the [current-page:url:relative] token instead of the [current-page:url:absolute] token.

so your canonical tag would become something like: http://www.mywebsite[current-page:url:relative]


Drupal 8

For nodes you have to use hook_ENTITY_TYPE_view_alter as that's the place where they got added to initially from NodeViewController::view().

And let me note that you are probably better off by simply redirecting all your incoming traffic to SSL by default: How to simply make the whole site HTTPS?

 * Implements hook_ENTITY_TYPE_view_alter().
function MYMODULE_node_view_alter(array &$build, Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display) {
  if (isset($build['#attached']['html_head_link'])) {
    foreach ($build['#attached']['html_head_link'] as $key => $head) {
      if ((isset($head[0]['rel']) ? $head[0]['rel'] : FALSE) == 'canonical') {

        $url = \Drupal\Core\Url::fromRoute('<current>', [], ['absolute' => 'true'])

        $url = str_replace('https://', 'http://', $url);

        $build['#attached']['html_head_link'][$key][0]['href'] = $url;

I just found out, that in the end we'll find all the head tags in hook_preprocess_html in the $variables['page']['#attached'] array to be altered.


Call me crazy and please correct me if I'm wrong, but can't you just hard-code the URL with the HTTP?

I'm sure there's something I'm missing, but if you drop in the full URL instead of using the token, you'll end up with that particular URL as the canonical for every variation of the page Drupal creates.

The caveat is that it creates an update nightmare as you have to remember to change the canonical if the alias of the page ever changes.

  • Sometimes, like when you use Domain Access, some articles are only avaliable on particular domains, and hard-coding URL would create dead links.
    – Mołot
    Oct 8, 2014 at 14:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.