Cash on delivery rules for Indian stores: how we restrict COD in WooCommerce, and the Shopify plan catch
By the Brightcode team, a small web agency in Delhi NCR. Reviewed by Gaurav Khokkar, Founder. If you build stores for Indian brands, you'll get this request sooner or later: "Can we turn off cash on delivery for some or
By the Brightcode team, a small web agency in Delhi NCR. Reviewed by Gaurav Khokkar, Founder.
If you build stores for Indian brands, you'll get this request sooner or later: "Can we turn off cash on delivery for some orders?"
It sounds like a settings toggle. Sometimes it is. More often the client wants rules. No COD above a certain cart value. No COD for a few pincodes the courier won't collect cash in. No COD on custom-made products that can't be resold if the parcel comes back.
The business reason is simple. A COD order that's refused at the door costs the store shipping both ways, and the product sits in transit for a week or two. Prepaid orders don't have that problem.
We set COD rules differently on WooCommerce and on Shopify, and Shopify has a plan limit that catches people out.
Step 1: Write the rules down before you write code
We ask the client for the rules in plain words and put them in a small table, because "turn off COD sometimes" means different things to sales, operations and the courier.
| Rule | Example | Why |
|---|---|---|
| Cart value cap | No COD above ₹5,000 | Higher-value refusals hurt more |
| Pincode block list | No COD for pincodes the courier won't collect cash in | Courier limits |
| Product exclusions | No COD if the cart has a made-to-order item | Can't resell a returned custom item |
| Customer type | No COD for wholesale accounts | They pay by invoice |
The numbers are the client's, not ours. Get them in writing, because someone will ask in three months why a customer couldn't pick COD.
Step 2: Use the built-in settings first (WooCommerce)
WooCommerce's own Cash on Delivery gateway already has two useful settings under WooCommerce → Settings → Payments → Cash on delivery:
- Enable for shipping methods, so COD only shows for, say, your courier method and not for store pickup.
- Accept for virtual orders, which you'll usually leave off.
If those cover the client's rules, stop there. Less custom code means fewer things to maintain.
Step 3: Add the rules with one filter (WooCommerce)
For anything more, the hook is woocommerce_available_payment_gateways. It gets the list of gateways that can be shown and lets you remove some. The core COD gateway's ID is cod.
<?php
/**
* Plugin Name: Store COD Rules
* Description: Hides Cash on Delivery based on cart value, pincode and product tags.
*/
add_filter( 'woocommerce_available_payment_gateways', 'bc_cod_rules' );
function bc_cod_rules( $gateways ) {
if ( is_admin() || ! isset( $gateways['cod'] ) ) {
return $gateways;
}
if ( ! function_exists( 'WC' ) || ! WC()->cart || ! WC()->customer ) {
return $gateways;
}
$max_cod = 5000; // from the client's rules table
$blocked = array( '110000', '122000' ); // placeholder pincodes, replace with the courier's list
$no_cod_tag = 'made-to-order'; // product tag slug
// 1. Cart value cap (subtotal before shipping and fees)
if ( (float) WC()->cart->get_subtotal() > $max_cod ) {
unset( $gateways['cod'] );
return $gateways;
}
// 2. Pincode block list (shipping postcode, falls back to billing)
$pin = WC()->customer->get_shipping_postcode() ?: WC()->customer->get_billing_postcode();
if ( $pin && in_array( preg_replace( '/\D/', '', $pin ), $blocked, true ) ) {
unset( $gateways['cod'] );
return $gateways;
}
// 3. Product exclusions
foreach ( WC()->cart->get_cart() as $item ) {
$product_id = $item['product_id'];
if ( has_term( $no_cod_tag, 'product_tag', $product_id ) ) {
unset( $gateways['cod'] );
break;
}
}
return $gateways;
}
A few notes before you ship this:
-
Put it in a small plugin, not the theme's
functions.php. Theme updates and theme switches shouldn't take payment rules with them. -
Subtotal or total?
get_subtotal()is the product value before shipping.get_total( 'edit' )includes shipping, fees and tax. Pick one, match it to how the client wrote the rule, and say which one in a code comment. - Block checkout. WooCommerce's developer blog says this filter used to be ignored by the block-based checkout for a while, and now works with it. We still test the rules on whichever checkout the store uses, classic or block.
- Tell the customer why. A COD option that silently disappears causes support calls. Add a short line near the payment step, like "Cash on delivery isn't available for this order", when a rule kicks in.
Keep the pincode list somewhere the operations team can edit (an option page, a CSV in the media library, whatever suits the store), instead of a hard-coded array. The array above is only for the example.
Step 4: Shopify, where the plan matters
On Shopify, COD is a manual payment method you switch on in Settings → Payments. Turning it on or off for the whole store is easy. Rules per order take more work.
Shopify's tool for this is a payment customization function (Shopify Functions). It can hide, rename or reorder payment methods at checkout based on the cart. Shopify's own tutorial for it is an example that hides "Cash on Delivery" when the cart total is above a set amount. So the logic is supported.
The limit is who can run it. Shopify's docs say stores on any plan can use public apps from the Shopify App Store that contain functions, but only stores on Shopify Plus can use custom apps that contain Shopify Function APIs. Its help centre table says the same: "Custom apps built with Shopify Functions" are Plus-only.
In practice that gives you three options for a non-Plus Indian store:
- Use a public app from the App Store that offers payment rules. Check its reviews, its monthly price and whether it supports the exact rule (pincode lists are where many fall short).
- Build and list your own public app if you're an agency that needs this across many stores. That's a real product with review and support costs, not a weekend job.
- Move the rule out of checkout. For example, show a COD availability check on the product page by pincode, and keep checkout itself standard.
Two more Shopify details worth knowing when you scope this:
- Shopify doesn't charge its third-party transaction fee on manual payment methods such as COD. Online payments through Razorpay or other gateways do carry that fee in India, because Shopify Payments isn't available here. That's one reason Indian clients care so much about the COD share.
- On non-Plus stores, a hide operation removes the payment method from checkout entirely. Hiding it from only some placements is a Plus-only option.
If you're advising a client who is still choosing a platform, this is a fair point to put in front of them. Payment rules that are one PHP filter on WooCommerce can mean a paid app or a Plus plan on Shopify. We wrote a longer Shopify vs WooCommerce comparison for Indian stores for owners, covering fees, COD and upkeep.
Step 5: Test it like a release
Payment rules can break without any error. A plugin update, a new shipping method or a theme change can bring COD back where it shouldn't be, or hide it for everyone. Our test list for every store:
- A cart just under and just over the cap (₹4,999 and ₹5,001 in the example). Off-by-one mistakes live here.
- A blocked pincode, then the same cart with an allowed pincode. Check that the payment list updates when the address changes, without a page reload.
- A cart with one made-to-order item among normal items.
- A logged-in wholesale account, if that rule exists.
- The same checks on a real phone, on mobile data, because that's where most Indian orders are placed.
On WooCommerce, the first three are easy to cover with a Playwright test against staging. On Shopify, test in a development store with the app installed before it touches the live checkout.
The short version
- Get the COD rules from the client in writing, with the numbers
- On WooCommerce, try the built-in COD settings, then one filter in a small plugin
- Decide subtotal vs total on purpose, and tell customers why COD is missing
- On Shopify, the logic exists, but custom function apps need Plus; plan for a public app or a different approach
- Test the edges of every rule after each update
For the shopper-facing side of checkout (trust, error messages, mobile forms), our list of checkout fixes that improve e-commerce conversion is where we start.
How do you handle COD rules on stores you look after? We'd like to hear what's worked, especially on Shopify, in the comments.
Written by the team at Brightcode, a Delhi NCR agency that builds Shopify and WooCommerce stores and keeps them running with managed hosting and care.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.