Skip to content

EU Discount Pricing Rules for WooCommerce: The 30-Day Lowest-Price Requirement

By Jasper Frumau WooCommerce

If your shop shows a crossed-out price, a “-20%” badge, or a “was €X, now €Y” line anywhere, the EU’s Omnibus Directive has had a specific opinion about that number since 2022 — and most small stores have never heard of it. The rule is simple to state and easy to get wrong: the “before” price you show has to be the lowest price you charged in the last 30 days, not yesterday’s price, not an average, and definitely not a price you invented for the sale.

This guide covers what the rule actually requires, who it applies to, the exemptions, how to implement it in WooCommerce without hand-tracking prices in a spreadsheet, and what enforcement looks like in practice — including a fresh 2026 sweep that found 1 in 3 online stores getting it wrong. Written for store owners, not lawyers, by Jasper Frumau — WordPress and WooCommerce developer at Imagewize, based in the EU. Last updated: September 4, 2026.

Quick Summary: If you show any price reduction — a sale badge, a strikethrough price, a “was/now” pair — EU law (Directive 2019/2161, the “Omnibus Directive,” amending the older Price Indication Directive) requires the “before” price to be the lowest price you charged in the 30 days before the discount started, not whatever price happened to be showing the day before. Personalized offers and loyalty-program pricing sit outside the rule entirely; perishables and newly launched products are exemptions individual member states may choose to grant, not EU-wide guarantees. On penalties, member states must make a maximum fine of at least 4% of annual turnover (or at least €2 million where turnover can’t be established) available for widespread cross-border infringements — that’s a floor on the ceiling, not the smallest fine a single shop can face. A March 2026 EU-wide sweep found 1 in 3 online stores checked were still getting it wrong. For WooCommerce, a small price-history plugin handles the tracking automatically — you don’t need to build this yourself.

In This Guide

What the Omnibus Directive Actually Requires

Article 6a of the Price Indication Directive (98/6/EC), added by the EU’s 2019 Omnibus Directive, requires that any announcement of a price reduction state the lowest price the trader charged in a period of at least 30 days before the reduction. Not the price on the shelf yesterday. Not an average across the last month. The single lowest point in that 30-day window — and that’s the number your “before” price has to show.

The Court of Justice of the EU settled exactly how the calculation works in Case C-330/23, Aldi Süd (26 September 2024): a discount must be calculated from the 30-day low, and the older practice of striking through whatever price you charged most recently is no longer permissible. So if a product sold for €80 three weeks ago, dropped to €65 during a flash sale ten days ago, and sat at €75 yesterday, the reference price for a new “reduced” price claim has to be €65 — the lowest point, full stop, regardless of what the price happened to be right before the new sale started.

Price 3 weeks agoPrice 10 days ago (flash sale)Price yesterdayRequired reference price today
€80€65€75€65 — the 30-day low, not yesterday’s €75

Note — every price above is inside the window. Three weeks is 21 days, so all three count. Prices older than the lookback drop out entirely: if that same product had also sold for €55 six weeks ago, it would sit outside the 30 days and be ignored, and the reference price today would still be €65. The window rolls forward each day, so a low price does eventually age out on its own — but only by the calendar. You can’t accelerate it by putting the price back up in the meantime, which is exactly what the €75 above fails to do.

The rule sits inside the wider Omnibus Directive, which also touched fake review disclosure and search-ranking transparency — but the price-reduction rule is the one that affects nearly every WooCommerce store that ever runs a sale, which is why it’s the focus here.

Does This Apply to My Store?

If you sell to consumers (B2C) anywhere in the EU and you ever display a price reduction — a “-20%” badge, a strikethrough original price, a “was/now” pair, a seasonal sale banner — this rule applies to you, regardless of your store’s size or where you’re hosted. It’s consumer-protection law, so it’s triggered by where your customers are, not where your business is registered.

  • Covers: any visual or written claim that a price has been reduced — sale badges, strikethrough pricing, “was/now,” percentage-off callouts, seasonal campaign banners.
  • Doesn’t strictly cover: a price you simply lower with no reference to what it used to be — if you’re not announcing a reduction, there’s nothing to substantiate. The moment you show a “was” price or a percentage, the rule is live.
  • Gray area worth treating conservatively: discount codes that reveal a “was/now” comparison once applied (common in WooCommerce carts) function the same way in a customer’s eyes as a sale badge — track the reference price the same way rather than assuming codes are exempt.

B2B-only stores (no consumer sales at all) fall outside this specific rule, since it’s part of consumer-protection law. If you sell to both businesses and consumers through the same WooCommerce install, the rule applies to whichever prices your consumer-facing catalog shows.

The Exemptions

