---
gid: b96be8d2-1a22-4aa7-850f-43de89c4d0de
title: Building metafield writes into extensions
description: Learn how to write to metafields from a Customer account UI extension.
---
import CustomerAccountUiCreate from 'app/views/partials/apps/customer-accounts/ui-extensions/create.mdx'
Writing to metafields directly from the [Customer Account API](/docs/api/customer) enables you to
store additional information about customers within Shopify, without making a separate call to
the [GraphQL Admin API](/docs/api/admin-graphql), a third-party server, or other external resource.
In this tutorial, you'll create a **Profile** page extension that will enable a merchant
to collect a customer’s preferred nickname and pass that input into a metafield.
## Limitations
Metafield writes are only supported on the [`Customer`](/docs/api/customer/latest/objects/Customer), [`Order`](/docs/api/customer/latest/objects/Order), [`Company`](/docs/api/customer/latest/objects/Company), and [`CompanyLocation`](/docs/api/customer/latest/objects/CompanyLocation) objects. Metafield writes are available as of the `2024-07` version of the Customer Account API.
## What you'll learn
In this tutorial, you'll learn how to do the following tasks:
- Use the GraphQL Admin API to create a metafield definition with permissions to read and write to metafields using the [Customer Account API](/docs/api/customer).
- Create an extension that’s rendered on the customer account **Profile** page.
- Use the Customer Account API to write data to a metafield.
The development store should be pre-populated with test data.
Scaffold an app that uses Shopify CLI. This tutorial is compatible with the [Remix template](/docs/apps/build/build?framework=remix).
The Customer Account API requires access to Level 1 Protected Customer Data. [Request access](/docs/apps/launch/protected-customer-data#request-access-to-protected-customer-data) for your app.
### Create a customer account UI extension
### Configure access scopes for your app
In your app’s `shopify.app.toml` file, include the required [access scopes](/docs/apps/build/cli-for-apps/app-configuration#access_scopes). The example code needs the `write_customers` access scope to create a metafield definition on the `CUSTOMER` resource with the GraphQL Admin API.
To read or write metafields on the `CUSTOMER` resource using the Customer Account API, the `customer_read_customers` and `customer_write_customers` scopes will be required.
After updating the `shopify.app.toml` file, deploy the scope changes to your app:
```bash
shopify app deploy
```
### Create the metafield definition
Use the GraphQL Admin API to create a metafield definition with write permissions for the Customer Account API.
The GraphQL Admin API access scope corresponding to the object the metafield is defined on is required to create the metafield definition.
In our example, the `write_customer` scope is required to define a metafield on the `Customer` object. The `write_orders` scope is required to define a metafield on the `Order` object.
To create a new metafield definition on app installation, use the `afterAuth` hook that the Remix template provides.
Begin by checking if a metafield definition exists on the object with a matching key and namespace.
The `AdminApiContext` and `ShopifyRestResources` used in the `getMetafield` function need to be imported.
If there's no existing metafield definition, use the GraphQL Admin API's [`metafieldDefinitionCreate`](/docs/api/admin-graphql/latest/mutations/metafieldDefinitionCreate) mutation to create it.
### Set up the targets for your extension
Set up the targets for your customer account UI extension. [Targets](/docs/api/customer-account-ui-extensions/latest/targets) control where your extension renders in the customer account flow.
You'll use a [block extension target](/docs/api/customer-account-ui-extensions/latest/extension-targets-overview#block-extension-targets) to render a card on the **Profile** page and to render a modal when the button is clicked.
#### Reference the targets in your configuration file
This example code uses the [`customer-account.profile.block.render`](/docs/api/customer-account-ui-extensions/latest/targets/profile-(default)/customer-account-profile-block-render) target
In your extension's [`shopify.extension.toml`](/docs/apps/build/app-extensions/configure-app-extensions) configuration file, create an `[[extensions.targeting]]` section with the **`target`**, an identifier that specifies where you're injecting code into Shopify, and **`module`**, the path to the file that contains the extension code.
---
Whenever you edit your extension configuration file, you need to restart your server for the changes to take effect.
#### Create files for your targets
Create files in your extension's `src` directory for each of your targets.
In this example, you'll create a file for the **Profile** page extension. The filenames must match the `module` [paths you specified](#reference-the-targets-in-your-configuration-file).
### Build the **Profile** page extension
Use [checkout](https://shopify.dev/docs/api/checkout-ui-extensions/latest/components) and [customer account](/docs/api/customer-account-ui-extensions/latest/components) extension UI components to build the UI of your extension.
In this example, a new [`Card`](/docs/api/customer-account-ui-extensions/latest/components/card) component is added to the **Profile** page.
The card displays the current nickname. A [`Button`](/docs/api/checkout-ui-extensions/latest/components/actions/button) component is rendered that opens a [`Modal`](/docs/api/checkout-ui-extensions/latest/components/overlays/modal) component where a customer can update their nickname. The modal contains a [`TextField`](/docs/api/checkout-ui-extensions/latest/components/forms/textfield) component where the user can input their new nickname.
Fetch the customer's nickname metafield value by querying the Customer Account API. Display the returned nickname value in the card.
[Localization](/docs/apps/build/customer-accounts/localization) can be used to translate the UI of your extension into multiple languages.
In this example, English is the default locale by including `en.default.json` in the `locales`.
In our example, French is also supported by providing an `fr.json` file in the `locales` directory.
### Write the user input to your metafield
Make a request to the [`metafieldsSet`](/docs/api/customer/latest/mutations/metafieldsSet) mutation to write the user input to the metafield.
Pass the [previously defined](#create-the-metafield-definition) `key` and `namespace` to the `metafieldsSet` mutation to identify the metafield you want to update.
The `ownerId` is the ID of the object whose metafield you want to update. In this example, it is the ID of the current customer.
In this case, the `value` is the new nickname that the customer has inputted.
### Preview the extension
Use the Shopify CLI to preview your extension to make sure that it works as expected.
1. In a terminal, navigate to your app directory.
2. Either start or restart your server to build and preview your app
```bash
shopify app dev
```
3. If prompted, select a development store.
4. Once started, press `p` or navigate to the preview or follow the preview link in the developer console.
5. Click on the **Install your app** link to install the app on your development store.
6. In the developer console page, click the preview link for your extension target.
7. You will be prompted to log in to customer accounts. Once logged in, you will see your extension on the **Profile** page.
8. Click the edit icon in the `Preferences` card to open the modal and update the nickname metafield value.
You can use a different [placement reference](/docs/apps/build/customer-accounts/test#block-targets) to preview the block target in different locations on the **Profile** page.
##### Extension not rendering
Ensure that your app is installed on the development store you're testing with.
Check your browser's developer console for any errors that might be preventing the extension from rendering.
##### Metafield not updating
If the metafield value isn't being properly persisted, for example if the value that you specified isn't being saved after a page reload, do the following:
- Ensure that the `namespace` and `key` used to [create the metafield definition](#create-the-metafield-definition) match the values being used in the `metafieldsSet` [mutation](#write-the-user-input-to-your-metafield).
- Check your network traffic for the response to the `metafieldsSet` mutation. The response will contain a `userErrors` field that will provide more information about what went wrong.
- If you changed access scopes in your `shopify.app.toml` file after installing the app, then deploy the new scopes by calling `shopify app deploy` and follow the app installation link again.
- If the metafield definition wasn't created properly, then you can force the re-creation by uninstalling the app, deleting the `/prisma/dev.sqlite` file, and reinstalling the app.
## Tutorial complete!
Nice work - what you just built could be used by Shopify merchants around the world! Keep the momentum going with these related tutorials and resources.
### Next Steps
#### Working with metafields
Explore methods for adding and storing custom data about a Shopify resource with metafields.
#### Extension placement
Explore extension placement options and make informed decisions on where to position them.
#### Localize your extension
Learn about localizing your customer account UI extensions for international merchants and customers.
#### Extension targets
Learn about the extension targets offered in customer account.
#### Customer account components
Learn about the components you can use to build customer account UI extensions.
#### Checkout components
Learn about the checkout components you can use to build customer account UI extensions.
#### UX guidelines
Follow our UX guidelines for customer accounts to ensure a consistent and satisfying user experience.
#### Figma UI kit
Explore Figma components for checkout and account UI extensions.