Canonical_url and hreflang tags holding back search result

Topic summary

A Shopify store’s SEO audit via Screaming Frog revealed issues with hreflang tag implementation that may be negatively impacting search rankings. The tool recommends using only the canonical_url variable within hreflang tags instead of the current approach.

Current Implementation:

  • Hardcoded base URLs for different regions (US .com, CA .ca, FR .ca/fr)
  • Manual URL construction using string replacement on shop.url
  • Template-specific logic for homepage, product, and collection pages

Proposed Solution:

  • Replace hardcoded URLs with {{ canonical_url }}{{ request.path }} pattern
  • Dynamically construct hreflang URLs using Shopify’s built-in variables
  • Apply consistent approach across all page templates

Status: The developer is seeking validation on whether their proposed solution correctly addresses the SEO concern, as they’re new to this topic and uncertain if the approach is optimal.

Summarized with AI on November 3. AI used: claude-sonnet-4-5-20250929.

Our client is using ‘Screaming Frog’ Seo tool to test the shopify store and it suggests that 'We should include only the ‘canonical_url’ in the ‘hreflang’ tag of every page. Also, they said that this is probably holding back their search results in the shopify store.

I am working on this code, I was searching documentation and more to figure it out and find a solution, this topic is new for me, our current code in ‘theme.liquid’ is the following one:

<!doctype html>
<html class="no-js" lang="{{ request.locale.iso_code }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="">
<link rel="canonical" href="{{ canonical_url }}">

<!-- Imaginary Store Hreflang -->
{% assign base_url_us = shop.url %}
{% assign base_url_ca = shop.url | replace: ".com", ".ca" %}
{% assign base_url_fr = shop.url | replace: ".com", ".ca/fr" %}

{% if template == 'index' %}
<link rel="alternate" hreflang="x-default" href="{{ base_url_us }}/">
<link rel="alternate" hreflang="en-US" href="{{ base_url_us }}/">
<link rel="alternate" hreflang="en" href="{{ base_url_us }}/">
<link rel="alternate" hreflang="en-CA" href="{{ base_url_ca }}/">
<link rel="alternate" hreflang="fr-CA" href="{{ base_url_fr }}">
<link rel="alternate" hreflang="fr" href="{{ base_url_fr }}">
{% elsif template == 'product' %}
<link rel="alternate" hreflang="x-default" href="{{ base_url_us }}{{ product.url }}">
<link rel="alternate" hreflang="en-US" href="{{ base_url_us }}{{ product.url }}">
<link rel="alternate" hreflang="en" href="{{ base_url_us }}{{ product.url }}">
<link rel="alternate" hreflang="en-CA" href="{{ base_url_ca }}{{ product.url }}">
<link rel="alternate" hreflang="fr-CA" href="{{ base_url_fr }}{{ product.url }}">
<link rel="alternate" hreflang="fr" href="{{ base_url_fr }}{{ product.url }}">
{% elsif template == 'collection' %}
<link rel="alternate" hreflang="x-default" href="{{ base_url_us }}{{ collection.url }}">
<link rel="alternate" hreflang="en-US" href="{{ base_url_us }}{{ collection.url }}">
<link rel="alternate" hreflang="en" href="{{ base_url_us }}{{ collection.url }}">
<link rel="alternate" hreflang="en-CA" href="{{ base_url_ca }}{{ collection.url }}">
<link rel="alternate" hreflang="fr-CA" href="{{ base_url_fr }}{{ collection.url }}">
<link rel="alternate" hreflang="fr" href="{{ base_url_fr }}{{ collection.url }}">
{% else %}
<link rel="alternate" hreflang="x-default" href="{{ base_url_us }}{{ request.path }}">
<link rel="alternate" hreflang="en-US" href="{{ base_url_us }}{{ request.path }}">
<link rel="alternate" hreflang="en" href="{{ base_url_us }}{{ request.path }}">
<link rel="alternate" hreflang="en-CA" href="{{ base_url_ca }}{{ request.path }}">
<link rel="alternate" hreflang="fr-CA" href="{{ base_url_fr }}{{ request.path }}">
<link rel="alternate" hreflang="fr" href="{{ base_url_fr }}{{ request.path }}">
{% endif %}
</head>

I found a solution, which I do not know if it is the right one, the probably solution is the following one:

<!doctype html>
<html class="no-js" lang="{{ request.locale.iso_code }}">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="theme-color" content="">
<link rel="canonical" href="{{ canonical_url }}">

<!-- Imaginary Store Hreflang -->
<link rel="alternate" hreflang="x-default" href="{{ canonical_url }}">
<link rel="alternate" hreflang="{{ request.locale.iso_code }}" href="{{ canonical_url }}">
</head>

Any help would be soo valuable for me.

Thanks