Skip to main content

Manage values

Metafields are key-value pairs that let you store custom data on Shopify resources like products, customers, and orders. This guide shows you how to create, read, update, and delete metafield values using the GraphQL Admin API.


  • Your app can make authenticated requests to the GraphQL Admin API.
  • You have the appropriate scopes, such as write_products and write_customers, based on owner type.
  • You've created a metafield definition for your metafield. The definition establishes the schemas (structure and rules) for metafields. If you're creating metafields for common use cases, you can skip this step.

Create metafields by including them when creating or updating resources (like productCreate or productUpdate). Alternatively, use metafieldsSet for standalone metafield operations.

Note

The metafield's namespace, key, and type must match its corresponding metafield definition.

Anchor to App-owned metafield exampleApp-owned metafield example

Create app-owned metafields for your app-owned defitions. This gives your app exclusive control over both the definition (schema) and the metafield (value). App ownership is established using the namespace $app.

This example uses productCreate to create a product along with an app-owned metafield:

GraphQL

POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
mutation CreateProductWithAppMetafield {
productCreate(
input: {
title: "Analytics-Tracked Product"
metafields: [
{
namespace: "$app"
key: "internal_analytics"
value: "{\"views\": 0, \"lastViewed\": null}"
type: "json"
}
]
}
) {
product {
id
title
metafield(namespace: "$app", key: "internal_analytics") {
id
value
}
}
userErrors {
field
message
}
}
}

Anchor to Merchant-owned metafieldsMerchant-owned metafields

Create merchant-owned metafields for your merchant-owned definitions. Merchant-ownership ensures shared management access across apps and in the Shopify admin. Merchant ownhership is established using any namespace that isn't reserved for apps or Shopify (see Metafield ownership).

This example uses productCreate to create a product along with a merchant-owned metafield.

GraphQL

POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
mutation CreateProductWithMetafield {
productCreate(
input: {
title: "Premium Laptop"
metafields: [
{
namespace: "product_details"
key: "warranty_info"
value: "2 year limited warranty"
type: "multi_line_text_field"
}
]
}
) {
product {
id
title
metafield(namespace: "product_details", key: "warranty_info") {
id
value
}
}
userErrors {
field
message
}
}
}

Anchor to Creating multiple metafieldsCreating multiple metafields

Set multiple metafields at once by passing an array. This is more efficient than making separate requests for each metafield. See metafield limits for maximum batch sizes.

GraphQL

POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
mutation CreateProductWithMultipleMetafields {
productCreate(
input: {
title: "Cotton T-Shirt"
metafields: [
{
namespace: "specs"
key: "weight"
value: "{\"value\": 2.5, \"unit\": \"KILOGRAMS\"}"
type: "weight"
},
{
namespace: "specs"
key: "material"
value: "Cotton blend"
type: "single_line_text_field"
}
]
}
) {
product {
id
title
metafields(first: 10, namespace: "specs") {
edges {
node {
key
value
}
}
}
}
userErrors {
field
message
}
}
}

Anchor to Using standard definitionsUsing standard definitions

Shopify provides pre-defined metafield schemas for common use cases like ISBN numbers, ingredients, and product specifications. Using these standard definitions saves you from creating custom definitions and ensures compatibility across themes and apps.

Standard definitions auto-enable when you create metafield values using their namespace and key (like facts and isbn):

GraphQL

POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
mutation AddISBNToProduct {
productUpdate(
input: {
id: "gid://shopify/Product/123456789"
metafields: [
{
namespace: "facts"
key: "isbn"
value: "978-3-16-148410-0"
type: "single_line_text_field"
}
]
}
) {
product {
id
metafield(namespace: "facts", key: "isbn") {
id
value
definition {
standardTemplate {
id
name
}
}
}
}
userErrors {
field
message
}
}
}

Once enabled, Shopify owns the schema, but the metafields (values) created are merchant-owned. See the standard definitions list for available standard namespaces and keys.


Query metafields through their parent resource using GraphQL. This example retrieves a product along with its metafields, demonstrating three common patterns: fetching metafields (with pagination), getting a specific metafield by namespace/key, and filtering by namespace.

GraphQL

POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
query GetProductWithMetafields {
product(id: "gid://shopify/Product/1234567890") {
id
title
metafields(first: 10) {
edges {
node {
namespace
key
value
type
}
}
}
warranty: metafield(namespace: "product_details", key: "warranty_info") {
value
}
productDetails: metafields(namespace: "product_details", first: 20) {
edges {
node {
key
value
}
}
}
}
}

For advanced querying techniques, see Query using metafields.


Update metafields using the resource mutation approach. Metafields automatically update if the namespace/key combination already exists.

GraphQL

POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
mutation UpdateProductMetafield {
productUpdate(
input: {
id: "gid://shopify/Product/1234567890"
metafields: [
{
namespace: "product_details"
key: "warranty_info"
value: "Extended 3 year warranty available"
type: "multi_line_text_field"
}
]
}
) {
product {
metafield(namespace: "product_details", key: "warranty_info") {
value
updatedAt
}
}
userErrors {
field
message
}
}
}
Note

The type must match the original definition. You can't change a metafield's type by updating its value.


Delete metafields using the metafieldsDelete mutation with their namespace, key, and owner ID.

GraphQL

POST https://{shop}.myshopify.com/api/{api_version}/graphql.json
mutation DeleteMetafield {
metafieldsDelete(metafields: [
{
ownerId: "gid://shopify/Product/1234567890"
namespace: "product_details"
key: "warranty_info"
}
]) {
deletedMetafields {
key
namespace
ownerId
}
userErrors {
field
message
}
}
}
Note

Deleting a resource (using productDelete or customerDelete for example) automatically deletes all associated metafields. Use metafieldsDelete when you want to remove specific metafields while keeping the resource.


Common errors and their solutions when working with metafields.

ErrorCauseSolution
"Value is invalid for type"Wrong format for typeCheck type formats
"Validation failed"Value doesn't meet validation rulesCheck definition's validation constraints
"Type mismatch"Type doesn't match definitionUse the exact type from definition
"JSON parse error"Invalid JSON formatValidate JSON and escape properly

Following these practices helps ensure efficient, reliable metafield management and prevents common issues:

  • Batch operations: Set multiple metafields in one request by passing an array (see limits).
  • Validate before saving: Check value format matches type requirements
  • Use consistent formatting: Maintain consistent JSON structures and date formats
  • Handle references carefully: Verify referenced resources exist
  • Escape JSON properly: Use JSON.stringify() for complex values
  • Query efficiently: Use specific namespaces/keys instead of fetching all
  • Cache metafield IDs: Store IDs for frequently accessed metafields


Was this page helpful?