One day, you get a customer message saying the discount code is dead. You test it, and either it works fine for you, or it does nothing at all, so you start wondering where the issue lies.
WooCommerce coupons can fail in many different ways, and each has its own fix.
This guide walks through them in the order worth checking, starting with the quickest wins. Stop as soon as the symptom matches what your customers are seeing.
Why your WooCommerce discount coupon codes aren’t working
Most coupon failures trace back to 1 of these 7 causes, roughly in order of how often they happen:
- Coupon settings: the feature is off, the coupon is still a draft, or a usage rule is blocking it
- The Apply button does nothing: a JavaScript problem, not a settings one
- A plugin or theme conflict
- Caching serving stale cart data
- The coupon field is missing entirely
- Email restrictions that behave differently for guests
- Click-to-apply URL coupons failing silently
Start at the first cause below and work down. Each section tells you how to confirm it and what to change.
Check your coupon settings
Most of the time, the problem is a setting, not a bug. These checks clear the majority of cases.
1. First, confirm coupons are switched on.
Go to WooCommerce → Settings → General, find the Enable coupons section, and tick Enable the use of coupon codes. If that box is unticked, no code will ever apply.

2. Second, check that the coupon is published.
Every coupon is a WordPress post, and it has to be in Published status, not Draft. Find it under Marketing → Coupons. A coupon left in draft (common after a bulk import) reads to WooCommerce as if it doesn’t exist.

3. Third, look at the usage restrictions.
Not all of them are obvious about what they do, and that can cause confusion.
- Minimum spend is measured on the cart subtotal plus tax, not the subtotal alone.
- Exclude sale items blocks a per-cart coupon as soon as any sale item is in the cart.
- Individual use only stops a coupon from stacking with any other.

