---
schema_version: "1"
id: a5c5ccb9a060391f55884ea041a2838490d323d473bf4e69836542c965fce0a8
title: Multiple Tax Levels in B2C Commerce
collection: admin
version: current
locale: en-us
portal_url: https://docs.salesforce.com/admin/current/en-us/cc/264-0-0/b2c_multiple_tax_levels.md
canonical_url: https://help.salesforce.com/s/articleView?id=cc.b2c_multiple_tax_levels.htm&release=264.0.0&type=5
source_site: help.salesforce.com
content_type: documentation
content_hash: 1a1a0ba29970b95a571c9caf2c92c75c78338266aba45795c50e10dddf66e465
description: Track federal, state, county, and local taxes individually on a line item while B2C Commerce keeps one aggregated tax amount. Beginning with B2C Commerce 26.10, Multiple Tax Levels is generally available, and line items without tax items behave as they do today.
products:
  - Commerce
  - B2C Commerce
release: "264"
---
# Multiple Tax Levels in B2C Commerce

Track federal, state, county, and local taxes individually on a line item while B2C Commerce keeps one aggregated tax amount. Beginning with B2C Commerce 26.10, Multiple Tax Levels is generally available, and line items without tax items behave as they do today.

In many jurisdictions, more than one tax applies to a product or shipping charge, such as federal, state, county, and local tax. Multiple Tax Levels tracks each of those taxes individually on a line item and keeps the item's single, aggregated tax amount. Baskets, shipments, and orders continue to total against that aggregated amount.

The capability is native across Script API, Salesforce Commerce API (SCAPI), import and export, and Salesforce Order Management. Store the tax breakdown in native tax items instead of custom attributes, JSON, or custom cartridge code. Custom tax fields or mapping codes aren't required.

Your tax-provider integration retrieves the applicable taxes and attaches them to each line item from a basket calculation hook. B2C Commerce sums the individual taxes into the line item's aggregated tax field and carries the breakdown into SCAPI responses, the order export, and Salesforce Order Management.

Beginning with B2C Commerce 26.10, Multiple Tax Levels is generally available to all merchants. There's nothing to turn on and no rollout gate. The capability is opt-in: nothing changes until your integration sets individual tax items on a line item. A line item with no tax items set behaves as it does without this capability, so existing storefronts, orders, and integrations continue to work.

![Note](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-cc-b2c_merchandiser_administrator-264-0-0-production-enus/ea76f372-6cfa-42a6-8e7c-05c6df7abed8/images/icon_note.png)

Note A line item uses either individual tax items or the classic single aggregated-tax approach, never both. Setting the tax with a single-tax Script API method removes any individual tax items previously set on that line item.

## Why Use Multiple Tax Levels

Use Multiple Tax Levels for these outcomes.

- Retire custom workarounds. Store the per-level breakdown in native tax items instead of extra attributes, JSON, or custom code.
- Support compliance and auditing. Track federal, state, county, and local taxes per level in multi-jurisdiction regions such as the US, the EU, and Canada.
- Standardize tax-provider integrations. Tax providers such as Avalara and Vertex integrate through one Script API instead of custom implementations.
- Preserve data fidelity. The tax-level breakdown is kept from the basket through export, import, and Order Management ingestion.

## What the Platform Does Versus What You Do

B2C Commerce aggregates, exposes, exports, and transfers tax items. Your tax-provider integration retrieves the applicable taxes and sets them on each line item.

Platform Versus Integration  
| Concern | Owner |
| --- | --- |
| Sum the individual tax values into the line item's aggregated tax field | Platform |
| Use the aggregated value for basket, shipment, and order tax totals | Platform |
| Expose the breakdown in SCAPI (Shopper Baskets, Shopper Orders, and Shopper Customers) | Platform |
| Export the breakdown natively in the order XML and round-trip it on import | Platform |
| Transfer the individual tax items to Salesforce Order Management on order export | Platform |
| Show the tax breakdown in Business Manager | Platform |
| Retrieve the applicable taxes from your tax provider | Your tax-provider integration |
| Set the taxes on each line item with `LineItem.setTaxes()` and `LineItemTax` | Your basket calculation hook |

## Tax Items

A line item can carry up to 10 tax items. Each tax item represents one level of tax, for example one entry for federal and one for state, and has these properties.

Tax Item Properties   
| Property | Required | Description |
| --- | --- | --- |
| Tax ID | Yes | A tax-provider-defined identifier for the tax, such as `federal`, `state`, or `district`. Blank values are rejected. Leading and trailing whitespace is trimmed. |
| Tax rate | Yes | The tax rate as a decimal value. For example, a 5% rate is stored as `0.05`. |
| Tax value | No | The tax amount, in the purchase currency. If omitted, the platform computes it from the tax rate and the line item's tax basis. |

