No results found

Try a different search query

Popular searches:

Add to Cart

Cart

You have no purchases yet

Browse Marketplace

Setting up multilingualism in OpenCart: hreflang, x-default and language prefixes in URL

Why Google indexes only one language of your OpenCart store and how to fix it using language prefixes, hreflang, and x-default.

7 min read
6
0
Setting up multilingualism in OpenCart: hreflang, x-default and language prefixes in URL

A multilingual store on OpenCart rarely falls in search results for obvious reasons. More often, something else happens: products are translated, languages are connected, the switcher works, but Google indexes only one language version, the second seems not to exist. The reason is almost always one — incorrect URL structure and lack of SEO markup for languages. Let's figure out how to fix this on OpenCart 3.x (the logic is the same for 2.x).

 

1. Why standard OpenCart ruins SEO of a multilingual store

OpenCart by default switches language through session and cookie, not through URL. That is, the Ukrainian and English versions of a product live at one address, and which one to show is decided by the visitor's cookie.

For a search engine, this is a disaster. Googlebot comes without your cookie, sees one language (usually the default), and simply doesn't find the second — there's no separate URL for it to index. In practice, it looks like this: in Search Console, hundreds of pages in the main language and almost empty for the second, even though the content is fully translated.

The conclusion is simple: each language version of a page must live at its own unique address. Without this, all other settings make no sense.

 

2. Language prefix in URL

The most convenient way to give each language its own URL is a language prefix in the path:

 

https://example.com/uk/product/...
https://example.com/en/product/...
https://example.com/pl/product/...

In theory, you can distribute languages across subdomains (en.example.com) or separate domains (example.com.ua + example.com), but this is more expensive to maintain and only makes sense for large international projects with separate teams. For a typical store, a prefix in the path is the optimal option.

Separately, you need to decide what to do with the primary language.

 

There are two working approaches here:

 

A. Prefix for all languages, including the primary

/ua/product/...
/en/product/...

 

B. Primary language without prefix, others — with prefix

/product/...        ← Ukrainian (default)
/en/product/...     ← English

Option B looks cleaner for the primary market and is usually chosen. But it's more complex: you need to correctly serve the default language without a prefix and not create duplicates (so the same Ukrainian page doesn't open both at / and at /ua/). The main rule is to choose one approach and stick to it throughout the site, without exceptions for individual pages.

Clean OpenCart 3 doesn't know how to do language prefixes in SEO URLs at all. You need a module that embeds a language segment into routing: determines the language from the URL, serves the correct locale, and generates all internal links already with the prefix.

 

3. hreflang markup

hreflang tells the search engine which version of a page is intended for which language or region. Without it, Google may show an English speaker a Ukrainian page or decide that two language versions are duplicates and keep only one in the index.

In the <head> of each page, a complete set of links to all its language versions is added — including the page itself:

 

html

<link rel="alternate" hreflang="uk" href="https://example.com/" />
<link rel="alternate" hreflang="en" href="https://example.com/en" />
<link rel="alternate" hreflang="pl" href="https://example.com/pl" />
<link rel="alternate" hreflang="x-default" href="https://example.com/" />

 

Four rules that 90% of implementations fail on:

  • Bidirectionality. If the Ukrainian page points to the English one as an alternative, the English page must point back to the Ukrainian. One-way links are silently ignored by Google — you won't see an error, it just won't work.
  • Absolute URLs. Only a full address with https://. Relative paths (/en/...) don't work.
  • Self-references. A page must contain hreflang to itself, otherwise the cluster is considered incomplete.
  • Identical sets. On all pages in the cluster, the set of alternatives must be identical.

 

As for language codes: the standard is ISO 639-1 (uk, en, pl). Region is added via hyphen only if needed: en-gb, en-us, pl-pl. It's important not to confuse — in hreflang, language is mandatory, and region is optional. The notation hreflang="ua" is incorrect because ua is a country code, not a language code; Ukrainian is always uk.

Regional variants are needed when one language targets multiple countries with different content — for example, English for the US and Britain with different prices. For a typical Ukrainian store, simple uk, en, pl without regions is enough.

 

4. The meaning of x-default

x-default is the version of a page for everyone whose language you haven't explicitly provided for. A Canadian with French browser language, a Brazilian, a visitor from Asia — if there's no separate hreflang for their language, Google will show exactly x-default.

 

html

<link rel="alternate" hreflang="x-default" href="https://example.com/" />

Here you put either an international version (often English), or the main language of the store, or a separate language selection page. For a store aimed only at Ukraine, x-default can point to the Ukrainian home page — that's sufficient. The element is not formally required, but without it you leave it up to Google to decide "what to show everyone else," and it doesn't always guess correctly.

 

5. Canonical and hreflang together

This is the place where things most often break, because two tags perform opposite tasks and easily conflict.

canonical says "this is the main version among duplicates." hreflang says "this is another language version, not a duplicate." If you mix them up — Google will listen to canonical and remove language versions from the index.

