Skip to content

Entity Profiles

Entity profiles let a customer save who or what they shop for — pets, babies, vehicles, plants, family members — directly on their customer account. Each profile is stored as a Shopify metaobject (save_profile) and indexed on a customer metafield (savelayer.profiles), so themes, Liquid, Functions, Flow, and dynamic-source pickers in the theme editor can all read it.

Plan requirement: Same as the rest of the customer-account channel — requires the Pro plan or above. See Customer Account.

Why this exists

Pet stores, baby stores, parts stores, supplement brands — any merchant whose customers shop for a specific entity benefits from persisting "who this is for." Once the profile lives on the customer record, the merchant can:

  • Render personalized lists (Saves for Rex, Saves for the truck).
  • Filter recommendations or recharge subscriptions per profile.
  • Drive Shopify Flow workflows (e.g. "remind customer when Rex's food was last ordered").
  • Use dynamic-source bindings in the theme editor without writing custom Liquid.

Data model

SurfaceWhere it livesOwned by
save_profile metaobjectShopify metaobjects (canonical)SaveLayer
customer.metafields.savelayer.profilesCustomer record (list.metaobject_reference)SaveLayer maintains it
save_list.profile referencesave_list metaobject (optional)Merchant or app — links a list to a profile

Each save_profile carries:

  • customer_id (required, used for ownership checks)
  • profile_name (display name — "Rex")
  • profile_type (free-form; SaveLayer ships defaults for pet, baby, vehicle, person, plant, custom)
  • attributes (JSON bag — { breed: "labrador", age: 5 })
  • created_at, updated_at, state

Customer-side identity is always resolved server-side from the SaveLayer JWT, never from a payload field. SaveLayer enforces ownership on every read or write before touching the metaobject.

API

All endpoints share the customer-account auth model — call /api/customer-account/auth/exchange first to mint a SaveLayer JWT, then send Authorization: Bearer <jwt> on subsequent calls. See Customer Account for the exchange flow.

GET /api/customer-account/profile/list

Returns the active profiles owned by the authenticated customer.

json
{
  "ok": true,
  "data": {
    "profiles": [
      {
        "id": "gid://shopify/Metaobject/123",
        "name": "Rex",
        "type": "pet",
        "attributes": { "breed": "labrador", "age": 5 },
        "createdAt": "2026-04-25T00:00:00.000Z",
        "updatedAt": "2026-04-25T00:00:00.000Z"
      }
    ]
  }
}

POST /api/customer-account/profile/create

json
{ "name": "Rex", "type": "pet", "attributes": { "breed": "labrador" } }

Returns { ok: true, data: { profile: { ... } } } and rebuilds customer.metafields.savelayer.profiles.

POST /api/customer-account/profile/update

json
{ "id": "gid://shopify/Metaobject/123", "name": "Rexford" }

Only the fields you send are changed. attributes is replaced wholesale when present.

POST /api/customer-account/profile/delete

json
{ "id": "gid://shopify/Metaobject/123" }

Soft-flips state=deleted, then issues a hard metaobjectDelete. The customer metafield is rebuilt to drop the reference. If the hard delete fails, the soft state still removes it from filtered queries and the metafield index.

Customer Account UI extension

SaveLayer ships a built-in customer-account UI extension at extensions/savelayer-customer-account-profiles/ that gives customers a CRUD surface for their profiles using the standard customer-account web components (Page, BlockStack, TextField, Select, Button, etc.). It targets the same customer-account.page.render extension target as the Saved Items extension.

Merchants can override the offered profile types via the extension's profile_types setting (comma-separated) — leave blank for the SaveLayer defaults.

Reading profiles in your theme

Because profiles are referenced from a customer metafield, they show up in the theme editor's dynamic-source picker. To read them in Liquid:

liquid
{% for profile in customer.metafields.savelayer.profiles.value %}
  <h3>{{ profile.profile_name }}</h3>
  <p>{{ profile.profile_type }}</p>
{% endfor %}

To filter saves to a specific profile, store the profile reference on save_list.profile when the list is created and filter your save list query by that field.