Tax ID and Tax rate are required. A tax item created without either is rejected. Tax value is optional. Supply a pre-computed amount, or leave it out so that the platform derives it from the tax rate and the line item's tax basis. These two options correspond to the two ways to create a tax level: `new LineItemTax(taxId, taxRate)` (the platform computes the value) and `new LineItemTax(taxId, taxRate, taxValue)` (you provide it). When the value is omitted, reading it back before calculation returns nothing until the platform computes it.

## Aggregated Tax

B2C Commerce sums the individual tax values, derives a combined tax rate, and stores the result on the line item's aggregated tax fields. Basket, shipment, and order tax totals continue to use that aggregated value, so downstream totals behave as they do without Multiple Tax Levels.

The aggregate and the per-level breakdown are exposed side by side.

- Script API: Read the aggregate from the line item with `getTax()` (the summed amount) and `getTaxRate()` (the combined rate). Read the individual levels with `getTaxes()`.
- SCAPI: The aggregate is the line item's `tax` and `taxRate` fields. The per-level breakdown is in the `taxItems` array. Each tax item uses `id`, `rate`, and `value`.

![Multiple Tax Levels Example](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-cc-b2c_merchandiser_administrator-264-0-0-production-enus/ea76f372-6cfa-42a6-8e7c-05c6df7abed8/images/icon_example.png)

Multiple Tax Levels Example

A basket contains a product priced at US$100, subject to a 10% federal tax and a 5% state tax.

Example Tax Items   
| Level | Rate | Value |
| --- | --- | --- |
| Federal | `0.10` | $10 |
| State | `0.05` | $5 |
| Aggregated tax (line item) | Combined | $15 |

The line item carries a $10 federal tax item and a $5 state tax item. B2C Commerce stores $15 as the line item's aggregated tax value.

Retrieved through SCAPI (Shopper Baskets, Shopper Orders, or Shopper Customers), the same line item returns the aggregated tax alongside the per-level breakdown.

```json
{
  "productItems": [
    {
      "itemId": "b1c2d3e4f5",
      "productId": "product-100",
      "quantity": 1,
      "price": 100.00,
      "taxBasis": 100.00,
      "tax": 15.00,
      "taxRate": 0.15,
      "taxItems": [
        { "id": "federal", "rate": 0.10, "value": 10.00 },
        { "id": "state",   "rate": 0.05, "value": 5.00 }
      ]
    }
  ]
}
```

Custom attributes registered on a tax item are returned on the corresponding entry. SCAPI exposes them with a `c_` prefix.

```json
{
  "id": "state",
  "rate": 0.05,
  "value": 5.00,
  "c_jurisdictionType": "State",
  "c_jurisdiction": "NJ"
}
```

## Retrieve and Set Tax Items

There's nothing to turn on. Customize your cartridge and basket calculation hook to:

- Retrieve the taxes that apply to each line item from your tax provider.
- Build one `LineItemTax` per level and assign them to the line item with `LineItem.setTaxes()` (up to 10 levels per line item). Read them back with `LineItem.getTaxes()`.

This example taxes the US$100 product with 10% federal and 5% state tax. B2C Commerce sums the two values into the line item's aggregated tax field ($15).

```javascript
var ArrayList   = require('dw/util/ArrayList');
var LineItemTax = require('dw/order/LineItemTax');
var Money       = require('dw/value/Money');

var taxes = new ArrayList();

taxes.add(new LineItemTax('federal', 0.10, new Money(10.00, 'USD')));
taxes.add(new LineItemTax('state',   0.05, new Money(5.00,  'USD')));

productLineItem.setTaxes(taxes);
```