Now, WooCommerce does show a different error message for each of these, but the wording is generic and easy to misread. The table below maps the message to the setting that controls it.
| What the customer sees (wording varies) | What it usually means | Where to check |
|---|---|---|
| The coupon doesn’t exist | Coupon is still a draft, or the code has a typo or trailing space | Marketing → Coupons publish status, and the code itself |
| The coupon has expired | Expiry date has passed | The coupon’s expiry date field |
| The usage limit has been reached | The overall usage limit is used up | Usage limits → Usage limit per coupon |
| The minimum spend isn’t met | Subtotal plus tax is below the threshold | Usage restrictions → Minimum spend |
| The coupon can’t be combined | Another coupon is applied and this one is individual-use only | Usage restrictions → Individual use only |
| The coupon doesn’t apply to this cart | A sale item is present with Exclude sale items on, or product/category limits exclude the cart | Usage restrictions → Exclude sale items, Products, Categories |
| The email isn’t allowed (or asks for an email) | Email restriction set, and the billing email doesn’t match or hasn’t been entered yet | Usage restrictions → Allowed emails |
If the settings all look right and the code still won’t take, the problem is likely further down the stack. The next suspect is the button itself.
The Apply button does nothing
This is the most unsettling version of the problem. The customer types a valid code, clicks Apply, the page flickers or a spinner appears, and the total never changes, with no errors or feedback.
That pattern points to JavaScript, not settings. On the classic cart and checkout, WooCommerce intercepts the Apply click and sends it as an AJAX request to its apply_coupon endpoint. If a script on the page breaks, that request never fires, and nothing happens. WooCommerce notes that a single JavaScript error can interrupt cart and checkout functions and even break code loaded by unrelated plugins.
You can see it happen in your browser’s developer tools:
- Open the Console first and look for errors in red.
- Switch to the Network tab, click Apply, and watch for the apply_coupon request.
- If the request never fires, the problem is front-end: a script, the markup, or a loading error.
- If it does fire, check the response. A 200 can still carry a WooCommerce error notice, while a 4xx or 5xx points to a nonce, security, server, caching, or routing issue.
The usual culprits are scripts that interfere with the checkout: page builder checkout widgets, string-replacement or translation plugins, aggressive JavaScript minification, and some analytics or marketing plugins. Browser extensions can do it too.
These are examples to test, not an official or exhaustive list. The fastest way to confirm a conflict is the deactivation test in the next section.
💡 Pro tip: To avoid this entirely, we recommend using a plugin for automatic discounts, such as WooCommerce Discounts by Studio Wombat. It calculates everything on the server and does not depend on an Apply button or that AJAX request at all.
Plugin and theme conflicts
If the Apply button or the coupon field is misbehaving, a conflict is the most likely cause. Testing is the only way to find it, and WooCommerce documents a reliable method.
Back up your site or use a staging copy first. Then:
- Switch to a default theme such as Twenty Twenty-Five, or to WooCommerce’s own Storefront, and test the coupon again. If it works on the default theme, your active theme or its checkout template overrides are involved.
- If the theme isn’t the cause, deactivate every plugin except WooCommerce and the extension you’re troubleshooting.
- Reactivate plugins one at a time, testing the coupon after each. The plugin that breaks it when switched back on is your conflict.
To work through this faster, reactivate in order of likelihood: caching, then page builders, then security or SEO plugins, then string-replacement or translation plugins, then everything else.
💡 Pro tip: The WordPress.org plugin Health Check & Troubleshooting has a Troubleshooting Mode that disables plugins only for your own admin session. Customers keep seeing the live site while you test.
Watch for host-installed drop-in plugins too. WooCommerce notes that some hosts pre-install drop-in caching that you can’t deactivate from the plugins screen, which is a common hidden cause. That overlap with caching is worth a closer look on its own.
Cache problems
Caching is meant to speed up your store, but cart and checkout are dynamic pages that change per customer. When they get cached, coupon behavior goes stale: edits don’t show up, deleted coupons still appear, or a code only works after a manual cache flush.
The trap is that “clearing the cache” often means clearing only one layer. A typical store runs several at once:
- Browser and static-asset cache
- A WordPress page-cache plugin
- An object or session cache, such as Redis or Memcached
- A server or reverse-proxy cache, such as NGINX FastCGI or Varnish
- A CDN or edge cache, such as Cloudflare
WooCommerce’s official rule is to keep Cart, Checkout, and My Account out of full-page caching at every layer, because they have to stay dynamic. If your caching system also caches the database, the same docs suggest excluding the WooCommerce session (_wc_session_) so cart state isn’t served stale.
Specifics depend on your stack. WooCommerce confirms that WP Rocket auto-excludes the cart, checkout, and account pages, and recommends avoiding JavaScript file minification on WooCommerce stores. For any other cache plugin or CDN, check that the same set of pages is excluded in that tool’s own settings rather than assuming the defaults are safe.
If only one of several codes applies after a flush, that’s usually not caching at all. Re-check Individual use only, stacking rules, usage limits, and product or category restrictions first.
Missing coupon field
Sometimes the customer can’t even enter a code, because the input field isn’t on the page. The fix depends on whether the field is genuinely absent or just hidden.
Inspect the page in your browser. If the field isn’t in the HTML at all, it’s a template or settings issue. If it’s in the HTML but not visible, CSS is hiding it (look for display: none).
The common causes:
- Coupons are disabled globally (back to WooCommerce → Settings → General).
- On block checkout, the Coupon Form block is sometimes removed from the layout to save space, so it might be hidden behind a link that says something like “click here to enter your code.”
- On classic checkout, a theme or plugin removed the coupon form, often through a remove_action() snippet, or a form-coupon.php template override is missing or outdated.
- A page builder or custom checkout layout doesn’t include a coupon form.
- CSS is hiding the field or its toggle.
For a classic checkout, check whether a snippet removed woocommerce_checkout_coupon_form, and whether your theme overrides form-coupon.php. For a block or page-builder checkout, confirm the layout actually includes a coupon form or the Coupon Form block.
Once customers can see and use the field, the remaining failures tend to be about who is trying to use the code.
Email restrictions for guest checkout
A classic head-scratcher: The coupon works when you’re logged in as admin, but guests say it fails. The coupon is usually fine. The guest flow is missing something WooCommerce needs.
The most common reason is an email restriction. If the coupon’s Allowed emails field is filled in, WooCommerce validates the code against the customer’s billing email. A logged-in admin passes because WooCommerce already knows their account email. A guest on the cart page often fails to complete checkout because they haven’t entered a billing email yet.
To reproduce it the way a customer experiences it:
- Open the store in an incognito window, logged out.
- Go to checkout and enter the guest billing email first.
- Wait for the totals to refresh, then apply the coupon.
The fix depends on intent. For a coupon anyone should be able to use, leave Allowed emails empty. For a private, email-restricted coupon, make sure the coupon field sits after the email field at checkout, or require customers to log in first.
🤔 Did you know? WooCommerce also accepts a wildcard in Allowed emails. Entering *@gmail.com lets any Gmail address use the coupon.
URL-based coupons have their own quirks, which is the next thing to rule out.
Click-to-apply URL coupons
A click-to-apply link is meant to drop a code into the cart automatically when a customer clicks it from an email. WooCommerce core doesn’t have a universal URL-coupon format, so the right link depends on the plugin creating it. Check that plugin’s documentation for the exact format before assuming the link is broken.
These links fail silently for a few reasons: a malformed or rewritten campaign link, tracking parameters that break parsing, a redirect that strips the coupon parameter, an edge cache serving the landing page without running the coupon logic, or a cart session that isn’t created in time. Ordinary coupon validation (expiry, usage limits, restrictions) can also be the real cause.
To find the culprit, send yourself a clean link with no tracking parameters first. If the discount applies, add the tracking parameters back one at a time until one breaks it.
Fix recurring coupon problems with automatic discounts
If you keep hitting these failures, it’s worth asking whether coupon codes are the right tool at all. WooCommerce Discounts takes a different approach: instead of customers entering codes, you set rules that apply discounts automatically based on cart contents, user role, or a schedule.
That design sidesteps 3 of the failure modes above:
- There’s no Apply button and no AJAX request, so the “button does nothing” JavaScript failure can’t happen to the discount itself.
- Rules are calculated on the server in memory, so a cache-locked database lookup can’t block them.
- Discounts and tiered pricing tables show on the product page, instead of staying invisible until a code is entered.
It’s a replacement for the coupon workflow, not a patch for native coupon bugs. A couple of honest limits: WooCommerce Discounts doesn’t issue click-to-apply URL coupons, and native coupons are still the right choice when you need a per-campaign code to track.
Pricing starts at €49/year or €159 one-time for a single site, and there’s a 14-day refund policy and a live demo rather than a free trial. You can run it alongside your existing coupons rather than ripping them out.
Get your discounts working
Whatever the fix, test it the way a customer would: in an incognito window, logged out, at the same checkout stage they reach. Testing as a logged-in admin skips email restrictions and often skips cached pages, so “it works for me” doesn’t prove it works for them.
If the incognito test passes, ship it. If the same problems keep coming back across campaigns, that’s the signal to try automatic discounts and leave the Apply button behind.