Skip to main content

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:

FieldLocationDescription
with_tax.amountCart meta.display_priceTotal cart value including tax, in minor units (e.g., cents)
with_tax.formattedCart meta.display_priceFormatted total cart value including tax (e.g., "$99.99")
without_tax.amountCart meta.display_priceTotal cart value excluding tax, in minor units
without_tax.formattedCart meta.display_priceFormatted total cart value excluding tax
without_discount.amountCart meta.display_priceSubtotal before any discounts, in minor units
without_discount.formattedCart meta.display_priceFormatted subtotal before any discounts
discount.amountCart meta.display_priceTotal discount amount (negative value), in minor units
discount.formattedCart meta.display_priceFormatted total discount amount
tax.amountCart meta.display_priceTotal tax amount, in minor units
tax.formattedCart meta.display_priceFormatted total tax amount
shipping.amountCart meta.display_priceShipping cost, in minor units (if applicable)
shipping.formattedCart meta.display_priceFormatted shipping cost (if applicable)
item.unit.amountCart item meta.display_pricePrice per unit before discounts, in minor units
item.unit.formattedCart item meta.display_priceFormatted price per unit before discounts
item.value.amountCart item meta.display_priceTotal value for this item (unit price × quantity), in minor units
item.value.formattedCart item meta.display_priceFormatted total value for this item
item.discount.amountCart item meta.display_priceDiscount amount for this item (negative value), in minor units
item.discount.formattedCart item meta.display_priceFormatted discount amount for this item
item.discounted.amountCart item meta.display_pricePrice after discount, in minor units
item.discounted.formattedCart item meta.display_priceFormatted 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

  1. Determine tax strategy early: Decide if you'll use Elastic Path's calculation or a third-party tax service
  2. Consider tax complexity: Different jurisdictions have different tax rules and rates
  3. Keep tax rates updated: Tax rates can change - ensure your system stays current
  4. Document tax decisions: Maintain clear records of tax-related implementation choices
  5. 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
tip

For a real-world implementation of cart totals calculation that uses the initializeCart utility, see the SPA Cart Example on GitHub.