PrestaShop has two concepts that look alike and are not: several languages inside one shop, and several shops inside one installation (multistore). Hreflang behaves differently in each, and most problems come from treating the second as if it were the first.
First: friendly URLs and a language prefix
Before touching hreflang you need each language to have its own URL. If your shop distinguishes language through a parameter like ?id_lang=2, there is nothing to tag: to Google that is one URL with a parameter, not two versions.
- 1.Go to Shop Parameters → Traffic & SEO and enable friendly URLs.
- 2.Under International → Localization → Languages, check that each language is active and has the correct ISO code. That code ends up in the hreflang tag.
- 3.Confirm your URLs look like example.com/en/category and example.com/fr/categorie. If you still see id_lang in the address bar, regenerate the .htaccess from Traffic & SEO.
Check the default language too. In some installations the main language is served both with and without a prefix, and both URLs return 200. That is duplicate content before hreflang even enters the picture: pick one and redirect the other.
Case 1: several languages in one shop
This is the straightforward case. With friendly URLs on and languages configured correctly, PrestaShop knows every variant of each product, category and CMS page, because they are the same database entity with different translations.
Even so, PrestaShop does not always print the tags on its own depending on version and theme. Check the source of a product page: if you see no alternate tags in the head, you need a module. There are free options covering this case, generating the group from the shop’s active languages.
Case 2: multistore with separate domains
This is the real problem. If example.es and example.fr are separate shops in a multistore setup, each one only knows its own languages. Neither knows the other exists, so no automatic mechanism can build the full group: by default hreflang covers languages within a single shop, not shops against each other.
The solution without a paid module is to build the group in the template, reading the shop URL table. Override head.tpl in your child theme:
{* themes/your-child-theme/templates/_partials/head.tpl *}
{* Hreflang group across multistore shops.
$path must be the same canonical path on every domain. *}
{assign var=path value=$urls.current_url|replace:$urls.base_url:''}
<link rel="alternate" hreflang="es-ES"
href="https://example.es/{$path}" />
<link rel="alternate" hreflang="fr-FR"
href="https://example.fr/{$path}" />
<link rel="alternate" hreflang="x-default"
href="https://example.es/{$path}" />This block assumes the same path exists in both shops. In multistore setups the catalogue often differs: a product you only sell in Spain will produce a tag pointing at a 404 on the French shop. Gate the block to shared pages — home, main categories, CMS — or maintain a product-level mapping.
Modules: when they pay off
In PrestaShop, modules are the equivalent of WordPress plugins, with one important difference: the ones that handle multi-domain properly tend to be paid. They pay off when the catalogue differs between shops, because they manage exceptions product by product, which is exactly what a template cannot do without becoming unmanageable.
- •One domain with several languages: a free module is enough, or even native behaviour depending on your version.
- •Multistore with domains and an identical catalogue: the template is enough and adds no dependencies.
- •Multistore with differing catalogues: paid module. Maintaining exceptions by hand creates more errors than it solves.
The three typical PrestaShop faults
| Symptom | Cause | Fix |
|---|---|---|
| Tags point at URLs containing id_lang | Friendly URLs off, or .htaccess not regenerated | Enable friendly URLs and regenerate .htaccess |
| Each shop declares only its own languages | Multistore: shops are unaware of each other | Manual group in head.tpl, or a multi-domain module |
| Wrong language code | ISO code wrong under Localization → Languages | Fix the ISO code; it propagates to every tag |
Validate the whole group, not one URL
In PrestaShop the most expensive fault is the multistore one, and it is invisible from a single page: each shop looks perfectly coherent on its own. Only by comparing the URLs from every shop at once do you see that none of them declares the others.
Try the tool for free
Analyze your URLs with Hreflang Validator by iRankly. No sign-up, no credit card.
If you are on another platform, or want the conceptual detail of what each attribute does: