A lot of the projects we’ve worked on over the last few years with Shopify Plus have been fairly heavily international, with multiple independent Shopify stores. We’d generally be responsible for architecting how these stores worked from an international perspective and a big part of that is international traffic handling.
Although, on paper, hreflang may seem pretty straightforward with Shopify, in most instances there are actually a number of edge cases that need to be handled, in order for hreflang to work fully as expected. The most common edge cases are:
- Products, collections, blog posts or pages not being available across all stores – meaning if you apply a blanket rule, you’ll have hreflang links that lead to a 404. This is the one we’re focusing on in this guide.
- GEO IP conflicts – Google and other search engines not being able to crawl all alternate links due to GEO IP redirects.
- Dynamic pages – dynamic pages that are noindex’d or canonicalised being referenced within hreflang tags (e.g. filtered pages).
The biggest and most commonly not covered one of these, by a long way, is the first one and that’s the one we’ll be focusing on primarily in this guide.
What is hreflang?
So, to take a step back for those who aren’t fully familiar with this – hreflang is an html attribute that highlights region-specific and / or language-specific versions of the given page to search engines. The rel alternative annotations are designed to help search engines fully understand which pages are designed for which users.
Although it may seem simple on the face of things, hreflang is actually very complex, particularly when you’re working with big sites with complex, inconsistent catalogs. I’m not an SEO and don’t offer SEO services (I’m more commenting on how the solution should be architected with Shopify), if you need help with hreflang specifically, I’d suggest talking to Aleyda Solis, Carl Hendy or Sam Hurley, who are three SEOs I can strongly recommend.
Why is Hreflang complex with Shopify?
As most readers of this article or guide will know, Shopify doesn’t have a native multi-store offering, with the majority of merchants instead having completely independent Shopify stores for different regions or countries.
The main complexity that this causes is that there is no relationship between the stores – meaning you can’t rely on a common ID (e.g. a product ID in Magento, which would be global) or tag to link the different entities together. As a result of this, the average implementation would rely on Shopify stores using the same URL handles across page types and would then change the domains within the theme, meaning an hreflang setup could look something like:
- <link rel=”alternate” href=”https://www.testsite.co.uk/” hreflang=”en-GB” />
- <link rel=”alternate” href=”https://eu.testsite.com/” hreflang=”x-default” />
- <link rel=”alternate” href=”https://us.testsite.com/” hreflang=”en-US” />
- <link rel=”alternate” href=”https://fr.testsite.com/” hreflang=”fr” />
- <link rel=”alternate” href=”https://de.testsite.com/” hreflang=”de” />
This would then be the same for pages, collections, pages and blog posts. This big issue here though comes when these are different for different stores, as there’s no way of the different stores knowing that the pages don’t exist.
There’s no bulletproof fix for this right now (without creating a custom matrix externally or storing values in a PIM, which we do with one client) – you’re going to need to manage manually or rely on theme logic with manual intervention via either metafields or theme options.
How should hreflang be approached with multiple Shopify stores?
So, this is the main question that needs to be answered. Overall, there are two core approaches if you’re going to have these nuances between stores – these are to use the same URL keys and then manually intervene when there are product, collection, page or blog post nuances (via metafields or theme options as mentioned above) OR store all hreflang references as metafields (which is very messy if you’re managing manually due to needing to edit across all stores). Overall, for manageability, you probably want to avoid the second route unless you have a separate system (like a PIM) to manage this and are then pushing the data into Shopify, which can actually work really well..
Just to quickly cover how this would work (we do this with one client), you’d store the URL key for each local version of the product in the PIM and then pass each of the alternative URLs into Shopify as a metafield (either with or without the hreflang references). This may seem complex, but it’s actually a nice, scalable way to approach it. The issue is that this wouldn’t cover pages and blog posts, which you’d then likely do via a blanket rule with manual intervention where needed.
But, the approach we’d recommend for the average store (assuming there are limited differences) would be to use the same handles across all stores in all cases and then creating logic within the theme to reference this handle for each reference (replacing the domain) unless over-ridden. You’d then either create fields in the theme where you list hreflang exceptions (an approach I’ve seen WeMakeWebsites use, that’s worked well) or have a metafield where you can specify different hreflang references if needed (overriding the blanket logic). I’d say the first option has worked better for me, but the second option is likely better if you have a lot of nuances / differences.
It’s worth noting that the biggest cause of these differences in the catalog is generally having separate warehouses (so products not always existing) or local specific variations of products. If you have local language sites or even just country-specific sites, this can also create differences in content pages.
What if I have no catalog or page nuances between stores?
If the content and pages on your stores are exactly the same, you can simply create the theme logic to create the references and then just change the domain where needed for each reference (with the same URL handle). So an example for a product could be:
- <link rel=”alternate” href=”https://www.testsite.co.uk/product-123″ hreflang=”en-gb” />
- <link rel=”alternate” href=”https://eu.testsite.com/product-123″ hreflang=”x-default” />
- <link rel=”alternate” href=”https://us.testsite.com/product-123″ hreflang=”en-us” />
- <link rel=”alternate” href=”https://fr.testsite.com/product-123″ hreflang=”fr” />
- <link rel=”alternate” href=”https://de.testsite.com/product-123″ hreflang=”de” />
So the theme logic would include the domains and the targeting and the handle would then just be appended to each one.
If you have any questions on how to approach this with Shopify, please feel free to email me or add to the comments below.