How7o
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Reading: How to Dynamically Change Currency in WooCommerce
Share
How7oHow7o
Font ResizerAa
  • OS
Search
  • Home
  • Tools
  • Prank Screens
  • Learn
  • Blog
  • Contact
Follow US
© 2024–2026 How7o. All rights reserved.
How7o > Free Laravel, PHP, WordPress & Server Tutorials > Web Development > How to Dynamically Change Currency in WooCommerce
Web Development

How to Dynamically Change Currency in WooCommerce

how7o
By how7o
Last updated: May 10, 2026
7 Min Read
WooCommerce dynamic currency switcher — cookie-stored currency applied via woocommerce_currency filter
SHARE

A woocommerce currency switcher is three pieces: a form or query parameter that lets the visitor pick a currency, a cookie that remembers the choice across requests, and a filter on woocommerce_currency that changes which currency WooCommerce reports everywhere. The filter handles the display side (symbol, code, formatting); it doesn’t convert prices — for that you need a multi-currency pricing layer.

Contents
  • TL;DR
  • The HTML switcher
  • Allow-list validation
  • The cookie
  • The filter
  • The conversion caveat
  • Frequently asked questions
  • Related guides
  • References

Last verified: 2026-04-23 on WooCommerce 9.x with WordPress 6.5. Originally published 2023-02-10, rewritten and updated 2026-04-23.

TL;DR

// functions.php
$allowed = array( 'USD', 'EUR', 'GBP' );

// Resolve requested or stored currency
global $how7o_dynamic_currency;
if ( isset( $_GET['currency'] ) && in_array( $_GET['currency'], $allowed, true ) ) {
    $how7o_dynamic_currency = $_GET['currency'];
    setcookie( 'currency', $how7o_dynamic_currency, time() + ( 30 * DAY_IN_SECONDS ), '/' );
} elseif ( isset( $_COOKIE['currency'] ) && in_array( $_COOKIE['currency'], $allowed, true ) ) {
    $how7o_dynamic_currency = $_COOKIE['currency'];
} else {
    $how7o_dynamic_currency = 'USD';
}

// Apply it
add_filter( 'woocommerce_currency', function ( $currency ) {
    global $how7o_dynamic_currency;
    return $how7o_dynamic_currency ?: $currency;
} );

The HTML switcher

<form method="get">
    <label for="currency">Currency:</label>
    <select id="currency" name="currency">
        <option value="USD">USD</option>
        <option value="EUR">EUR</option>
        <option value="GBP">GBP</option>
    </select>
    <button type="submit">Switch</button>
</form>

A plain GET form — submits to the same URL with ?currency=XXX. The PHP snippet picks up the parameter on the next request.

Allow-list validation

$allowed = array( 'USD', 'EUR', 'GBP' );

if ( isset( $_GET['currency'] ) && in_array( $_GET['currency'], $allowed, true ) ) {
    // safe — $_GET['currency'] is one of the three
}

Never trust $_GET directly. The allow-list makes sure only known currency codes reach the cookie and the filter — preventing tampering that would plant garbage into user sessions or trigger downstream errors when WooCommerce looks up a bogus currency’s symbol.

woocommerce currency switcher — $_GET allow-list stores a cookie, woocommerce_currency filter applies it

The cookie

setcookie(
    'currency',
    $chosen,
    time() + ( 30 * DAY_IN_SECONDS ),
    '/',                // path — must be / for site-wide
    '',                 // domain — leave empty for current host
    is_ssl(),           // secure — only over HTTPS
    false               // httponly — keep false if JS reads it
);

WordPress’s DAY_IN_SECONDS constant keeps the math readable. Path '/' is critical — subpath cookies won’t reach /cart/ and /checkout/. is_ssl() flags the cookie as secure when the request came in over HTTPS.

The filter

add_filter( 'woocommerce_currency', function ( $currency ) {
    global $how7o_dynamic_currency;
    return $how7o_dynamic_currency ?: $currency;
} );

woocommerce_currency is the master filter — WooCommerce calls it whenever it needs the current currency code (for prices, cart totals, PayPal requests, etc.). Returning our stored value overrides the admin-configured default for this request only.

The conversion caveat

This filter only changes which currency is displayed. If your base currency is USD and a $10 product is shown with the EUR symbol, it’s shown as €10 — not converted. Three options for real pricing:

  • Informational only — the switcher shows the currency label for staff reference, prices stay in base currency (fine for B2B where invoices are always in the base currency).
  • Filter prices manually — pair woocommerce_currency with woocommerce_product_get_price and multiply by an FX rate from a config table. Doable for 3–5 currencies; brittle as the list grows.
  • Use a multi-currency plugin — WooCommerce Multi-Currency, WPML WCML, WooCommerce Payments built-in multi-currency. Handles per-currency pricing, rate updates, tax calculations. Right answer for production.

Frequently asked questions

What’s the quickest woocommerce currency switcher?

