Skip to content Skip to sidebar

This thread is resolved. Here is a description of the problem and solution.

Problem:
You are using WPML with WooCommerce Multilingual & Multicurrency on a catalogue-only site without any pricing, cart, or checkout functionalities. Despite disabling multcurrency, WCML is still setting 'wcml_client_currency' and 'wcml_client_currency_language' cookies, which prevent Varnish from caching guest responses.

Solution:
We recommend implementing a custom MU plugin to selectively remove these specific WCML cookies on guest WooCommerce catalogue pages, while preserving other necessary cookies like those for WPML language settings. Here's a step-by-step guide on how to do this:

<?php<br />/**<br /> * Plugin Name: Strip WCML Currency Cookies for Catalogue Cache<br /> * Description: Removes unnecessary WCML currency Set-Cookie headers for guest catalogue pages so Varnish can cache first responses.<br /> */<br /><br />add_action( 'template_redirect', function () {<br />    if ( is_admin() || is_user_logged_in() || wp_doing_ajax() ) {<br />        return;<br />    }<br /><br />    if ( function_exists( 'is_cart' ) && ( is_cart() || is_checkout() || is_account_page() ) ) {<br />        return;<br />    }<br /><br />    $is_catalogue_context =<br />        ( function_exists( 'is_shop' ) && is_shop() ) ||<br />        ( function_exists( 'is_product' ) && is_product() ) ||<br />        ( function_exists( 'is_product_category' ) && is_product_category() ) ||<br />        ( function_exists( 'is_product_tag' ) && is_product_tag() ) ||<br />        is_tax( get_object_taxonomies( 'product' ) );<br /><br />    if ( ! $is_catalogue_context ) {<br />        return;<br />    }<br /><br />    add_action( 'shutdown', function () {<br />        if ( headers_sent() ) {<br />            return;<br />        }<br /><br />        $headers = headers_list();<br /><br />        header_remove( 'Set-Cookie' );<br /><br />        foreach ( $headers as $header ) {<br />            if ( stripos( $header, 'Set-Cookie:' ) !== 0 ) {<br />                continue;<br />            }<br /><br />            if (<br />                stripos( $header, 'wcml_client_currency=' ) !== false ||<br />                stripos( $header, 'wcml_client_currency_language=' ) !== false<br />            ) {<br />                continue;<br />            }<br /><br />            header( $header, false );<br />        }<br />    }, 9999 );<br />}, 20 );<br />?>

This approach is safe for a catalogue-only site and does not interfere with WPML's language handling or WooCommerce's product categorization and filtering. If you find this solution not applicable due to updates or it doesn't fit your case, please check related known issues at https://wpml.org/known-issues/, verify the version of the permanent fix, and confirm that you have installed the latest versions of themes and plugins. If issues persist, we highly recommend opening a new support ticket at WPML support forum.

This is the technical support forum for WPML - the multilingual WordPress plugin.

Everyone can read, but only WPML clients can post here. WPML team is replying on the forum 6 days per week, 22 hours per day.

This topic contains 3 replies, has 0 voices.

Last updated by Bobby 1 month, 1 week ago.

Assisted by: Bobby.

Author Posts
June 1, 2026 at 6:41 am #18072168

xavierC-5

We use WPML with WooCommerce Multilingual & Multicurrency. This is a pure catalogue site — no prices, no cart, no checkout, no currency of any kind. Multicurrency is disabled in WCML settings.

Despite this, WCML is still setting these cookies on every guest page response:
Set-Cookie: wcml_client_currency=VND
Set-Cookie: wcml_client_currency_language=en

These cookies serve no purpose on our site and are preventing Varnish from caching guest responses.
Is there a setting, hook, or filter to stop WCML from setting these currency cookies on guest responses when no currency is used at all?

June 1, 2026 at 11:37 pm #18074205

Bobby
WPML Supporter since 04/2015

Languages: English (English )

Timezone: America/Los_Angeles (GMT-07:00)

Hi there,

The behavior is expected from our side as the cookie exists so that if the user switches currency on page 1, they still see that currency on page 5.

Unfortunately there is no out of the box way to "deactivate" the cookie.

You could attempt some things to remove it via custom code, Claude and ChatGPT have some recommendations, however, I would be very careful as none of this has been tested by our team.

Here is the recommendation recommended by the Ai, again please note that this is not something that we expect a client to deactivate as it is useful for operating ecommerce sites.

--------------- Do Not Test without a backup in place, generated by Ai ----------

Filter WCML before it registers its session hooks
WCML exposes a filter to short-circuit the multi-currency initialisation. Try this early (e.g. in functions.php or an MU plugin):

// Prevent WCML from initialising currency sessions entirely for guests

add_filter( 'wcml_enable_multi_currency', '__return_false' );

If that alone isn't enough (it depends on WCML version), combine with:

add_filter( 'wcml_load_multi_currency', '__return_false' );
add_filter( 'wcml_multi_currency_is_enabled', '__return_false' );

June 2, 2026 at 2:05 am #18074338

xavierC-5

Hi Bobby,

Thank you for your explanation regarding the `wcml_client_currency` and `wcml_client_currency_language` cookies.

Our use case is a bit different from a normal ecommerce store:

* The site uses WooCommerce only as a catalogue structure.
* There are no visible prices.
* There is no cart.
* There is no checkout.
* There is no currency switcher.
* Multicurrency is disabled.
* The site uses WPML with two languages, so we must preserve language behavior.
* We still need WooCommerce Multilingual & Multicurrency active because the catalogue uses WooCommerce products, product categories, attributes, and filters.

The issue is that WCML still sends these response headers on guest catalogue/filter pages:

Set-Cookie: wcml_client_currency=...
Set-Cookie: wcml_client_currency_language=...

On Cloudways/Varnish, any `Set-Cookie` response header prevents the first guest response from being cached. This means product category/filter pages require extra PHP hits before Varnish can serve a HIT.

We tested a targeted MU plugin that removes only these two WCML currency `Set-Cookie` headers on guest WooCommerce catalogue pages, while preserving any other cookies such as WPML language cookies.

This is the MU plugin we tested:

<?php
/**
* Plugin Name: Strip WCML Currency Cookies for Catalogue Cache
* Description: Removes unnecessary WCML currency Set-Cookie headers for guest catalogue pages so Varnish can cache first responses.
*/

add_action( 'template_redirect', function () {
if ( is_admin() || is_user_logged_in() || wp_doing_ajax() ) {
return;
}

if ( function_exists( 'is_cart' ) && ( is_cart() || is_checkout() || is_account_page() ) ) {
return;
}

$is_catalogue_context =
( function_exists( 'is_shop' ) && is_shop() ) ||
( function_exists( 'is_product' ) && is_product() ) ||
( function_exists( 'is_product_category' ) && is_product_category() ) ||
( function_exists( 'is_product_tag' ) && is_product_tag() ) ||
is_tax( get_object_taxonomies( 'product' ) );

if ( ! $is_catalogue_context ) {
return;
}

add_action( 'shutdown', function () {
if ( headers_sent() ) {
return;
}

$headers = headers_list();

header_remove( 'Set-Cookie' );

foreach ( $headers as $header ) {
if ( stripos( $header, 'Set-Cookie:' ) !== 0 ) {
continue;
}

if (
stripos( $header, 'wcml_client_currency=' ) !== false ||
stripos( $header, 'wcml_client_currency_language=' ) !== false
) {
continue;
}

header( $header, false );
}
}, 9999 );
}, 20 );

What the plugin is intended to do:
1. Run only on frontend guest requests.
2. Skip logged-in users, admin, AJAX, cart, checkout, and account pages.
3. Run only on WooCommerce catalogue contexts:
- shop
- product page
- product category
- product tag
- product taxonomies / filters
4. Temporarily remove all Set-Cookie headers.
5. Re-add every Set-Cookie header except:
- wcml_client_currency
- wcml_client_currency_language
6. Preserve other cookies, especially WPML language behavior.

We are not trying to disable WPML language cookies, and we are not trying to remove all cookies. We only want to stop the two WCML currency cookies because this site has no pricing, no cart, no checkout, and no currency switching.

Could you please review this approach and confirm:

1. Is this safe for a catalogue-only WooCommerce site using WPML in two languages?
2. Could removing only these two `Set-Cookie` headers cause any product/category/attribute translation issue?
3. Is there a more official WPML/WCML hook to prevent these two currency cookies from being sent in the first place?
4. Would your suggested filters be safer than this header-level removal?

Suggested filters from your previous reply:

add_filter( 'wcml_enable_multi_currency', '__return_false' );
add_filter( 'wcml_load_multi_currency', '__return_false' );
add_filter( 'wcml_multi_currency_is_enabled', '__return_false' );

Our preference would be to prevent WCML from sending the cookies at source, but we need to keep WooCommerce multilingual catalogue functionality active.

Best,
Xavier

June 2, 2026 at 7:45 pm #18076941

Bobby
WPML Supporter since 04/2015

Languages: English (English )

Timezone: America/Los_Angeles (GMT-07:00)

Hi Xavier,

Thank you for the detailed writeup

To answer your four questions directly:

1. Is the MU plugin approach safe for a catalogue-only WPML site?

Yes. The logic is sound. You're acting at the HTTP header level after WordPress and WCML have already done their internal work, so you're not interfering with any PHP-side state. WPML language routing, translated product categories, attributes, and taxonomy filters all operate independently of these two cookies. Removing them from the response has no effect on any of that.

2. Could removing these two headers cause any translation issues?

No. The wcml_client_currency and wcml_client_currency_language cookies are exclusively used by WCML's currency session machinery — price display, currency switching, and conversion. Since your site has none of those features active, nothing reads these cookies on the way in, and nothing breaks when they are absent. WPML's language cookies (wpml_referer_url, _icl_current_language, etc.) are separate and your plugin correctly preserves them.

3. Is there a more official hook to prevent the cookies being set at source?

The closest upstream option is a combination of these filters, added early (e.g. in an MU plugin before WCML initialises):

add_filter( 'wcml_enable_multi_currency', '__return_false' );
add_filter( 'wcml_load_multi_currency', '__return_false' );

However, the availability and effect of these filters depends on your exact WCML version, and in several versions they suppress the switcher UI without fully preventing the cookie-writing code path from running. This means they may not reliably solve the Varnish problem on their own.

4. Are the filters safer than the header-level removal?

Not necessarily — and for your specific goal (ensuring Varnish can cache guest responses) the header-level approach is actually more reliable, because it guarantees the Set-Cookie headers are absent from the response regardless of what WCML does internally. The filters are closer to the source but less predictable across WCML versions.

My recommendation for your setup is to keep your MU plugin as the primary fix, and optionally add the wcml_enable_multi_currency and wcml_load_multi_currency filters alongside it. The filters reduce unnecessary WCML initialisation work; the header scrubbing ensures the Varnish problem is definitively solved either way.

One small suggested improvement to your shutdown hook, since you are on a catalogue-only site and guests will never have WordPress auth cookies, the re-add loop is safe as-is. But if you ever extend the site to allow user accounts, you may want to add an explicit guard to always preserve any cookie whose name starts with wordpress_ or wp-settings-, just as a precaution.