To make your code reusable, you can replace hard-coded variables in your function with metafield values. Using [metafields](/docs/apps/build/custom-data/metafields) enables merchants and staff to customize your function by entering values and options in interfaces provided by your app. This guide introduces how input queries and metafields work in Shopify Functions. For an overview of how data is input to and output from Shopify Functions, refer to [Function input and output](/docs/apps/build/functions/input-output). ## How it works Shopify Functions belong to and can affect the behavior of objects in the Shopify data model. The object associated with a function is known as the **function owner**. For example, the owner of a Discount API function is a discount. You use an [Admin UI extension](/docs/api/admin-extensions) or [embedded app page](/docs/apps/build/app-surfaces#embedded-app-pages) to create merchant interfaces for managing function owners and their metafields. Refer to the [available APIs documentation](/docs/api/functions#apis-in-developer-preview) for specifics on what's supported by each Function API. Then, you use input queries to provide the metafields as input to your function. <figure class="figure"><img src="https://cdn.shopify.com/shopifycloud/shopify_dev/assets/api/functions/configuration-53208a7caa27c8a1b343dc26a1b94f942345f69b312b02af43ed6c43150ffdfe.png" class="lazyload" alt="A diagram showing the relationship between a function, an app, and metafields, as used when configuring functions" width="65%" height="1632"></figure> > Tip: > You can also use metafield values from anywhere within Shopify's data model to build your function's logic. For example, you can use metafields on products in the cart or the current customer. ## Creating your merchant interface Some Function APIs enable you to create a merchant interface for configuring your function using either [embedded app pages](/docs/apps/build/app-surfaces#embedded-app-pages) or [Admin UI extensions](/docs/api/admin-extensions). Refer to the [available APIs documentation](/docs/api/functions#apis-in-developer-preview) for specifics on what's supported by each Function API. You need to configure specific properties in your [function extension configuration](/docs/api/functions/configuration) based on the method that you use for creating a merchant interface. ### Using Admin UI extensions Some Function APIs enable you to create a merchant interface to create and edit the function owner using [Admin UI extensions](/docs/api/admin-extensions). To configure a UI extension to be used for configuring your function, you must specify the `extension.ui.handle` property in your `shopify.extension.toml` file. Ensure that the value for `extension.ui.handle` matches the handle property of the corresponding UI extension in your app. The following example shows the properties in the `shopify.extension.toml` file: <p> <div class="react-code-block" data-preset="file"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar "></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script data-option="filename" data-value="shopify.extension.toml"></script> <script type="text/plain" data-language="toml"> RAW_MD_CONTENT[extension.ui] handle = "ui-extension-handle" END_RAW_MD_CONTENT</script> </div> </p> ### Using embedded app pages Some Function APIs enable you to create a merchant interface using [embedded app pages](/docs/apps/build/app-surfaces#embedded-app-pages). Use [App Bridge](/docs/api/app-bridge) and [Polaris](https://polaris.shopify.com/) to create a seamless merchant experience within the Shopify admin. You have the option to configure the routes in your application that merchants will use to create and edit the function owner, such as a discount. The default path for both properties is the root directory of your app (`/`). | Property | Description | Example | |---|---|---| | `ui.paths.create` | The route to create a new function owner. | `/my-discount-type` | | `ui.paths.details`| The route to edit the function owner. | `/my-discount-type/:id` | The following example shows the properties in the `shopify.extension.toml` file: <p> <div class="react-code-block" data-preset="file"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar "></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script data-option="filename" data-value="shopify.extension.toml"></script> <script type="text/plain" data-language="toml"> RAW_MD_CONTENT[extensions.ui.paths] create = "/my-discount-type/:functionId" details = "/my-discount-type/:functionId/:id" END_RAW_MD_CONTENT</script> </div> </p> #### Dynamic ID values If you specify the `:id` or `:functionId` in the `ui.paths` properties in `shopify.extension.toml`, then the URL is updated with the following values: | URL Path | Update | Availability | |---|---|---| | `:id` | The `:id` is dynamically replaced by the ID of the function owner. | `ui.paths.details` | | `:functionId`| The `:functionId` is dynamically replaced by the ID of the function. | `ui.paths.create` and `ui.paths.details` | The ID values are needed as input to the create, update, and delete mutations for your customizations. By using dynamic IDs, you can avoid managing hardcoded values in your app. ### Creating Metafields with GraphQL You can use the [GraphQL Admin API](/docs/api/admin-graphql) to create and update your function owner and its metafields. [Metafields](/docs/apps/build/custom-data/metafields) are supported on all function owner types, and can be used to store custom values for your function logic. The following is an example of a mutation that would set metafields on a discount function owner, when implementing a Discount API function. <p> <div class="react-code-block" data-preset="file"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar "></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script data-option="filename" data-value="set-metafields.graphql"></script> <script type="text/plain" data-language="graphql"> RAW_MD_CONTENTmutation CreateDiscount { discountAutomaticAppCreate(automaticAppDiscount: { functionId: "f0c17828-da1a-4748-810d-3c3cab2bc977", title: "My Discount", startsAt: "2022-06-01T00:00:00Z", metafields: [ { namespace: "$app:my-function", type: "json", key: "function-configuration", value: "{\"value\":\"42\"}" } ] }) { automaticAppDiscount { discountId } userErrors { field message } } } END_RAW_MD_CONTENT</script> </div> </p> ### Configuring creation workflows for function owners There are some cases where you might not want the merchant to create a function owner themselves. For example, the function could be an implementation detail of a bigger feature and it could make more sense for the bigger feature to manage the function owner lifecycle. You can configure the function to opt-out of the default function owner creation workflow. This means that the app will solely be responsible for creating the function owner. While this means the merchant can't create a function owner in the Shopify admin, they can still edit, activate, or deactivate one created by the app. You can configure this with the following property in your [function extension configuration](/docs/api/functions/configuration). | Property | Description | Type | |---|---|---| | `ui.enable_create` | Whether the merchant can create a function owner in the Shopify admin. The default value is `true`. | Boolean | ## Reading metafields with input queries All [Function APIs](/docs/api/functions) provide access to the function owner, and its metafields, as part of their GraphQL schema. This means that you can access the metafield values set by merchants using input queries, and use those values in your function's logic. The following is an example of an input query that would retrieve a metafield on a discount function owner, when implementing a Discount API function. <p> <div class="react-code-block" data-preset="file"> <div class="react-code-block-preload ThemeMode-dim"> <div class="react-code-block-preload-bar "></div> <div class="react-code-block-preload-placeholder-container"> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> <div class="react-code-block-preload-code-container"> <div class="react-code-block-preload-codeline-number"></div> <div class="react-code-block-preload-codeline"></div> </div> </div> </div> <script data-option="filename" data-value="src/run.graphql"></script> <script type="text/plain" data-language="graphql"> RAW_MD_CONTENT{ discountNode { metafield(namespace: "$app:my-function", key: "function-configuration") { value } } } END_RAW_MD_CONTENT</script> </div> </p> ## Best practices This section provides some best practices for using metafields for function input. ### Use a reserved prefix in your metafield namespace You should use a [reserved prefix](/docs/apps/build/custom-data/ownership#reserved-prefixes) in your metafield namespace, so that other apps can't use your metafields. ### Use JSON metafields for complex configurations Metafields support many [types of data](/docs/apps/build/custom-data/metafields/list-of-data-types), but functions will often require nested and/or repeating data structures. Using a single JSON metafield can simplify the management and querying of your configuration. ### Manage configuration changes with new metafields If you need to make breaking changes to your function configuration data, then you can implement the [Parallel Change (Expand and Contract)](https://martinfowler.com/bliki/ParallelChange.html) pattern using additional metafields: 1. Update your function's logic to simultaneously read configuration from your existing and new metafields, preferring the newer data, if present. 2. Change your function UI to simultaneously update both your existing and new metafields. 3. Use the GraphQL Admin API to [migrate existing data](/docs/apps/build/custom-data/metafields/manage-metafields) from your old metafields to your new metafields. 4. After you've finished the migration, remove any UI and function logic for your old metafields. 5. Use the GraphQL Admin API to remove your old metafields. > Tip: > To edit metafields outside of a merchant's web session, such as in an offline maintenance job, you can request an [offline access token](/docs/apps/build/authentication-authorization/access-tokens/offline-access-tokens) during app installation. ## Next steps - Learn how to [use variables in input queries](/docs/apps/build/functions/input-output/use-variables-input-queries) with Shopify Functions.