StorefrontsAccounts & orders

Accounts & orders

Shoppers can check out as guests with no account. Signing in adds order history, saved addresses (where enabled), and store credit.

Sessions

Shopper sessions are signed with SESSION_SECRET (see Configuration) and stored in an httpOnly cookie — read only on the server. If SESSION_SECRET is unset, sign-in degrades gracefully to guest checkout: the store still works, orders just aren’t attributed to an account.

A checkout is attributed to a signed-in shopper only when the session’s tenant matches this store’s tenant — a session for another store can never tag this store’s order.

Order history

const { orders } = await store.shopper.orders({ limit: 20 });
const order = await store.shopper.order(orderId);

These require an authenticated shopper (the SDK call runs server-side with the shopper’s session established). For a guest, there is no history — which is a real “no account”, not an error.

Store credit

const balance = await store.storeCredit.balance();

Returns the shopper’s store-credit balance for this tenant. To spend it at checkout, pass apply_store_credit: true to store.checkout.submit (see Checkout) — the platform re-checks the real balance and never over-applies.

Honest absence, again

A shopper with no orders returns an empty list because they genuinely have none. That is different from a failed read. If store.shopper.orders(...) throws, show an error state — do not render “no orders yet”, which tells the shopper something false. Distinguish:

try {
  const { orders } = await store.shopper.orders();
  return orders.length ? <OrderList orders={orders} /> : <EmptyState />; // truly none
} catch {
  return <ErrorState />;   // we couldn't find out — NOT an empty state
}

Guest vs authenticated checkout

  • Guestcustomer_ref: "guest:<email>". No session needed.
  • Authenticated — the shopper’s ref, resolved from the session server-side. Never trust a shopper id from the request body; derive it from the session.