TABLE OF CONTENTS

  1. Important notes
  2. Example 1 - Forcing a specific currency in all cases
  3. Example 2 - Selecting the currency depending on the active language
    1. Example 2.1 - Using WPML
    2. Example 2.2 - Using Polylang
    3. Example 2.3 - Using WeGlot
    4. Example 2.4 - Using TranslatePress
  4. Example 3 - Setting the currency in specific conditions
  5. Example 4 - Manually setting the currency against user's session and profile
  6. Example 5 - Setting a specific currency for search engine crawlers
  7. Example 6 - Forcing checkout in a specific currency
  8. Example 7 - Forcing the currency depending on user's role
  9. Example 8 - Forcing the currency for API requests
    1. Example 8.1 - Forcing the currency for calls to the new WooCommerce API
    2. Example 8.2 - Forcing the currency for calls to the legacy WooCommerce API
  10. Example 9 - Set the currency using a custom URL argument


Important notes

The code in this article is considered a customisation. As such, it's outside the scope of our support service. Should you need assistance implementing the code, please feel free to contact us to request a consultation.


Setting the currency for current session and user's profile

The Currency Switcher will check for a selected currency during the woocommerce_init event. To force the selected currency to a specific one, set the value of $POST ["aelia_cs_currency"] in a hook attached to woocommerce_init event (the user is already authenticated when such event is fired). The hook must have a priority of 0 (zero), as the Currency Switcher will run its own with a priority of 1.


Examples

To use the code in the examples, simply place it in your theme's functions.php. See How to Safely Add Custom Code to WordPress Sites for more information on how to do that.


Example 1 - Forcing a specific currency in all cases

This example shows how to force the currency to a specific value on page load. This code is useful if you would like to use the Currency Switcher features to enter product prices in multiple currencies in the backend, but you would like to sell them in a single currency. 

add_filter('wc_aelia_cs_selected_currency', function($selected_currency) {
  // Only change the currency on the frontend
  if(!is_admin() || defined('DOING_AJAX')) {
    // Force selected currency to US Dollars. This will ensure that all 
    // customers will always see prices and place orders in that currency
    $selected_currency = 'USD';
  }

  return $selected_currency;
}, 10);

  

Example 2 - Selecting the currency depending on the active language


Tip: if you use one of these snippets, selecting another currency manually will not have any effect. The code snippet will force the currency back to the one linked to the language.  


Example 2.1 - Using WPML

add_action('woocommerce_init', function() {
  // Only change the currency on the frontend
  if(!is_admin() || defined('DOING_AJAX')) {
    // Map each language to a currency
    $language_currency_map = array(
      // German = EUR
      'de' => 'EUR',
      // Swedish = SEK
      'sv' => 'SEK',
      // Norwegian = NOK
      'no' => 'NOK',
    );
    
    if(defined('ICL_LANGUAGE_CODE') && isset($language_currency_map[ICL_LANGUAGE_CODE])) {
      $_POST['aelia_cs_currency'] = $language_currency_map[ICL_LANGUAGE_CODE];
    }
    else {
      // Default: USD
      $_POST['aelia_cs_currency'] = 'USD';
    }  
  }
}, 0);

Example 2.2 - Using Polylang

add_action('woocommerce_init', function() {
  // Only change the currency on the frontend
  if(!is_admin() || defined('DOING_AJAX')) {
    // Map each language to a currency
    $language_currency_map = array(
      // German = EUR
      'de' => 'EUR',
      // Swedish = SEK
      'sv' => 'SEK',
      // Norwegian = NOK
      'no' => 'NOK',
    );
    
    if(function_exists('pll_current_language') && isset($language_currency_map[pll_current_language()])) {
      $_POST['aelia_cs_currency'] = $language_currency_map[pll_current_language()];
    }
    else {
      // Default: USD
      $_POST['aelia_cs_currency'] = 'USD';
    }  
  }
}, 0);

Example 2.3 - Using WeGlot

add_action('woocommerce_init', function() {
  // Only change the currency on the frontend
  if(!is_admin() || defined('DOING_AJAX')) {
    // Map each language to a currency
    $language_currency_map = array(
      // German = EUR
      'de' => 'EUR',
      // Swedish = SEK
      'sv' => 'SEK',
      // Norwegian = NOK
      'no' => 'NOK',
    );
    
    if(function_exists('weglot_get_current_language') && isset($language_currency_map[weglot_get_current_language()])) {
      $_POST['aelia_cs_currency'] = $language_currency_map[weglot_get_current_language()];
    }
    else {
      // Default: USD
      $_POST['aelia_cs_currency'] = 'USD';
    }  
  }
}, 0);

Example 2.4 - Using TranslatePress

