WooCommerce tax and price-based facets
If you have facets that have the product price set as their data source, be aware of the following settings and intricacies regarding tax/VAT.
If you have enabled taxes in WooCommerce’s General tab settings, you’ll see a Tax tab with all tax related settings. With the “Prices entered with tax” setting, you can determine if the entered product prices are including or excluding tax/VAT:
Facets with the product price set as data source will index the price as it is entered, and are not aware of any WooCommerce tax settings.
This means that if you have set “Yes, I will enter prices inclusive of tax”, and “Display prices in the shop” as “Including tax”, a price-based facet will correctly show prices including tax/VAT, in line with how prices are displayed in the shop. Nothing needs adapting.
However, if you have your prices entered without tax/VAT, even with “Display prices in the shop” set to “Including tax”, price-based facets will show prices excluding tax/VAT. This may be confusing for your users.
Depending on your website’s or customers’ country, tax rates may be fixed, or dynamically calculated based on the user’s location. If the rates are fixed, like VAT in EU countries, it is possible to let price-based facets index prices including VAT, even if they are entered excluding VAT, by using the facetwp_index_row
hook:
Index facets with one fixed tax rate
The following example shows how to use the facetwp_index_row hook to index the facet’s facet_value
(the technical value, as seen in the URL) and the facet_display_value
(the value displayed in the facet) including a fixed, hard-coded 21% VAT rate.
To apply this, add the following snippet to your (child) theme’s functions.php, and re-index:
How to use custom PHP code?
PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info
add_filter( 'facetwp_index_row', function( $params, $class ) { $tax_rate = 1.21; // Fixed 21% tax rate if ('my_facet_name' == $params['facet_name']) { // Replace ''my_facet_name' with the name of your facet. $params['facet_value'] = !empty($params['facet_value']) ? (float)$params['facet_value'] * $tax_rate : $params['facet_value']; $params['facet_display_value'] = !empty($params['facet_display_value']) ? (float)$params['facet_display_value'] * $tax_rate : $params['facet_display_value']; } return $params; }, 10, 2 );
Note that in above example, both the facet_value
and facet_display_value
are separately multiplied by 1.21
. For Simple Products you could just calculate one, and copy it to the other, as both values will be the same. But for Variable Products (which are indexed if FacetWP’s “Support product variations” setting is enabled), the lowest variation price is indexed in facet_value
and the highest in facet_display_value
, so they will be different and need to be calculated separately.
Index facets with multiple fixed tax rates
The above example will only work if your products all have the same tax rate applied. But it is also possible that your products can have different tax rates set, for example a “Standard rate” or a “Reduced rate”.
These so-called “Tax Classes” can be set up in the Tax options. By default there are three tax classes: Standard rate, Reduced rate, and Zero rate. For each, you can set up a tax rate by clicking “Insert row” and entering a percentage in the “Rate %” column. You can also set up custom rates with the “Additional tax classes” setting.
Then, the tax rate can be chosen on the product page, with the “Tax Class” setting:
In this situation, if we want the price-based facet to index the product price including tax/VAT, we need to get the tax rate set in the product’s chosen Tax class setting, and use that to recalculate the indexed price for that product.
To do this, add the following snippet to your (child) theme’s functions.php, and re-index:
How to use custom PHP code?
PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info
add_filter( 'facetwp_index_row', function( $params, $class ) { if ( 'my_price_facet' == $params['facet_name'] ) { // Replace 'my_price_facet' with the name of your facet. $post_id = $params['post_id']; $product = wc_get_product($post_id); $rate_float = 1.0; if ( $product ) { $tax_class = $product->get_tax_class(); // Get the tax class set for the product $tax_rates = WC_Tax::get_rates($tax_class); // Get the tax rate for the chosen tax class if ( $tax_rates ) { $first_tax_rate = reset($tax_rates); $rate_string = $first_tax_rate['rate']; $rate_float = number_format(1 + ( floatval($rate_string) / 100 ), 2);// round to 2 decimals } } $params['facet_value'] = !empty($params['facet_value']) ? (string)(floatval($params['facet_value']) * $rate_float) : $params['facet_value']; $params['facet_display_value'] = !empty($params['facet_display_value']) ? (string)(floatval($params['facet_display_value']) * $rate_float): $params['facet_display_value']; } return $params; }, 10, 2 );
Note that this code will only work if there is one rate defined per Tax Class, and no location/country is set in the first column.
Index facets with multiple fixed tax rates based on country
If your website offers products in multiple countries, each with a different (but fixed) VAT rate for each Tax Class, like in the EU, the situation gets a bit more complicated. A solution could be to create a separate facet for each country, and show/hide the correct facet based on the country of the user.
In this situation, each Tax Class will have a tax rate set for each country, with a country code in the first column:
To let a facet index the correct price including tax/VAT for a specific country, we need to get the rate for the specified country. We can do this with the get_rates_from_location() method. The country code (as set in the Tax class setting) needs to be passed in the second argument, as the first value in the array. This example gets the product’s tax rate set for the German DE
country code:
How to use custom PHP code?
PHP code can be added to your (child) theme's functions.php file. Alternatively, you can use the Custom Hooks add-on, or a code snippets plugin. More info
add_filter( 'facetwp_index_row', function( $params, $class ) { if ( 'my_price_facet_DE' == $params['facet_name'] ) { // Replace 'my_price_facet_DE' with the name of your facet. $post_id = $params['post_id']; $product = wc_get_product($post_id); $rate_float = 1.0; if ( $product ) { $tax_class = $product->get_tax_class(); // Get the tax class set for the product $tax_rates = WC_Tax::get_rates_from_location($tax_class, array('DE','','','')); // Get the tax rate for the chosen tax class, for country code 'DE' if ( $tax_rates ) { $first_tax_rate = reset($tax_rates); $rate_string = $first_tax_rate['rate']; $rate_float = number_format(1 + ( floatval($rate_string) / 100 ), 2);// round to 2 decimals } } $params['facet_value'] = !empty($params['facet_value']) ? (string)(floatval($params['facet_value']) * $rate_float) : $params['facet_value']; $params['facet_display_value'] = !empty($params['facet_display_value']) ? (string)(floatval($params['facet_display_value']) * $rate_float): $params['facet_display_value']; } return $params; }, 10, 2 );
For an overview of other useful methods in WooCommerce’s WC_Tax
class, see this page.
Dynamic tax rates based on the user’s location
If your products have dynamic tax rates based on the user’s location, the above examples will not work. FacetWP’s indexed values for facets are stored (and thus ‘hardcoded’) in the indexing database table. They cannot be updated dynamically, based on a user’s location. In this case, the best option is to display prices and the facet values excluding tax/VAT and set “Display prices in the shop” to “Excluding tax”.