Skip to main content
Version: 2.11

Extending Models Using Metadata

Saleor gives you the possibility to customize your shop without modifying the core. You can extend most of the common models using the metadata API.

Metadata allows you to store additional information about each object, for example external identifiers for items synchronized with a third party platform. You can also use metadata to customize the way your storefront looks and behaves.

Supported object types#

The following models contain metadata fields which data can be modified:

  • Attribute
  • Category
  • Checkout
  • Collection
  • Product
  • ProductVariant
  • ProductType
  • App
  • User

Private and public metadata#

All objects support two sets of metadata:

  • metadata is public and visible to unauthenticated users.
  • privateMetadata is protected and visible only to staff users, plugins, and Apps with appropriate permissions.

Modifying both requires the permission to manage the item that metadata is attached to.

Querying metadata#

All of the objects types listed above implement the same interface:

interface ObjectWithMetadata {  privateMetadata: [MetadataItem]!  metadata: [MetadataItem]!}

Each metadata item is a key-value pair:

type MetadataItem {  key: String!  value: String!}

Here's an example query that fetches the metadata of the first product:

{  products(first: 1) {    edges {      node {        id        name        metadata {          key          value        }      }    }  }}


{  "data": {    "products": {      "edges": [        {          "node": {            "id": "UHJvZHVjdDo3Mg==",            "name": "Apple Juice",            "metadata": [              {                "key": "vatlayer.code",                "value": "standard"              },              {                "key": "vatlayer.description",                "value": "standard"              }            ]          }        }      ]    }  }}

Updating metadata#

The following GraphQL mutations allow you to update and remove metadata:

type Mutation {  updateMetadata(id: ID!, input: [MetadataInput!]!): UpdateMetadata  updatePrivateMetadata(    id: ID!    input: [MetadataInput!]!  ): UpdatePrivateMetadata  deleteMetadata(id: ID!, keys: [String!]!): DeleteMetadata  deletePrivateMetadata(id: ID!, keys: [String!]!): DeletePrivateMetadata}

All resulting types have the same shape:

type UpdateMetadata {  metadataErrors: [MetadataError!]!  item: ObjectWithMetadata}


Here's an example of how a product's metadata could be updated:

mutation {  updateMetadata(    id: "UHJvZHVjdDo3Mg=="    input: [{ key: "special_product", value: "true" }]  ) {    metadataErrors {      field      code    }    item {      metadata {        key        value      }    }  }}

And the same field being removed:

mutation {  deleteMetadata(id: "UHJvZHVjdDo3Mg==", keys: ["special_product"]) {    metadataErrors {      field      code    }    item {      metadata {        key        value      }    }  }}