add_action('woocommerce_init', function() {
  // Only change the currency on the frontend
  if(!is_admin() || defined('DOING_AJAX')) {
    // Map each language to a currency
    $language_currency_map = array(
      // German = EUR
      'de_DE' => 'EUR',
      // Swedish = SEK
      'sv_SE' => 'SEK',
      // Norwegian = NOK
      'no_NO' => 'NOK',
    );
    
    global $TRP_LANGUAGE;
    // Find the currency that matches the language set by TranslatePress
    if(!empty($TRP_LANGUAGE) && isset($language_currency_map[$TRP_LANGUAGE])) {
      $_POST['aelia_cs_currency'] = $language_currency_map[$TRP_LANGUAGE];
    }
    else {
      // Default: USD
      $_POST['aelia_cs_currency'] = 'USD';
    }  
  }
}, 0);

Example 3 - Setting the currency in specific conditions

If you want to set the currency only in specific cases, you can write a filter for hook wc_aelia_cs_selected_currency.  

add_filter('wc_aelia_cs_selected_currency', function($selected_currency) {
  // Replace <SOME CONDITION IS SATISFIED> with the appropriate condition 
  if(<SOME CONDITION IS SATISFIED>) {
    // Force selected currency to US Dollars
    $selected_currency = 'USD';
  }

  return $selected_currency;
}, 10);

The above filter will set the currency only for current page load. User's cookies and profile will be unaffected, thus the currency stored in them will be used on next page load (unless you change it again, via code). 


Example 4 - Manually setting the currency against user's session and profile

If you wish to store the currency in user's cookie and profile, you can use the following code.   

// Let's set the currency to USD
$selected_currency = 'USD';
// Store currency in cookies
wc_setcookie('aelia_cs_selected_currency', $selected_currency);

// Store currency in user's profile (user meta)
$user_id = get_current_user_id();
update_user_meta($user_id, 'aelia_cs_selected_currency', $selected_currency);

  

Example 5 - Setting a specific currency for search engine crawlers

Out of the box, search engine crawlers are treated like any other visitor. If you need to make sure that crawlers receive a specific currency, the code below shows how you can do that.

/**
 * Indicates if the current visitor is a bot.
 *
 * @return bool
 */
function aelia_visitor_is_bot(): bool {
  $user_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
  $bot_types = 'bot|crawl|slurp|spider|facebookexternalhit|facebook';

  return !empty($user_agent) ? preg_match("/$bot_types/", $user_agent) > 0 : false;
}

/**
 * Always sets the active currency to a specific one for bots.
 */
add_filter('wc_aelia_cs_selected_currency', function($selected_currency) {
  // Only change the currency for bots, and only on the frontend
  if(aelia_visitor_is_bot() && (!is_admin() || defined('DOING_AJAX'))) {
    // Always force selected currency to US Dollars. Bots will always see prices in that currency
    $selected_currency = 'USD';
  }

  return $selected_currency;
}, 999);


Example 6 - Forcing checkout in a specific currency

If you wish to allow customers to browse the site in a currency of their choice, but force them to complete the checkout in a specific currency, the following code shows an example of how you can do that.


Important

We tested this customisation with the standard checkout page provided by WooCommerce. If you use a custom checkout page, e.g. using Gutenberg blocks, page builders, or plugins that disable WooCommerce's ajax calls, this code might not work. We can't provide assistance in relation to these customisations. We recommend to contact your developers and ask them to test and, eventually, adapt the custom code to your specific site.

/**
 * Injects a parameter that identifies the "checkout" context in the
 * script arguments for the Ajax calls. This will allow to force the
 * currency during those calls.
 *
 * @param array $params
 * @return array
 */
function aelia_inject_context_params($params) {
  if(is_checkout() && isset($params['wc_ajax_url'])) {
    if(strpos($params['wc_ajax_url'], '?') > 0) {
      $params['wc_ajax_url'] .= '&';
    }
    else {
      $params['wc_ajax_url'] .= '?';
    }
    // Add a parameter to the Ajax request, to keep track that it was triggered
    // on the checkout page
    $params['wc_ajax_url'] .= 'aelia_context=checkout';
  }
  return $params;
}

add_action('woocommerce_init', function() {
  // If the AFC is not installed, the Currency Switcher can't 
  // be loaded either. In this case, we can stop here
  if(!function_exists('aelia_wc_version_is')) {
    return;
  }

  // WooCommerce 3.5.1 introduced a breaking change in the filters used to alter the
  // cart fragment script parameters
  // @since WooCommerce 3.5.1
  if(aelia_wc_version_is('>=', '3.5.1')) {
    /**
     * Adds parameters to the Ajax request used to refresh the minicart. The additional
     * parameters will be used to determine the context in which the request was made,
     * so that we can know if we should force the currency because we are on the
     * checkout page.
     *
     * @param array params An array of parameters.
     * @return array
     */
    add_filter('woocommerce_get_script_data', function($params, $handle) {
      if($handle === 'wc-cart-fragments') {
        $params = aelia_inject_context_params($params);
      }
      return $params;
    }, 10, 2);
  }
  else {
    /**
     * Adds parameters to the Ajax request used to refresh the minicart. The additional
     * parameters will be used to determine the context in which the request was made,
     * so that we can know if we should force the currency because we are on the
     * checkout page.
     *
     * @param array params An array of parameters.
     * @return array
     */
    add_filter('wc_cart_fragments_params', function($params) {
      $params = aelia_inject_context_params($params);
      return $params;
    });
  }
});

