Most PrestaShop merchants treat price display as a styling question — a font size, a strikethrough colour, where the "incl. VAT" note sits. In Europe it is none of those things. Whether you show net or gross, whether a unit price has to appear next to the sticker price, and which country's rule applies when a French customer buys from your German store are all questions with a legal answer, and getting them wrong is the kind of thing a competitor reports or a consumer authority spot-checks. The good news: almost every one of these rules maps onto a specific PrestaShop setting. This guide is about exactly that mapping — what the law on price presentation requires, and the precise back-office switch, field or tax rule that satisfies it.
To keep this focused: this post owns price display — net vs gross, unit pricing, and how reduced prices must be shown. The mechanics of VAT itself — which rate applies, OSS/IOSS registration, the reverse-charge for cross-border B2B — live in their own guides, linked at the points where they connect. If your question is "what rate do I charge," start with tax configuration in PrestaShop and VAT in the EU: OSS, IOSS and what your store must handle. If your question is "what price do I show," you're in the right place.
The one rule that underpins everything: B2C prices are gross
In every EU member state, the price a consumer sees must be the total they pay — VAT included. This comes from the Consumer Rights Directive and the Price Indication Directive (98/6/EC): the "selling price" shown to a consumer is the final price including all taxes. A product that costs €100 plus 21% VAT is shown to a shopper as €121.00, full stop. Net-only pricing to consumers isn't a stylistic preference you can switch on; it's non-compliant.
This catches people out because PrestaShop has no single "Display prices tax included" master switch on a settings page — gross-versus-net display is governed by the customer group. Every visitor belongs to a group, and each group has a Price display method set to either Tax included or Tax excluded. The behaviour your anonymous shoppers and ordinary retail customers see is controlled by the default groups under Customers → Groups — on a standard install those are Visitor, Guest and Customer. For any store selling to consumers, the Price display method on each of those must be Tax included. So what does that actually change? It controls whether product pages, category lists, the cart and the search results render the gross or the net figure to that visitor. Leave a default group on "Tax excluded" — a state some imported themes and B2B-oriented setups carry — and every consumer-facing price for those shoppers is technically unlawful in Europe, even though VAT is still calculated correctly at the order line.
One nearby setting people confuse with this: under International → Taxes there's a Display tax in the shopping cart toggle (the configuration key PS_TAX_DISPLAY), but that only governs whether tax appears on its own line in the cart — it does not control the gross/net display of catalogue prices. The group Price display method is the lever that does.
Two things the group display method does not do, which trips people up: it doesn't add the literal "incl. VAT" wording (that's theme template text — more below), and a B2B group set to net is exactly the mechanism you use to serve net prices alongside B2C gross. That second point is where most mixed stores get into trouble, so it gets its own section.
Showing net to businesses, gross to consumers — without breaking the law for either
Net pricing isn't forbidden — it's required reading for the right audience. The standard, lawful pattern is: verified business customers see net (excluding VAT) with a clear "excl. VAT" indication, and everyone else sees gross. PrestaShop handles this with the same customer-group mechanism described above — a dedicated B2B group simply gets the opposite display method.
Go to Customers → Groups, create or edit a group (for example a "Wholesale" or "B2B" group), and set Price display method to Tax excluded. The field is stored as the group's price_display_method, and PrestaShop resolves which figure a given visitor sees from their group's setting via Product::getTaxCalculationMethod(). A customer assigned to that group now sees net prices throughout the shop; a retail customer in a default group still sees gross. Both are compliant for their audience — provided your theme labels the net display clearly so a business buyer is never in doubt that VAT will be added.
The practical friction is everything around that toggle: assigning customers to the right group, handling visitors who haven't logged in yet, and letting a buyer flip between views when your catalogue legitimately serves both. Building that group plumbing, the VAT-number-gated registration, and the payment-on-account terms that usually come with it is a project in itself — we cover the whole B2B setup in B2B e-commerce with PrestaShop: VAT handling, net prices and payment terms, and the cross-border reverse-charge that zero-rates a valid EU VAT number is part of the OSS/IOSS guide.
If you want a cleaner experience than swapping groups by hand — a visible net/gross switch the shopper controls, or automatic per-group display without theme edits — that's the gap our Tax Display Switcher module fills. The benefit it buys you: a store that legitimately serves both retail and trade customers can show each the price they're legally entitled to see, configured from the back office, without forking your theme to do it.
The "incl. VAT" wording is template text, not a setting
Here's a distinction that costs German merchants real money: setting a group's display method to "Tax included" makes the price gross, but it does not on its own print the words "inkl. MwSt." next to it. That label is theme output, and several countries — Germany most strictly — require the wording, not just the gross number.
In PrestaShop's default themes the price block is rendered by the product-prices.tpl template (under themes/<your-theme>/templates/catalog/_partials/). On the product page itself the theme prints a generic tax indicator via {$product.labels.tax_short}, which resolves to "(tax incl.)" or "(tax excl.)" — not the localised tax name. The country-specific wording is driven elsewhere: there's a per-country Display tax label switch under International → Localization → Countries (the display_tax_label field), and the tax's own name — which you set under International → Taxes and apply per country under International → Tax Rules — is what surfaces in the tax-label contexts (notably the cart, carrier and checkout). To get correct German wording showing you usually have to edit the theme template to print the literal "inkl. MwSt." text near the price, because core only gives you the generic "(tax incl.)" string out of the box. So what? A German store that shows €119,00 with no "inkl. MwSt." text fails the Preisangabenverordnung even though the math is right — and that's a template-and-tax-name fix, not a price recalculation.
Germany's PAngV: the strictest rulebook, and what it demands in PrestaShop
If you sell to German consumers, you're effectively writing your price-display config to the toughest standard in the EU. The Preisangabenverordnung (PAngV) requires consumer-facing prices to:
- Include VAT (19% standard, 7% reduced) — your default customer groups set to Tax included, plus the correct German tax rule.
- Carry the literal "inkl. MwSt." (or "inkl. gesetzlicher MwSt.") wording — the tax-label point above.
- State shipping costs or link to them near the price — usually a "zzgl. Versandkosten" line with a link to your shipping CMS page, placed in the price block.
- Show a unit price (Grundpreis) for anything sold by weight, volume, length or area — a 500 ml shampoo at €8.99 must also display "€17,98 / 1 Liter".
The Grundpreis rule catches far more products than owners expect: cosmetics, food, cleaning products, fabric by the metre, cable by the metre, anything where a shopper would reasonably compare quantities. The practical takeaway many merchants land on is to configure their whole store to German standards and serve every market that way — it's a conservative baseline rather than a universal compliance guarantee — German-style VAT, shipping and unit-price display is a strong common standard, but it doesn't on its own satisfy every national language, disclosure, Omnibus, sector or checkout rule — so you build it once instead of branching display logic per country. The unit-price half of that has a dedicated PrestaShop field, which is the next section.
Unit pricing: the product field most stores leave empty
Unit pricing — price per kg, per litre, per metre, per piece — is mandatory EU-wide (Directive 98/6/EC) for goods sold by measurable quantity, and PrestaShop has had a first-class field for it for years. Most stores simply never fill it in.
On the product page, open the Pricing tab and find Price per unit (older 1.6/1.7 builds label it "Unit price"). You enter the unit (per kg, per litre, per m, "piece") and PrestaShop computes the per-unit figure from the product price. Under the hood these are the product's unit_price_ratio and unity fields, and the front office renders the result automatically — the "€17,98 / 1 Liter" line appears next to the price with no template surgery. So what does filling it in actually buy you? Compliance for the products where it's required, and a quiet conversion benefit: a clear per-litre or per-kg figure is exactly what a comparison shopper is looking for, and showing it removes a reason to bounce to a competitor who did the math for them.
Two operational notes from doing this at scale. First, for a large catalogue you don't want to type the unit on hundreds of products by hand — the field is exposed in the CSV product import (Advanced Parameters → Import), so map your "unit" and "unit price ratio" columns and set them in bulk. Second, the displayed unit price is derived from the base price, so if your base price is gross (as it should be for B2C), the unit price inherits that — keep the two consistent or a German Grundpreis check will flag the mismatch.
Reduced prices: showing discounts the Omnibus way
The Omnibus price-reduction rules have applied across EU member states through national laws since the 2022 implementation deadline, subject to local details — so how you display a discount is regulated, not just whether you offer one. When you advertise a price reduction, the reference price you strike through must be the lowest price the product was sold at in the previous 30 days, unless a local exception applies — not the original full price, and definitely not a number you inflated the week before the sale.
A worked example: a product normally sits at €50. You ran a weekend promo at €40 two weeks ago. You now launch a new sale at €35. The lawful reference is €40 (the 30-day low), so you present it as €40 → €35, a 12.5% reduction — not €50 → €35 at 30% off. The rule reaches strikethrough pricing on product pages, sale banners, promotional emails, and every Black Friday / clearance event. It does not reach personalised reductions (a loyalty discount on one customer's cart), genuine bundle pricing, or products on the market less than 30 days.
Where this bites in PrestaShop specifically: the platform's Catalog price rules and Specific prices (the per-product "Add a specific price" panel on the Pricing tab) render the original price as the struck-through reference by default — and "original price" in core means your catalogue price, which is not the same as the 30-day low the Omnibus rule demands. Stock PrestaShop has no native memory of "lowest price in the last 30 days," so a literal strikethrough of the catalogue price can overstate the discount and breach the rule. The compliant approaches are to set your specific-price reference deliberately to the true 30-day low, or to use a module that records price history and renders the correct reference automatically. Either way, treat the default strikethrough as something to verify, not trust.
Cross-border: whose pricing rules apply?
When you target consumers in another EU country, that country's mandatory consumer-protection rules may apply to those sales — it isn't a simple "always the customer's country" rule, but turns on whether you direct your activities at that market. A German store that actively targets French consumers may have to follow French presentation rules for those sales; target Poland and the Polish enforcement of Omnibus (UOKiK actively monitors online stores) can be what you're judged against. So design for each market you serve. The pragmatic answer most merchants reach is the one already mentioned: build to the strictest common standard — gross prices with explicit VAT wording, unit prices everywhere they apply, Omnibus-correct references — and you're covered in every market without branching your front office per country.
The rate that drives the gross figure does change by destination, and PrestaShop handles that through tax rules keyed to the delivery country — configure a tax rule group per country under International → Tax Rules and assign it to your products, and the displayed gross price recalculates from the shipping address. The registration and reporting side of charging another country's VAT (OSS thresholds, when you must register) is its own subject, covered in the OSS/IOSS guide; how returns and refunds interact across borders is in cross-border returns.
A note on the documents downstream of the price
The price you display and the price on the invoice have to agree, and the invoice has its own legal content rules. If you're tightening price display, it's worth checking the invoice at the same time — gross/net presentation, VAT breakdown and the mandatory fields are covered in invoice customization in PrestaShop: PDF templates and legal requirements, and the wider obligations around selling in the EU sit in the store owner's guide to EU e-commerce law.
The price-display checklist for a PrestaShop store
- Default groups set to gross — Customers → Groups → Visitor / Guest / Customer → Price display method = Tax included for any B2C store (there is no single global "display prices tax included" switch).
- VAT wording showing — correct tax name under International → Taxes plus the per-country Display tax label setting, and usually a small theme template edit so the price block prints "incl. VAT" / "inkl. MwSt.", not just the gross number.
- B2B groups set to net — Customers → Groups → Price display method = Tax excluded, with clear "excl. VAT" labelling for those buyers only.
- Shipping-cost reference near the price — a "plus shipping" line linking to your shipping CMS page, required for Germany.
- Unit prices filled in — the Pricing tab's Price-per-unit field (unit_price_ratio / unity) for every product sold by weight, volume, length or area; bulk-set via CSV import.
- Omnibus reference verified — strikethrough reference set to the true 30-day low, not the catalogue price; don't trust the default.
- Per-country tax rules — Tax Rules groups assigned so the gross figure recalculates by delivery country for OSS sales.
Price-display rules exist to stop deceptive pricing, and the stores that follow them get more than fine-avoidance: a shopper who sees an honest total, a real per-litre figure and a discount that isn't smoke-and-mirrors is a shopper who trusts the rest of your store too. On PrestaShop the whole compliant picture is reachable from settings you already have — the work is knowing which toggle answers which rule, and not leaving the unit-price field, the tax label or the 30-day reference on their unhelpful defaults.
Comments
No comments yet. Be the first!
Be the first to ask a question or share useful feedback.
Leave a comment
Share a question, an installation detail, or feedback that could help another reader.