11 May 2026 · 4 min read

Cash on delivery breaks every platform

Every platform is built for card payments. Almost nobody here pays by card.

Shopify, WooCommerce, Meta Ads, Google Analytics and every courier dashboard share one belief. An order is an order when the money arrives. In Bangladesh the money arrives a week later, at the door, in cash, if it arrives at all. Between 70 and 90 percent of orders on the stores I run are cash on delivery. Every tool in the stack quietly gets that wrong. The errors add up.

An order is a promise, not a sale

On a card store, a placed order is revenue. On a cash on delivery store, a placed order is a phone number and a hope. The gap between the two is the return rate. On a store nobody manages, it is brutal. 25 to 40 percent of parcels come back undelivered. Each one costs the outbound charge, the return charge, and a week when the product cannot be sold.

So the first job is confirmation. Every cash on delivery order gets a call or an OTP before it ships. Shopify has no built-in step for this. I build it from three parts. A Flow automation that tags the order pending. An SMS gateway like SSL Wireless or BulkSMS BD for the OTP. A rule that nothing goes to the courier without the confirmed tag. On WooCommerce the same thing is a custom order status and a webhook. It is not glamorous. It halves the return rate.

Fake and duplicate orders

Placing an order costs nothing. So people place them for fun, by accident, or three times because the page did not respond. Competitors place them to burn your courier budget. Bots place them because the form has no protection.

The defences come in layers. Check the phone number against a small blocklist of numbers with two or more past returns. Ask for an OTP on the first order from a number. Put Cloudflare Turnstile on the checkout for WooCommerce. Add a Flow rule that flags two orders from one phone within ten minutes, so the confirmation call can merge them. None of this is hard. All of it is missing from the default install.

The courier integration

Pathao, Steadfast, RedX and Paperfly all have APIs. All of them are different. All of them change without much notice. A proper integration does three things. It creates the consignment when the order is confirmed. It writes the tracking ID back to the order. It checks the status, so the store knows when a parcel is delivered, returned or stuck. Most stores skip this and use a spreadsheet by hand. That works until the day they do 80 orders.

The status sync is the part that matters. Delivered means revenue. Returned means restock, and refund the delivery charge in the accounts. Stuck for three days means someone calls the customer before the courier gives up.

Reconciliation

The courier collects the cash, takes its charge and a percentage, and pays out weekly. The payout never matches the order total. Partial deliveries. A customer who paid 50 taka less after an argument at the door. A parcel marked delivered that came back. I build a reconciliation sheet. It pulls delivered orders from the store and matches them line by line against the courier statement. Every store finds money in the first month. One found eleven percent.

Analytics lie

GA4 counts a purchase when the thank-you page loads. Meta Pixel fires the Purchase event at the same moment. Both are now counting promises. If 30 percent come back, your reported revenue is 30 percent too high. Your return on ad spend is 30 percent too high. And Meta’s algorithm is learning to find people who place orders, not people who accept parcels.

The fix is to move the money event. Fire Purchase from the server, through the Conversions API, when the order is confirmed and not when it is placed. Send a refund event when it returns. GA4 gets the same treatment through the Measurement Protocol. The reported numbers drop in the first week, and the founder panics. Then the ads get better. For the first time, the platform is learning from real sales.

The order of operations

Confirmation first, because it fixes returns and fakes at once. Courier API second, because it makes status visible. Server-side events third, because they need the confirmed status to exist. Reconciliation always, because the money is already leaking.

This week

Pull last month’s orders and the courier statement side by side. Count how many were returned. Add up what those returns cost in delivery charges alone. Then look at your Meta Ads dashboard. It does not know about a single one of them. That gap is the size of the problem. It is the number to fix first.

All notes