Configure Tax Calculation
Why tax configuration matters
Section titled “Why tax configuration matters”Tax compliance is not optional. Every sale must collect the correct tax based on the product type, the customer’s location, and applicable exemptions. Miscalculating tax leads to audit risk, penalties, and customer disputes. Commerce supports both built-in tax tables and external tax providers so you can handle domestic and international tax scenarios accurately.
This guide covers setting up tax categories, configuring a tax provider, managing exemptions, and handling international tax rules.
What you will do
Section titled “What you will do”- Define tax categories for your products
- Configure tax jurisdictions and rates
- Integrate an external tax calculation provider
- Handle tax exemptions and international rules
Define tax categories
Section titled “Define tax categories”Tax categories group products by their tax treatment. Different product types are taxed at different rates — clothing may be exempt in some states, while digital goods have special rules.
In the Commerce UI:
- Navigate to Commerce > Administration > Tax Categories
- Click Add Tax Category
- Enter a name (e.g., “Taxable Goods”, “Clothing”, “Digital Products”, “Food”)
- Assign the category to each variant on its properties tab
using EPiServer;
using EPiServer.Commerce.Catalog.ContentTypes;
public class TaxCategoryService
{
private readonly IContentRepository _contentRepo;
public TaxCategoryService(
IContentRepository contentRepo)
{
_contentRepo = contentRepo;
}
public void SetTaxCategory(
ContentReference variantLink,
string taxCategoryName)
{
var variant = _contentRepo
.Get<VariationContent>(variantLink)
.CreateWritableClone<VariationContent>();
variant.TaxCategoryId =
GetTaxCategoryId(taxCategoryName);
_contentRepo.Save(variant,
EPiServer.DataAccess.SaveAction.Publish,
EPiServer.Security.AccessLevel.NoAccess);
}
private int GetTaxCategoryId(string name)
{
var taxCategories = CatalogTaxManager
.GetTaxCategories();
var row = taxCategories.TaxCategory
.FirstOrDefault(tc => tc.Name == name);
return row?.TaxCategoryId ?? 0;
}
} Configure tax jurisdictions
Section titled “Configure tax jurisdictions”Tax jurisdictions define the geographic areas where specific tax rates apply. Set rates per jurisdiction and tax category combination.
In the Commerce UI:
- Navigate to Commerce > Administration > Taxes
- Create a jurisdiction (e.g., “California”, “EU-Standard”)
- Set the rate for each tax category within the jurisdiction
- Associate the jurisdiction with the appropriate markets
| Jurisdiction | Tax category | Rate |
|---|---|---|
| California | Taxable Goods | 7.25% |
| California | Food (unprepared) | 0% |
| New York | Taxable Goods | 8.00% |
| New York | Clothing (under $110) | 0% |
| EU-Standard | All goods | 20% |
Integrate an external tax provider
Section titled “Integrate an external tax provider”For complex multi-jurisdiction tax calculation, integrate a tax service like Avalara or Vertex that maintains current rates and rules.
using EPiServer.Commerce.Order;
public class ExternalTaxCalculator : ITaxCalculator
{
private readonly HttpClient _httpClient;
public ExternalTaxCalculator(
HttpClient httpClient)
{
_httpClient = httpClient;
}
public Money GetTaxTotal(
IOrderGroup orderGroup,
IMarket market, Currency currency)
{
var shipment = orderGroup
.GetFirstShipment();
var address = shipment.ShippingAddress;
var request = new TaxRequest
{
Lines = shipment.LineItems
.Select(li => new TaxLine
{
ItemCode = li.Code,
Quantity = li.Quantity,
Amount = li.PlacedPrice
* li.Quantity,
TaxCode = GetTaxCode(li.Code)
}).ToList(),
Destination = new TaxAddress
{
City = address.City,
State = address.RegionCode,
PostalCode = address.PostalCode,
Country = address.CountryCode
}
};
var response = _httpClient
.PostAsJsonAsync(
"https://api.tax-provider.com/calculate",
request)
.GetAwaiter().GetResult();
var result = response.Content
.ReadFromJsonAsync<TaxResponse>()
.GetAwaiter().GetResult();
return new Money(result.TotalTax, currency);
}
private string GetTaxCode(string variantCode)
{
// Map variant to tax provider's tax code
return "P0000000";
}
} Handle exemptions and international rules
Section titled “Handle exemptions and international rules”Tax exemptions apply to specific customers (resellers, nonprofits) or product types. International sales may require VAT handling or reverse charge mechanisms.
Exemption scenarios:
| Scenario | Implementation |
|---|---|
| Reseller exemption | Store the customer’s resale certificate; skip tax on their orders |
| Nonprofit | Verify tax-exempt status; apply zero rate |
| Cross-border EU | Apply reverse charge for B2B; destination VAT for B2C |
| Digital goods | Apply the tax rate of the customer’s country (EU MOSS rules) |
Common issues
Section titled “Common issues”| Issue | Cause | Fix |
|---|---|---|
| Tax showing as $0 on all orders | No tax jurisdiction configured for the customer’s address | Add jurisdictions matching your customers’ locations |
| Wrong tax rate applied | Tax category not assigned to the variant | Verify every variant has the correct tax category |
| External provider returns error | API credentials expired or service unavailable | Check credentials and implement a fallback to built-in tax tables |
| Exempt customer still charged tax | Exemption not applied to the customer profile | Verify the customer’s exemption certificate is linked to their contact |