Store Security

Why Your WooCommerce Discount Plugin Broke After You Switched to Block Checkout

WooCommerce Tips

When Block Checkout Breaks Your Discounts

Why the migration to WooCommerce’s block-based cart and checkout silently breaks certain discount plugins β€” and the architectural difference that prevents it.

You switched to WooCommerce’s block-based cart and checkout β€” maybe WooCommerce installed it by default, maybe your theme recommended it, maybe you just updated one day and found the layout had changed. Everything looked fine. Then a customer mentioned they weren’t seeing the discounted price at checkout. Or your cart total stopped reflecting the campaign you had running. Or the sale price displayed correctly on the product page, but disappeared the moment the item was added to the block cart.

This is a real failure mode, and it is not caused by a misconfiguration on your end. It is caused by an architectural mismatch between how certain discount plugins apply their pricing and how WooCommerce’s block-based cart and checkout renders prices.

Understanding the distinction is useful because it tells you whether the problem is fixable with a setting change, or whether it requires a different tool.

What changed when WooCommerce introduced block checkout

WooCommerce has had two ways to display the cart and checkout for years. The older approach uses PHP shortcodes β€” [woocommerce_cart] and [woocommerce_checkout] β€” rendered through WooCommerce’s classic PHP templates. Most stores that existed before 2022 are on this setup.

The newer approach uses Gutenberg blocks β€” the Cart Block and Checkout Block β€” introduced in WooCommerce 8.3 and made the default for new WooCommerce installations. Stores created after that version get block checkout out of the box.

Visually, the two can look nearly identical. The blocks can be styled to match your theme just as the classic templates can. Many store owners who migrated to block checkout did not realise that the rendering engine underneath had changed significantly β€” and that the change had implications for any plugin that hooks into the classic cart rendering pipeline.

Is your store using block checkout? Go to WooCommerce → Settings → Advanced → Page setup. If your Cart and Checkout pages contain a Cart Block or Checkout Block (visible in the page editor), you are on block checkout. If you see shortcode text like [woocommerce_cart], you are on classic checkout.

How discount plugins used to hook into the cart

The classic WooCommerce cart and checkout are rendered by PHP. When a customer views the cart page or proceeds to checkout, WooCommerce fires a series of PHP action and filter hooks that plugins can attach to.

The relevant ones for discount plugins are:

  • woocommerce_cart_calculate_fees β€” lets plugins add fee or discount line items to the cart total at calculation time
  • woocommerce_before_calculate_totals β€” fires before WooCommerce recalculates cart totals, letting plugins modify cart item prices mid-session
  • woocommerce_cart_item_price β€” a display filter that controls what price is shown per line item in the cart

Many WooCommerce discount plugins β€” particularly those built as rule engines β€” apply their discounts through these hooks. The product retains its original price in the database. The discount is calculated and injected at cart calculation time, in memory, every time the cart is rendered or updated.

This approach has worked reasonably well for years on classic checkout. The hooks fire reliably during PHP rendering, the discount appears in the cart total, and the customer sees the reduced price at checkout.

Why block cart and checkout bypass those hooks

The block-based cart and checkout do not go through the same PHP template rendering pipeline. They are React-powered components that communicate with WooCommerce through the Store API β€” a REST-like endpoint that handles cart data, product data, and checkout operations.

When a customer adds a product to the cart and views it in the block cart, WooCommerce is not rendering a PHP template. It is fetching cart data through the Store API and rendering the result in JavaScript.

Here is where the breakage happens: the PHP hooks that cart-level discount plugins rely on β€” woocommerce_cart_calculate_fees, woocommerce_before_calculate_totals, and friends β€” either do not fire in the block checkout rendering context, fire differently, or fire at a point in the process that the block cart does not read from.

The result is that a plugin that has been faithfully applying discounts through those hooks for years appears to stop working the moment the store switches to block checkout. The discount logic is still running. The hooks are still firing somewhere in the process. But the block cart is not picking up the modified prices the way the classic template did.

Why it is silent: The product page usually still shows the discounted price, because product page rendering goes through PHP and those hooks fire normally there. It is specifically the block cart and block checkout where discounts disappear or display incorrectly. This can make the problem hard to spot in testing if you only check the product page.

This is not a hypothetical edge case. It has been documented on WordPress.org support forums by users of several popular discount plugins. At least one major competitor in this space β€” Flycart’s Discount Rules for WooCommerce β€” has publicly acknowledged that their plugin lacks full block checkout integration as of recent versions. When a plugin with hundreds of thousands of installs lists block checkout compatibility as an open issue, you can assume many stores have quietly been affected without realising it.

