Market and language URLs: /fr/, /en-ca/ and ?country=

How Shopify builds international URLs: subfolders like /fr/ and /en-ca/, subdomains and domains, ?country= deep links and locale-aware links in themes.

Subfolder
your-store.com/fr/, /en-ca/
Deep link
?country=<ISO code>
Where
Markets > market > Domain / language
SEO
Automatic hreflang and self-canonicals
Last checked

In short

Shopify gives each published language and each market its own URL: a subfolder such as your-store.com/fr/ or /en-ca/ by default, or a subdomain or separate domain you set under Markets > Domain / language. To send a campaign to one country inside a multi-country market, add ?country=DE. In themes, build links with routes.* in Liquid and Shopify.routes.root in JavaScript so visitors keep their language and currency.

How to use it

  1. Add the language under Settings > Languages and publish it; Shopify creates the /<language>/ path.
  2. Under Markets, open a market and choose subfolder, subdomain or top-level domain for it.
  3. In the theme, replace hardcoded /cart, /search and /collections links with routes.cart_url, routes.search_url and object .url values.
  4. For campaigns to one country without its own URL, link to your-store.com?country=<code>.

Code

locale-aware-links.liquid
{%- comment -%}
  Never hardcode /cart or /search: a visitor on /fr/ or /en-ca/ would be sent
  back to the default language and currency. routes.* and object .url values
  include the current locale path.
{%- endcomment -%}
<a href="{{ routes.cart_url }}">Cart</a>
<a href="{{ routes.all_products_collection_url }}">All products</a>
<a href="{{ product.url }}">{{ product.title }}</a>

{%- comment -%} The same rule in JavaScript: build on Shopify.routes.root ("/" or "/fr/"). {%- endcomment -%}
<script>
  fetch(window.Shopify.routes.root + 'cart.js')
    .then((response) => response.json())
    .then((cart) => console.log(cart.currency))
    .catch((error) => console.error(error));
</script>

{%- comment -%}
  A country switcher posts to /localization with country_code, which switches
  the visitor's country and currency. Output it only if there's a choice.
{%- endcomment -%}
{%- if localization.available_countries.size > 1 -%}
  {% form 'localization' %}
    <select name="country_code" onchange="this.form.submit()">
      {%- for country in localization.available_countries -%}
        <option value="{{ country.iso_code }}" {% if country.iso_code == localization.country.iso_code %}selected{% endif %}>
          {{ country.name }} ({{ country.currency.iso_code }})
        </option>
      {%- endfor -%}
    </select>
  {% endform %}
{%- endif -%}
urls.txt
# Subfolder per language: Shopify creates it when you publish a language
https://your-store.com/            primary language
https://your-store.com/fr/         French

# Subfolder per market on the same domain, for example a Canada market
https://your-store.com/en-ca/
https://your-store.com/en-ca/products/example-product

# Other domain strategies set under Markets > (market) > Domain / language
https://fr.your-store.com/         subdomain
https://your-store.fr/             top-level domain

# Deep link to one country inside a multi-country market (ISO 3166 code)
https://your-store.com?country=DE

# Cart permalinks and Ajax calls keep working under the prefix
https://your-store.com/fr/cart/12345678901234:1
https://your-store.com/en-ca/cart.js

Written by Lintel. MIT license: free to use in your own store and in client work.

Limits and edge cases

  • Shopify adds hreflang tags and self-referencing canonicals for every subfolder and domain, so /fr/products/shirt isn’t treated as a duplicate of /products/shirt.
  • Visitors in the EU aren’t redirected automatically between EU countries; offer a country selector.
  • A hardcoded /cart link sends a visitor on /fr/ back to the default language and currency.
  • International domains need a custom domain; myshopify.com can’t carry them.

Questions

How do Shopify language URLs work?
Each published language gets a path on the domain, such as /fr/, unless you assign it its own subdomain or domain under Markets.
How do I link to a specific country in Shopify Markets?
Use the market’s URL if it has one, or add ?country=DE (any ISO country code) to the link.
Are Shopify market subfolders bad for SEO?
No. Shopify adds hreflang tags and canonicals that link the versions, and subfolders share the main domain’s authority.
Why does my cart switch currency when I open it?
Usually a hardcoded /cart link in the theme. Use routes.cart_url so the market’s path is kept.
  • Checked on a Shopify store on the date shown. Shopify changes its admin often; if a step looks different, the idea usually still works.
  • Examples use placeholder IDs and your-store.myshopify.com. Replace them with your own.
  • MIT license for the code snippets.

Need this built, tested and maintained for your store? See Shopify development.

Have something to build? Let’s talk it through.

Taking a limited number of projects at a time. Every brief is read by an engineer, not a salesperson.

Gencer KarakayaShopify Engineer

An engineer reads your brief, and we reply by email.