Skip to content

Show prices with and without taxes in Shopify

Many business located in some countries (especially in the UE) may need to show prices both including and excluding taxes. This is even more a necessity for those selling in B2B.

This tutorial shows a way to implement this in a dynamic way, based on actual market and taxes configuration. This strategy may be better than hardcoding tax rates in the theme like many community discussions suggest… (👀 https://community.shopify.com/t/how-to-display-price-with-and-without-vat/342718)

View the demo for France (password: brush)

It allows customers to see products prices:

  1. Both including and excluding tax
  2. In a dynamic way by using actual market and taxes data…
  3. … rather than hardcoding taxe rates in Liquid files.

Key point: Instead of updating (bloating!) Liquid template files with as may taxe rates avaible, making calculations, breaking the separation of concerns principle, etc… and having to do this for each file for a feature (featured product, product block on list, product info on product detail, search suggestions, …), we do a unique and cached AJAX call to our Brush backend and use elegant Javascript to update all price blocks at once. Whatever the number of blocks displaying prices.

See branch on backend tutorial repo tutorial/taxes-included-excluded and its Excl. tax price calculation commit.

See branch on frontend tutorial repo tutorial/taxes-included-excluded and its Excl. tax price calculation commit.

  • api/routes/brush/tax-rate/GET.ts

    • Uses the draftOrderCalculate GraphQL mutation…
    • … to simulate a 100 order in the current currency.
    • Extracts tax-related information.
    • Calculates the tax-exclusive amount from the tax-inclusive product price.
    • Returns a normalized structure containing the tax rate.
  • Tax Calculation Logic

    • Centralized in the backend instead of being duplicated in Liquid templates.
    • Uses the actual tax configuration configured in Shopify Markets.
    • Ensures consistency with Shopify’s own tax engine.
    • Exposes tax information to the storefront through a lightweight endpoint.
  • Price Blocks

    • Existing price components continue to render normally.
    • No need to duplicate tax calculations across:
      • Product cards
      • Product pages
      • Featured products
      • Search suggestions
      • Collection grids
      • Any future component displaying prices
  • Data Attributes

    • Price elements expose product and variant pricing information through HTML attributes.
    • JavaScript can discover all price blocks automatically.
    • Keeps Liquid focused on rendering markup only.
  • Taxes Service

    • Performs a single AJAX request to the Brush backend.
    • Retrieves market tax information once.
    • Shares the result across the entire page.
  • DOM Updater

    • Scans the page for price blocks.
    • Calculates and formats tax-exclusive prices.
    • Injects additional UI below existing prices.
    • Updates all matching components at once.
  • Cached API Result

    • Responses are cached aggressively to LocalStorage thanks to Brush Stores powered by Alpine Store.
    • Prevents repeated Shopify Admin API requests from the theme.
  • Tax-Included Price

    • Remains the primary displayed Shopify price.
    • Continues to benefit from Shopify formatting and localization.
  • Tax-Excluded Price

    • Generated dynamically from backend-provided tax data.
    • Displayed alongside the regular price.
    • Automatically adapts when the customer changes market.
  • Shopify renders prices normally.
  • Product cards and product pages display their standard prices.
  • No extra tax calculations are performed in Liquid.
  • The storefront performs a single request to the Brush backend.

  • Brush determines:

    1. The active Shopify market.
    2. The applicable tax rate.
  • The response is cached for future requests.

  • The frontend scans the DOM for price components.
  • Each price block is enhanced automatically.
  • The tax-exclusive amount is displayed below the standard price.

Because the tax information is fetched only once, the cost remains constant whether the page contains:

  • 2 products
  • 20 products
  • 200 products

4. Market Changes Are Handled Automatically

Section titled “4. Market Changes Are Handled Automatically”
  • If a customer browses from another market:
    • Shopify applies the corresponding market configuration.
    • Brush retrieves the appropriate tax settings.
    • Prices are recalculated using the correct rate.

No Liquid changes are required when:

  • Adding a new market
  • Changing a VAT rate
  • Expanding internationally
  • Shopify remains responsible for product pricing.
  • Gadget remains responsible for tax calculations.
  • JavaScript remains responsible for presentation.

Each layer focuses on its own concern, making the implementation easier to maintain over time.

  • Avoid hardcoding VAT rates

    Tax rates evolve. Markets evolve. Regulations evolve. If you hardcode 20%, 21%, or 19% directly in Liquid files, you’ll eventually have to hunt them down across your theme.

  • Keep tax logic out of Liquid

    Liquid is great for rendering HTML. It is much less suited for business logic and calculations spread across multiple components. Centralizing tax calculations keeps templates clean and maintainable.

  • Use Shopify Markets as the source of truth

    Shopify already knows which market a customer belongs to. Reuse that information instead of maintaining a separate tax configuration layer.

  • Fetch once, update everywhere

    A single cached AJAX request is usually cheaper and easier to maintain than repeating calculations in every template that displays prices.

  • Design for scalability

    New product cards, recommendation blocks, quick views, search suggestions, and collection pages automatically benefit from the feature because the frontend enhances all price blocks uniformly.

  • Respect separation of concerns

    • Shopify → product and market data
    • Gadget → tax calculations
    • Theme → rendering
    • JavaScript → UI enhancement

    This separation makes future maintenance significantly easier.

  • Think beyond VAT

    The same pattern can be reused for:

    • B2B pricing displays
    • Margin indicators
    • Wholesale pricing
    • Eco-tax breakdowns
    • Country-specific pricing information

    Once the architecture is in place, additional price-related enrichments become straightforward to implement.

With this approach, customers can instantly see both:

  • Tax-inclusive prices
  • Tax-exclusive prices

while the store remains fully aligned with Shopify Markets configuration.

Instead of scattering tax formulas throughout the theme, we leverage Shopify as the source of truth, Brush as the calculation layer, and a single frontend enhancement script to update every price component consistently across the storefront.