How to tell if your discount plugin is affected

The diagnostic is straightforward, but you need to test the right combination: the discount must be active, and you need to check the block cart, not the product page.

Test 1: Check whether discounts survive the cart

  1. Set up a discount campaign or rule in your plugin.
  2. Add a discounted product to the cart as a guest or customer.
  3. Open the cart page. Confirm whether the discounted price β€” not the original price β€” is displayed.
  4. Proceed to the checkout page. Confirm whether the order total reflects the discount.

If the product page shows a strikethrough sale price but the cart shows full price, or if the order total at checkout does not include the discount, your plugin is affected.

Test 2: Check how your plugin applies discounts

If you have access to your plugin’s documentation or settings, look for how it describes its discount method. Language like “applies fees at cart level”, “modifies cart item prices on the fly”, “uses woocommerce_cart_calculate_fees“, or “real-time price adjustment” describes the hook-based approach that is vulnerable to block checkout.

If the documentation describes setting WooCommerce sale prices directly, modifying product-level pricing, or working through WooCommerce’s native sale price mechanism, the plugin is likely using an approach that is not affected by the block checkout change.

Test 3: Check WordPress.org support forums

Search the plugin’s WordPress.org support forum for “block checkout” or “blocks”. If there are multiple unanswered threads or threads where the plugin author acknowledges the limitation, that is a reliable signal about the current state of compatibility.

The approach that works with both: price-level modification

There is a fundamentally different way to apply discounts in WooCommerce, and it does not have this problem.

Instead of intercepting the cart at calculation time through PHP hooks, a plugin can write discounts directly to the product’s WooCommerce sale price field β€” the same field that WooCommerce itself uses when you manually set a sale price on a product. When the campaign activates, the sale price is set. When the campaign ends, it is cleared. The product always has the correct current price stored in the database.

From WooCommerce’s perspective β€” and from the block cart’s perspective β€” this is indistinguishable from a manually entered sale price. The block cart reads the product’s sale price through the Store API, gets the discounted value, and displays it correctly. No hooks, no interception, no dependency on how the cart rendering pipeline is structured.

This approach works on classic checkout, block checkout, REST API integrations, headless WooCommerce setups, and any future checkout architecture WooCommerce introduces β€” because it works at the data layer, not the presentation layer.

The tradeoff is that this kind of plugin has to manage the sale prices actively. It sets them when a campaign starts and removes them when a campaign ends. This requires a scheduler β€” something that runs at the right time to activate and deactivate discounts reliably. A plugin built this way needs a solid scheduling system underneath.

How Smart Cycle Discounts handles this: Smart Cycle Discounts applies discounts by writing to WooCommerce’s native sale price system. When a campaign activates, discounted products receive sale prices. When the campaign ends, those sale prices are removed automatically. This is why it works with block cart and checkout without any special configuration β€” the block cart reads product prices the same way everything else does, and the price it reads is already the discounted one. There is no hook dependency to break.

What about cart-level discount types?

It is worth acknowledging the limitation of the price-level approach: it works cleanly for product-level discounts β€” percentage off, fixed amount off, sale price reductions. It is less naturally suited to discounts that are inherently cart-level, like “10% off your entire order when you spend over $100” or “add this item free to orders over $75.”

Cart-level conditions still require some cart-awareness, and a plugin doing this correctly for block checkout needs to integrate with WooCommerce’s Store API extensions rather than relying solely on the classic PHP hook pipeline. This is a harder engineering problem, and it is one reason why certain discount types have lagged behind in block checkout compatibility across the ecosystem.

If your discounts are primarily product-level β€” sale prices, BOGO offers where the discount applies to specific products β€” the price-level approach covers your use case fully. If you need cart-total-based spend thresholds, the picture is more nuanced, and the specific plugin you are using matters.

This is not a niche problem β€” it will affect more stores over time

Block checkout is the default for new WooCommerce installations. WooCommerce’s own roadmap has consistently moved toward Gutenberg-native experiences across the board. The classic shortcode cart and checkout are not going away immediately, but their long-term trajectory is clear.

Stores that have been running on classic checkout for years will migrate β€” some deliberately, some when a theme update or page builder change creates a conflict that gets resolved by switching to blocks. When that happens, any discount plugin relying on the classic hook pipeline will break in the same way described above.

