# Non-webhook fields and models [Framework v1.6.0+](https://docs.gadget.dev/guides/gadget-framework)  Some fields on Shopify models are **non-webhook**: they are not included in Shopify webhook payloads. This means they need to be manually fetched using Shopify's GraphQL API. Your Shopify models and fields can be configured to automatically fetch these fields on incoming webhooks. These non-webhook fields are also populated during a Shopify [data sync](https://docs.gadget.dev/guides/plugins/shopify/syncing-shopify-data) or [nightly reconciliation](https://docs.gadget.dev/guides/plugins/shopify/shopify-webhooks#reconciliation-of-webhooks). Webhook-only field configuration is only available if your Shopify connection uses Shopify API version `2025-04` or greater. ## Fetch on webhook vs fetch later  Each non-webhook field on a model that receives webhooks can be configured as follows: * **Fetch on webhook**: When a webhook is received for that model, Gadget fetches the full data for that field from the Shopify API and updates the record. The field is populated as soon as the webhook is processed. * **Fetch later**: This is the default for new apps. The field is not fetched when the webhook is processed. It remains `null` or unchanged until the next sync or reconciliation. You can change this per field: open the field configuration for a non-webhook field on a webhook-enabled model and choose whether to fetch on webhook or fetch later. ### Rate limits and request time  When you set a non-webhook field to fetch on webhook, Gadget makes one or more requests to the Shopify API for each webhook that affects that model. For example, has many fields require paginating through queries to fetch all related child data, so a single webhook can trigger multiple API calls. Consider the following: * **Shopify API rate limits**: Each request counts against your app's Shopify API rate limit. High-volume webhooks, such as orders or products, with many non-webhook fields set to fetch on webhook can potentially consume a lot of your available rate limit. This is especially true when has many fields require multiple paginated requests per webhook. * **Gadget request time**: Fetching on webhook uses request time on Gadget while the API calls run. If you enable fetch on webhook for many fields or on high-traffic models, webhook processing can take longer and use more of your plan's request time. Use **fetch later** for non-webhook fields when you do not need the data immediately. The nightly reconciliation will populate them without adding per-webhook API calls. ## Adding non-webhook fields  For new apps, only fields included in Shopify webhook payloads are added to models by default. Non-webhook fields are not added automatically. To add non-webhook fields to a model: 1. Open the model in the Gadget editor. 2. Use the **Add fields** dropdown to add the non-webhook fields you need. 3. For each non-webhook field, configure whether to **fetch on webhook** or **fetch later**. ### Available non-webhook fields  | Model Name | Fields | | --- | --- | | Shopify Company | `Contact Count``Contacts Count``Orders Count``Locations Count``Default Role``Lifetime Duration``Main Contact``Total Spent``Contact Roles``Contact Role Assignments` | | Shopify Company Address | `Company Name``Formatted Address``Formatted Area` | | Shopify Company Contact | `Customer``Is Main Contact``Lifetime Duration` | | Shopify Company Location | `Orders Count``Currency``Timeline Comment``Market``Tax Registration ID``Total Spent``Role Assignments` | | Shopify Company Contact Role | `Name``Note` | | Shopify Company Contact Role Assignment | `Company``Company Contact``Role` | | Shopify App Purchase One Time | `Shopify Created At``Name``Price``Status``Test` | | Shopify App Subscription | `Shopify Created At``Current Period End``Name``Return Url``Status``Test``Trial Days``Line Items` | | Shopify Asset | `Checksum``Content Type``Key``Shopify Created At``Shopify Updated At``Size` | | Shopify Bulk Operation | `File Size``Object Count``Partial Data URL``Query``Root Object Count``URL` | | Shopify Company Location Catalog | `Catalog` | | Shopify Checkout Applied Gift Card | `Amount Used``Balance``Last Characters` | | Shopify Checkout | `Discount Code``Applied Discount``Credit Card``Legal Notice URL``Order``Order Status URL``Payment Due``Payment URL``Payments``Privacy Policy URL``Refund Policy URL``Requires Shipping``Reservation Time``Reservation Time Left``Shipping Policy URL``Shipping Rate``Shopify Payments Account ID``Subscription Policy URL``Tax Exempt``Tax Manipulations``Terms Of Sale URL``Terms Of Service URL``Total Tip Received``Web URL` | | Shopify Checkout Shipping Rate | `Handle``Price``Title` | | Shopify Collection | `Description``Feedback``Legacy Resource Id``Products Count``SEO` | | Shopify Collect | `Product` | | Shopify Customer Address | `Coordinates Validated``Formatted``Formatted Area``Latitude``Longitude``Timezone``Validation Result Summary` | | Shopify Customer Mergeable | `Is Mergeable``Reason``Error Fields``Merge In Progress` | | Shopify Customer | `Customer Store Credit Accounts``Accepts Marketing``Accepts Marketing Updated At``Last Order``Last Order Name``Marketing Opt In Level``Number Of Orders``Payment Methods``Tags``Email Marketing Consent``SMS Marketing Consent``Statistics``Mergeable``Locale``Amount Spent``Can Delete``Display Name``Legacy Resource Id``Lifetime Duration``Market``Product Subscriber Status``Unsubscribe Url``Valid Email Address``Has Timeline Comment``Data Sale Opt Out` | | Shopify Customer Payment Method | `Revoked Reason``Revoked At``Subscription Contracts` | | Shopify Discount | `Applies On Subscription``Applies On One Time Purchase``Recurring Cycle Limit``Codes Count``Combines With``Discount Class``Ends At``Starts At``Async Usage Count``Short Summary``Summary``Minimum Requirement``Has Timeline Comment``Total Sales``Destination Selection``Maximum Shipping Price``Type``Customer Gets``Customer Buys``Codes``Discount ID``App Discount Type``Error History``Uses Per Order Limit``Applies Once Per Customer``Shareable URLs``Usage Limit` | | Shopify Discount Redeem Code | `Code``Async Usage Count``Created By` | | Shopify Discount Customer Gets Product | `Product` | | Shopify Discount Customer Buys Product | `Product` | | Shopify Discount Customer Gets Product Variant | `Product Variant` | | Shopify Discount Customer Buys Product Variant | `Product Variant` | | Shopify Discount Customer Gets Collection | `Collection` | | Shopify Discount Customer Buys Collection | `Collection` | | Shopify Dispute | `Dispute Evidence``Amount Set``Reason Details` | | Shopify Dispute Evidence | `Shipping Address``Billing Address``Customer Email Address``Customer First Name``Customer Last Name``Product Description``Uncategorized Text``Submitted By Merchant On``Fulfillments``Cancellation Policy File``Customer Communication File``Refund Policy File``Service Documentation File``Shipping Documentation File``Uncategorized File` | | Shopify Dispute File Upload | `Dispute Evidence Type``File Size``File Type``Original File Name``URL` | | Shopify Dispute Evidence Fulfillment | `Shipping Date``Shipping Tracking Number``Shipping Carrier``Dispute Evidence` | | Shopify Domain | `URL` | | Shopify Draft Order | `Discount Codes``Accept Automatic Discounts``Allow Discount Codes In Checkout``Warnings``Billing Address Matches Shipping Address``Default Cursor``Has Timeline Comment``Invoice Email Template Subject``Legacy Resource Id``Line Items Subtotal Price``Market Name``Market Region Country Code``Phone``Platform Discounts``PO Number``Presentment Currency Code``Ready``Reserve Inventory Until``Subtotal Price Set``Total Discounts Set``Total Price Set``Total Line Items Price Set``Total Quantity Of Line Items``Total Shipping Price Set``Total Tax Set``Total Weight``Transformer Fingerprint``Visible to Customer``Purchasing Company``Purchasing Company Contact``Purchasing Company Location``Purchasing Entity``Tax Exemptions` | | Shopify Draft Order Line Item | `Approximate Discounted Unit Price Set``Bundle Components``Discounted Total Set``Fulfillment Service Handle``Original Total Set``Original Unit Price Set``Original Unit Price With Currency``UUID``Custom Attributes``Custom Attributes V2``Weight` | | Shopify Draft Order Platform Discount | `Allocations``Automatic Discount``Bxgy Discount``Code``discountClass``Presentation Level``Short Summary``Summary``title``Total Amount``Total Amount Price Set` | | Shopify Draft Order Platform Discount Allocation | `Draft Order Platform Discount``Quantity``Reduction Amount``Reduction Amount Set``Target` | | Shopify Duty | `Country Code Of Origin``Harmonized System Code``Tax Lines``Price Set` | | Shopify Fulfillment | `Display Status``Delivered At``Estimated Delivery At``In Transit At``Requires Shipping``Total Quantity``Tracking Info` | | Shopify Fulfillment Line Item | `Admin GraphQL API ID` | | Shopify Fulfillment Order | `Assigned Location``Delivery Method``Destination``Fulfill At``Fulfillment Holds``International Duties``Fulfillment Order Line Items``Merchant Requests``Order``Request Status``Supported Actions``Fulfill By``Shopify Created At``Shopify Updated At``Location``Order Name``Order Processed At` | | Shopify Fulfillment Order Line Item | `Order Line Item``Remaining Quantity``Quantity``Inventory Item``Variant``Image``Financial Summaries``Product Title``Requires Shipping``SKU``Variant Title``Vendor``Warnings``Weight` | | Shopify Fulfillment Order Destination | `Address 1``Address 2``City``Company``Country Code``Email``First Name``Last Name``Location``Phone``Province``Zip` | | Shopify Delivery Method | `Additional Information``Branded Promise``Max Delivery DateTime``Min Delivery DateTime``Method Type``Presented Name``Service Code``Source Reference` | | Shopify Fulfillment Order Merchant Request | `Kind``Message``Request Options``Response Data``Sent At` | | Shopify Fulfillment Hold | `Display Reason``Reason``Reason Notes``Handle``Held By App``Held By Requesting App` | | Shopify Inventory Item | `Product Variant``Duplicate Sku Count``Legacy Resource Id``Tracked Editable``Unit Cost``Inventory History Url``Measurement``Locations Count` | | Shopify Inventory Level | `Shopify Created At``Can Deactivate``Deactivation Alert``Quantities` | | Shopify Inventory Quantity | `Admin GraphQL API ID``Name``Quantity``Shopify Updated At` | | Shopify Location | `Activatable``Address Verified``Deactivatable``Deactivated At``Deletable``Fulfills Online Orders``Has Active Inventory``Has Unfulfilled Orders``Legacy Resource Id``Local Pickup Settings V2``Ships Inventory``Suggested Addresses` | | Shopify Market | `Regions``Market Web Presences``Currency Settings``Enabled``Primary` | | Shopify Market Region | `Name``Code` | | Shopify Market Web Presence | `Alternate Locales``Domain``Root URLs``Subfolder Suffix` | | Shopify Market Catalog | `Catalog` | | Shopify Order | `Processing Method``Transactions``Additional Fees``Purchasing Entity``Purchasing Company Contact``Cancellation``Shopify Protect``Payment Terms``Risk``Retail Location``Fulfillments Count``Transactions Count``Total Cash Rounding Adjustment``Business Entity``Billing Status Matches Shipping Address``Alerts``Can Mark As Paid``Can Notify Customer``Capturable``Cart Discount Amount Set``Closed``Current Cart Discount Amount Set``Current Subtotal Line Items Quantity``Current Total Weight``Edited``Fulfillable``Fully Paid``Has Timeline Comment``Legacy Resource Id``Merchant Editable``Merchant Editable Errors``Net Payment Set``Original Total Price Set``Refundable``Refund Discrepency Set``Requires Shipping``Restockable``Return Status``Total Capturable Set``Total Outstanding Set``Total Received Set``Total Refunded Set``Total Refunded Shipping Set``Total Tip Received Set``Unpaid``Customer Journey Summary` | | Shopify Order Line Item | `Discounted Total Set``Discounted Unit Price After All Discounts Set``Discounted Unit Price Set``Original Total Set``Unfulfilled Discounted Total Set``Unfulfilled Original Total Set``Merchant Editable``Non Fulfillable Quantity``Refundable Quantity``Restockable``Unfulfilled Quantity` | | Shopify Order Transaction | `Location``Authorization Expires At``Refund``Multicapturable``Account Number``Amount Rounding Set``Amount Set``Formatted Gateway``Manually Capturable``Maximum Refundable V2``Settlement Currency``Settlement Currency Rate``Shopify Payments Set` | | Shopify Payment Terms | `Order``Draft Order``Overdue``Translated Name` | | Shopify Payment Schedule | `Due``Expected Payment Method` | | Shopify Product | `SEO``Product Category``Compare At Price Range` | | Shopify Product Variant | `Tax Code``Available For Sale``Selected Options``Presentment Prices` | | Shopify Refund Duty | `Original Duty``Amount Set` | | Shopify Refund | `Shopify Updated At``Total Refunded Set` | | Shopify Refund Line Item | `Price Set` | | Shopify Return | `Name``Decline``Status``Order``Return Line Items``Exchange Line Items``Return Shipping Fees``Total Quantity``Total Exchange Line Items``Refunds``Reverse Fulfillment Orders` | | Shopify Return Shipping Fee | `Amount Set` | | Shopify Exchange Line Item | `Order Line Item` | | Shopify Reverse Fulfillment Order | `Reverse Fulfillment Order Line Items``Order``Reverse Deliveries``Status``Third Party Confirmation Status` | | Shopify Reverse Fulfillment Order Line Item | `Fulfillment Line Item``Dispositions``Reverse Fulfillment Order` | | Shopify Reverse Fulfillment Order Disposition | `Quantity``Type``Location` | | Shopify Reverse Delivery | `Deliverable``Reverse Delivery Line Items``Reverse Fulfillment Order` | | Shopify Reverse Delivery Line Item | `Quantity``Dispositions``Reverse Fulfillment Order Line Item``Reverse Delivery` | | Shopify Return Line Item | `Return Reason``Return Reason Definition``Customer Note``Quantity``Refundable Quantity``Refunded Quantity``Return Reason Note` | | Shopify Shipping Line | `Delivery Category``Custom``Shipping Rate Handle` | | Shopify Shop | `Billing Address``Shop Address``Plan``Plan Public Display Name``Alerts``Countries In Shipping Zones``Currency Formats``Customer Accounts``Description``Order Number Format Prefix``Order Number Format Suffix``Resource Limits``Rich Text Editor Url``Ships To Countries``Timezone Abbreviation``Timezone Offset``Timezone Offset Minutes``Unit System``Url``Customer Accounts V2` | | Shopify Selling Plan Group | `Shopify Created At` | | Shopify Selling Plan | `Category``Inventory Policy``Shopify Created At` | | Shopify Store Credit Account | `Company Location``Balance` | | Shopify Subscription Billing Attempt | `Origin Time``Completed At``Next Action URL``Shopify Created At` | | Shopify Subscription Contract | `Last Billing Attempt Error Type``Delivery Method``App``App Admin URL``Billing Attempts``Customer Payment Method``Delivery Price``Discounts``Last Payment Status``Lines``Next Billing Date``Note``Orders``Origin Order``Shopify Created At``Shopify Updated At` | | Shopify Subscription Line | `Current Price``Custom Attributes``Discount Allocations``Admin GraphQL API ID``Line Discounted Price``Subscription Pricing Policy``Quantity``Requires Shipping``Selling Plan``SKU``Taxable``Title``Variant` | | Shopify Subscription Manual Discount | `Admin GraphQL API ID``Entitled Lines``Recurring Cycle Limit``Rejection Reason``Target Type``Title``Type``Usage Count``Value` | | Shopify Tender Transaction | `Amount Set` | | Shopify Theme | `Assets``Prefix``Processing Failed` | ## Upgrading an existing app  When you upgrade, existing non-webhook fields configured to fetch on webhook will continue to do so. You can reconfigure these fields at any time: open the field configuration in the Gadget editor and choose **fetch on webhook** or **fetch later** for each non-webhook field. You can also edit the [model's `schema.gadget.ts` file](https://docs.gadget.dev/reference/metadata-files#shopify-configuration) locally by setting `fetchData: "onWebhook"` or `fetchData: "later"` on a field's Shopify config: ```typescript export const schema: GadgetModel = { type: "gadget/model-schema/v1", storageKey: "DataModel-Shopify-Product", fields: { // fetch the seo field on product webhooks seo: { fetchData: "onWebhook", }, }, }; ``` In schema files, `fetchData: "later"` is the default for non-webhook fields. Gadget only writes `fetchData` config when you choose **fetch on webhook**, so fields using the default behavior may not show a `fetchData` setting in `schema.gadget.ts`. Examining your app's `schema.gadget.ts` file is the recommended way to configure fetch behaviour for non-webhook fields. To confirm which fields fetch on webhook after an upgrade, search your `schema.gadget.ts` files for `onWebhook`. Gadget preserves your app's behavior when upgrading to framework v1.6.0 by keeping the existing, under-the-hood default behavior. ## Reacting to fetch later fields in action code  Fields set to **fetch later** are only populated during a [sync](https://docs.gadget.dev/guides/plugins/shopify/syncing-shopify-data) or [nightly reconciliation](https://docs.gadget.dev/guides/plugins/shopify/shopify-webhooks#reconciliation-of-webhooks). Use the following patterns in your action code to detect and respond to those updates. Check `trigger.type` to run code only when the update came from a sync or reconciliation: ```typescript export const onSuccess: ActionOnSuccess = async ({ trigger }) => { if ( trigger.type === "shopify_sync" || trigger.type === "shopify_webhook_reconciliation" ) { // do something with a non-webhook field } }; ``` Use `record.changed()` to run code only when a specific field was updated: ```typescript export const onSuccess: ActionOnSuccess = async ({ api, record, params, logger, }) => { if (record.changed("someField")) { // This code will run when someField is updated during a sync logger.info(`someField was updated to: ${record.someField}`); } }; ``` ## Conditionally webhook-synced models  Some Shopify models do not have their own webhook topics but can be configured to sync when a parent model's webhook runs. We call these **conditionally webhook-synced** models. When the parent model receives webhooks and has a has many relationship to such a child model, you can configure that has many field to fetch on webhook. When enabled, child records are created or updated whenever the parent's webhook is processed. For example, `ShopifyInventoryQuantity` is a non-webhook model. It is related to `ShopifyInventoryLevel`, which receives webhooks, with the `quantities` field, so that `ShopifyInventoryLevel` has many `ShopifyInventoryQuantity`. When you enable **fetch on webhook** for the `quantities` field on `ShopifyInventoryLevel`, each inventory level webhook will create or update the related `ShopifyInventoryQuantity` records. The following table lists conditionally webhook synced models. For each, configure **fetch on webhook** for the given field on the parent model to sync the child when the parent's webhook is processed. | Model | Parent model | Field on parent (configure fetch on webhook) | | --- | --- | --- | | `Shopify Asset` | `Shopify Theme` | `assets` | | `Shopify Checkout Shipping Rate` | `Shopify Checkout` | `shippingRate` | | `Shopify Collect` | `Shopify Collection` | `products` | | `Shopify Company Contact Role` | `Shopify Company` | `contactRoles` | | `Shopify Company Contact Role Assignment` | `Shopify Company Location` | `roleAssignments` | | `Shopify Company Location Catalog` | `Shopify Company Location` | `catalogs` | | `Shopify Customer Mergeable` | `Shopify Customer` | `mergeable` | | `Shopify Delivery Method` | `Shopify Fulfillment Order` | `deliveryMethod` | | `Shopify Discount Customer Buys Collection` | `Shopify Discount` | `customerBuysCollections` | | `Shopify Discount Customer Buys Product` | `Shopify Discount` | `customerBuysProducts` | | `Shopify Discount Customer Buys Product Variant` | `Shopify Discount` | `customerBuysProductVariants` | | `Shopify Discount Customer Gets Collection` | `Shopify Discount` | `customerGetsCollections` | | `Shopify Discount Customer Gets Product` | `Shopify Discount` | `customerGetsProducts` | | `Shopify Discount Customer Gets Product Variant` | `Shopify Discount` | `customerGetsProductVariants` | | `Shopify Discount Redeem Code` | `Shopify Discount` | `codes` | | `Shopify Dispute Evidence` | `Shopify Dispute` | `disputeEvidence` | | `Shopify Dispute Evidence Fulfillment` | `Shopify Dispute Evidence` | `fulfillments` | | `Shopify Dispute File Upload` | `Shopify Dispute Evidence` | `cancellationPolicyFile` | | `Shopify Draft Order Platform Discount` | `Shopify Draft Order` | `platformDiscounts` | | `Shopify Draft Order Platform Discount Allocation` | `Shopify Draft Order Platform Discount` | `allocations` | | `Shopify Fulfillment Hold` | `Shopify Fulfillment Order` | `fulfillmentHolds` | | `Shopify Fulfillment Order Destination` | `Shopify Fulfillment Order` | `destination` | | `Shopify Fulfillment Order Line Item` | `Shopify Fulfillment Order` | `fulfillmentOrderLineItems` | | `Shopify Fulfillment Order Merchant Request` | `Shopify Fulfillment Order` | `merchantRequests` | | `Shopify Inventory Quantity` | `Shopify Inventory Level` | `quantities` | | `Shopify Market Catalog` | `Shopify Market` | `marketCatalogs` | | `Shopify Market Region` | `Shopify Market` | `regions` | | `Shopify Market Web Presence` | `Shopify Market` | `marketWebPresences` | | `Shopify Reverse Delivery` | `Shopify Reverse Fulfillment Order` | `reverseDeliveries` | | `Shopify Reverse Delivery Line Item` | `Shopify Reverse Delivery` | `reverseDeliveryLineItems` | | `Shopify Reverse Fulfillment Order` | `Shopify Return` | `reverseFulfillmentOrders` | | `Shopify Reverse Fulfillment Order Disposition` | `Shopify Reverse Fulfillment Order Line Item` | `dispositions` | | `Shopify Reverse Fulfillment Order Line Item` | `Shopify Reverse Fulfillment Order` | `reverseFulfillmentOrderLineItems` | | `Shopify Store Credit Account` | `Shopify Customer` | `customerStoreCreditAccounts` | | `Shopify Subscription Line` | `Shopify Subscription Contract` | `lines` | | `Shopify Subscription Manual Discount` | `Shopify Subscription Contract` | `discounts` | ## Non-webhook models  Some Shopify models have no webhook topics and cannot inherit webhooks from a parent. We call these **non-webhook** models. They are only updated when you run a sync. Gadget adds a [`scheduledShopifySync` global action](https://docs.gadget.dev/guides/plugins/shopify/syncing-shopify-data#scheduledshopifysync-global-action) to keep these models up to date on a daily schedule. The following list shows non-webhook models: * Shopify App * Shopify App Credit * Shopify App Installation * Shopify App Usage Record * Shopify Article * Shopify Balance Transaction * Shopify Blog * Shopify Business Entity * Shopify Carrier Service * Shopify Catalog * Shopify Checkout Applied Gift Card * Shopify Comment * Shopify Country * Shopify Discount Code * Shopify Event * Shopify File * Shopify Fulfillment Service * Shopify Gift Card * Shopify Order Risk * Shopify Page * Shopify Payments Account * Shopify Payout * Shopify Price List * Shopify Price List Price * Shopify Price Rule * Shopify Province * Shopify Quantity Price Break * Shopify Redirect * Shopify Return Reason Definition * Shopify Script Tag ## Potential data inconsistencies  There are cases where not fetching data on webhook could lead to confusion. In these special cases, Gadget notifies you on the affected model's data viewer about potential inconsistencies in data, and suggests enabling fetch on webhook for the affected field. Those special cases are: * **Product webhooks** - If the webhook payload has more variant IDs in `variant_gids` than full variant objects in `variants`, and the `variants` field on `ShopifyProduct` is not set to fetch on webhook, a banner is shown on the `ShopifyProductVariant` data viewer. * **Product webhooks** - If the webhook payload includes `media`, and neither the product media nor the variant media relationship is set to fetch on webhook, a banner is shown on the `ShopifyFile` data viewer. The banner suggests enabling fetch on webhook for `media` on `ShopifyProduct` and/or `media` on `ShopifyProductVariant`, depending on which models you have enabled. For example, if `ShopifyProductMedia` is enabled, configuring `media` on `ShopifyProduct` is sufficient. * **Fulfillment order webhooks** - If no non-webhook fields on `ShopifyFulfillmentOrder` are set to fetch on webhook, a banner is shown on the `ShopifyFulfillmentOrder` data viewer.