--- title: Manage metafields description: >- Learn how to create, read, update, and delete metafields using the GraphQL Admin API source_url: html: 'https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields' md: >- https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md --- ExpandOn this page * [Requirements](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#requirements) * [Creating metafields](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#creating-metafields) * [Retrieving metafields](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#retrieving-metafields) * [Updating metafields](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#updating-metafields) * [Deleting metafields](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#deleting-metafields) * [Error handling](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#error-handling) * [Best practices](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#best-practices) * [Next steps](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#next-steps) # Manage metafields 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 perform CRUD operations (create, read, update, and delete) on metafields using the GraphQL Admin API. [Metafield definitions](https://shopify.dev/docs/apps/build/custom-data/metafields/definitions) establish the schemas for metafields. This page focuses on managing the actual metafield values. *** ## Requirements * Your app can make [authenticated requests](https://shopify.dev/docs/api/admin-graphql#authentication) to the GraphQL Admin API. * You have the appropriate scopes, such as `write_products` and `write_customers`, based on owner type. *** ## Creating metafields You can add metafields by including them in resource creation operations such as [`productCreate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/productcreate) and [`customerCreate`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/customercreate). Alternatively, use the dedicated [`metafieldsSet`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/metafieldsSet) mutation for standalone metafield operations across any resource type. Tip Create a corresponding definition before creating the metafield. The definition specifies the type, validations, and permissions. Learn more about [managing metafield definitions](https://shopify.dev/docs/apps/build/custom-data/metafields/definitions). ### App-owned metafield example App-owned metafields can be created using the `$app` reserved namespace. Use app-owned metafields when your app needs exclusive control over the values, such as analytics or internal state. ## GraphQL POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json ```graphql 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 } } } ``` ### Merchant-owned metafields Merchant-owned metafields can be created using any [non-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/permissions). Use merchant-owned metafields when the values should be shared across multiple apps or full control is needed in the Shopify admin. ## GraphQL POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json ```graphql 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 } } } ``` ### Creating multiple metafields You can set multiple metafields at once by passing an array. This is more efficient than making separate requests for each metafield. See [metafield limits](https://shopify.dev/docs/apps/build/custom-data/metafields/metafield-limits) for maximum batch sizes. ## GraphQL POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json ```graphql 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 } } } ``` *** ## Retrieving metafields You can query metafields through their parent resource using GraphQL. This example retrieves a product along with its metafields, demonstrating three common patterns using the `metafield` and `metafields` fields: fetching all metafields, getting a specific one by namespace/key, and filtering by namespace. ## GraphQL POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json ```graphql 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 by metafield value](https://shopify.dev/docs/apps/build/custom-data/metafields/query-by-metafield-value). *** ## Updating metafields You can 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 ```graphql 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](https://shopify.dev/docs/apps/build/custom-data/metafields/list-of-data-types) must match the original definition. You can't change a metafield's type by updating its value. *** ## Deleting metafields Delete metafields using the [`metafieldsDelete`](https://shopify.dev/docs/api/admin-graphql/latest/mutations/metafieldsDelete) mutation with their namespace, key, and owner ID. ## GraphQL POST https://{shop}.myshopify.com/api/{api\_version}/graphql.json ```graphql 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. *** ## Error handling Common errors and their solutions when working with metafields. | Error | Cause | Solution | | - | - | - | | "Value is invalid for type" | Wrong format for type | Check [type formats](https://shopify.dev/docs/apps/build/custom-data/metafields/list-of-data-types) | | "Validation failed" | Value doesn't meet validation rules | Check definition's validation constraints | | "Definition not found" | No definition for namespace/key | Create definition first | | "Type mismatch" | Type doesn't match definition | Use the exact type from definition | | "JSON parse error" | Invalid JSON format | Validate JSON and escape properly | *** ## Best practices 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](https://shopify.dev/docs/apps/build/custom-data/metafields/metafield-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 *** ## Next steps * Create [metafield definitions](https://shopify.dev/docs/apps/build/custom-data/metafields/definitions) to include data validation for metafield values. * Learn about [access controls](https://shopify.dev/docs/apps/build/custom-data/permissions) for app-owned metafields. * Learn how to [query resources by metafield values](https://shopify.dev/docs/apps/build/custom-data/metafields/query-by-metafield-value) for filtering and search. *** * [Requirements](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#requirements) * [Creating metafields](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#creating-metafields) * [Retrieving metafields](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#retrieving-metafields) * [Updating metafields](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#updating-metafields) * [Deleting metafields](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#deleting-metafields) * [Error handling](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#error-handling) * [Best practices](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#best-practices) * [Next steps](https://shopify.dev/docs/apps/build/custom-data/metafields/manage-metafields.md#next-steps)