WPCS - WordPress Currency Switcher Professional

Currency switcher not working with a cache plugin in WordPress: fixes

A currency switcher not working with a cache plugin in WordPress usually shows one of four symptoms: prices stay in the base currency after switching, the currency jumps back to the default on the next page, clicking the switcher does nothing, or everything works while you are logged in and fails for visitors. Two different things cause this. A page cache serves stored HTML that was built for another visitor, and JavaScript optimization (delay, defer, minify, combine) breaks the order in which the switcher's scripts run. Both have a fix that keeps your cache and your speed scores.

Why a page cache breaks currency switching

The [wpcs_price] shortcode converts the amount in PHP while WordPress builds the page. A page cache saves that finished HTML and sends the same copy to the next visitors, so they all see the currency of the visitor who filled the cache. The visitor's chosen currency is still remembered, but PHP never runs for a cached page, so nothing uses it.

The fix is in Settings → Currency Switcher → Options: set I am using cache plugin on my site to Yes. With this option on, the page loads as cached, and then the plugin's script front.js:

  1. collects every price printed by [wpcs_price] (each one is a span.wpcs_price carrying its original amount in data-amount);
  2. sends one POST request to /wp-admin/admin-ajax.php with action=wpcs_get_prices_html;
  3. replaces the prices with the answer, which is calculated for this visitor, and sets the switcher to the visitor's currency.

Three details matter when you troubleshoot:

  • Until that answer arrives, the switcher ignores clicks, so it never switches from a stale state. If the request is blocked or fails, the switcher stays dead. It is a typical reason for "clicking does nothing".
  • The option is written into the page as a small script variable. Pages cached before you changed it still carry the old value, so clear every cache layer after saving: cache plugin, server cache and CDN.
  • Only [wpcs_price] prices are redrawn. A [wpcs_current_currency] label, or values printed by PHP code in a template with $WPCS->wpcs_exchange_value(), stay as cached. Exclude pages that rely on them from the page cache.

The same request also applies GeoIP rules to visitors of cached pages; if detection itself is wrong, see GeoIP currency detection not working.

Is the wpcs_get_prices_html request slowing down the site?

Speed tests such as GTmetrix list a POST to admin-ajax.php with wpcs_get_prices_html near the end of the waterfall, sometimes with a long time next to it. Here is what it really costs:

  • It is one request per page view, sent on every page that loads the plugin's script, because the switcher needs the visitor's currency even where no price is shown. At most 500 prices are sent in one request.
  • It starts after the HTML is parsed and does not block the page from displaying. The visitor sees the page first; the prices update a moment later.
  • Its duration is roughly the time WordPress needs to load without page cache. On a healthy site that is a fraction of a second. If it takes several seconds, every uncached request on the site is that slow, and the cause is in the plugins or hosting, not in this request.
  • With JavaScript delayed until the first interaction, the request starts only when the test tool simulates one, so it shows up late and inflates the "fully loaded" time without affecting what the visitor sees.

Turn the option off only if no page cache stores your pages: no cache plugin, no server cache and no CDN caching of HTML. Then PHP prints the right currency directly. With any page cache in place, turning it off breaks switching for visitors.

Find JavaScript errors before changing settings

Test in a private window where you are not logged in. Page caches and most optimization plugins skip logged-in administrators, which is why the switcher can work perfectly for you and fail for every visitor. Open the developer tools (F12), reload, and look at the Console:

Console messageWhat happened
wpcs_array_of_get is not defined or wpcs_current_currency is not definedThe small inline script with the switcher's settings was delayed or moved below the plugin's script files
jQuery is not definedjQuery was delayed or deferred while scripts that need it ran
Errors in a combined or minified fileAny error in a combined file stops the code after it, the switcher included

