# Orders and buy again

> Show the logged-in customer's orders. Covers the order list and its pages, the order page with its products and shipments, status labels, printing, and the Buy again button that puts an order back in the cart.

Status: Ready (Smootify 2.0)  
1.x page: https://docs.smootify.io/docs/accounts/order-listing  
URL: https://www.smootify.io/docs/build/orders  
Updated: 2026-10-10

Customers see their past orders in their account. This page builds the order list, the page of a single order with its products and shipments, and a Buy again button that puts the products of an order back in the cart.

> [!NOTE]
> Customer accounts must be set up first: see [Customer accounts](https://www.smootify.io/docs/build/account). Put these parts on account pages, since they need a logged-in customer.

## How it fits together

What Smootify needs:

- for the list: a `customer-orders` element with one `customer-order` inside, the template of each order;
- for the order page: a page at `/account/order` with an `order-page` element on it;
- inside an order, a `line-item` for its products and an `order-fulfillment` for its shipments, if you show them.

What is up to you:

- which details each order shows, and the design;
- whether you build an order page at all. `order="statusUrl"` can link to Shopify’s own page for the order instead.

## 1. The order list

1. Add a Custom element with the tag `customer-orders`.
2. Inside it, add a Custom element with the tag `customer-order`. Design it as one order: Smootify repeats it once per order, newest first.
3. Inside it, add the order values of step 2, and a link to the order page with `order="url"`.

```html
<customer-orders limit="10">
  <customer-order>
    <div order="name">#1001</div>
    <div order="processedAt">1/1/2026</div>
    <div order="fulfillmentStatus">Status</div>
    <div order="totalPrice">$0.00</div>
    <a href="#" order="url">View order</a>
  </customer-order>
  <button data-action="load">Load more</button>
</customer-orders>
```

- **How many.** `limit` on `customer-orders` sets the orders per page. Without it, the list shows 5.
- **No orders.** Show an empty state with `customer-condition="no-orders"` on the same page. The list is what counts the orders, so this condition works only on a page that has it. If the list cannot load, neither `has-orders` nor `no-orders` shows, and a next page that fails to load leaves the orders already on screen.
- **While it loads.** Add `skeleton="text"` or `skeleton="block"` to the placeholders you want to shimmer until the orders arrive. See [loading](https://www.smootify.io/docs/reference/attributes/loading).

**More orders.** Pagination buttons are Custom elements with the tag `button`, inside `customer-orders` and outside `customer-order`. There are two kinds:

- **Load more**, a `button` with `data-action="load"`: adds the next orders below the ones shown; hidden when there are no more orders.
- **Previous and next**, `button` elements with `data-action="previous"` and `data-action="next"`: show the previous or the next page of orders instead; each one is hidden when there is no page in its direction.

## 2. Order values

These work in a row of the list and on the order page.

| Attribute | What it shows |
|---|---|
| `order="name"` | the order name, such as `#1001` |
| `order="processedAt"` | the order date, in the visitor’s date format |
| `order="financialStatus"` | the payment status |
| `order="fulfillmentStatus"` | the shipping status: `UNFULFILLED` until the first shipment, then that shipment’s status |
| `order="subtotalPrice"`, `order="totalShipping"` | the subtotal, the shipping |
| `order="totalTax"`, `order="totalPrice"` | the taxes, the total |
| `order="totalDiscounts"` | the discounts of the order, on its lines and on shipping; removed when the order has none |
| `order="totalRefunded"` | the amount refunded |
| `order="shippingAddress"`, `order="billingAddress"` | the addresses, one line under the other |
| `order="note"`, `order="email"`, `order="phone"` | what the customer entered at checkout |
| `order="cancelReason"` | why the order was cancelled |

Three values go on a Text link or a Link block:

- `order="url"`: your order page for this order;
- `order="statusUrl"`: Shopify’s own page for this order, in the customer’s Shopify account;
- `order="customerUrl"`: the customer’s profile in their Shopify account.

An element whose value is missing, such as a cancel reason on an order that was not cancelled, is taken out. The full list is in [order values](https://www.smootify.io/docs/reference/attributes/order).

**Status labels.** The statuses show Shopify’s codes, such as `PAID`. To show your own words, add a script with the labels to the head code of your site, next to the options script. Write every label in the same script:

```html
<script>
  window.SmootifyStatusLabels = {
    PAID: "Paid",
    PENDING: "Awaiting payment",
    UNFULFILLED: "Being prepared",
  };
</script>
```

The keys are the codes as Shopify sends them. The same script holds the statuses of [subscriptions](https://www.smootify.io/docs/build/account-subscriptions). The codes of each status:

| Value | Codes | Without a label |
|---|---|---|
| `order="financialStatus"` (payment) | `PENDING`, `AUTHORIZED`, `PAID`, `PARTIALLY_PAID`, `PARTIALLY_REFUNDED`, `REFUNDED`, `VOIDED`, `EXPIRED` | the code, such as `PENDING` |
| `order="fulfillmentStatus"` (shipping) | `UNFULFILLED` until the first shipment, then that shipment's `SUCCESS`, `CANCELLED`, `ERROR` or `FAILURE` | the code, such as `UNFULFILLED` |
| `subscription="status"` | `ACTIVE`, `PAUSED`, `CANCELLED`, `EXPIRED`, `FAILED`, `STALE` | the code with a capital letter only at the start, such as Paused |

Example labels: `PENDING: "Awaiting payment"`, `UNFULFILLED: "Being prepared"`, `PAUSED: "On hold"`.

## 3. The order page

1. In Webflow, create a page in the `account` folder with the slug `order`, so its address is `/account/order`. For another address, set it in the option `orderPageUrl`.
2. Add a Custom element with the tag `order-page`, and put the order values inside it.

The page shows the order that `order="url"` links to: the link adds the order number to the address. A visitor who is not logged in gets the same treatment as on the other account pages: with the option `accountPageRedirectTo: "passwordless-login"`, the Shopify login opens and then comes back to the same order, so a link to an order in an email works. Opened by a logged-in customer without an order in the address, or for an order that is not theirs, the page goes to your home page.

**Products.** Inside `order-page`, add a Custom element with the tag `line-item`. Design it as one product: Smootify repeats it once per product of the order. Design only one: the other copies you make are removed.

```html
<order-page>
  <h1 order="name">#1001</h1>
  <line-item>
    <img line-item="image">
    <div line-item="name">Product</div>
    <div line-item="option"><span option="name">Size</span>: <span option="value">M</span></div>
    <div line-item="quantity">1</div>
    <div line-item="totalPrice">$0.00</div>
  </line-item>
  <div order="totalPrice">$0.00</div>
</order-page>
```

Inside `line-item`:

- `line-item="name"`, `line-item="title"`, `line-item="sku"`, `line-item="vendor"`, `line-item="quantity"`: texts;
- `line-item="image"` on an Image, taken out when the product has no image;
- `line-item="price"`, `line-item="totalPrice"`, `line-item="totalDiscount"`: amounts;
- `line-item="option"` on a Div block: one copy per option and per property of the line, such as a size or an engraving, with `option="name"` and `option="value"` inside. Properties whose name starts with `_` are left out.

The full list is in [order line values](https://www.smootify.io/docs/reference/attributes/line-item).

**Shipments.** Add a Custom element with the tag `order-fulfillment`, the template of one shipment. Inside it, these values fill a shipment:

| Attribute (inside `order-fulfillment`) | What it shows |
|---|---|
| `fulfillment="status"` | the status of the shipment, in lowercase: success, cancelled, error or failure |
| `fulfillment="latestShipmentStatus"` | the latest delivery status, such as in transit or delivered, in lowercase |
| `fulfillment="estimatedDeliveryAt"` | the expected delivery date, or `TBD` when Shopify does not know it |
| `fulfillment="trackingCompany"` | the carrier |
| `fulfillment="trackingNumber"` | the tracking number |
| `fulfillment="trackingUrl"` | on a link: the tracking page; taken out when there is none |
| `fulfillment="updatedAt"` | the date of the last update |

Wrap the shipments section in an element with `order-condition="has-fulfillments"`: it hides while the order has no shipment.

```html
<div order-condition="has-fulfillments">
  <order-fulfillment>
    <div fulfillment="status">Status</div>
    <a href="#" fulfillment="trackingUrl">Track the parcel</a>
  </order-fulfillment>
</div>
```

**Printing.** To print the order, wrap the part to print in a Custom element with the tag `printable-element`, and give it an ID in its element settings, such as `order`. A Custom element with the tag `print-button` and `data-target="order"` prints that part alone. See [`print-button`](https://www.smootify.io/docs/reference/elements/print-button).

The rows of the order list can hold `line-item` and `order-fulfillment` too, for example to show small product images in each order.

## 4. Buy again

A Custom element with the tag `button` and `data-action="buy-again"` puts the products of an order back in the cart, each with its variant, its quantity and its properties, such as an engraving or an uploaded file. It works inside `customer-order`, in the list, and inside `order-page`.

```html
<button data-action="buy-again"><div data-state="default">Buy again</div><div data-state="loading">Adding…</div></button>
```

- **Straight to checkout.** Add `data-buy-now="true"` to the button to send the customer to checkout instead of the cart.
- **While it works.** The elements inside the button with `data-state="default"` and `data-state="loading"` swap, and the button gets the class `is-loading`. Then the mini cart opens, as after any addition.
- **What stays out.** Products that no longer exist, the products of a Shopify bundle (the order does not say which bundle they formed), and products priced by the [product configurator](https://www.smootify.io/docs/features/product-configurator) or [name your price](https://www.smootify.io/docs/features/name-your-price). A product Shopify refuses, such as a sold-out one, is not added either.
- **Subscriptions** come back as one-time purchases.
- **Nothing to buy.** When nothing in the order can be bought again, the button hides itself.

## Before you publish

> [!STUCK]
> - **The order page sends you to the home page.** It was opened without an order in its address, or by a customer the order does not belong to. Open it from an `order="url"` link. A visitor who is not logged in goes to the home page too unless `accountPageRedirectTo` is `"passwordless-login"`.
> - **The order link leads to a missing page.** The order page is not at `/account/order`. Move it there, or set `orderPageUrl`.
> - **Statuses show codes such as `PAID`.** Add the `SmootifyStatusLabels` script with your words.
> - **Buy again or the pagination does nothing.** It is a Webflow Button, which is a link. Use a Custom element with the tag `button`.
> - **The Buy again button is missing on an order.** Nothing in that order can be bought again: its products are deleted, part of a bundle, or had a custom price.
> - **The products you designed disappear.** Only the first `line-item` is the template. Design one; Smootify repeats it.

## Coming from 1.x

- The order rows, their children and their images no longer shimmer on their own while loading. Add `skeleton` to the placeholders you want.
- Buy again is new in 2.0.
