WPMake

← Back to BlogHow to Add “Buy Again” / Reorder to WooCommerceTUTORIAL

How to Add “Buy Again” / Reorder to WooCommerce

⏱ 6 min read  ·  👤 iamprazol  ·  Sep 5, 2026

Reorder is one of the few post-purchase features WooCommerce already ships. It is called order_again, it works, and it is hedged about with restrictions that most stores never find out about.

What core already does

On the My Account orders list, completed orders get an “Order again” button. Clicking it fills the cart with that order’s items and sends the customer to the cart.

The gate is a filter, and its default is a single status:

$statuses_for_reordering = apply_filters(
    'woocommerce_valid_order_statuses_for_order_again',
    array( 'completed' )
);

There is a second gate that is easier to miss. The handler in WC_Cart_Session requires is_user_logged_in() before it will do anything at all. Guests cannot reorder, even holding a valid link — which matters a lot if a meaningful share of your customers check out as guests.

And a third, in the capability layer: order_again is granted by comparing the current user against the order’s user, so a customer can only reorder their own orders. That one is correct and should stay.

Widening the status rule

If you mark orders processing and rarely move them to completed, your customers have never seen a reorder button. This is common and easily fixed:

add_filter(
    'woocommerce_valid_order_statuses_for_order_again',
    function ( $statuses ) {
        $statuses[] = 'processing';
        return $statuses;
    }
);

Unlike widening the cancellation statuses, this one is safe. Reordering creates a new cart; it does not touch the original order, the payment or the stock allocation. The only judgement call is whether “buy this again” makes sense for an order that has not arrived yet — for consumables it often does.

The four failure modes

An order is a snapshot of a catalogue that has since moved on. Four things can have changed between then and now, and core handles them in a way that is defensible but thin.

Looking at populate_cart_from_order(), an item is silently skipped when:

  • The product no longer exists. $item->get_product() returns nothing, and the loop continues.
  • A variable product has no variation recorded. Skipped, to avoid adding an unconfigured product.
  • The product is out of stock. is_in_stock() is false, and the loop continues.
  • An add-to-cart validation filter rejects it — a plugin enforcing a minimum quantity, a membership restriction, a role-based price rule.

Then, at the end, core counts what it could not add and prints one notice:

2 items from your previous order are currently unavailable and could not be added to your cart.

That is better than silence, and it is not enough. It does not say which two items, and it does not say why — out of stock, discontinued and blocked-by-a-rule are three different problems with three different customer responses.

And there is a fifth change core says nothing about at all: the price. Reorder adds the current product to the cart at the current price. A customer reordering something that has gone up 15% finds out at the cart, having believed they were repeating a known purchase. Nothing warned them.

Show a reconciliation summary first

The fix is a screen between the button and the cart that says what changed, before anything is added.

A review screen before reorder listing each item from the previous order with its quantity and what will happen to it, above an Add to cart button
“Nothing has been added yet” is the important line. The customer decides after seeing the differences, not after discovering them in the cart.

A useful summary states an outcome per item, in the customer’s language:

  • Will be added — in stock, same price, nothing to say.
  • Price has changed — show both prices. Do not bury this.
  • Out of stock — say so, and where you can, offer the backorder or a notify-me rather than a dead end.
  • No longer available — the product is gone. Link the nearest equivalent if you have one.
  • Partly available — they ordered three, you have one.

Then one button: add what is available. The customer arrives at the cart with no surprises in it, which is the entire objective.

The trust argument is simple. A reorder that quietly drops two of five items is a reorder the customer will check every time from then on — and checking every time is the friction the feature existed to remove.

Merge or replace?

Core has already decided this for you, and probably not the way you would.

if ( apply_filters( 'woocommerce_empty_cart_when_order_again', true ) ) {
    $cart = array();
}

Reorder empties the cart by default. A customer who was mid-shop, clicks “Order again” out of curiosity, and loses everything they had chosen is a customer with a genuine complaint.

You can switch it off:

add_filter( 'woocommerce_empty_cart_when_order_again', '__return_false' );

But blind merging has its own failure: the customer already had two of an item in the cart, reorders an order containing three, and ends up with five without having asked for five.

The honest answer is to ask, but only when it matters. If the cart is empty — which it usually is, because people arrive at their order history from an email — do not ask anything. If the cart has items in it, that is the one moment a prompt is worth the interruption.

Where to put the button

Both places, and they are different hooks. On the orders list, through woocommerce_my_account_my_orders_actions. On the single order page, after the items table. The guide to changing that page covers the mechanics.

Label it in the customer’s words. “Order again” is WooCommerce’s phrasing; “Buy these again” tells people it is the items they are getting back, which is the question they were actually asking.

An honest note on whether this is worth building

Reorder is the feature most likely to be oversold to you, so here is the plain version.

It works on consumables — coffee, supplements, pet food, filters, printer ink, anything with a natural refill cycle. For those stores the order page is genuinely a sales channel and reorder friction is worth attacking. The case for treating your orders page as a revenue channel is about exactly that kind of store.

It does close to nothing on one-off purchases. If you sell furniture, or jewellery, or a piece of equipment somebody buys once every five years, a Buy Again button will be clicked by approximately nobody. That is not a failure of implementation. Amazon’s Buy Again works because a large share of Amazon’s catalogue is things people rebuy, and your catalogue is probably not.

Build it — the core filter alone is a five-minute change, and the reconciliation screen is an afternoon. Just do not expect it to move revenue unless your products get used up.

How to Add “Buy Again” / Reorder to WooCommerce