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
- Guest —
customer_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.