---
title: "Storefront customization for developers"
url: "https://zendra.com/docs/storefront-customization/"
description: "Use Zendra’s customer metafields to build conditional storefront content in Liquid — show or hide content by membership status or plan."
published: "2026-06-22T23:38:19+00:00"
modified: "2026-06-23T01:46:41+00:00"
---

Zendra publishes each customer’s membership status to Shopify **customer metafields**, so you can build conditional storefront content in Liquid — show or hide sections by membership status or by plan — without using Zendra’s app blocks. The metafields are created automatically when Zendra is installed and are readable in the storefront.

These fields read off the logged-in `customer` object, so conditional logic only resolves for logged-in customers. Treat logged-out visitors as non-members.

## When you’d use this

- Show a members-only section, or hide content from non-members, directly in a theme template.
- Render a plan-specific banner or coupon (for example, only for Gold members).
- Greet members by tenure (“Member since 2024”).
- Build member logic into a section or block where Zendra’s own app block doesn’t fit.

## How it works

Zendra syncs three queryable customer metafields under its app namespace, `app--284688121857`. They’re updated automatically on every membership change and are read-only to merchants.

| Field (merchant-facing name) | Liquid | Type | Value |
|---|---|---|---|
| \[Zendra\] Member Status | `customer.metafields.app--284688121857.member_status` | text | `active`, `inactive`, or `none` |
| \[Zendra\] Active Plans | `customer.metafields.app--284688121857.active_plans` | list of text | the plan slugs the customer currently has active access to |
| \[Zendra\] Member Since | `customer.metafields.app--284688121857.member_since` | date & time | date of the customer’s first-ever membership activation |

`member_status` is the quickest member / non-member check; `active_plans` lets you branch by specific plan; `member_since` supports tenure-based content.

### Show content to members only

```
{% if customer.metafields.app--284688121857.member_status.value == 'active' %}
  <p>Members-only content here.</p>
{% else %}
  <p><a href="/pages/membership">Join to unlock this.</a></p>
{% endif %}
```

### Render plan-specific content

`active_plans` is a list of plan slugs, so use `contains` to target one plan:

```
{% assign plans = customer.metafields.app--284688121857.active_plans.value %}
{% if plans contains 'gold' %}
  <div class="member-notice">
    <p>A notice for Gold members — a coupon to use at checkout.</p>
  </div>
{% endif %}
```

### Greet members by tenure

```
{% assign since = customer.metafields.app--284688121857.member_since.value %}
{% if since %}
  <p>Member since {{ since | date: '%B %Y' }}.</p>
{% endif %}
```

## Good to know

- **Confirm the namespace.** `app--284688121857` is Zendra’s app namespace and is the same on every store that installs Zendra. To verify it for your store, go to **Settings » Metafields » Customers** in Shopify admin, then **More actions » View read-only definitions**.
- **Use `.value`.** In Liquid a metafield is an object; append `.value` to read it. For `active_plans` (a list type), `.value` returns an array you can iterate or test with `contains`.
- **Slugs, not names.** `active_plans` holds plan *slugs* (e.g. `gold`), which may differ from the display name. Confirm a plan’s slug in its Zendra settings before hardcoding it.
- **Managed by Zendra.** These fields are set by the app and are read-only — don’t write to them from the theme; edit memberships in Zendra and the values follow.
- **There’s also an internal `memberships` blob** used for content restrictions and Shopify Functions. It stores plan IDs rather than slugs and isn’t the intended theme surface — build storefront logic on the three queryable fields above.

## Common issues

- **Nothing renders for a logged-in member.** Confirm the customer truly has active access (`member_status` is `active`), and that you’re reading `.value`. A bare `customer.metafields.app--284688121857.member_status` returns the object, not the string.
- **A plan check never matches.** You’re likely comparing against the plan’s display name — use its slug.
- **Fields are missing entirely.** The metafield definitions are created when Zendra installs. If they’re absent, reopen Zendra to trigger setup (a backfill runs for existing members).

## Keep learning

- [Member content protection](/docs/member-content-protection/) — Zendra’s built-in gating, when you don’t need custom Liquid.
- [Managing members](/docs/managing-members/) — the same data, used for segments and analytics.
- [Zendra app blocks & widgets](/docs/zendra-app-blocks-widgets/) — the no-code storefront blocks.
