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
- Add the language under Settings > Languages and publish it; Shopify creates the /<language>/ path.
- Under Markets, open a market and choose subfolder, subdomain or top-level domain for it.
- In the theme, replace hardcoded /cart, /search and /collections links with routes.cart_url, routes.search_url and object .url values.
- 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.
Shopify documentation
- 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.
