Customer Accounts

Shopify handles account authentication itself — passwords, sessions, password resets — so a theme never touches credentials directly. What a theme does control is how the login, registration, and account pages actually look, built with a mix of the customer object and specialized Liquid form tags.

The customer object

When a shopper is logged in, customer is populated across the whole storefront, not just on account pages — useful for things like greeting a returning customer by name anywhere in the theme:

Liquid checking login state
{% if customer %}
  <p>Welcome back, {{ customer.first_name }}</p>
{% else %}
  <a href="/account/login">Log in</a>
{% endif %}

Login and registration forms

Rather than posting to raw endpoints yourself, Liquid provides {% form %} variants scoped specifically to customer actions, which handle the correct field names and CSRF protection automatically:

Liquid templates/customers/login.liquid
{% form 'customer_login' %}
  <input type="email" name="customer[email]" required>
  <input type="password" name="customer[password]" required>
  <button type="submit">Log in</button>
{% endform %}
Liquid templates/customers/register.liquid
{% form 'create_customer' %}
  {% if form.errors %}
    <ul>
      {% for field in form.errors %}
        <li>{{ form.errors.messages[field] }}</li>
      {% endfor %}
    </ul>
  {% endif %}
  <input type="email" name="customer[email]" required>
  <input type="password" name="customer[password]" required>
  <button type="submit">Create account</button>
{% endform %}

form.errors is populated automatically after a failed submission (a duplicate email, a too-short password), so the template just needs to display whatever messages Shopify already generated.

The account and order history pages

templates/customers/account.liquid is a logged-in customer's dashboard, typically showing recent orders through customer.orders and stored addresses through customer.addresses:

Liquid order history
{% for order in customer.orders %}
  <a href="{{ order.customer_url }}">
    Order {{ order.name }} — {{ order.created_at | date: "%B %d, %Y" }} — {{ order.total_price | money }}
  </a>
{% endfor %}

New customer accounts and the Customer Account API

Newer Shopify stores can opt into "new customer accounts," a Shopify-hosted account experience served from a separate domain rather than rendered through theme Liquid templates at all. When enabled, a theme's job shrinks to linking out to that hosted experience rather than rendering templates/customers/*.liquid itself.

Extending that hosted experience is done through a different API entirely — the Customer Account API. It's worth understanding how it's fundamentally different from the Admin and Storefront APIs covered elsewhere in this course: those two authenticate an app, which then acts on a merchant's or shopper's behalf. The Customer Account API instead authenticates the shopper themself, using a standard sign-in flow, so an app built against it reads and updates only that one signed-in person's own orders, profile, and addresses — never anyone else's data, and never anything store-wide.

Note: never attempt to read or store a customer's password or payment details from theme code — Shopify never exposes them to Liquid or theme JavaScript in the first place, by design.