WooCommerce Order Status Notifications: Which Events to Automate
"Where's my order?" is the most common support question in e-commerce — and it's entirely preventable. The customer isn't asking because they're impatient; they're asking because nobody told them what happened. Every unanswered status change becomes a ticket, and every ticket costs time, money and goodwill.
WhatsApp order notifications close that loop automatically: the moment an order's status changes in WooCommerce, the customer gets a WhatsApp message with the update. This guide maps which events deserve a message, which don't, and how to make sure each order sends exactly one confirmation — no gaps, no duplicates.
The message map
| WooCommerce event | When it fires | WhatsApp template |
|---|---|---|
| Order paid / processing | payment_complete, or status → processing | order_confirmation |
| Order completed | status → completed | order_shipped (tracking) |
| Order cancelled | status → cancelled | order_cancelled |
| Order refunded | order_refunded | Refund notice |
| Cart abandoned | separate checkout event | cart_recovery sequence |
| On hold / payment failed | status → on-hold / failed | order_on_hold / payment_failed |
That's the full set most stores need. Six events, six templates, one WhatsApp message per event — and the first three alone eliminate the "where's my order?" ticket entirely.
The hooks behind the map
WooCommerce fires distinct hooks for each moment:
woocommerce_thankyou— the order-received page renders. Route by payment method here: COD orders get their confirmation flow, prepaid orders wait for payment capture.woocommerce_payment_complete— an online payment is captured. This is the prepaid store's confirmation trigger.woocommerce_order_status_changed— fires on any status transition, including custom statuses. This is the workhorse for processing, completed, cancelled, on-hold and failed.woocommerce_order_status_completed— the moment to send tracking/shipping details.woocommerce_order_refunded— refund processed; send the refund notice.
A connector that only listens to one or two of these leaves half the journey silent. The map above needs all of them wired.
What NOT to automate
The fastest way to annoy a customer is to message them at every status blip. Skip:
- Pending — the customer hasn't paid; a message here is nagging
- Checkout-draft — carts in progress aren't orders yet
- Internal statuses — anything your team uses that the customer never sees
The right shape is three core touchpoints — placed → shipped → delivered — plus cancellation, refund, and the recovery/on-hold exceptions. Nine messages per order is how you earn opt-outs.
COD stores: processing is your confirmation
Here's the detail most guides get wrong: COD orders never fire payment_complete — there's no payment to complete. If your integration only listens to that hook, it silently does nothing for every cash-on-delivery order, which is 18–31% of the order book at most Indian D2C stores.
For COD stores, the processing status is the confirmation event: order accepted → customer gets the confirmation (and ideally the COD confirm-to-dispatch check from the [COD confirmation playbook](/blog/cod-confirmation-whatsapp-cut-rto-fake-orders/)). Map processing → order_confirmation and your COD orders get the same experience as prepaid ones.
Custom statuses
woocommerce_order_status_changed fires for every transition, including store-specific custom statuses ("Ready for pickup", "QC passed", "Awaiting supplier"). Decide deliberately: either map each custom status to a message, or explicitly skip it — a generic "your order status changed" message with no useful information is noise. The rule of thumb: message only when the customer can do something with the information.
On-hold and payment-failed: the 24/7 unlock
Within the 24-hour customer-service window, you can send free-form messages. Outside it — including most automated status updates — every message must use an approved template. Stores that only submit order_confirmation find their on-hold and payment-failed messages silently skipped outside the window.
Submit order_on_hold and payment_failed as UTILITY templates and every status path works around the clock:
- On hold — "{{1}}, order {{2}} is on hold because of {{3}}. Reply here and we'll sort it out." (this is also a save-the-sale moment)
- Payment failed — "{{1}}, the payment for order {{2}} (₹{{3}}) didn't go through. Retry here: {{4}}"
Exactly one message per order
Duplicate confirmations are a classic integration bug — the same order firing both payment_complete and status_changed (processing), or a webhook redelivery creating a second message. The fix is deduplication at the event level: each message is keyed to a unique event identifier (<order_id>.<event_type>), so a re-delivered webhook or a double-fired hook can never send twice. Verify it: place a test order and confirm exactly one confirmation arrives, one shipping update, one cancellation.
Quiet hours and timezones
Status updates are transactional, but they're still messages — a 2am "your order shipped" is fine for the customer to read later, while a 2am cart-recovery or on-hold message reads as harassment. Send by the customer's local time where it matters, and respect quiet hours for anything that expects a reply.
Ready to automate?
The Tech Pad wires the full WooCommerce map — order events → approved templates → dedupe → quiet hours — with a shared inbox where every reply lands. Start free for 30 days →