---
title: Update cart metafields
description: Use a cart handler to update cart metafields.
source_url:
  html: >-
    https://shopify.dev/docs/storefronts/headless/legacy/hydrogen/cart/metafields
  md: >-
    https://shopify.dev/docs/storefronts/headless/legacy/hydrogen/cart/metafields.md
api_name: hydrogen
---

Legacy Hydrogen

These pages refer to Hydrogen versions 2026-04 and earlier. For versions 2026-10 and later, refer to the latest [Hydrogen docs](https://shopify.dev/docs/storefronts/hydrogen). If you're not using the latest version of Hydrogen, then we recommend that you migrate your storefront. To learn more, refer to [Migrate to the latest version of Hydrogen](https://shopify.dev/docs/storefronts/hydrogen/migrate).

# Update cart metafields

This guide shows you how to use a cart handler to update cart metafields.

***

## Requirements

* You've completed the [quickstart guide](https://shopify.dev/docs/storefronts/headless/legacy/hydrogen/getting-started).
* You've [set up a cart handler](https://shopify.dev/docs/storefronts/headless/legacy/hydrogen/cart/setup).

***

## Step 1: Read cart metafields

Update the cart query fragment to return cart metafields. For more information, refer to the [default `CartApiQuery` fragment](https://github.com/Shopify/hydrogen/blob/f4c30410d29291ea5550d85a5976d822da0f24b4/packages/hydrogen/src/cart/queries/cartGetDefault.ts).

The following example adds the`metafield` field:

## File

## server.js

##### JavaScript

```jsx
const cart = createCartHandler({
  storefront,
  getCartId: cartGetIdDefault(request.headers),
  setCartId: cartSetIdDefault(),
  cartQueryFragment: CART_QUERY_FRAGMENT,
});

const CART_QUERY_FRAGMENT = `#graphql
  fragment CartApiQuery on Cart {
    metafield(namespace: "custom", key: "gift") {
      value
    }
    id
    checkoutUrl
    totalQuantity
    buyerIdentity {
      countryCode
      customer {
        id
        email
        firstName
        lastName
        displayName
      }
      email
      phone
    }
    lines(first: $numCartLines) {
      edges {
        node {
          id
          quantity
          attributes {
            key
            value
          }
          cost {
            totalAmount {
              amount
              currencyCode
            }
            amountPerQuantity {
              amount
              currencyCode
            }
            compareAtAmountPerQuantity {
              amount
              currencyCode
            }
          }
          merchandise {
            ... on ProductVariant {
              id
              availableForSale
              compareAtPrice {
                ...CartApiMoney
              }
              price {
                ...CartApiMoney
              }
              requiresShipping
              title
              image {
                ...CartApiImage
              }
              product {
                handle
                title
                id
              }
              selectedOptions {
                name
                value
              }
            }
          }
        }
      }
    }
    cost {
      subtotalAmount {
        ...CartApiMoney
      }
      totalAmount {
        ...CartApiMoney
      }
      totalDutyAmount {
        ...CartApiMoney
      }
      totalTaxAmount {
        ...CartApiMoney
      }
    }
    note
    attributes {
      key
      value
    }
    discountCodes {
      applicable
      code
    }
  }

  fragment CartApiMoney on MoneyV2 {
    currencyCode
    amount
  }

  fragment CartApiImage on Image {
    id
    url
    altText
    width
    height
  }
`;
```

##### TypeScript

```jsx
const cart = createCartHandler({
  storefront,
  getCartId: cartGetIdDefault(request.headers),
  setCartId: cartSetIdDefault(),
  cartQueryFragment: CART_QUERY_FRAGMENT,
});

const CART_QUERY_FRAGMENT = `#graphql
  fragment CartApiQuery on Cart {
    id
    metafield(namespace: "custom", key: "gift") {
      value
    }
  }
`;
```

***

## Step 2: Create a metafield form

Use React Router's [`useFetcher`](https://reactrouter.com/api/hooks/useFetchers#usefetchers) hook to create a form that submits information that you want to store in a metafield. The hook submits a form request to the `/cart` route's action when users submit with this metafield form. You can use this component anywhere in the app.

When you use `fetcher.submit`, make sure there's a data key with the name `CartForm.INPUT_NAME`. The key value must be a JSON stringified object with `action` and `inputs` defined.

## File

## /app/components/ThisIsGift.jsx

##### JavaScript

```jsx
import {useFetcher} from '@react-router';
import {CartForm} from '@shopify/hydrogen';

export function ThisIsGift({metafield}) {
  const fetcher = useFetcher();

  return (
    <div>
      <input
        checked={metafield?.value === 'true'}
        type="checkbox"
        id="isGift"
        onChange={(event) = /> {
          fetcher.submit(
            {
              [CartForm.INPUT_NAME]: JSON.stringify({
                action: CartForm.ACTIONS.MetafieldsSet,
                inputs: {
                  metafields: [{
                    key: 'custom.gift',
                    type: 'boolean',
                    value: event.target.checked.toString(),
                  }],
                },
              }),
            },
            {method: 'POST', action: '/cart'}
          )
        }}
      />
      <label htmlFor="isGift">This is a gift</label>
    </div>
  );
}
```

##### TypeScript

```jsx
import {useFetcher} from '@react-router';
import {CartForm} from '@shopify/hydrogen';
import type {Cart} from '@shopify/hydrogen/storefront-api-types';

export function ThisIsGift({
  metafield,
}: {
  metafield: Cart['metafield'];
}) {
  const fetcher = useFetcher();

  return (
    <div>
      <input
        checked={metafield?.value === 'true'}
        type="checkbox"
        id="isGift"
        onChange={(event) = /> {
          fetcher.submit(
            {
              [CartForm.INPUT_NAME]: JSON.stringify({
                action: CartForm.ACTIONS.MetafieldsSet,
                inputs: {
                  metafields: [{
                    key: 'custom.gift',
                    type: 'boolean',
                    value: event.target.checked.toString(),
                  }],
                },
              }),
            },
            {method: 'POST', action: '/cart'}
          )
        }}
      />
      <label htmlFor="isGift">This is a gift</label>
    </div>
  );
}
```

***

## Step 3: Handle the update metafield form request

Handle the update metafield form request in an `action`. Use the `cart`, created from [`createCartHandler`](https://shopify.dev/docs/api/hydrogen/2026-04/utilities/cart/createcarthandler), to handle cart mutation requests to the Storefront API.

## File

## /app/routes/cart.jsx

##### JavaScript

```jsx
import {CartForm} from '@shopify/hydrogen';
import invariant from 'tiny-invariant';

export async function action({request, context}) {
  const {cart} = context;

  const formData = await request.formData();
  const {action, inputs} = CartForm.getFormInput(formData);

  let result;

  switch(action) {
    case CartForm.ACTIONS.MetafieldsSet:
      result = await cart.setMetafields(inputs.metafields);
      break;
    default:
      invariant(false, `${action} cart action is not defined`);
  }

  // The Cart ID might change after each mutation, so update it each time.
  const headers = cart.setCartId(result.cart.id);

  return json(
    result,
    {status: 200, headers},
  );
}
```

##### TypeScript

```jsx
import {
  type CartQueryData,
  CartForm,
} from '@shopify/hydrogen';
import invariant from 'tiny-invariant';

export async function action({request, context}: ActionArgs) {
  const {cart} = context;

  const formData = await request.formData();
  const {action, inputs} = CartForm.getFormInput(formData);

  let result: CartQueryData;

  switch(action) {
    case CartForm.ACTIONS.MetafieldsSet:
      result = await cart.setMetafields(inputs.metafields);
      break;
    default:
      invariant(false, `${action} cart action is not defined`);
  }

  // The Cart ID might change after each mutation, so update it each time.
  const headers = cart.setCartId(result.cart.id);

  return json(
    result,
    {status: 200, headers},
  );
}
```

***

## Next steps

* Learn how to [update buyer identity](https://shopify.dev/docs/storefronts/headless/legacy/hydrogen/cart/buyer-identity).

***
