Disable Cash on Delivery for Some Products
Disable cash on delivery for specific products in WooCommerce: the filter, a working snippet, cart-total and postcode limits, and how to keep conversions.

Cash on delivery keeps stores alive in markets where card penetration is low and trust is earned slowly. It also has the worst unit economics of any payment method you offer: refused deliveries, return freight, cash handling, and money that arrives weeks late. The answer is rarely to switch it off — it is to disable cash on delivery for specific products, order values and delivery areas where the losses concentrate.
Where COD actually costs money
Before writing a rule, look at your own refusal data. In practice the losses cluster in four places:
- High-value orders. A refused €900 order costs a hundred times more than a refused €9 one, and the refusal rate does not fall with value — it rises.
- Perishable, custom or personalised goods. Anything you cannot put back on the shelf turns a refusal into a total write-off.
- Heavy or bulky items where the return leg costs more than the product margin.
- Specific delivery areas with a known refusal pattern, whether that is a region, a postcode range or a courier's rural zone.
Each of those maps cleanly to a rule.
What WooCommerce gives you out of the box
Core COD settings are thinner than most merchants expect. You get:
- Enable for shipping methods — restrict COD to selected shipping methods.
- Accept for virtual orders — a simple on/off for downloadable and virtual products.
That is all. There is no product rule, no category rule, no order-value threshold and no postcode filter. Everything below is built on the same `woocommerce_available_payment_gateways` filter that drives every other conditional payment rule in WooCommerce.
Rule 1: disable COD for specific products
```php add_filter( 'woocommerce_available_payment_gateways', function ( $gateways ) { if ( is_admin() || ! WC()->cart ) { return $gateways; }
$no_cod_products = array( 812, 913, 1044 );
foreach ( WC()->cart->get_cart() as $item ) { if ( in_array( (int) $item['product_id'], $no_cod_products, true ) ) { unset( $gateways['cod'] ); break; } }
return $gateways; } ); ```
Use `product_id` rather than `variation_id` if the rule applies to the whole product; check both when only one variation is affected.
Rule 2: an order-value ceiling
```php add_filter( 'woocommerce_available_payment_gateways', function ( $gateways ) { if ( is_admin() || ! WC()->cart ) { return $gateways; }
if ( WC()->cart->get_cart_contents_total() > 250 ) { unset( $gateways['cod'] ); }
return $gateways; } ); ```
Decide deliberately whether the threshold uses the total including or excluding tax and shipping, and document it — support will ask.
Rule 3: delivery-area limits
Read the customer's address from `WC()->customer` inside the same filter, and fall back from shipping to billing when shipping is empty. Two things to remember: the address can change while the customer is on the checkout page, so the gateway list must re-evaluate on the AJAX update, and a postcode list needs normalising for case and spaces before you compare it.
Doing it without maintaining PHP
Three snippets on one filter already means three places to look when COD misbehaves. WooCommerce Payment Gateway Per Product puts product, category, role and cart conditions in one rule table in wp-admin, so the COD policy is visible and a shop manager can adjust the threshold after a bad month without a developer.
Keep the conversion you have
Restricting COD is a trade-off, not a free win. Protect the upside:
- Keep one frictionless alternative visible in every case where COD disappears — usually a card or a local wallet, not a bank transfer.
- Explain it at the point of loss. A one-line notice at checkout beats a customer assuming the site is broken.
- Offer a partial deposit for high-value orders instead of removing COD outright, if your gateway supports it.
- Measure before and after. Watch checkout completion for the affected products for four weeks; if the drop in completed orders costs more than the refusals did, loosen the rule.
Test plan
Run the affected product alone, with a normal product, just under and just over the value threshold, inside and outside an allowed postcode, and on both classic and block checkout. Then place one live COD order on a product that should still allow it, to prove the rule removed only what it was meant to.
Next step Pull your last 200 COD orders, mark the refused ones, and see where they cluster. Build a rule for that cluster only — in a snippet if it is one condition, in [Payment Gateway Per Product](/plugins/woocommerce-payment-gateway-per-product) if it is several.
FAQ
- How do I disable cash on delivery for a specific product in WooCommerce?
- Unset the cod gateway inside the woocommerce_available_payment_gateways filter when that product ID is present in the cart. WooCommerce's built-in COD settings only restrict by shipping method, not by product.
- Can I disable COD above a certain order value?
- Yes. Compare WC()->cart->get_cart_contents_total() with your threshold in the same filter and remove the gateway above it. Most stores that lose money on COD lose it on the highest-value orders.
- Can I limit cash on delivery to certain postcodes?
- Yes. Read the customer's shipping postcode or country from WC()->customer inside the filter and remove COD outside your list. Fall back to the billing address when shipping is empty, and remember the address may change mid-checkout.
- Does WooCommerce support COD restrictions out of the box?
- Only partly. Core lets you enable COD for selected shipping methods and toggle it for virtual orders. Product, category, value and postcode rules need a snippet or a rules plugin.
- Will removing cash on delivery hurt my sales?
- It depends on the market. Where COD is a habit, removing it entirely can cost a large share of orders, so restrict it by product, value or area rather than switching it off, and keep one low-friction alternative visible.
This article is part of our WooCommerce payments topic hub, where the related plugins and guides live together.


