Skip to content

customer

The customer object is the authenticated buyer for the current storefront. It contains buyer-visible identity, address, order, loyalty, referral, review reward, store-credit, tag, and metafield data.

Availability and context

customer is available globally and is normally nil for a guest. Always guard customer properties with {% if customer %}. Live customer data comes only from the authenticated storefront customer session; a customer identifier in a URL or theme setting cannot load another buyer. On verified visual-editor account pages, Sellerlane instead injects a fixed, non-persisted sample customer so the account UI can be previewed without exposing live buyer data.

Examples

Render signed-in and guest states

{% if customer %}
<p>Hi {{ customer.first_name | default: customer.name | escape }}!</p>
<a href="{{ routes.account_url }}">View your account</a>
{% else %}
<p>Welcome!</p>
<a href="{{ routes.account_login_url }}">Sign in</a>
{% endif %}

Example output for a signed-in buyer:

<p>Hi Asha!</p>
<a href="/account">View your account</a>

For a guest, the same template renders:

<p>Welcome!</p>
<a href="/account/login">Sign in</a>

Paginate the buyer’s orders

{% if customer %}
{% paginate customer.orders by 10 %}
<ul>
{% for order in customer.orders %}
<li>
<a href="{{ routes.account_url }}/orders/{{ order.id }}">{{ order.name | escape }}</a>
— {{ order.created_at | date: '%d %b %Y' }}
— {{ order.total_price | money }}
</li>
{% else %}
<li>You have not placed an order yet.</li>
{% endfor %}
</ul>
{{ paginate | default_pagination }}
{% endpaginate %}
{% endif %}

Example output:

<ul>
<li><a href="/account/orders/ord_01J8">#1042</a> — 12 Jul 2026 — ₹2,498.00</li>
</ul>

Orders are returned newest first. last_order is the newest non-test order and is nil when the customer has no eligible order.

Paginate saved addresses

{% if customer %}
{% paginate customer.addresses by 10 %}
{% for address in customer.addresses %}
<address>
{{ address.name | escape }}<br>
{{ address.address1 | escape }}<br>
{{ address.city | escape }}, {{ address.province_code | escape }}
</address>
{% else %}
<p>No saved addresses.</p>
{% endfor %}
{{ paginate | default_pagination }}
{% endpaginate %}
{% endif %}

Example output:

<address>
Asha Rao<br>
12 Residency Road<br>
Bengaluru, KA
</address>

Show buyer-owned rewards safely

{% if customer %}
<p>Lifetime spend: {{ customer.total_spent | money }}</p>
{% if customer.personal_rewards_available %}
{% if customer.referral_url != blank %}
<a href="{{ customer.referral_url }}">Share your referral link</a>
{% endif %}
{% else %}
<p>Personal rewards cannot be used on company purchases.</p>
{% endif %}
{% if customer.store_credit_account.balance > 0 %}
<p>Store credit: {{ customer.store_credit_account.balance | money }}</p>
{% endif %}
{% endif %}

Example output:

<p>Lifetime spend: ₹24,880.00</p>
<a href="/?ref=ASHA24">Share your referral link</a>
<p>Store credit: ₹500.00</p>

personal_rewards_available is true for a personal shopper or a wholesale contact who explicitly selected personal purchasing. It is false while that contact is shopping for a company or has not selected a purchasing identity. The flag controls presentation; the checkout still checks the purchase context and reward eligibility. A visible balance does not make every reward spendable.

Loyalty holds, membership, and promotional adjustments

customer.loyalty includes these buyer-owned fields in addition to the program, balances, history, and redemption options:

Field within customer.loyaltyMeaning
unrecovered_pointsPreviously spent points that must be offset by later earnings; not a money amount.
current_tier_expires_atMembership end instant when present; do not infer an unlimited membership when absent.
pending_awards / pending_awards_totalUp to 50 pending point awards and the full count. Rows include points, the buyer’s order reference, hold reason/action, creation time, and an optional estimated release time.
pending_referrals / pending_referrals_totalUp to 50 pending advocate rewards and the full count. Rows include amount or percentage, currency, and creation time. They deliberately omit the friend’s order, hold reason, and other private details.
reward_recoveries / reward_recoveries_totalUp to 50 promotional-credit adjustment records and the full count. These are not cash invoices to the buyer.

Each recovery row exposes id, currency, invalidated_at, and these decimal strings in currency minor units: invalidated_amount_cents, recovered_amount_cents, waived_amount_cents, expired_amount_cents, and outstanding_amount_cents. Keep those categories separate. Outstanding value was not recovered; a waiver accepts the merchant cost rather than paying the buyer again. Preserve the strings when passing values to JavaScript instead of converting large amounts to floating-point numbers.

An estimated release date is conditional on continued eligibility. Do not render pending amounts as available or hide existing history merely because the program is paused. The three lists are bounded snapshots, not complete paginated exports; use their total fields to disclose when only part of the history is shown. See Rewards: settings and recovery for accepted offers, retries and adjustment reporting.

