The share of orders in the window that were moved to a Refunded status, a direct read on product quality, fulfilment accuracy, and margin leakage.
At a glance
Refund Rate is the percentage of orders in the window that ended up Refunded. It is one of the cleanest health signals you have: a creeping rate points at a quality problem, a fulfilment error, a misleading product page, or a payment dispute pattern. Because OpenCart records refunds as a status change rather than recalculating order totals, refunds do not reduce your headline revenue automatically, so this gauge is how you see the leakage that the revenue cards do not.
| What it measures | Refunded orders ÷ total orders in the window, expressed as a percentage. |
| Order source | Order status lives in oc_order with history in oc_order_status / the order-history table. A refund is a transition to the Refunded status. |
| Refund treatment | OpenCart records a refund as a status change, not a recalculation. Order totals in oc_order are not reduced, so refunds do not lower the revenue cards on their own. |
| Tax / shipping on refunds | OpenCart stores order totals and tax separately. Whether tax and shipping were returned depends on how the refund was issued; the status change alone does not break out the components. |
| Partial refunds | A partial refund may not move the order to a Refunded status at all, depending on how the merchant or gateway records it. This gauge counts orders that reached the Refunded status, so partials handled without a status change are not captured here. |
| Denominator | Total orders created in the window (the same population the order-volume cards use). |
| Multi-store | Orders carry a store_id; by default the rate is computed across every storefront. |
| Time window | 30D |
| Alert trigger | > 5% |
| Roles | owner, finance, operations |
Calculation
Worked example
An Italian footwear store on OpenCart 4.x. The 30-day window covers 14 Feb 26 to 15 Mar 26. The store ran a clearance on a discontinued line during the window.| Segment | Orders | Refunded | Read |
|---|---|---|---|
| Full-price ranges | 1,840 | 41 | ~2.2%, healthy |
| Clearance line (sizing ran small) | 260 | 49 | ~18.8%, the problem |
| Total | 2,100 | 90 | |
| Refund Rate (this card) | 4.29% | just under the 5% alert |
- The blended rate hides a hot spot. Overall the store sits at 4.29%, below the 5% alarm. But the clearance line alone refunded at nearly 19%, dragged up by a sizing issue. A single number can look acceptable while one product haemorrhages. Slicing by product is how you find it.
- The headline revenue cards did not move. OpenCart records each refund as a status change and leaves the order total untouched, so the revenue cards still show all 2,100 orders at full value. This gauge is the only place the 90 refunds surface, which is exactly why it exists.
- One more clearance week would have tripped the alarm. At 4.29% the rate is one bad batch away from the 5% trigger. The owner pulled the clearance line early rather than risk both the refund cost and the alert, a decision the trend made obvious.
- Partial refunds may be undercounted. If the store issued any partial refunds without moving the order to Refunded, those would not appear in this gauge. The merchant cross-checks against the payment gateway to confirm the status-based count is complete.
Sibling cards merchants should reference together
| Card | Why pair it with Refund Rate |
|---|---|
| Cancellation Rate | The pre-fulfilment sibling. Cancellations stop an order before it ships; refunds reverse one after. Together they bound order failure. |
| Order Volume | The denominator. A refund-rate move on thin volume can be a handful of orders, not a trend. |
| Average Order Value | High-AOV refunds hurt margin disproportionately; read the two together to size the cash impact. |
| Order Status Distribution | Shows Refunded as a share of all statuses, useful for spotting a shift in the status mix. |
| Revenue at Risk (live) | A rising refund rate is one of the at-risk signals this composite reflects. |
| Repeat Customer Rate | Refunds erode loyalty; a high refund rate often precedes a fall in repeat purchasing. |
Reconciling against OpenCart
Where to look in the OpenCart admin: Sales → Orders, filtered to the Refunded status, gives you the refunded-order count this gauge uses as its numerator. Reports → Sales → Orders can break orders down by status across a period, letting you see Refunded against the total. Each order’s history tab (backed byoc_order_status) shows when and by whom the refund status was applied. For the money side, your payment extension’s own records (and the gateway dashboard) hold the actual refund amounts, which OpenCart’s order totals do not reflect.
OpenCart admin views that look like the same number but aren’t:
- The Dashboard shows no refund breakdown; it will not reflect this rate.
- A gateway’s refund total is a sum of money refunded, not a count of orders, and includes partials that may never have changed the OpenCart status.
- Reports → Sales → Returns tracks RMA / return requests, which is a different workflow from a Refunded order status; a return request is not necessarily a refunded order.
| Reason | Direction of divergence |
|---|---|
| Timezone. The window is evaluated in UTC by default; OpenCart timestamps follow the store timezone. Orders near a boundary day fall on different sides. | ±1 day’s orders at the boundary |
Multi-store. Orders carry a store_id; the rate is computed across all storefronts unless filtered. A single-store admin view differs. | Either direction |
| Partial refunds without a status change. Partials recorded only at the gateway, with no move to Refunded, are not counted here. | Card lower than a money-based refund view |
| Status-name customisation. A renamed or custom refund status needs mapping; otherwise some refunds may not be counted. | Card lower if a custom status is unmapped |
| Returns vs refunds. RMA/return requests are a separate workflow and are not this gauge. | Card lower than a returns report |
| API / DB sync lag. A refund applied in the last minute may not yet be reflected. | Self-resolves at next sync |
Known limitations / merchant FAQs
Does a refund reduce my revenue figures automatically? No. OpenCart records a refund as a status change and leaves the order total inoc_order untouched. The revenue cards therefore still count the original value. This gauge is the place to watch refund leakage that the revenue cards do not subtract.
Are partial refunds counted?
Only if the order was moved to a Refunded status. Many partial refunds are recorded at the gateway without changing the OpenCart status, and those are not captured here. If you issue a lot of partials, cross-check against the gateway, which reports refunded value including partials.
My rate looks fine but one product refunds constantly, why don’t I see it?
The headline gauge is blended across all orders. A single problem product can refund heavily while the overall rate stays under the threshold. Slice by product (Reports → Products Purchased plus the order history) to find the hot spot the blended number hides.
What is the difference between this and Cancellation Rate?
A cancellation stops an order before fulfilment; a refund reverses one after payment. They sit on opposite sides of fulfilment. Reading Cancellation Rate alongside this gauge gives you the full picture of order failure.
Is a Returns report the same as this?
No. Reports → Sales → Returns tracks RMA / return requests, a separate workflow. A return request is not automatically a Refunded order, so the two numbers will differ.
I renamed my refund status, will the gauge still work?
OpenCart lets you rename and add statuses. The gauge maps to the Refunded status as configured for your install; a renamed or custom refund status may need a one-time mapping so every refund is counted.
What is a healthy refund rate?
It varies by category, but the 5% alert reflects a common line above which refunds usually signal a real problem rather than normal trading. Apparel and footwear run higher because of sizing; consumables run lower. Watch the trend against your own baseline more than any absolute figure.