Skip to main content
The Store API supports storing arbitrary key-value metadata on carts (orders) and line items. Metadata is useful for tracking custom information like gift messages, attribution data, or integration-specific fields.
Metadata is different from metafields. Metadata is simple JSON storage (untyped, no schema), while metafields are structured, typed, and schema-defined. Use metadata for integration data and internal tracking. Use metafields for customer-facing custom attributes.

Cart Metadata

You can attach metadata when creating a cart:
const cart = await client.carts.create({
  metadata: {
    utm_source: 'google',
    utm_campaign: 'summer_sale',
    referral_code: 'FRIEND20',
  },
})

Cart Metadata (Update)

Update metadata on an existing cart:
await client.carts.update(cart.id, {
  metadata: {
    gift_message: 'Happy Birthday!',
    preferred_delivery: 'morning',
  },
}, { spreeToken: cart.token })

Item Metadata

Attach metadata to individual items when adding or updating them:

When Adding an Item

await client.carts.items.create(cart.id, {
  variant_id: 'variant_abc123',
  quantity: 1,
  metadata: {
    personalization: 'John',
    gift_wrap: true,
  },
}, { spreeToken: cart.token })

When Updating an Item

Updating metadata merges with existing values rather than replacing them:
await client.carts.items.update(cart.id, 'li_xyz789', {
  metadata: {
    personalization: 'Jane', // Updates existing key
    engraving: 'With Love',  // Adds new key
  },
}, { spreeToken: cart.token })
Metadata values can be any JSON-serializable type: strings, numbers, booleans, arrays, or nested objects.

Metadata Structure

Metadata is stored as a flat JSON object. You can use any keys and values:
{
  "metadata": {
    "string_value": "hello",
    "number_value": 42,
    "boolean_value": true,
    "nested_object": {
      "key": "value"
    }
  }
}

Metadata vs Metafields

Spree has two permanent, complementary systems for custom data — metadata for machines, metafields for humans.
MetadataMetafields
PurposeDeveloper escape hatch — integration IDs, sync stateMerchant-defined structured attributes
SchemaSchemaless JSON — no definition requiredDefined via MetafieldDefinitions (typed, validated)
ValidationNoneType-specific validation
VisibilityWrite-only in Store API, readable in Admin APIConfigurable (admin-only or public)
Admin UIJSON previewDedicated form fields
Best forIntegration data, tracking, attribution, write-and-forgetProduct specs, custom attributes, customer-facing data
API accessWrite via Store API, read via Admin APIRead/write via both APIs
Both systems are here to stay. For more details on metafields, see the Metafields guide.