Nil values, ordering, and limits

  • customer.orders is newest first. Direct iteration exposes at most 20 orders; pagination supports a page size of up to 20.
  • Direct customer.addresses iteration exposes at most 20 addresses, and its maximum pagination page size is also 20.
  • Direct customer.review_rewards iteration exposes at most 20 records; pagination supports a page size of up to 250.
  • orders_count and addresses_count use 25001 to mean “more than 25,000.”
  • default_address and last_order can be nil. Missing email, phone, first name, last name, combined name, birthday, and referral string properties are empty strings.
  • has_account is true only when the identity state is enabled for passwordless access. has_avatar? currently always returns false.
  • store_credit_account is always an object for a customer; its balance defaults to zero when no credit account exists. total_spent and that balance are currency minor units and should be formatted with money.

Customer data is private to the authenticated buyer. Customer metafields are resolved only for that buyer, and customer-typed references are redacted from general storefront metafield traversal. Never cache customer-rendered HTML in a shared public cache.

Properties

PropertyDescription
customer.accepts_marketingtrue when opted in to marketing.
customer.addressesSaved addresses, limited to the first 20 without pagination; maximum pagination page size 20.
customer.addresses_countTotal saved-address count, capped by the storefront count sentinel.
customer.b2b?true when the current session is an authenticated company (wholesale) contact.
customer.birthdayDate-only birthday in YYYY-MM-DD, or an empty string.
customer.birthday_locked_untilISO instant until birthday self-service can be changed again, or an empty string.
customer.company_available_locations_countNumber of company locations the contact can order for; 0 for D2C sessions. Fetch the list itself from the paginated locations endpoint.
customer.company_purchasing_only?true when the store’s “Company purchasing only” setting applies to this wholesale contact, so the theme must not offer the “Purchasing personally” option. Always false for D2C shoppers and guests. Display gating only — the seller re-enforces it at the session and checkout seams.
customer.current_companyCurrent wholesale session’s company as { id, name }, or nil for D2C sessions.
customer.current_locationActive ordering location as { id, name }, or nil until the contact selects one.
customer.default_addressDefault address, or nil.
customer.emailEmail address, or an empty string.
customer.first_nameFirst name, or an empty string.
customer.has_accounttrue when the customer identity is enabled for passwordless account access.
customer.has_avatar?false until a storefront customer-avatar source is configured.
customer.idUnique identifier.
customer.last_nameLast name, or an empty string.
customer.last_orderMost recent non-test order, or nil.
customer.loyaltyAuthenticated customer loyalty summary and balances; an inactive zero-balance summary is returned when no account exists.
customer.metafieldsMetafields on this resource.
customer.nameCombined first and last name, or an empty string.
customer.ordersNewest-first orders, limited to the first 20 without pagination and to 20 per page. Build account links from routes.account_url and the order ID; list results do not populate order.customer_url.
customer.orders_countOrder count, using 25001 as the “more than 25,000” sentinel.
customer.personal_rewards_availabletrue for personal shopping, including a wholesale contact who explicitly chose personal purchasing; false for company shopping or an unresolved company purchasing identity. A presentation gate, not proof that a particular reward can be spent.
customer.phonePhone number, or an empty string.
customer.referral_codeAuthenticated customer referral code, or an empty string.
customer.referral_summaryAuthenticated customer referral-program summary; an inactive zero-value summary is returned when none exists.
customer.referral_urlRoot-relative same-store referral path, or an empty string.
customer.referrals_countNumber of referrals attributed to the customer.
customer.purchasing_personally?true only when a wholesale buyer explicitly chose the Purchasing personally identity; false when no purchase identity was selected.
customer.review_rewardsReview reward records visible to the authenticated customer: first 20 without pagination, with a maximum page size of 250.
customer.review_rewards_countNumber of visible review reward records.
customer.store_credit_accountAlways-present object whose balance is the authenticated customer’s store credit in currency minor units, defaulting to zero.
customer.tagsTags as an array of strings.
customer.tax_exempttrue when the customer is tax exempt.
customer.total_spentLifetime order spend in currency minor units; format with money.

Property names are generated from the storefront engine (CustomerDrop), so the list matches what themes can access. {{ customer | json }} is a curated identity and aggregate subset; it does not serialize addresses, orders, rewards, loyalty, referrals, store credit, metafields, or last_order. Inspect those properties directly.

Sellerlane differences from Shopify

  • Storefront accounts use Sellerlane’s OTP/passwordless identity flow. has_account therefore means an enabled passwordless identity, not that the customer created a Shopify-style password.
  • loyalty, referral properties, review rewards, birthday properties, and store_credit_account are Sellerlane extensions scoped to the authenticated customer, or to the fixed non-persisted sample on a verified editor account preview.
  • Company context uses the compact current_company and current_location records described above. Do not assume they expose richer company/location objects or a complete list of available locations.
  • Sellerlane excludes test orders from last_order so account summaries do not present test activity as a buyer purchase.