Calculate Totals & Tax
This guide explains how to calculate and display cart totals, including taxes, in your Elastic Path implementation.
Using getCart for Totals Calculation
Cart totals information is included in the meta.display_price
object when retrieving a cart with the getCart
SDK method:
import { getCart, getCartId } from "@epcc-sdk/sdks-shopper";
// Fetch cart with totals information
const fetchCart = async () => {
const cartId = getCartId();
if (!cartId) {
throw new Error("No cart found");
}
const response = await getCart({
path: {
cartID: cartId,
},
query: {
include: ["items"], // Include cart items in the response
},
});
// Cart totals are available in meta.display_price
return response.data;
};
Available Pricing Fields
The cart response contains several pricing components. Here's a comprehensive overview of all available pricing fields:
Field | Location | Description |
---|---|---|
with_tax.amount | Cart meta.display_price | Total cart value including tax, in minor units (e.g., cents) |
with_tax.formatted | Cart meta.display_price | Formatted total cart value including tax (e.g., "$99.99") |
without_tax.amount | Cart meta.display_price | Total cart value excluding tax, in minor units |
without_tax.formatted | Cart meta.display_price | Formatted total cart value excluding tax |
without_discount.amount | Cart meta.display_price | Subtotal before any discounts, in minor units |
without_discount.formatted | Cart meta.display_price | Formatted subtotal before any discounts |
discount.amount | Cart meta.display_price | Total discount amount (negative value), in minor units |
discount.formatted | Cart meta.display_price | Formatted total discount amount |
tax.amount | Cart meta.display_price | Total tax amount, in minor units |
tax.formatted | Cart meta.display_price | Formatted total tax amount |
shipping.amount | Cart meta.display_price | Shipping cost, in minor units (if applicable) |
shipping.formatted | Cart meta.display_price | Formatted shipping cost (if applicable) |
item.unit.amount | Cart item meta.display_price | Price per unit before discounts, in minor units |
item.unit.formatted | Cart item meta.display_price | Formatted price per unit before discounts |
item.value.amount | Cart item meta.display_price | Total value for this item (unit price × quantity), in minor units |
item.value.formatted | Cart item meta.display_price | Formatted total value for this item |
item.discount.amount | Cart item meta.display_price | Discount amount for this item (negative value), in minor units |
item.discount.formatted | Cart item meta.display_price | Formatted discount amount for this item |
item.discounted.amount | Cart item meta.display_price | Price after discount, in minor units |
item.discounted.formatted | Cart item meta.display_price | Formatted price after discount |
Calculation Methods
Elastic Path uses two calculation methods that affect how totals are calculated:
- Simple method: Discounts applied after tax, rounding at unit level
- Line method: Discounts applied before tax, rounding at line level
The default for stores created after February 2020 is the "line" method.
For details, see Calculate Cart and Order Totals.
Tax Management
Elastic Path offers several approaches to handle taxes in your shopping cart implementation.
Adding Tax Items to a Cart Item
Tax items are applied to specific cart items, not directly to the cart:
import { addTaxItemToCart, getCartId } from "@epcc-sdk/sdks-shopper";
// Get the current cart ID
const cartId = getCartId();
// Add a tax item to a specific cart item
// Note: You must have an existing cart item to apply tax to
const cartItemId = "cart-item-12345"; // ID of an existing cart item
const response = await addTaxItemToCart({
path: {
cartID: cartId,
cartitemID: cartItemId, // Required: ID of the cart item to apply tax to
},
body: {
data: {
type: "tax_item",
name: "CA State Tax",
jurisdiction: "California",
code: "CA_STATE_TAX",
rate: 0.0725, // 7.25%
},
},
});
Important Notes About Tax Items:
- Tax items must be applied to existing cart items
- You need the cart item ID (
cartitemID
) to apply a tax - The tax rate is specified as a decimal (e.g., 0.0725 for 7.25%)
Best Practices for Tax Management
- Determine tax strategy early: Decide if you'll use Elastic Path's calculation or a third-party tax service
- Consider tax complexity: Different jurisdictions have different tax rules and rates
- Keep tax rates updated: Tax rates can change - ensure your system stays current
- Document tax decisions: Maintain clear records of tax-related implementation choices
- Test across regions: Verify tax calculations for different geographic locations
Integrating with Cart Initialization
When calculating totals, it's important to ensure a cart exists first. You can use the SDK's built-in initializeCart
utility:
import { getCart, initializeCart } from "@epcc-sdk/sdks-shopper";
// Get cart totals, creating a cart if needed
const getCartTotals = async () => {
// First ensure a cart exists using the SDK's initializeCart utility
const cartId = await initializeCart();
// Fetch cart with totals
const response = await getCart({
path: {
cartID: cartId,
},
query: {
include: ["items"],
},
});
// Extract pricing information
const pricing = response.data?.data?.meta?.display_price;
if (!pricing) {
return {
subtotal: "$0.00",
discount: "$0.00",
tax: "$0.00",
total: "$0.00",
};
}
return {
subtotal: pricing.without_discount?.formatted || "$0.00",
discount: pricing.discount?.formatted || "$0.00",
tax: pricing.tax?.formatted || "$0.00",
total: pricing.with_tax?.formatted || "$0.00",
hasDiscount: (pricing.discount?.amount || 0) < 0,
};
};
For more details on cart initialization, see the Elastic Path documentation.
Understanding Cart Total Components
The cart response contains several pricing components in the meta.display_price
object:
// Extract pricing information from cart response
const getCartPricing = (cart) => {
if (!cart?.data?.meta?.display_price) return null;
const pricing = cart.data.meta.display_price;
return {
// Total with tax included
total: pricing.with_tax?.formatted || "$0.00",
// Subtotal before discounts
subtotal: pricing.without_discount?.formatted || "$0.00",
// Discount amount (negative value)
discount: pricing.discount?.formatted || "$0.00",
// Tax amount
tax: pricing.tax?.formatted || "$0.00",
// Shipping cost
shipping: pricing.shipping?.formatted || "$0.00",
// Check if a discount has been applied
hasDiscount: (pricing.discount?.amount || 0) < 0,
};
};
UI Implementation
Common patterns for displaying cart totals:
// Cart totals display component
const CartTotals = ({ pricing }) => {
if (!pricing) return null;
return (
<div className="mt-4 border-t border-gray-200 pt-4">
<h3 className="text-md font-medium mb-3">Cart Summary</h3>
<div className="space-y-2 text-sm">
<div className="flex justify-between">
<span>Subtotal</span>
<span>{pricing.subtotal}</span>
</div>
{pricing.hasDiscount && (
<div className="flex justify-between text-green-600">
<span>Discount</span>
<span>{pricing.discount}</span>
</div>
)}
{pricing.shipping !== "$0.00" && (
<div className="flex justify-between">
<span>Shipping</span>
<span>{pricing.shipping}</span>
</div>
)}
<div className="flex justify-between">
<span>Tax</span>
<span>{pricing.tax}</span>
</div>
<div className="flex justify-between font-medium text-black border-t border-gray-200 pt-2 mt-2">
<span>Total</span>
<span>{pricing.total}</span>
</div>
</div>
</div>
);
};
Special Considerations
- B2B tax handling: Business customers may have different tax requirements
- International tax concerns: Different regions have different tax rules
- Tax exemption handling: Some customers may be exempt from certain taxes
For a real-world implementation of cart totals calculation that uses the initializeCart
utility, see the SPA Cart Example on GitHub.