The store owners most at risk are those who:

  • Installed WooCommerce recently (block checkout is the default)
  • Updated a theme or page builder and unknowingly switched rendering engines
  • Migrated their checkout pages to blocks for the improved performance or design flexibility
  • Are planning a site rebuild and intend to use block-based templates throughout

If any of those describe your situation, checking your discount plugin’s block checkout compatibility now β€” before a sale campaign goes live β€” is a much better experience than discovering the problem mid-promotion when a customer notices the price at checkout does not match what the product page promised.

Quick pre-launch check: Before any major sale campaign, add a discounted product to a cart session, open the cart page, and confirm the discounted price is showing. If you have recently changed anything about your checkout pages, do this even if the plugin has always worked before. The breakage is not always obvious from the admin side.

FAQ

Why does my WooCommerce discount plugin not work with block checkout?

Most likely because your plugin applies discounts through PHP cart hooks like woocommerce_cart_calculate_fees or woocommerce_before_calculate_totals. The block-based cart and checkout use the Store API rather than PHP template rendering, so those hooks either do not fire or are not read by the block cart in the same way. The discount logic runs, but the output does not reach the block cart’s price display.

How do I know if I am using WooCommerce block checkout or classic checkout?

Go to WooCommerce → Settings → Advanced → Page setup and click through to your Cart and Checkout pages. Open them in the WordPress editor. If you see a “Cart” block or “Checkout” block in the block editor, you are on block checkout. If you see shortcode text like [woocommerce_cart], you are on classic checkout. New WooCommerce installs (version 8.3 and later) default to block checkout.

Can I fix a hook-based discount plugin’s block checkout compatibility without switching plugins?

The fix requires changes on the plugin developer’s side β€” specifically, implementing proper Store API extensions so the discount logic integrates with the block cart data layer rather than relying on classic PHP hooks. Some plugin developers have done this work; others have not. Check the plugin’s recent changelog and support forum. If the developer has not addressed it, reverting to classic checkout shortcodes is the only workaround on your end.

What is the difference between a cart-fee discount and a sale price discount in WooCommerce?

A cart-fee discount is applied at calculation time through PHP hooks β€” the product keeps its original price, and the discount appears as a line item or price adjustment when the cart is processed. A sale price discount is written directly to the product’s WooCommerce sale price field, the same way a manual sale price would be. The block cart reads product prices through the Store API and gets the correct price regardless of which checkout rendering system is in use. Only the cart-fee approach is vulnerable to block checkout breakage.

My discounts show on the product page but disappear in the block cart. Is that the block checkout problem?

Yes, that is the exact symptom. Product pages in WooCommerce use PHP rendering, and discount hooks typically still fire there. The block cart fetches data through a different path. If the product page shows a strikethrough sale price but the cart displays full price, your plugin is applying the discount through a mechanism that the block cart is not reading. The discount is running but is not reaching the price the block cart displays.

Will switching to block checkout break my coupon codes too?

No. WooCommerce’s native coupon system is fully supported in block checkout and has been since blocks were introduced. Coupons apply at a different layer than the PHP pricing hooks that third-party discount plugins use. The coupon input field is built into the Checkout Block and processed through WooCommerce’s core coupon handling. Coupon codes should work correctly on block checkout without any changes.

Is WooCommerce block checkout going to replace classic checkout permanently?

WooCommerce’s direction has been clearly toward block-native experiences, and block checkout has been the default for new installations since version 8.3. Classic checkout shortcodes are not scheduled for removal in any announced timeline, but they are not receiving active feature development either. For stores planning to be around long-term, block checkout compatibility in every plugin you rely on is worth confirming now rather than treating as a future concern.

The one thing worth checking today

The block checkout breakage is not dramatic. There is no error message. The discount plugin still shows as active. The product page still shows the sale price. The problem only surfaces when a real customer goes to pay β€” and by that point, you have already run the promotion and potentially sent the emails.

The root cause comes down to where the discount is applied. Plugins that modify prices at the product level work because the block cart reads product prices the same way everything else does. Plugins that intercept the cart through PHP hooks work on classic checkout but have an uncertain relationship with block checkout that depends entirely on what work the plugin developer has done.

The check is simple: activate a discount, add the product to a cart, open the cart page, and look at the price. Do that before your next promotion goes live. If the number in the cart does not match the number on the product page, you have found the problem before it found you.