FOX - WooCommerce Currency Switcher Professional

Currency Switcher Resets to Default Currency on the Next Page

A visitor picks euros, opens the next page and sees the default currency again. Or the currency jumps: euros on the shop page, dollars on the product, euros once more after adding to cart. When a currency switcher resets to default currency like this, FOX has not forgotten anything by itself. One of three things happened: the page came from a cache and never reached the plugin, the storage that holds the visitor's choice did not keep it, or something on the site set a different currency again. Below: each cause with its fix, a diagnosis, and why a cached page can show the wrong currency for a second before it corrects itself.

How FOX remembers the selected currency

When a visitor clicks a currency, FOX opens the same page with ?currency=EUR in the address (or, with No GET data in link enabled in the Options tab, sends the choice by AJAX and reloads the page). The plugin writes the code into the storage selected in Currency storage. On every later request it reads the currency back from there.

If the storage has nothing for this visitor, FOX treats them as new: they get the Welcome currency, and the GeoIP rules if you use them. That is often the default currency people see "coming back". A cached page shows yet another one: the currency of whoever was cached first.

A page cache serves the page

This is the cause in most cases. A cached page carries the currency of whoever generated it, and FOX does not run for the visitor who receives the copy. Why the two collide, and the two honest ways out, are explained in why a currency switcher and a page cache fight each other. The symptoms that point to the cache:

  • The currency sticks for you while you are logged in, but not in a private window. Most page caches skip logged-in users.
  • The currency sticks once something is in the cart. Many server caches skip visitors with the woocommerce_items_in_cart cookie.
  • The page with ?currency= in the address is right, and the next page without it is wrong.
  • Two browsers show two different currencies on the same page.

The fix on the FOX side is one setting: I am using cache plugin on my site = Yes in the Options tab, then purge every cache. With it, each page asks the server for the visitor's real currency after loading and redraws the prices when the cached ones differ. Leave it off on a shop without page cache: there FOX already prints the right prices on the server.

Two more rules apply to every cache, whatever its brand:

  • Cart, checkout and account pages are never cached. Cache plugins exclude the standard WooCommerce pages, but a checkout page built by a theme or a funnel plugin is often missing from the list.
  • With No GET data in link enabled, switching reloads the same address, and a cache answers that reload with the old currency. On a cached shop this option needs the cache option, or it looks as if the switcher does nothing.

Cache layers

A shop can have three caches, each purged and configured on its own: the cache plugin, the server cache of the hosting (SiteGround, Kinsta and other managed hosts run one) and a CDN such as Cloudflare. Purging one does not purge the others. Optimizers that delay or combine JavaScript (WP Rocket, LiteSpeed Cache, NitroPack and others) can also keep the redraw from running: see FOX and WP Rocket and currency switcher stuck loading after JS optimization for the exclusions. Page fragment caching (such as the mfunc blocks of W3 Total Cache) is not needed: FOX redraws the prices itself.

When the redraw does not run

The cache option only helps if the redraw request is actually sent and answered:

  • Pages without prices. FOX sends the request only when the page contains product prices. On a cached home page, blog post or contact page without prices, the switcher keeps the currency of the cached copy. The choice is not lost: the next page with prices shows it. If the switcher label on such pages matters, exclude them from the page cache.
  • Prices printed in a non-standard way. FOX finds prices by the wrapper it adds to the WooCommerce price HTML: <span class="woocs_price_code" … data-product-id="…">. A theme, page builder or discount plugin that builds the price HTML itself drops that wrapper, so FOX sees no prices on the page. View the page source and search for woocs_price_code; if it is missing around the prices, disable plugins and switch to a default theme until it appears.
  • Blocked AJAX. A firewall or security plugin that blocks /wp-admin/admin-ajax.php for visitors stops the redraw. The currency then looks random, because every page shows whatever was cached.

The currency storage loses the choice

If the currency resets even with every cache switched off, the storage is not keeping the visitor's choice, and every page is a first visit. Currency storage in the Options tab decides how FOX recognises a visitor:

