# Working with `shopify.app.toml` files  `shopify.app.toml` files are used to manage your Shopify app configuration settings. For the full TOML schema and Shopify-specific settings, see [Shopify's app configuration documentation](https://shopify.dev/docs/apps/build/cli-for-apps/app-configuration). In framework `v1.7+`, Gadget automatically creates and manages the primary `shopify.app.toml` file for each environment. If your app uses an older framework version, see . ## Primary TOML files [Framework v1.7.0+](https://docs.gadget.dev/guides/gadget-framework)  In framework `v1.7+`, Gadget manages one primary TOML file for each development environment and one primary TOML file for production. For your production environment, the primary file is `shopify.app.toml`. Gadget will automatically update this production TOML file when a Shopify connection configuration is set in your production environment. For each development environment, Gadget creates a primary `shopify.app..toml` file when you add a Shopify connection configuration in the editor. These files include the Shopify app URLs, access scopes, and webhook subscriptions that Gadget manages for that environment: ```toml // in shopify..app.toml # Learn more about working with Shopify TOML files with Gadget at http://docs.gadget.dev/ client_id = "" name = "" application_url = "https://--.gadget.app/api/shopify/install-or-render" embedded = true [auth] redirect_urls = ["https://--.gadget.app/api/connections/auth/shopify/callback"] [access_scopes] scopes = "read_products,read_orders" [webhooks] api_version = "2024-10" [[webhooks.subscriptions]] topics = ["products/create", "products/update", "products/delete"] uri = "https://webhooks.gadget-services.net/shopify/v1?domain=--.gadget.app" [[webhooks.subscriptions]] compliance_topics = ["customers/data_request", "customers/redact", "shop/redact"] uri = "https://webhooks.gadget-services.net/shopify/v1?domain=--.gadget.app" ``` Gadget will automatically provide the correct values for the required URL and ID fields. ## Connecting a `shopify.app.toml` file to a Shopify app  By default, Gadget will manage `shopify.app.toml` files and you will not need to interact with them. If you are building Shopify extensions for your app, you will need to connect the correct `shopify.app.toml` to your Shopify app using `ggt` and the Shopify CLI. 1. Install and use [Gadget's CLI, ggt](https://docs.gadget.dev/reference/ggt#install-ggt), to pull your project down to your local machine. 2. Install the [Shopify CLI](https://shopify.dev/docs/api/shopify-cli#installation) locally and use it to sign in to your Shopify Partners account. 3. Run the `yarn shopify:config:use:` command to specify the `shopify.app.toml` file that should be used for your Shopify app: ```sh # for a development environment yarn shopify:config:use:development # for production environment yarn shopify:config:use:production ``` 4. Deploy your Shopify CLI app: ```sh yarn shopify:deploy:development # for production environment yarn shopify:deploy ``` 5. Connect to your existing Shopify app when prompted. ## Webhook subscriptions [Framework v1.7.0+](https://docs.gadget.dev/guides/gadget-framework)  In framework `v1.7+`, webhook subscriptions are defined in your TOML file as `[[webhooks.subscriptions]]` entries. Gadget automatically generates these entries when you enable Shopify models or configure Shopify webhook triggers on global actions in the editor. In `v1.7+` apps, which Shopify models are enabled is computed automatically from the model files in your current environment and the scopes in `[access_scopes]`. When you enable or disable models through the editor, Gadget updates the webhook subscriptions in this file to match. See the [1.7 migration guide](https://docs.gadget.dev/guides/gadget-framework/v1-7-migration#enabled-shopify-models-are-now-computed-automatically) for details. Each `[[webhooks.subscriptions]]` entry can include the following fields (see [Shopify's subscription configuration docs](https://shopify.dev/docs/apps/build/cli-for-apps/app-configuration#subscriptions) for full details): | Field | Description | | --- | --- | | `topics` | An array of Shopify webhook topics, such as `["products/create", "products/update"]` | | `uri` | The webhook delivery URI | | `compliance_topics` | An array of compliance/GDPR topics, such as `["customers/data_request", "customers/redact", "shop/redact"]` | | `filter` | A Shopify webhook filter string. Optional. | | `include_fields` | An array of fields to include in the webhook payload. Optional. | Webhook URIs in `v1.7+` apps use a centralized proxy format: ```markdown https://webhooks.gadget-services.net/shopify/v1/{optional-trigger-key}?domain={your-app-env-domain} ``` * For model webhooks without a `filter` or `include_fields`, the `{optional-trigger-key}` is omitted. These topics are grouped into the default `[[webhooks.subscriptions]]` entry that includes all standard data model topics. * For model webhooks with a `filter` or `include_fields`, and for global action webhooks, the `{optional-trigger-key}` matches the `triggerKey` defined in the action code. These get their own separate `[[webhooks.subscriptions]]` entry. Here is an example of a 1.7+ TOML file with webhook subscriptions: ```toml // in example shopify.app.toml with webhook subscriptions [webhooks] api_version = "2024-10" # Model webhook subscriptions (auto-generated for enabled models) [[webhooks.subscriptions]] topics = ["products/create", "products/update", "products/delete"] uri = "https://webhooks.gadget-services.net/shopify/v1?domain=my-app--development.gadget.app" # Model action webhook with filter and include_fields (linked via triggerKey) [[webhooks.subscriptions]] topics = ["products/update"] filter = "vendor:Nike" include_fields = ["id", "title", "vendor", "updated_at"] uri = "https://webhooks.gadget-services.net/shopify/v1/shopifyProduct-update?domain=my-app--development.gadget.app" # Global action webhook subscription (linked via triggerKey) [[webhooks.subscriptions]] topics = ["orders/create"] uri = "https://webhooks.gadget-services.net/shopify/v1/myGlobalAction?domain=my-app--development.gadget.app" # Compliance webhook subscription [[webhooks.subscriptions]] compliance_topics = ["customers/data_request", "customers/redact", "shop/redact"] uri = "https://webhooks.gadget-services.net/shopify/v1?domain=my-app--development.gadget.app" ``` You can also manually edit the `[[webhooks.subscriptions]]` entries in the TOML file. Changes made in the TOML file will be reflected in the Gadget editor on sync. Gadget does **not** automatically deploy your TOML file changes to Shopify. After editing your TOML file, you must run `shopify app deploy` using the Shopify CLI to push the changes to Shopify. For production environments, Gadget runs `shopify app deploy` automatically during deployment. Models with Shopify metafield fields, such as metaobjects, are an exception. Their webhooks are **not** managed through the TOML file. Instead, Gadget registers their webhooks per-shop using the Shopify GraphQL API. For these models, webhook configuration such as `shopifyFilter` and `includeFields` remains in action code, not in the TOML file. For more details on how webhook triggers work in `v1.7+` apps, see the [triggers guide](https://docs.gadget.dev/guides/actions/triggers) and the [working with Shopify webhooks guide](https://docs.gadget.dev/guides/plugins/shopify/shopify-webhooks). ### Webhook filtering  In framework `v1.7+`, webhook filters and include fields are configured directly in the TOML `[[webhooks.subscriptions]]` entries using the `filter` and `include_fields` fields. Gadget writes these automatically when you configure them through the editor. ```toml // in shopify.app.toml # Trigger key: shopifyProduct-update [[webhooks.subscriptions]] topics = ["products/update"] uri = "https://webhooks.gadget-services.net/shopify/v1/shopifyProduct-update?domain=my-app--development.gadget.app" filter = "vendor:Nike" include_fields = ["id", "title", "vendor", "updated_at"] ``` ## Multiple development environments  You will have a different primary TOML file for each environment. This means that if you are working on an app as a team, you may have multiple TOML files in your project. Each environment has its own primary TOML file, and you will also have a separate TOML file for your production app. You will usually have a separate primary TOML file for each development environment in your project. For example, you may have the following primary TOML files in a single app: ```markdown // in example of toml files in a single app shopify.app.toml // for your production environment's Shopify app shopify.app.development.toml // for your development environment shopify.app.carl-dev.toml // for a carl-dev development environment ``` In this setup, `shopify.app.toml` for production and `shopify.app..toml` for each development environment are the primary TOML files. To switch between environment configurations while building, you can use the Shopify CLI's [`shopify app config use` command](https://shopify.dev/docs/api/shopify-cli/app/app-config-use): ```bash // example of switching to a development environment yarn shopify:config:use:development ``` To see the current configuration, you can use the Shopify CLI's [`shopify app info` command](https://shopify.dev/docs/api/shopify-cli/app/app-info). ```bash // in get current configuration yarn shopify:info ``` ## Secondary TOML files  Secondary TOML files are additional `shopify.app.*.toml` files for the same environment that connect extra Shopify apps. Secondary TOML files are supported, but they are not the default workflow. Gadget manages the primary TOML file for each environment. You are responsible for keeping any secondary TOML files in sync and deploying them separately. This also applies to production. If you add multiple Shopify app configurations to production, Gadget will not automatically create or manage those extra TOML files for you. You need to create and manage them manually. | | Primary TOML | Secondary TOML | | --- | --- | --- | | **File path** | `shopify.app.toml` for production, or `shopify.app.{environment}.toml` for development environments | Any additional `shopify.app.*.toml` files | | **Managed by** | Gadget automatically manages scopes, subscriptions, and URLs | You must keep in sync manually | | **Identifying in editor** | Has a distinct file icon in the Gadget editor | Has a different file icon | | **App URL** | Points to your environment's primary Shopify app | Points to the secondary Shopify app, visible in the `application_url` field | | **Deploy** | Gadget runs `shopify app deploy` automatically during production deploys | You must run `shopify app deploy` manually for each secondary TOML | ## Pre-framework v1.7 behavior  If your app uses a framework version earlier than `v1.7`, the TOML workflow differs from the default behavior described above. ### TOML file management  Only newer Gadget apps automatically receive managed TOML files. Older Shopify apps may require you to create and maintain TOML files manually. ### Shopify-managed installs  Shopify-managed installs only applied to pre-framework `v1.7` apps. If your app still relies on that setup, upgrade to framework `v1.7+` instead of adding new Shopify-managed install configuration to an older TOML workflow. If you still need the older setup while migrating, see [Shopify App OAuth](https://docs.gadget.dev/guides/plugins/shopify/oauth#shopify-managed-installation-for-gadget-apps). ### Webhook subscriptions  Gadget manages [Shopify webhook subscriptions](https://docs.gadget.dev/guides/plugins/shopify/shopify-webhooks) automatically. You do not need to add or edit `[[webhooks.subscriptions]]` entries in the `shopify.app.toml` file. In pre-v1.7 apps, do not manually manage webhook subscriptions in the `shopify.app.toml` file. ### Webhook filtering  Webhook filters and include fields are configured in action code using the `shopifyFilter` and `includeFields` options, not in the `shopify.app.toml` file. For full details on filtering Shopify webhooks, see the [webhook filtering guide](https://docs.gadget.dev/guides/plugins/shopify/shopify-webhooks#filtering-shopify-webhooks). Previous versions of the `shopify.app.toml` file in Gadget apps included `include_config_on_deploy = false`. This prevented TOML settings from being pushed to Shopify when `shopify app deploy` was run using Shopify CLI, such as when deploying Shopify extensions. Shopify has deprecated this setting. All changes in a TOML file are now pushed to Shopify whenever `shopify app deploy` runs.