Finally, I found the solution.
Step1: Create metafield definition.
GraphQL mutation:
mutation CreateMetafieldDefinition($definition: MetafieldDefinitionInput!) {
metafieldDefinitionCreate(definition: $definition) {
createdDefinition {
id
key
name
namespace
}
userErrors {
field
message
code
}
}
}
Variables:
{
"definition": {
"name": "App Environment",
"namespace": "$app:<my-app-name>",
"key": "app_url",
"description": "Metadata used to store the app environment",
"access": {
"admin": "MERCHANT_READ",
"storefront": "PUBLIC_READ"
},
"type": "single_line_text_field",
"ownerType": "SHOP"
}
}
Step 2: Set metafields.
GraphQL mutation:
mutation MetafieldsSet($metafields: [MetafieldsSetInput!]!) {
metafieldsSet(metafields: $metafields) {
metafields {
id
key
namespace
value
createdAt
updatedAt
}
userErrors {
field
message
code
}
}
}
Variables:
{
"metafields": [
{
"key": "app_url",
"namespace": "$app:<my-app-name>",
"type": "single_line_text_field",
"value": "<server-url>",
"ownerId": "gid://shopify/Shop/<shop-id>"
}
]
}
Step 3: Get shop metafields using storefront API on customer account UI extension.
const response = await fetch(
`shopify://storefront/api/2025-01/graphql.json`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
query: `
query {
shop {
metafields(identifiers: [
{
namespace: "$app:<my-app-name>",
key: "app_url"
}
]) {
namespace
key
value
}
}
}
`,
}),
}
);
const { data } = await response.json();
const value = data.shop.metafields?.[0]?.value;