This article was last updated in May 2021
Due to how WP Engine's caching system is configured, it can interfere with features like geolocation and currency selection, by storing and serving the same content to all visitors. In some cases, a visitor from the US could be seeing content for Germany, while a visitor from the UK could be seeing content for Canada. This happens because WP Engine's caching stores a single copy of each content (e.g. a product page), which is what every visitor ends up seeing. Plugins can't fix this (and shouldn't), as they are not even loaded when the incorrect content is served.
We're aware of that issue, as we encountered it, and tried to address it, for quite a while. The WP Engine Team should also be familiar with the behaviour, as many of our customers who run WooCommerce site on the WP Engine service had to implement some fixes to address the caching logic.
The possible solution can be summarised as follows:
1. Configure the caching service to take into account visitor's currency
We have an article explaining how to configure the caching service to serve the correct content (see How to add dynamic caching to your site), depending on the absence/presence of the active currency and/or active country cookies. The logic is the following:
- Cookie "aelia_cs_selected_currency" absent -> First time visitor -> Skip cache and serve fresh content.
- Cookie "aelia_cs_selected_currency" present -> Returning visitor -> Use the cookies to serve the content from the cache.
We have been informed that some of WP Engine support staff tried to exclude the Currency Switcher cookie from the cache instead. That's not necessarily effective. The approach of "excluding the cookie from the cache" means "skip the cache when the cookie is present". That is:
- Cookie "aelia_cs_selected_currency" absent -> Serve cached content (the same content to everyone, which may or may not be correct).
- Cookie "aelia_cs_selected_currency" present -> Skip cache and serve fresh content.
This is the opposite of what our article describes, and it might not work correctly. The cache should always be used when the cookie is present (taking into account the value of the cookie), and skipped when the cookie is absent.
Skipping the cache when the cookie is present can yield wrong results. It can also have a significant impact on performance, as aelia_cs_selected_currency must be set 100% of the time to identify the content to be served. That would effectively mean always skipping the cache.
2. Use our Cache Handler, as a workaround, after configuring the cache to take into account URL arguments
Our Cache Handler (also documented in the article linked in the previous paragraph) works by running a script on each page, which generates unique URLs for each page. Those URLs have an extra argument appended to them, whose value changes depending on elements such as the active country and currency. This workaround works in most cases, but please be aware that, on WP Engine, in the past it caused infinite redirect loops on some sites (see section 2.1, below). When that happened, it turned out to be due to how WP Engine's caching was configured:
- WP Engine served the content for https://yoursite.com.
- The Cache Handler saw that the content is in the wrong currency (e.g. GBP, while it should be USD).
- The Cache Handler fetched the ID of the correct URL and performed a redirect, e.g. to yoursite.com/?ph=2314865892346. The "ph" part is generated dynamically, by the Cache Handler, depending on customer's country and currency, making the URL unique. The purpose of that is to drive the caching layer into storing a separate copy of the content for each currency.
- WP Engine served the content for yoursite.com, ignoring the extra URL argument and serving the old content still.
- The Cache Handler repeated the same logic repeats from #2, because the content was still the incorrect one (in GBP). This caused an infinite reload loop.
In another case, the WP Engine server even seemed to try acting "too intelligent". It noticed that visits to https://yoursite.com were redirected to a different URL (e.g. yoursite.com/?ph=2314865892346), so it decided to perform the redirection itself, on the server side. That caused another glitch:
- A visitor from the UK landed of https://yoursite.com.
- The WP Engine server redirected them to yoursite.com/?ph=2314865892346 (URL for GBP) immediately, without even loading the home page.
- A visitor from Germany landed of https://yoursite.com.
- The WP Engine server redirected them to yoursite.com/?ph=2314865892346 (URL for GBP), instead of letting the Cache Handler determine the correct URL.
- A visitor from the US landed of https://yoursite.com.
- The WP Engine server redirected them to yoursite.com/?ph=2314865892346 (URL for GBP) again.
This made it look like the Cache Handler was redirecting the users to the wrong location, whereas it was the server itself doing that, behind the scenes.
2.1 How WP Engine tried to fix the redirect loop issue
WP Engine tried to "exclude the ph argument", introduced by the Cache Handler, from the cache. Based on our understanding, that would have meant "don't serve cached content when the ph argument is present." As far as we know, that didn't always work, as visitors kept receiving cached content. We speculate that this is because the URL argument is ignored anyway by the server, like described in the "infinite loop" scenario. Besides, even if it worked, skipping the cache when the "ph" argument is present would defeat the purpose of having a dynamic URL in the first place, as the behaviour would become the following:
- WP Engine serves the content for https://yoursite.com
- The Cache Handler sees that the content is in the wrong currency (e.g. GBP, while it should be USD).
- The Cache Handler gets the ID of the correct URL and performs a redirect, e.g. to https://yoursite.com?ph=2314865892346
- WP Engine skips the cache (in theory), serving content for https://yoursite.com?ph=2314865892346 dynamically.
- The visitor goes to another page. The page URL also has the "ph" argument appended to it (like any other link on the site).
- WP Engine skips the cache, serving content dynamically.
The result would be the same as skipping the cache when the currency cookie is present, which basically means "always".
3. Conclusion
Ideally, the issue caused by the caching layer would have to be solved at that level. The Currency Switcher can't do anything about that, as the wrong content is served by the WP Engine server before the plugin is even loaded. This gives the following options to fix the issue:
- You could try to contact WP Engine, to see if they can configure their caching service as we described in our knowledge base, but it's possible that they can't do it. We have been discussing this kind of issue for years now, and they always told us that they can't add site-specific settings to their caching layer (other hosting providers, such as Kinsta, are more flexible, from that perspective).
- If WP Engine doesn't want to configure the caching service as described, you can try using our Cache Handler, as described above, keeping in mind that there may be some glitches to address. Those issues don't depend on our plugin either, it's just how the server works.
- If the Cache Handler doesn't work in "redirect" mode, because WP Engine's servers keep serving the wrong content, you can try to enable the "Ajax" mode instead. That mode has a couple of drawbacks:
- It fires up to three Ajax calls at every page load, to fetch the correct content. These requests must be uncached, and that can increase the load on the server. WP Engine might complain about that.
- Pages would load with some prices, which would be replaced with the correct ones after a few moments. This can be noticeable, as the prices would change on the page.
- The Ajax mode can only update "standard" prices generated by WooCommerce, e.g. for products, price filters and so on. It can't "see" prices introduced by custom fields, such as product addons, options, and so on. If these prices are visible on the site, they won't be refreshed. - As a last resort, you could disable the WP Engine page caching altogether. That would prevent all the issues caused by caching, but it would have an impact on performance.
- As an "after last" resort, you could consider switching to a hosting provider with a more flexible caching solution. Kinsta is currently our managed hosting provider of choice, and they are happy to configure the caching layer as you need. They did that for many of our customers already.
Hosting providers such as Cloudways allow users to install caching plugins such as WP Rocket, Litespeed or Comet Cache (old, but still functional). Although a caching plugin is not as fast as a native service, it can still offer good performance, once configured correctly.
Alternatively, you could use a VPS, on which you can install Varnish, and configure that service to serve the correct cached content. The article linked earlier (How to add dynamic caching to your site) includes a section about Varnish, which points to the documentation written by one of our collaborators, Mike Andreasen, whom you can hire on Codeable. He's an expert in setting up the Varnish caching logic and can configure it for you.
Should you have any questions, please feel free to contact us, and we will be ready to assist you.
You can purchase our internationalisation solutions from our online shop.