Rule: canonical of each language page points to itself. The Ukrainian page — canonical to Ukrainian, English — to English. hreflang then lists all languages.

 

html

<!-- on the page /en/desktops -->
<link rel="canonical" href="https://example.com/en/desktops" />
<link rel="alternate" hreflang="uk" href="https://example.com/desktops" />
<link rel="alternate" hreflang="en" href="https://example.com/en/desktops" />

A typical mistake is to set canonical of all language versions to the Ukrainian "original" page. The logic "it's a translation of one product" seems reasonable, but for Google it's a direct signal "English and Polish are copies, don't index them." Result: traffic from only one language.

 

6. Sitemap and language switcher

An XML sitemap can duplicate hreflang via xhtml:link — this is an additional channel through which Google finds language connections, especially useful on large catalogs where the crawler doesn't reach every page.

 

xml

<url>
  <loc>https://example.com/en/desktops</loc>
  <xhtml:link rel="alternate" hreflang="uk" href="https://example.com/desktops"/>
  <xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/desktops"/>
</url>

The language switcher also affects SEO more than it seems. Two common mistakes: the switcher takes everyone to the homepage (instead of the same page in another language) and changes only the cookie, not the URL. The correct switcher leads to the language equivalent of the current page and changes the address itself — then each click forms a valid internal link that the search engine sees.

 

7. Ready-made solution: "SEO Multilang PRO" module

Doing everything described above on clean OpenCart means digging into the router, controllers, and templates and risking problems with each update. The SEO Multilang PRO module solves these tasks without changes to system code.


What it provides in terms of this article:

  • Language URLs with prefixes (/ua/..., /en/..., /pl/...) — each language gets its own address that Google can index separately. You can also set the same SEO URLs for different languages: they will remain unique thanks to the prefix, without manual duplication.
  • Primary language without prefix (approach B from section 2) — flexibly configurable, up to the option with prefixes for all languages.
  • Full control over hreflang and x-default, including regional variants (pl-pl, en-gb) — exactly what was discussed in sections 3–4, but without manually editing templates.
  • Language sitemaps with alternatives and language meta tags title/description/keywords for the homepage.
  • Language selection popup and correct redirection of a new visitor to the primary language without 301 redirect — that is, without harming indexing.
  • Support for multi-stores, regions and cities, multi-store in subfolders, shortcodes tied to languages and regions.


Technically important, the module does not change OpenCart system code, does not use ioncube, and does not contact the developer's server — if it's unavailable, the store continues to work. Broad compatibility: OpenCart 1.5.x, 2.x, 3.x and builds like ocStore, PHP from 5.6 to 8.4, any theme built according to OpenCart standards.

It's worth mentioning the separate option "Settings according to Ukrainian law" 🇺🇦. This is a sore subject for stores that make Ukrainian the primary language retroactively: the naive approach kills old positions. The module makes the transition correctly — Ukrainian gets the prefix /ua/..., and the old pages without a prefix remain in the index, so reindexing doesn't reset accumulated traffic. The redirect algorithm takes context into account: whether the user is entering for the first time, coming from search to a non-language page, or consciously switched languages themselves.

The module supports OpenCart 2.0.3–3.0.5, has documentation and a demo, license — for one domain.

 

8. Checklist before launch

  1. Each language version of a page has its own unique URL with a prefix.
  2. A single URL strategy has been chosen (prefix for all / primary without prefix) and maintained throughout the site.
  3. hreflang is on all pages, bidirectional, with absolute URLs and self-references.
  4. x-default has been added.
  5. canonical of each page points to itself, not to another language.
OCTemplates

OCTemplates

OCTemplates — команда розробників та дизайнерів з України з досвідом у веброзробці з 2002 року. З 2015 року спеціалізуються на шаблонах та модулях для OpenCart: швидких, SEO-оптимізованих і готових до роботи в реальних умовах e-commerce. Продукти OCTemplates використовують тисячі інтернет-магазинів у Європі, Азії, Північній Америці та Австралії. Кожен покупець отримує не лише готове рішення, а й технічну підтримку та консультації з налаштування магазину.

article
1
views
6
likes
0
followers
0

Recommended Products

by markimax

SEO multilang PRO

SEO Multilang PRO module for OpenCart - a powerful multi language optimization tool. Increase your store's visibility and SEO effectiveness

1
sales
708 ₴

Related Posts

Email Marketing for E-commerce Marketing

Email Marketing for E-commerce

How to build an effective email strategy for an online store: automation, segmentation, and best practices.

Email Marketing E-commerce Conversion
6,721 6 19 min
15 Jan 2026

Comments (0)

Replying to

Please log in to leave a comment

Log In

No comments yet

Be the first to comment on this article!

We use cookies

We use cookies and similar technologies to improve your experience, analyse traffic, and show personalised ads. Read our Cookie Policy for details.