Read $_GET['currency'] against an allow-list, store it in a cookie, and filter woocommerce_currency to return the stored value on subsequent requests. ~20 lines in functions.php. Changes which currency symbol and code WooCommerce emits throughout the storefront — but note this doesn’t convert the prices themselves; you still need a conversion layer or multi-currency pricing plugin for that.

Does the woocommerce_currency filter convert prices too?

No — it only changes which currency is displayed (symbol, code, ISO). Prices stay in the store’s base currency numerically unless something else converts them. For real multi-currency (EUR prices actually charged in EUR), reach for WooCommerce Multi-Currency or similar. The filter is only appropriate when prices happen to match across currencies or when you’re showing informational currency labels.

Is the cookie-based approach safe against CSRF?

The currency switch itself isn’t a destructive action, so CSRF isn’t the main concern — but always validate the $_GET value against an allow-list (in_array($_GET['currency'], ['USD', 'EUR', 'GBP'])) so an attacker can’t force an arbitrary string into the cookie. Skipping the allow-list lets someone plant junk values that cause downstream errors.

Can I use the customer’s IP to auto-detect currency?

Yes — Cloudflare sets CF_IPCountry, MaxMind GeoIP2 lookups give you a country code. Map country to currency server-side (default EUR for EU countries, GBP for UK, USD for others) and set the cookie on first visit. This works as a first-visit default but still let users override via the switcher — some UK customers browse with US pricing intentionally.

Where should the cookie path be set?

'/' — the cookie should apply site-wide, so every page honors the switch. Setting it on a sub-path (/shop/) means the cart and checkout (on /cart/ and /checkout/) wouldn’t see the cookie and would show the default currency. Always '/' unless you have a very specific reason.

Related guides

  • How to Add a Custom Fee in WooCommerce — another cart-surface customization.
  • How to Remove Checkout Fields in WooCommerce — simplifying what the customer sees.
  • How to Display Orders Instead of Dashboard on the WooCommerce My Account Page — My Account tweak.
  • Fix ERR_TOO_MANY_REDIRECTS in WordPress After Switching to HTTPS — cookie/domain configuration gotchas.

References

WooCommerce woocommerce_currency filter docs: woocommerce.com/document/add-new-currency-to-woocommerce.

TAGGED:phpWooCommercewordpress

Sign Up For Daily Newsletter

Be keep up! Get the latest breaking news delivered straight to your inbox.
[mc4wp_form]
By signing up, you agree to our Terms of Use and acknowledge the data practices in our Privacy Policy. You may unsubscribe at any time.
Share This Article
Facebook Copy Link Print
Previous Article WooCommerce product view counter — meta-based counter with increment and display hooks How to Display a Product View Counter in WooCommerce Without a Plugin
Next Article WooCommerce get customer ID from order — WC_Order::get_user_id How to Get the Customer ID from an Order ID in WooCommerce
Leave a Comment

Leave a Reply Cancel reply

You must be logged in to post a comment.

FacebookLike
XFollow
PinterestPin
InstagramFollow
Most Popular
Laravel Eloquent ORM — a model class mapping to a database table with query methods
Laravel Eloquent ORM: The Complete Guide to Querying Your Database
June 16, 2026
Set vi as the default editor in Ubuntu — a terminal opening the vim editor
How to Set vi (Vim) as the Default Editor in Ubuntu
June 8, 2026
rsync says ALL DONE but files are missing — a terminal showing ALL DONE next to an empty folder
rsync Says “ALL DONE” but Files Are Missing: How to Verify
June 8, 2026
Migrate a website to a new server with rsync — files copying from an old server to a new one over SSH
How to Migrate a Website to a New Server With rsync
June 8, 2026
Bun runtime — faster JS toolkit replacing npm in Laravel projects
How to Install Bun Runtime on Ubuntu (And Use It in a Laravel Project)
May 24, 2026

You Might Also Like

Send a simple email in Laravel using Mail::raw and SMTP
Web Development

How to Send a Simple Email in Laravel (Fast SMTP + Mail::raw)

4 Min Read
Deleting a Laravel user cascades to remove related posts, photos, and notifications
Web Development

How to Delete Related Records in Laravel Eloquent

6 Min Read
Get N elements from a JavaScript array with slice for pagination
Web Development

How to Get N Elements from an Array in JavaScript

5 Min Read
JavaScript check valid URL — URL constructor vs regex
Web Development

How to Check if a JavaScript String Is a Valid URL

5 Min Read
How7o

We provide tips, tricks, and advice for improving websites and doing better search.

Tools

  • Age Calculator
  • Word Counter
  • Image Upscaler
  • Password Generator
  • QR Code Generator
  • See all tools→

Pranks

  • Fake Blue Screen Prank
  • Hacker Typer
  • Fake iMessage Generator
  • Windows XP Crash Prank
  • Windows 11 Update Prank
  • See all prank screens →

Company

  • About Us
  • Blog
  • Contact
  • Privacy Policy
  • Terms of Service
  • Sitemap
© 2024–2026 How7o. All rights reserved.
Welcome Back!

Sign in to your account

Username or Email Address
Password

Lost your password?