Then open the Network tab, type admin-ajax into the filter and click the request with wpcs_get_prices_html. A working answer has status 200 and starts with {"prices":. Status 403 means the request is blocked (see the last section). Text or HTML before the opening brace means another plugin or a PHP notice printed output into the answer; the script cannot read it, so prices stay as cached and the switcher stays locked. No request at all with the option on means the script never ran: go back to the console.

WP Rocket, Perfmatters and other optimizers: what to exclude

The switcher needs three things to run in order: jQuery, the inline settings script that the plugin prints in the page head, and the files in the plugin's js folder (front.js plus the library of your drop-down view: ddslick, chosen or wSelect, and the Designer scripts if you use them). Delaying only some of them causes the not defined errors above.

In WP Rocket, go to File Optimization and add these lines to Excluded JavaScript Files under Delay JavaScript execution:

/wp-content/plugins/currency-switcher/
wpcs_
/jquery-?[0-9.](.*)(.min|.slim|.slim.min)?.js
/jquery-migrate(.min)?.js

The first line covers the plugin's files, wpcs_ is a keyword found in the inline settings script, and the last two lines keep jQuery from being delayed. If errors remain with Load JavaScript deferred on, exclude the plugin folder there too. WP Rocket explains both fields in Delay JavaScript execution and Exclude files from Load JavaScript deferred.

Other tools have the same switches under different names: script delay in Perfmatters, minify and merge in WP-Optimize, minify and combine in W3 Total Cache. Exclude the same plugin folder and jQuery, or turn off combining as a test. If the switcher works with the optimizer off, the problem is its configuration, and the console tells you which file is affected.

After every change, clear the cache and the optimizer's generated files (most plugins rebuild minified and combined files when you clear their cache), purge the CDN, and reload with Ctrl+F5. Testing against old optimized files is the most common reason a correct exclusion seems not to work.

Server cache you cannot turn off

Managed hosts often run their own page cache that cannot be disabled. Set I am using cache plugin on my site to Yes and clear the host's cache after the change.

Leave No GET data in link at No: the switcher then sends the visitor to the same page with ?currency=EUR, PHP builds that page and stores the choice. This only works while URLs with that parameter are not served from the cache. Many page caches skip URLs with query strings, but some host caches store each of them as a separate page. Then the choice is never stored, and the next page falls back to the previous currency. Ask the host to bypass the cache for the currency parameter. If they cannot, set No GET data in link to Yes. The choice is then saved by an admin-ajax.php request (wpcs_set_currency_ajax), which page caches do not store, and the reloaded page gets its prices redrawn. The same ?currency= parameter also lets you link to a page in a given currency, as shown in currency links without a shortcode.

Blocked requests: "You do not have sufficient permissions" and 403

When visitors who are not logged in see You do not have sufficient permissions to access this page on switching, or the requests above return 403, something blocks admin-ajax.php for anonymous requests: a security plugin's firewall, a "hide or lock wp-admin" feature, a hosting firewall rule or password protection of the /wp-admin/ folder. The plugin uses admin-ajax.php for these actions:

  • wpcs_get_prices_html: price redraw on cached pages;
  • wpcs_set_currency_ajax: switching when No GET data in link is Yes;
  • wpcs_convert_currency and wpcs_rates_current_currency: the converter and rates shortcodes.

Deactivate security and optimization plugins one at a time on a staging copy until the request returns 200, then allow admin-ajax.php with these actions in that plugin's settings, or ask the host to exclude it from its firewall rule.

Checklist

  • Tested logged out in a private window, after clearing all caches and pressing Ctrl+F5.
  • I am using cache plugin on my site is Yes wherever any page cache is active.
  • No red errors in the console; the wpcs_get_prices_html request returns 200 and starts with {"prices":.
  • The plugin folder, the wpcs_ inline script and jQuery are excluded from delay, defer and combine.
  • admin-ajax.php is not blocked for visitors.
  • URLs with ?currency= are not served from the cache, or No GET data in link is Yes.

If the switcher still fails, open a topic on the WPCS support forum with the page link, the console errors, the status and response of the admin-ajax request and the list of cache and optimization tools on the site.