Currency storageThe visitor is recognised byTypical reason for resets
Transientthe IP address; with the cache option on, a random key the browser keeps in localStorageVisitors share one IP (offices, mobile carriers) or the IP changes during the visit. A server behind a proxy or load balancer that does not pass X-Forwarded-For or X-Real-IP sees one address for everybody, so visitors overwrite each other's currency.
PHP Sessionthe PHPSESSID cookie and session data on the serverThe server deletes inactive sessions (PHP's default lifetime is 24 minutes), the cookie ends when the browser closes, or several PHP servers do not share sessions.
FOX Sessiona cookie that starts with wp_woocs_session_, valid 48 hours; data in the WooCommerce sessions tableA proxy or CDN that strips the cookie; the session ends after 48 hours.
Memcached, Redisthe IP address, like TransientA wrong Storage server or Storage port: nothing is saved. Only listed when the PHP extension exists; see Memcached or Redis as currency storage.

A Transient value expires a day after the visitor's last page view, or after 30 days in the browser key mode. When the currency resets without a cache, switch to another storage type, save and test again. A currency that "changes randomly" between pages on a shop without a cache is the shared-IP case: a session storage fixes it.

Two side effects to know. Changing the storage type forgets every stored currency once, so all visitors become new. And with PHP Session or FOX Session every visitor gets the session cookie on the first request, so adding that cookie to a cache's "never cache" list turns the cache off for almost everyone after their first page. With a page cache or a CDN, Transient plus the cache option is the combination built for caching: the browser key travels with the redraw and cart requests, and no cookie is involved.

Something sets the currency again

When the storage works and there is no cache, the currency resets because something writes a new one.

  • Links with ?currency=. Any address that contains currency=USD sets dollars for the visitor who opens it. A menu item, banner or button whose link was copied from the browser while a currency was selected resets every visitor who clicks it. Search menus, widgets and page content for currency=.
  • Code that calls set_currency() on every page. Snippets that choose a currency by language, user role or page and call $WOOCS->set_currency() on each request overwrite the visitor's choice each time. Search the child theme and code snippet plugins for set_currency. A snippet like that must only run when it should win, not on every page view.
  • The checkout. With Is multiple allowed set to No in the Advanced tab, FOX switches to the base currency at checkout, and the visitor keeps it afterwards. That is by design: the currency switches back to default after checkout explains it. Checkout by GeoIP rules does the same with the currency of the visitor's country; see checkout currency based on customer country.

GeoIP rules do not cause resets on their own: they apply on the first visit only. If the GeoIP currency comes back on every page, the visitor is "new" on every page, which is the storage problem above.

Find the cause step by step

  1. Reproduce it as a visitor. Open a private window, not logged in, with an empty cart. Choose a currency, then open a page without prices, a product page and the cart.
  2. See which currency the page was built in. Open the page source (Ctrl+U) and search for var woocs_current_currency; the "name" in it is the currency of the HTML. A page built in a currency you did not choose came from a cache, or the storage lost the choice.
  3. Watch the redraw. Open the developer tools (F12), reload, filter the Network tab by admin-ajax and find the request with action=woocs_get_products_price_html. An answer of [] means the stored currency equals the page currency. An answer with current_currency names the currency FOX has stored for you. No request means the cache option is off, the page has no prices with the FOX wrapper, or front.js did not run; a 403 means a firewall blocks it.
  4. Bypass the cache once. Add a parameter the cache has never seen, such as ?nocache=4821, changing the number each time. Caches either skip such addresses or have no copy of them yet, so WordPress builds the page fresh. If the currency is right there and wrong without it, the cache is the cause.
  5. Switch the caches off. Disable the cache plugin, the server cache in the hosting panel and the CDN cache, and purge all three. If the currency still resets, change Currency storage, then search for currency= links and set_currency code.
  6. Turn the layers back on one at a time, testing after each. The layer after which the reset returns is the one to configure.

The wrong currency shows for a second, then changes

On a cached shop with the cache option on, this flicker is expected. The cached page arrives with the prices of whoever was cached first. When the HTML has been parsed, front.js waits 300 ms, collects the prices and sends one request to admin-ajax.php. The server compares the page currency with the visitor's stored one and, if they differ, returns new price HTML that replaces the old prices and updates the switchers. The wait you see is the time until the script starts plus that request, which is never cached and loads all of WordPress. On a slow phone it can take several seconds.

To make it shorter or invisible:

  • Do not delay FOX's scripts. A delay-until-interaction setting holds the redraw until the visitor scrolls or taps. The exclusions are in the JS optimization article.
  • Make the page and the server faster. The redraw cannot start before the page is parsed, and it cannot finish faster than the server answers an uncached request.
  • Turn on Prices preloader. It is shown under the cache option in the Options tab once that option is on. It hides the cached prices behind a small spinner from the moment the page appears until front.js starts the redraw, which is the long part of the wait on a slow page or with delayed scripts. While the redraw request itself runs, the cached prices are visible again, so a slow server still shows them briefly.

The preloader has two known side effects. Products loaded later, by AJAX pagination, infinite scroll or an AJAX filter, are not redrawn, because the redraw runs once per page load, and nothing removes the spinner from their prices. Disable AJAX loading for cached product lists, or switch the preloader off. And a third-party variation template that changes the price without WooCommerce's standard variation events leaves the spinner on the variation price; use the standard template, or have its author remove the woocs_preloader_ajax class from .woocs_price_code after each change.

Switching the cache option off removes the flicker but brings back the reset, because the cached prices then stay as they are. The only setup with no flicker at all is not caching the pages that show prices. If the shop can afford the server load, that is the cleanest choice.

Checklist

  • Tested logged out, in a private window, with an empty cart, after purging every cache layer.
  • I am using cache plugin on my site = Yes if any page cache or CDN caches the shop pages, No if none does.
  • Cart, checkout and account pages, custom ones included, excluded from every cache.
  • Prices wrapped in woocs_price_code spans, and the woocs_get_products_price_html request answered with status 200.
  • Currency storage changed and tested if the reset happens without any cache.
  • No links with currency= in menus or content, no code that calls set_currency() on every page, Is multiple allowed = Yes if the currency must survive the checkout.

If the currency still resets after all of this, open a topic on the FOX support forum with the page link, your cache setup and the answer of the woocs_get_products_price_html request, and we will look at it.