For constructor and method details, see [LineItemTax](https://salesforcecommercecloud.github.io/b2c-dev-doc/docs/current/scriptapi/html/index.html?target=class_dw_order_LineItemTax.html) and [LineItem](https://salesforcecommercecloud.github.io/b2c-dev-doc/docs/current/scriptapi/html/index.html?target=class_dw_order_LineItem.html) in the Script API. See [Shopper Baskets](https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-baskets-v2?meta=Summary) for the basket calculation hook.

## Custom Attributes on Tax Items

Attach typed custom attributes directly to each tax level instead of storing metadata in a single JSON attribute on the parent product line item (for example `productLineItem.custom.ATTaxDetail`). Per-tax-level attributes are visible in Business Manager and simpler to replicate and integrate.

Use per-tax-level attributes to:

- Attach granular metadata, such as jurisdiction, exemption codes, tax authority, and cumulative-versus-gross flags, on the exact tax line they describe.
- Improve audit and reconciliation. Link a tax provider's own identifiers, such as an Avalara or Vertex calculation or transaction reference, directly to the relevant tax line.
- Simplify integrations. Independent software vendors (ISVs) read and write metadata through the standard Script API (`lineItem.getTaxes()[i].custom.<attr>`) instead of side-channel attributes.
- Pass metadata through to Order Management. Per-tax-level attributes flow to the Order Management side for clearer order ingestion.

Custom tax-line attributes use the same workflows as other system objects. They extend the `LineItemTax` system object type. Register the attribute definitions on `LineItemTax` in Business Manager, or import them in a `system-objecttype-extensions.xml` file that targets `type-id="LineItemTax"`. See [Custom Metadata Object Import/Export in B2C Commerce](https://help.salesforce.com/s/articleView?id=cc.b2c_custom_metadata_object_import_export.htm&release=264.0.0&type=5 "When using the system meta data import functionality, the entire definition is replaced. For example, suppose you have a custom group with three attribute groups and you want to add another attribute group to make four attribute groups. In this case, specify all four attribute group definitions in the import file.").

After the attributes are registered, assign values directly on the tax item.

```javascript
var t = new LineItemTax('NJ_STATE', 0.06, new Money(4.20, 'USD'));
t.custom.jurisdictionType = 'State';
t.custom.jurisdiction     = 'NJ';
// ...assign other registered attributes directly
```

![Note](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-cc-b2c_merchandiser_administrator-264-0-0-production-enus/ea76f372-6cfa-42a6-8e7c-05c6df7abed8/images/icon_note.png)

Note Only registered attributes are accepted. Any unregistered attribute name used in a script is rejected, which keeps tax-item data consistent across your site.

## Where the Tax Breakdown Appears

Multiple Tax Levels is supported natively across every data surface an order passes through. Custom attributes on tax items are fully supported across these surfaces too. Set and read them with Script API. They're returned in SCAPI responses, exported and re-imported through import and export, and carried to Order Management.

Tax Breakdown Surfaces  
| Surface | How the Breakdown Appears |
| --- | --- |
| Script API | Set and read up to 10 tax levels per line item during basket operations. |
| REST API (SCAPI) | Retrieved through the Shopper Baskets, Shopper Orders, and Shopper Customers endpoints. |
| Import and Export | Each line item's tax levels are included natively in the order export and re-imported without loss. Export of the new tax fields requires version 26.5 or later. |
| Order Management | When an order is exported to an order management system, its per-level tax breakdown travels with the order automatically. |

Multi-level tax data is available through the [Shopper Baskets](https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-baskets-v2?meta=Summary), [Shopper Orders](https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-orders?meta=Summary), and [Shopper Customers](https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-customers?meta=Summary) SCAPI endpoints, so storefronts and other front-end systems can render the full per-level tax breakdown without custom API workarounds. Both the Shopper Orders and Shopper Customers APIs that load a shopper's orders return the tax breakdown on those orders.

The order export XML natively includes a `<tax-items>` element, giving a structured export of `tax-id`, `tax-rate`, and `tax-amount` for each line item. Import round-trips the same data, so an order keeps its full tax-level breakdown through export and re-import. Export of the `<tax-items>` element requires version 26.5 or later, which preserves backward compatibility for earlier export consumers. The Script API and SCAPI surfaces are available regardless. See [Order Object Import and Export in B2C Commerce](https://help.salesforce.com/s/articleView?id=cc.b2c_order_object_import_export.htm&release=264.0.0&type=5 "For integration with external systems, and for working with test data, B2C Commerce can export and import order data as XML."). The following example shows multiple tax items on a single order line item.

```xml
<tax-items>
  <tax-item>
    <tax-id>Country Tax</tax-id>
    <tax-rate>0.05</tax-rate>
    <tax-amount>0.30</tax-amount>
  </tax-item>
  <tax-item>
    <tax-id>State Tax</tax-id>
    <tax-rate>0.03</tax-rate>
    <tax-amount>0.18</tax-amount>
  </tax-item>
</tax-items>
```

The breakdown travels in the standard order export and survives import. When B2C Commerce sends an order to Salesforce Order Management, the individual tax items transfer from each B2C Commerce line item to the corresponding line item in Order Management automatically. Custom tax fields or mapping codes aren't required to transfer this information. Any custom attributes on a tax item are also copied to Salesforce Order Management, the same way custom attributes are copied for other objects, provided the same custom attribute ID is defined on both systems.

After a shopper places an order, review the per-level tax breakdown in Business Manager when you view that order. See [View Tax Items in B2C Commerce](https://help.salesforce.com/s/articleView?id=cc.b2c_view_tax_items.htm&release=264.0.0&type=5 "After a shopper places an order, you can review the tax breakdown in Business Manager.").

- **[View Tax Items in B2C Commerce](https://help.salesforce.com/s/articleView?id=cc.b2c_view_tax_items.htm&release=264.0.0&type=5)**  
    After a shopper places an order, you can review the tax breakdown in Business Manager.