/**
 * Determines if we are processing an Ajax request triggered on the checkout page.
 *
 * @return bool
 */
function aelia_is_checkout_ajax_request() {
  if(defined('DOING_AJAX')) {
    $ajax_request = $_REQUEST['wc-ajax'] ?? null;

    // The "update_order_review" request updates the totals on the checkout page
    if(in_array($ajax_request, array('update_order_review', 'checkout')))  {
      return true;
    }

    // The "get_refreshed_fragments" updates the minicart. We only need to take
    // it into account if we are on the checkout page
    if(($ajax_request === 'get_refreshed_fragments') &&
       isset($_REQUEST['aelia_context']) && ($_REQUEST['aelia_context'] === 'checkout')) {
      return true;
    }
  }
  return false;
}

/**
 * Forces the checkout currency to USD.
 *
 * @param string selected_currency The currency selected originally.
 * @return string
 */
add_filter('wc_aelia_cs_selected_currency', function($selected_currency) {
  // If we are on the checkout page, or handling an Ajax request from that page,
  // force the currency to USD
  if(is_checkout() || aelia_is_checkout_ajax_request()) {
    $selected_currency = 'USD';
  }
  return $selected_currency;
}, 50);

Important notes

  • The Currency Switcher was designed to allow customers to pay in their currency of choice. Forcing the checkout in an arbitrary currency could impact on conversion, as customers might be presented with a different currency from the one they were looking at.
  • Forcing the checkout in a specific currency will set the prices to the ones you specified for that currency. Example:
    1- You set the price of Product A to 100 USD and 100 EUR.
    2- You use the custom code to force the checkout in USD.
    3- A customer browses the site in EUR and see the product price as "100 EUR".

    When the customer will reach the checkout, the currency will be force to USD and the product price will be 100 USD (i.e. the price you set for the product at step #1), not "100 EUR converted to USD".



Example 7 - Forcing the currency depending on user's role

If you wish to force the currency depending on which role was assigned to the active user, the following example will show you how to do that. Please note that, if a user has multiple roles, the code in the example might match more than one. In such case, the last matching role will determine the currency.

/**
 * Apply a different currency based on the user role.
 *
 * @param string selected_currency The currency selected by the Currency Switcher.
 * @return string A currency code.
 * @author Aelia <support@aelia.co>
 */
function aelia_set_currency_by_role($selected_currency) {
  if(is_user_logged_in()) {
    $current_user = wp_get_current_user();
    
    // Set the currency to EUR for EU Distributors
    if(in_array('eu_distributor', $current_user->roles)) {
      $selected_currency = 'EUR';
    }

    // Set the currency to USD for US Distributors
    if(in_array('us_distributor', $current_user->roles)) {
      $selected_currency = 'USD';
    }
  }
  return $selected_currency;
}
add_filter('wc_aelia_cs_selected_currency', 'aelia_set_currency_by_role', 10, 1);


Example 8 - Forcing the currency for API requests


Example 8.1 - Forcing the currency for calls to the new WooCommerce API

If you wish to force the currency used to prepare the response to API calls, the following example will show you how to do that. 

We tested this with the new WooCommerce API v1, v2 and v3. The legacy API, which is now obsolete, will need a different approach. If you use a client that relies on the legacy API, please refer to example 8.2, below. 

/**
 * Forces the currency for REST API calls.
 * 
 * @param bool $is_request_to_rest_api
 * @return bool
 */
add_filter('woocommerce_rest_is_request_to_rest_api', function($is_request_to_rest_api) {
  if($is_request_to_rest_api) {
    // If the call is to the REST API, force the currency to USD
    add_filter('wc_aelia_cs_selected_currency', function($currency) {
      return 'USD';
    }, 10);
  }

  return $is_request_to_rest_api;
}, 999);


Example 8.2 - Forcing the currency for calls to the legacy WooCommerce API

The following code snippet should be sufficient to force the currency in response to a call to the legacy WooCommerce API. 

Important: the legacy API has been obsolete since WooCommerce 2.6 and it should no longer be used. Due to that, it falls outside of our support service and we can't guarantee that it will work correctly.

add_action('woocommerce_init', function() {
  // Only change the currency on the frontend
  if(defined('WC_API_REQUEST') && WC_API_REQUEST) {
    // Always force selected currency to US Dollars
    // This will ensure that all customers will always see prices
    // and place orders in USD
    $_POST['aelia_cs_currency'] = 'USD';
  }
}, 0);

Example 9 - Set the currency using a custom URL argument

This example shows how to use a custom URL argument, instead of the default "aelia_cs_currency", to set the currency.

add_action('before_woocommerce_init', function() {
  // Only change the country on the frontend
  if(!is_admin() || defined('DOING_AJAX')) {
    // If a country was selected via a GET argument, pass it through the POST
    // data. This will make it look as if the visitor selected the country using
    // the widget
    if(isset($_GET['currency'])) {
      $_POST['aelia_cs_currency'] = $_GET['currency'];
    }
  }
}, 0);


You can purchase the Currency Switcher from our online shop.