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 how your storefront looks and behaves.
Supported object types
Metadata is available in all GraphQL types that implement the ObjectWithMetadata
interface. See the Implemented by section of the ObjectWithMetadata
interface for the full list of supported types.
Private and public metadata
All objects support two sets of metadata:
metadata
is public and visible to the unauthenticated users.privateMetadata
is protected and visible only to the staff users, plugins, and Apps with appropriate permissions.
Modifying both requires permission to manage the item that metadata is attached to.
Querying metadata
All of the object types listed above implement the same interface:
interface ObjectWithMetadata {
privateMetadata: [MetadataItem]!
privateMetafield(key: String!): String
privateMetafields(keys: [String!]): Metadata
metadata: [MetadataItem]!
metafield(key: String!): String
metafields(keys: [String!]): Metadata
}
Each MetadataItem
is a key-value pair:
type MetadataItem {
key: String!
value: String!
}
There is a special Metadata
scalar that returns an object literal with keys as fields.
The following example fetches the metadata of the first product using both approaches to show the resulting data structures:
{
products(first: 1) {
edges {
node {
id
name
metadata {
key
value
}
metafields
}
}
}
}
Response:
{
"data": {
"products": {
"edges": [
{
"node": {
"id": "UHJvZHVjdDo3Mg==",
"name": "Apple Juice",
"metadata": [
{
"key": "tax.group",
"value": "Food products"
}
],
"metafields": {
"tax.group": "Food products"
}
}
}
]
}
}
}
Selecting fields to return
By default, metafields
(privateMetafields
) will return all metadata assigned to an object. You can use the optional keys
argument to select the fields you want to return. We highly recommend that you only fetch the fields your application understands as it limits the amount of information being needlessly transferred.
The following example returns only the tax.group
field:
{
products(first: 1) {
edges {
node {
id
name
metafields(keys: ["tax.group"])
}
}
}
}
If you only care about a single field, use metafield
(privateMetafield
) together with field aliasing:
{
products(first: 1) {
edges {
node {
id
name
taxGroup: metafield(key: "tax.group")
}
}
}
}
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
}
For Order
and Checkout
types, it is recommended to use token
as the id
input value; for other types, use GraphQL ID.
Changing the Order
metadata is possible only with the use of token
.
All resulting types have the same shape:
type UpdateMetadata {
metadataErrors: [MetadataError!]!
item: ObjectWithMetadata
}
Examples
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
}
}
}
}
Filtering by metadata
Objects with metadata interface can be filtered by their values. Filtering is only available for public metadata.
query FavoriteProducts {
products(
filter: { metadata: { key: "isFavorite", value: "true" } }
first: 10
channel: "default-channel"
) {
edges {
node {
id
name
}
}
}
}
Response:
{
"data": {
"products": {
"edges": [
{
"node": {
"id": "UHJvZHVjdDoxNDA=",
"name": "Super Shirt"
}
}
]
}
}
}