# 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.

Page: https://lintelagency.com/resources/shopify-tricks/market-and-language-urls

## 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.

## Facts

- **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:** 2 November 2026

## 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

```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

```text
# 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
```

## 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

- [Domains and languages for markets](https://help.shopify.com/en/manual/markets/customizations/domains-and-languages)
- [International domains and deep links](https://help.shopify.com/en/manual/international/managing-international-domains)
- [International SEO for markets](https://help.shopify.com/en/manual/markets/seo)
- [Locale-aware URLs in themes](https://shopify.dev/docs/storefronts/themes/markets/multiple-currencies-languages)

## Related

- [Selling in many currencies from one Shopify store](https://lintelagency.com/journal/shopify-markets-multi-currency)
- [Translating a Shopify theme and its content](https://lintelagency.com/journal/shopify-theme-translations)
- [One Shopify store with Markets, or expansion stores?](https://lintelagency.com/journal/one-store-vs-expansion-stores)
- [Show local prices and languages with @inContext](https://lintelagency.com/resources/graphql/storefront-local-prices-in-context)

License: MIT. Free to use in your own store and in client work.