There is one true carve-out, plus three optional ones — and the distinction matters more than most guides admit. Paragraphs 3 to 5 of Article 6a don’t exempt anything themselves; they let each member state decide whether to relax the rule for certain goods. So “perishables are exempt” is only true in the countries that actually took that option. Check your own market before relying on any of the three.

  • Personalized offers and loyalty/membership pricing — genuinely outside the rule, everywhere. A discount shown only to a logged-in loyalty member, or generated by a personalization engine, isn’t a general “price reduction announcement” to the public, so Article 6a never engages. This one doesn’t depend on where you sell.
  • Perishable goods — optional (Art. 6a(3)). Member states may set different rules for goods liable to deteriorate or expire rapidly, which can mean exempting them outright or letting you use the immediately preceding price. Where a country hasn’t legislated it, food is treated like anything else.
  • Products on the market less than 30 days — optional (Art. 6a(4)). Member states may allow a shorter reference window for newly launched products. They aren’t automatically exempt; the permitted lookback is just shorter where the option was taken.
  • Progressively increasing discounts — optional (Art. 6a(5)), and the one WooCommerce stores hit most. If you run a staged sale that deepens over time (-20%, then -30%, then -50% without interruption), member states may let you keep referencing the single prior price from before the first reduction, instead of resetting to a new 30-day low at each step. This is exactly how most seasonal and clearance campaigns are built, so it’s worth confirming whether your market allows it before scheduling one.

Note: Because three of the four carve-outs above are national choices, the answer genuinely differs by country — this isn’t boilerplate hedging. The European Commission’s official guidance on interpreting Article 6a (2021/C 526/02) sets out what each derogation permits. If a specific campaign carries real legal exposure, a quick check with your national consumer authority (the ACM in the Netherlands, FPS Economy in Belgium, or your local Verbraucherzentrale/state authority in Germany) is worth the hour — this post explains the EU-wide baseline, not a legal opinion on your specific campaign.

How to Implement This in WooCommerce

WooCommerce doesn’t track price history natively — it only stores the current regular and sale price. Complying with the 30-day rule means recording every price change and computing the lowest value in the trailing window, which is exactly what a small category of plugins exists to do. For most SME stores, a plugin is faster and more reliable than tracking this manually in a spreadsheet.

PluginTypeBest for
WC Price HistoryFree, WordPress.orgSimplest option — tracks price history and displays the 30-day low automatically
WP Desk OmnibusPaidStores wanting configurable display rules (which products show the reference price, styling, multi-currency)
iworks/omnibusFree, GitHubDeveloper-maintained stores comfortable installing outside WordPress.org
FlyCart Discount Rules — Omnibus AddonPaid addonStores already running FlyCart’s Discount Rules plugin for cart-level promotions

Whichever you choose, the checklist is the same: install it before you run your next sale, let it start recording price history immediately (it needs real data — it can’t backfill a history that didn’t exist), then set your product pages to display the 30-day-low “reference price” automatically instead of hand-typing a “was” price into the product description. Test with one product first: put it on sale, check the front end shows the correct reference price, then roll it out store-wide.

For the developers: what the plugins are doing under the hood

None of this needs custom code for a typical store, but the mechanism is simple enough to sketch: hook every product save, append the current _price meta with a timestamp to a price-history table or serialized postmeta array, then filter woocommerce_get_price_html to compute the minimum value from entries inside the trailing 30 days and render it as the reference price whenever the current price sits below it. Note the hook choice — woocommerce_update_product, not one of the woocommerce_product_options_* actions, which only render fields in the admin product-data panel and never fire on save.

// Fires after a product is saved by any path: admin edit, bulk edit,
// quick edit, REST/CLI import, or a scheduled sale starting or ending.
add_action( 'woocommerce_update_product', 'iwz_log_price_snapshot' );

function iwz_log_price_snapshot( $product_id ) {
    $price   = get_post_meta( $product_id, '_price', true );
    $history = get_post_meta( $product_id, '_iwz_price_history', true ) ?: [];

    // Only record actual changes, or every save inflates the history.
    if ( end( $history ) === $price ) {
        return;
    }

    $history[ time() ] = $price;

    // Prune anything outside the lookback window, keeping one entry
    // before it so the 30-day low is still computable at the boundary.
    $cutoff  = time() - ( 30 * DAY_IN_SECONDS );
    $history = array_filter(
        $history,
        static fn( $ts ) => $ts >= $cutoff,
        ARRAY_FILTER_USE_KEY
    );

    update_post_meta( $product_id, '_iwz_price_history', $history );
}

The plugins above handle the pruning, the hook coverage across every price-change path (manual edit, bulk edit, scheduled sales, variable product variations), and the front-end display filter — which is most of the actual engineering effort, not the snapshot logic itself.

What Happens If You Don’t Comply

The headline number gets misquoted constantly, so it’s worth stating precisely: the Omnibus Directive requires member states to make available a maximum fine of at least 4% of the trader’s annual turnover in the country of infringement, or at least €2 million where turnover information isn’t available. It is a floor on the ceiling — a minimum for how high national law must let penalties go — not a minimum for what any individual store actually pays. That obligation is aimed at widespread infringements pursued through the EU’s Consumer Protection Cooperation network, meaning coordinated cross-border cases affecting consumers in several member states.

