TUTORIALWooCommerce has no returns feature. It has refunds — a merchant-side accounting action — and that is a different thing entirely. So every store eventually builds a returns process, and most of them build it badly, because they start from the wrong unit of work.
Get these separated before you design anything.
Conflating them is the standard failure. A system that treats “customer requests return” and “merchant issues refund” as one button will refund goods that never arrive back, and will do it repeatedly before anyone reconciles the stock.
The correct sequence is: request → approve → goods arrive → inspect → refund. Four states between the customer asking and the money moving. Every one of them is a place where the answer can change.

Five things. Fewer than five and you will be doing the rest by email anyway.
Days from delivery, not from order date. A customer whose parcel took two weeks to arrive has not used up half their return window in transit, and telling them they have is the fastest way to a public complaint.
If you have no delivery date — because you have no tracking — the honest fallback is order date plus your typical transit time, stated as such in your policy.
A free-text box gives you unanalysable prose. A fixed list gives you a report. Six or seven codes is plenty: wrong size, wrong item sent, damaged in transit, faulty, not as described, changed my mind, arrived too late.
Keep an optional note alongside it — customers will want to explain, and the explanation is often what tells you whether this is a courier problem or a product-page problem. Store the code for reporting and the note for context.
That note is untrusted input that will be rendered in your admin and in emails. Strip tags on write, cap the length, escape on every output.
This is the requirement people skip, and skipping it is what makes a returns system unusable within a month.
Customers do not return orders. They return one of the three shirts, or two of the six mugs. A whole-order return form forces every partial return back into email, which is where you started. Build the form as a list of order items with a quantity field on each, capped at what they bought minus what has already been returned.
A human decision, always. More on why below.
Not at approval — at receipt, once somebody has looked at what came back. Approving a return means “yes, send it to us”. Whether that item goes back on the shelf depends on the state it arrives in, and no rule set can decide that in advance.
Auto-approval is attractive at volume and wrong at the start, for three reasons that are not about trust.
Eligibility is more complicated than a rule engine. Hygiene items, personalised goods, sale items, perishables, anything already used — each store’s list is different and most of it lives in a person’s head rather than in product metadata.
The reason changes the outcome. “Faulty” and “changed my mind” produce different answers on who pays return shipping, and often different answers on whether a return is needed at all — for a low-value damaged item the cheapest resolution is frequently to refund and tell the customer to keep it.
Approval is a conversation opportunity. A meaningful share of returns are salvageable: the wrong size can be exchanged, the confusing product can be explained, the late arrival can be apologised for with a discount. Auto-approve and you never have that conversation. This is the same argument that applies to cancellation requests, and it holds more strongly here because the sums are larger.
Add auto-approval later, narrowly — a specific reason code, under a value threshold, for a customer with no return history. Not as the default.
Everything above is a form and a state machine. Return shipping is an operational problem, and it is where returns projects overrun.
The questions are all business questions, not software ones:
Start manual. On approval, email clear instructions: the address, the reference number to write on the parcel, who pays, and what happens next. It is not elegant and it works from day one, on any courier, in any country.
Automated label generation means a carrier account, an API integration, per-country rules and a support burden when a label fails to print. It is a project in its own right. Do it when your return volume makes the manual version painful, and not before — you will also know much more about your own process by then.
Three features that look like they belong and will double the work.
Exchanges. A return, plus a replacement order, plus reconciling any price difference in either direction, plus reserving the replacement stock while the return is in transit — or not reserving it and disappointing the customer twice. Handle exchanges as “return, refund, reorder” while you learn how often they actually come up.
Store credit. A ledger with a balance is a financial product. It attracts fraud, it needs an audit trail, it raises accounting questions, and in some jurisdictions it raises regulatory ones. A coupon code is a perfectly good first version.
Photo uploads. Genuinely useful for damage claims, and every file-upload feature is a security surface: file type validation, size limits, storage, and the fact that an admin will click whatever is uploaded. If you add it, whitelist image types by actual content rather than extension, and never serve uploads from a path that executes anything.
One store-wide window is a good default and a poor final answer. Electronics, clothing and perishables have genuinely different return economics.
Attach the rule to product categories rather than individual products, so a new product inherits the right policy on the day it is created rather than the day somebody remembers to configure it. Where an order spans categories with different windows, resolve per line item, not per order — and make sure the customer-facing form reflects that, or you will be explaining it in email.
Whatever you configure, your published policy page and your form must agree. A form that refuses a return your policy allows is worse than having no form.
They look similar and are not. A cancellation happens before the goods move and is mostly a status change. A return happens after delivery and involves physical goods, inspection and a decision about condition.
Two things are worth sharing between them: the request queue your team works from, and the customer-facing pattern of “you asked, here is your reference, here is when you will hear back”. Everything else — statuses, rules, outcomes — should stay separate.
Post-Purchase Hub does not do returns in 1.0. It handles cancellation requests, the timeline, delivery estimates, reorder, invoice access and contextual help, and returns are on the roadmap rather than in the box.
That is deliberate, and it is worth saying plainly on a post about returns: if returns are the problem you have today, install something that does returns today. The comparison of returns and RMA plugins covers the field and the criteria that actually separate them, which are operational rather than featural.