Returns and wishlist
The Commerce extension exposes the signed-in customer's return (RMA) requests to account templates through the user.rmas loop. The wishlist is different: it has no engine token family of its own and is rendered by the storefront script from a small item template and a set of data attributes.
Return requests (RMA)
Return requests belong to a signed-in customer. A template that contains the text user.rmas receives that customer's requests, so the loop renders on account pages and is empty for guests. Loop over the requests with {each user.rmas as=rma} and read each request with {rma.<field>}.
| Token | Meaning | Example |
|---|---|---|
{rma.rma_number} | Return request number | <span>{rma.rma_number}</span> |
{rma.order_number} | Number of the order that contains the item | <span>Order {rma.order_number}</span> |
{rma.order_item_id} | Identifier of the returned order item | <span>Item {rma.order_item_id}</span> |
{rma.item_name} | Name of the returned item | <span>{rma.item_name}</span> |
{rma.status} | Current return status | <span class="badge">{rma.status}</span> |
{rma.reason} | Reason the customer selected | <span>{rma.reason}</span> |
{rma.requested_qty} | Quantity the customer asked to return | <span>Qty {rma.requested_qty}</span> |
{rma.created_at} | Date the request was created, formatted like Jan 05, 2026 | <span>{rma.created_at}</span> |
A return request moves through these statuses: pending, approved, info_requested, customer_replied, rejected, received, refunded, and closed. Render the value directly or use it as a class hook; do not assume a fixed set of labels.
Empty state and pagination
Wrap the loop in {if user.rmas} to show it only when the customer has requests, and use {else} for an empty state.
{if user.rmas}
<ul class="returns">
{each user.rmas as=rma}
<li>
<a href="/user/billing/returns/{rma.rma_number}">
<span class="number">{rma.rma_number}</span>
<span class="status">{rma.status}</span>
<span class="item">{rma.item_name}</span>
<span class="qty">{rma.requested_qty}</span>
<span class="date">{rma.created_at}</span>
</a>
</li>
{/each}
</ul>
{else}
<p>No return requests yet.</p>
{/if}
The account RMA tab reads the current page query parameter and the search term from q. The following tokens describe the current page of results.
| Token | Meaning |
|---|---|
{user.rmas_count} | Total number of requests that match the search |
{user.rmas_page} | Current page number |
{user.rmas_pages} | Total number of pages |
{user.rmas_prev_page} | Previous page number; empty when there is none |
{user.rmas_next_page} | Next page number; empty when there is none |
{user.rmas_query} | Current search text |
Use {if user.rmas_prev_page} and {if user.rmas_next_page} to show a control only when that page exists, and put the token in the control value.
<div class="pager">
<span>Page {user.rmas_page} of {user.rmas_pages}</span>
{if user.rmas_prev_page}
<button type="button" data-page="{user.rmas_prev_page}">Previous</button>
{/if}
{if user.rmas_next_page}
<button type="button" data-page="{user.rmas_next_page}">Next</button>
{/if}
</div>
Account return flow
The account RMA tab and the standalone return page are driven by the storefront script rather than by these tokens. They bind to data-rma-* markers in the markup, list the customer's requests, and submit new ones with these fields: order number, order item id, requested quantity, reason, and description. A guest return also takes the order email. Reasons shown in the default examples are Damaged, Defective, Wrong Item, Not as Described, and Other.
A request detail exposes the admin note, resolution note, return label URL, return tracking number, return carrier, return address, requested info message, and customer reply. These live on the detail request, not on the {rma.*} loop tokens above.
Wishlist
The template engine has no {wishlist.*} token and no {each wishlist...} loop. The storefront script owns the wishlist, keeps it for guests and signed-in customers, and writes item cards into markers you place in the markup. It loads automatically with the other runtime scripts.
Markers
| Marker | Purpose |
|---|---|
data-ms-wishlist-page | Wraps a full wishlist page |
data-ms-wishlist-items | Container the item cards are written into |
data-ms-wishlist-empty | Element shown when the wishlist has no items |
data-ms-wishlist-total | Item count for the page or dropdown |
data-ms-wishlist-count | Item count shown beside a header link |
data-ms-wishlist-page-item-template | Template element for a page item card |
data-ms-wishlist-product-item-code | Optional product template code used to render cards |
data-ms-wishlist-toggle-item | Toggle button carrying a product id |
data-ms-wishlist-toggle | Toggle button paired with data-product-id |
data-ms-wishlist-dropdown-wrap | Wrapper for a wishlist dropdown |
data-ms-wishlist-dropdown-toggle | Button that opens the dropdown |
data-ms-wishlist-dropdown | Dropdown panel |
data-ms-wishlist-dropdown-items | Container the dropdown items are written into |
data-ms-wishlist-dropdown-empty | Element shown when the dropdown has no items |
data-ms-wishlist-dropdown-limit | Maximum items to show in the dropdown |
When data-ms-wishlist-product-item-code is omitted, the script renders each card with the product card template (product_item). Variant selection is read from nearby attributes such as data-ms-variant-id, data-ms-variant-sku, data-ms-variant-label, and data-ms-variant-attributes, and from the same attributes without the ms- prefix.
Item template tokens
The page and dropdown templates are plain markup with {...} placeholders that the script fills per item. They are not engine tokens. The available values are:
| Token | Meaning |
|---|---|
{product.id} | Product id |
{product.name} | Product name |
{product.link} | Product page URL |
{product.image_url} | Primary product image URL |
{product.price} | Formatted product price |
{product.brand} | Product brand |
{entry.product_id} | Saved product id |
{entry.variant_id} | Saved variant id, when the item has a variant |
{entry.variant_sku} | Saved variant SKU, when present |
{entry.variant_label} | Saved variant label, when present |
{entry.variant_key} | Saved variant key that identifies the exact item |
<div data-ms-wishlist-page>
<p><span data-ms-wishlist-total>0</span> saved items</p>
<div data-ms-wishlist-items></div>
<p data-ms-wishlist-empty class="hidden">Your wishlist is empty.</p>
<template data-ms-wishlist-page-item-template>
<a href="{product.link}">
<img src="{product.image_url}" alt="{product.name}">
<span>{product.name}</span>
<span>{product.price}</span>
</a>
</template>
</div>
A product card saves an item with a toggle button. The button carries the product id in its value.
<article data-ms-product-card>
<a href="{product.link}">{product.name}</a>
<button type="button" data-ms-wishlist-toggle-item="{product.id}" aria-label="Save to wishlist">Save</button>
<span data-ms-wishlist-count>0</span>
</article>
The script announces changes with an ms:wishlist:updated event on the document, and re-reads the page markers when content is replaced through ms:content-updated or ms:ajax:complete.