In practice, a small shop caught with a bad strikethrough price is far more likely to receive a correction order or a proportionate national fine than a turnover-percentage penalty. Belgium shows how this looks once transposed: its Code of Economic Law sorts infringements into six severity levels, with maximum fines of 4% of annual turnover for levels 1–2 and 6% for levels 3–6 (or €2 million where turnover is unknown). Again — maximums, applied according to severity, not a flat charge.

This isn’t a theoretical risk. On 26 March 2026, the European Commission and consumer protection authorities from 23 EU countries plus Iceland and Norway published the results of a coordinated “sweep” of online stores’ Black Friday and Cyber Monday discounts. Out of 314 traders checked, 30% — roughly 1 in 3 — incorrectly referenced their price reductions. The same sweep found 36% of traders adding optional items to customers’ baskets, but the discount-reference figure is the one directly relevant here, and it shows regulators are actively looking, not just legislating on paper. National authorities can follow up with enforcement against the traders identified.

Common Mistakes Stores Make

  • Briefly resetting to full price to “reset the clock.” Bumping the price back up for a day between sales doesn’t reset your 30-day low — the lowest price in the window still counts, regardless of what you did in between.
  • Assuming installing a plugin means you’re automatically compliant. Price-history plugins only work from the moment they start recording — install one the day before a big sale and it has no real history to calculate from yet.
  • Hand-typing a “was” price into a product description or banner. A manually written reference price drifts out of sync with reality the moment prices change again, and it’s the first thing an investigator checks against your actual price history.
  • Confusing this with VAT-inclusive pricing display. They’re separate rules — the reference-price requirement is about discount claims, VAT display is about whether the price shown includes tax. See our WooCommerce EU VAT setup guide if you haven’t confirmed your VAT display is correct too.
  • Treating store-wide sale banners differently from individual product badges. A homepage banner claiming “up to 50% off” is still a price-reduction announcement covering every product it applies to — the reference-price rule doesn’t only apply to per-product strikethrough pricing.
  • Setting up coupon codes without thinking about the reference price they reveal. A coupon that shows a customer a “was/now” comparison in the cart is subject to the same rule as a sale badge on the product page — the discount mechanism doesn’t matter, the displayed comparison does.

This rule sits alongside the other EU consumer-protection requirements already covered in this series — the 14-day cooling-off period for returns, and separately, the accessibility obligations under the European Accessibility Act. None of them are optional extras bolted onto “real” store setup — they’re part of what selling to EU consumers actually requires, alongside the conversion tactics that get people to buy in the first place. If you’re migrating a store into WooCommerce from another platform, our Shopify to WooCommerce migration guide covers where compliance fits into that process from day one.

Frequently Asked Questions

  • What is the EU’s 30-day lowest price rule? Under Article 6a of the Price Indication Directive (added by the 2019 Omnibus Directive), any announced price reduction must show the lowest price the trader charged in the 30 days before the reduction — not yesterday’s price, not an average.
  • Does this apply to small WooCommerce stores, or only large retailers? It applies regardless of store size. It’s consumer-protection law triggered by selling to EU consumers, not by company turnover or headcount.
  • What products are exempt from the 30-day price rule? Only one exclusion applies EU-wide: personalized offers and loyalty or membership pricing shown to specific customers rather than announced publicly. Perishable goods, products on the market less than 30 days, and progressively increasing discounts are optional derogations that each member state may choose to grant under Article 6a(3) to 6a(5), so confirm your own market rather than assuming they apply.
  • Can I reset my 30-day price history by briefly raising the price? No. The rule looks at the actual lowest price charged in the window — briefly restoring the full price for a day doesn’t erase a lower price you charged earlier in that same 30-day period.
  • Does WooCommerce track price history automatically? No — WooCommerce only stores the current regular and sale price. A price-history plugin (such as WC Price History or WP Desk Omnibus) is needed to record changes over time and calculate the 30-day low automatically.
  • What are the fines for non-compliance? The Omnibus Directive requires member states to make available a maximum fine of at least 4% of annual turnover, or at least €2 million where turnover information isn’t available, for widespread cross-border infringements. That is a floor on how high national penalties must be allowed to reach, not a minimum charge for a single store. Belgium, for example, sets maximums of 4% of turnover for severity levels 1 to 2 and 6% for levels 3 to 6.

Sources

This post is a practical guide for store owners, not legal advice. Where a campaign carries real exposure, confirm the position in your own market with a qualified adviser or your national consumer authority.

Need a WooCommerce Developer for Your Store?

We build and optimize WooCommerce stores for SMEs — from custom checkout flows and payment integrations to performance tuning and ongoing maintenance. Fixed-price quotes available.

  • Custom checkout and cart optimization
  • Payment gateway integration (Stripe, Mollie, PayPal)
  • WooCommerce performance and speed optimization
  • Ongoing store maintenance and support

Leave a Reply

Your email address will not be published.