Skip to content

Magento EU Tax Calculation Explained

Tax calculation is one of those areas in Magento you work through properly once and then hope to leave alone. Three tax classes and the tax rules that tie them together do the actual work. This article walks through that configuration step by step, with an eye on EU trade. Along the way it becomes clear why a customer's group has a say in the tax rate they are charged, which is not what its name suggests.

The three tax classes

A tax class is a label, nothing more. It holds no percentage and decides nothing on its own beyond which group something belongs to. Magento knows two types, kept apart in the tax_class table by the class_type column, and they are used in three places:

Tax class Type Maintained under Default
Product PRODUCT Product → Advanced Pricing tab, attribute tax_class_id Taxable Goods
Customer CUSTOMER Stores → Customer Groups, field tax_class_id Retail Customer
Shipping PRODUCT Stores → Configuration → Sales → Tax, Tax Classes section Taxable Goods

Shipping is the odd one out: it has no type of its own but falls back on a product tax class that you set centrally in the configuration and that applies to every shipping method. Set it to None and shipping costs stay untaxed while the items in the same cart are taxed as usual. That is one of the more common reasons why line items and order total refuse to add up.

Why the customer group decides

With the product tax class things are straightforward: it sits on the article as an attribute, you can see it in the product and change it there. The customer tax class works differently, because it does not sit on the customer at all. It sits on their customer group.

Every group under Stores → Customer Groups carries exactly one tax_class_id field, and every customer in that group inherits the value. A second field that could override the class for an individual customer, an address or a single order does not exist in the Magento core.

That makes the customer group the basis on which the entire tax calculation rests. It determines which tax class a buyer brings along, and with it which tax rules apply to them at all and which of the stored rates Magento eventually uses for their order. Everything else builds on top of that.

The tax rule brings classes and rates together

A tax class on its own triggers no calculation. Only the tax rule under Stores → Tax Rules makes the connection, and it always consists of the same three parts:

  1. One or more customer tax classes
  2. One or more product tax classes
  3. One or more tax rates from Stores → Tax Zones and Rates, each carrying a country, a region and a postcode

For a rule to take effect, three things have to be true at the same time: the buyer's customer tax class is part of the rule, the line item's product tax class is too, and the relevant address falls into the zone of one of the assigned rates. If any of these does not match, the rule does not apply. And if no rule applies at all, Magento simply charges no tax — there is no default rate it falls back on.

Priority and sort order

When several rules apply to the same item at once, the Priority field decides how Magento handles them:

  • Rules with different priorities are compounded — the lower number applies first, each further rule calculates its rate on the total of the preceding tax calculation (the Calculate off Subtotal Only checkbox turns that off)
  • Rules with the same priority are added and act together on the same net amount

The second case is intentional, for instance where a country levies state and regional tax side by side. In a European shop it is usually an oversight — there the standard and reduced rates are kept apart by the product tax class, so only one rule applies per item. It is worth a look whenever a rate turns out higher than expected.

What you should not confuse with priority is the Sort Order field. Magento 2 does not evaluate it anywhere — neither in the calculation nor when displaying the tax lines.

Which address counts when shipping and billing address differ is up to you. You set it under Stores → Configuration → Sales → Tax with the Tax Calculation Based On option, choosing between shipping address, billing address and shipping origin. Changing this single setting shifts the outcome of every order where the two addresses sit in different countries, so it is worth knowing where yours is set.

When billing and shipping address differ

What that choice of address means in practice shows up fastest in an example. Take a shop based in Germany. Two tax rates are on file, Germany at 19% and France at 20%, both assigned to the same tax rule — together with the customer tax class Retail Customer and the product tax class Taxable Goods. All customers sit in the default group General. Four orders differ in nothing but their addresses:

Billing address Shipping address Based On: Shipping Address Based On: Billing Address
Germany Germany 19% 19%
Germany France 20% 19%
France Germany 19% 20%
France France 20% 20%

The first and the last row are unremarkable: where both addresses match, the setting makes no difference. The interesting ones are the two in between. There the very same order comes to different amounts depending on where Tax Calculation Based On is set — and that is a single setting valid for the entire shop, not something you can choose per order.

Changing it does nothing to orders already placed, but it changes the calculation of every future cart. A test with two addresses in different countries shows within a minute which of the two columns your shop currently reflects.

What does not appear in any of the four rows is the customer. Whether the French address belongs to a private buyer or to a company with a valid VAT ID on file makes no difference to the result: both sit in the same customer group, carry the same customer tax class and are caught by the same rule. The VAT ID is not an element of a tax rule. Telling the two apart at all requires two separate customer groups. Magento can do the sorting itself — more on that in a moment.

Magento can do the assigning itself

Customer groups do not have to be maintained by hand. Under Stores → Configuration → Customers → Customer Configuration → Create New Account Options sits the setting Enable Automatic Assignment to Customer Group. With it switched on, Magento checks an entered VAT ID against VIES and assigns the buyer to one of four groups that you define right below it:

Case When it applies Setting
Domestic number valid, buyer's country = shop's country Group for Valid VAT ID - Domestic
Intra-union number valid, another EU country Group for Valid VAT ID - Intra-Union
Invalid VIES answers but does not know the number Group for Invalid VAT ID
Error VIES unreachable or the request failed Validation Error Group

This takes effect in two places. When a logged-in customer saves an address carrying a VAT ID, Magento changes their customer group permanently — so the number may well be handed in later. And in the cart the group is set on every recalculation of the totals, including for guests without an account. A guest with a valid number from another EU country gets their net invoice without anyone lifting a finger.

A single lever for everything

Convenient — as long as you know what it hinges on. Because whether the automation takes effect comes down to a single question: which address Magento looks at. That is set by Tax Calculation Based on in the same configuration group. It is not the identically named setting in the tax section that determines the rate — and the two can point at different addresses.

If the assignment goes by the billing address, a VAT ID on the shipping address does nothing. The buyer enters it, sees it sitting there in the checkout, and is charged tax anyway. Meanwhile the rate itself may be worked out from the shipping country. Anyone who has not set both options deliberately has a silent source of error here.

The real catch, though, sits deeper, and it is built into the design: Magento can influence tax through the customer group and nothing else. Every assignment it makes has to take that one route. So a validated VAT ID changes more than the taxation — it changes everything else hanging off the group: catalogue prices, cart rules, shipping costs, group-dependent content. A business customer moved into the B2B group because of their number may well pick up tier prices never intended for them, and for a logged-in customer they stay there until an address change pulls them back out.

Keeping tax cleanly separated therefore calls for groups that do nothing but distinguish tax. That is workable, but it costs you the groups as a tool for everything else.

On top of that, there is what the automation does not do on its own:

  • There are exactly four groups. Any gradation by country, rate or product type is not provided for
  • If VIES does not answer, the buyer lands in the error group. There is no second attempt, and nobody is told
  • The result is cached on the cart. Without Validate on Each Transaction, a number that has since become invalid keeps working

For a shop selling mostly at home and writing the occasional invoice to another EU country, that is enough. Sell there regularly and the limits show up sooner.

The tax class without that detour

That detour via the group is exactly what our extension EU VAT Enhanced takes out. It detaches the customer tax class from the customer group and determines it afresh for every calculation — from domestic or foreign, from shipping and billing address, and from the result of the VAT ID check against VIES. For our example that means the two French buyers can be treated differently without anyone touching their customer groups.

The structure itself stays as it is. The three tax classes remain, the tax rules remain, and you maintain them in the same places as before. The customer tax class is simply no longer read off the group but derived from address and validation result on every calculation. That frees the customer group up again for what you otherwise need it for — tier prices, cart rules, everything else. The settings involved are described in the documentation on tax classes and calculation.

This article describes how to set up a Magento shop and is not tax advice. Which treatment applies in your case is something neither we nor our software can judge. Please have anything binding confirmed by your tax advisor or the relevant authority.

What is a tax class in Magento?

A label without a percentage of its own. It assigns a product, a customer or the shipping to a group. The rate only comes from the tax rule, which connects a product tax class with a customer tax class and a tax rate.

Where is a customer's tax class set?

Not on the customer but on their customer group under Stores → Customer Groups. Every customer inherits the value of their group. A field that would override the class for a single order does not exist in the Magento core.

How do I add a new tax class?

There is no separate menu for it. Open Stores → Tax Rules, create a rule or edit an existing one and expand Additional Settings. From there you add product and customer tax classes via the plus sign. The product class then appears in the product under Advanced Pricing, the customer class in the customer group.

And sales to private customers elsewhere in the EU?

Those do not run on the VAT ID but on the rate of the destination country. Which one you have to store, and from when, is governed by the One Stop Shop scheme — we have written a separate article about OSS tax rates in Magento.

Why is no tax charged on an order at all?

Because no tax rule applies. Usually there is no rate on file for the country of the relevant address, or the rate that exists has not been assigned to a rule. Magento does not fall back on a default rate in that case but leaves the tax line out. Which address is relevant is set by Tax Calculation Based On.

Why is tax still charged despite a valid VAT ID?

Magento does switch the group for the cart dynamically once a validated number is present. If the tax stays anyway, it usually comes down to one of three things: Enable Automatic Assignment to Customer Group is not active, the number sits on the address that Tax Calculation Based on is not currently evaluating, or the target group carries a tax class for which a tax rule still applies — as in the domestic case, where no relief is intended either.

Post Comments

Be the first to share your thoughts on this post.

Submit Comment

This is a question to prove that you are a human.

Your comment appears publicly under the name you enter, once we have reviewed it. More in our privacy policy

Required Fields