--- title: Discount Function API description: Use the Discount Function API to create a single discount that applies to cart lines, order subtotal, and shipping rates. api_version: 2025-07 api_type: functions api_name: discount source_url: html: https://shopify.dev/docs/api/functions/latest/discount md: https://shopify.dev/docs/api/functions/latest/discount.md --- # Discount Function API The Discount Function API provides a unified schema for creating function extensions. A single function processes one discount (either code-based or automatic), but can apply savings across three discount classes: product, order, and shipping. For example, one discount can simultaneously reduce both order total and delivery costs. [Shopify Functions](https://shopify.dev/docs/api/functions/current) enable you to customize Shopify's backend logic. The Discount Function API integrates this logic into the checkout flow. Note You can activate a maximum of 25 discount functions on each store. All discount functions run concurrently, and have no knowledge of each other. The potential discount that a function outputs can be combined with the candidate from another discount, in alignment with the combination and stacking rules set on the [discount node](https://shopify.dev/docs/api/admin-graphql/latest/objects/DiscountNode). ### Use cases * Exclusions, where the discount doesn't apply to some cart lines in the order. * Tiered discounts on products, orders, and shipping when orders include qualifying item, subtotal, and delivery requirements. * Discount to cartlines that contain specific properties, such as an engraving on a ring. ## Function target Checkout ![Function Target](https://cdn.shopify.com/shopifycloud/shopify-dev/production/assets/assets/images/target-diagrams/cart-line-discount-target-diagram-D-GTle9M.png) Compatibility with Shopify surfaces Supported (7) Partially supported (4) Unsupported (3) * [B2B](https://shopify.dev/docs/apps/build/b2b): Supported * [Cart](https://shopify.dev/docs/storefronts/themes/architecture/templates/cart): Supported * [Checkout](https://shopify.dev/docs/apps/build/checkout): Supported * [Create Order API](https://shopify.dev/docs/api/admin-graphql/latest/mutations/orderCreate): Not supported * [Draft Order (Admin)](https://shopify.dev/docs/apps/build/b2b/draft-orders): Partially supported Discount functions with network access aren't supported on draft orders. * [Draft Order (Checkout)](https://shopify.dev/docs/apps/build/b2b/draft-orders): Partially supported Discount functions with network access aren't supported on draft orders. * [Order Edit (Admin)](https://shopify.dev/docs/apps/build/orders-fulfillment/order-management-apps/edit-orders): Not supported * [Order Edit (Checkout)](https://shopify.dev/docs/apps/build/orders-fulfillment/order-management-apps/edit-orders): Partially supported The function isn't re-run when editing an order. * [POS](https://shopify.dev/docs/apps/build/pos): Supported * [Pre-order and Try Before You Buy](https://shopify.dev/docs/apps/build/purchase-options/deferred): Not supported * [Shopify Admin](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries#creating-your-merchant-interface): Supported * [Storefront](https://shopify.dev/docs/storefronts/headless/building-with-the-storefront-api/): Supported * [Storefront Accelerated Checkout](https://shopify.dev/docs/storefronts/themes/pricing-payments/accelerated-checkout): Supported * [Subscription (Recurring Orders)](https://shopify.dev/docs/apps/build/purchase-options/subscriptions): Partially supported The function isn't re-run when the recurring orders are created. Fetch target Limited access Off The fetch target is limited to custom apps installed on Shopify Plus and Enterprise stores. You'll also need to [request network access](https://shopify.dev/docs/apps/build/functions/input-output/network-access) for functions, as it's not currently available on development stores or in a development preview. *** ## Getting started Scaffolding the function using [Shopify CLI](https://shopify.dev/docs/api/shopify-cli) automatically configures your TOML file. You can alter the default [configuration](https://shopify.dev/docs/api/functions/2025-07#configuration) to customize the way your function operates. ## Terminal ```terminal shopify app generate extension --template discount ``` [![](https://shopify.dev/images/icons/32/tutorial.png)![](https://shopify.dev/images/icons/32/tutorial-dark.png)](https://shopify.dev/docs/apps/build/discounts/build-product-discount-function) [TutorialBuild a discount function](https://shopify.dev/docs/apps/build/discounts/build-product-discount-function) *** ## Targets A [target](https://shopify.dev/docs/apps/build/app-extensions/configure-app-extensions#targets) is an identifier in `shopify.extension.toml` that specifies where you're injecting code into Shopify Function APIs, or other parts of the Shopify platform. Each target is composed of three to four namespaces. The name begins with a broad Shopify context and ends with the behavior of the extensible element. Note You can't configure [discount classes](https://shopify.dev/docs/apps/build/discounts#discount-classes) from a [checkout UI extension](https://shopify.dev/docs/api/checkout-ui-extensions). Discount classes are assigned based on their associated discount function targets: [`OrderDiscountCandidateTarget`](#CartLinesDiscountsGenerateRunResult.fields.operations.orderDiscountsAdd.candidates.targets), [`ProductDiscountCandidateTarget`](#CartLinesDiscountsGenerateRunResult.fields.operations.productDiscountsAdd.candidates.targets), and [`DeliveryDiscountCandidateTarget`](#CartDeliveryOptionsDiscountsGenerateRunResult.fields.operations.deliveryDiscountsAdd.candidates.targets). *** ### Cart run target `cart.lines.discounts.generate.run` The run target calculates and applies discounts to cart lines, orders, and shipping based on the provided cart context and discount configuration, including metafields. When your function is executed, Shopify provides the cart context as input to the run target, including details about cart lines, prices, quantities, buyer identity, and optionally fetch results from external providers. The target returns an ordered list of operations for calculating discounts. For example, you might use this to generate product and order discounts, and validate discounts. * Input OBJECT The `Input` object is the complete GraphQL schema that your function can query as an input to generate discounts. Your function only receives the fields that you request in the input query. To optimize performance, we highly recommend that you request only the fields that your function requires. * cart Cart! non-null The cart where the Function is running. A cart contains the merchandise that a customer intends to purchase and information about the customer, such as the customer's email address and phone number. * attribute Attribute The custom attributes associated with a cart to store additional information. Cart attributes allow you to collect specific information from customers on the **Cart** page, such as order notes, gift wrapping requests, or custom product details. Attributes are stored as key-value pairs. * key String ### Arguments The key of the cart attribute to retrieve. For example, `"gift_wrapping"`. *** * key String! non-null ### Fields The key or name of the attribute. For example, `"customer_first_order"`. * value String The value of the attribute. For example, `"true"`. * buyer​Identity Buyer​Identity Information about the customer that's interacting with the cart. It includes details such as the customer's email and phone number, and the total amount of money the customer has spent in the store. This information helps personalize the checkout experience and ensures that accurate pricing and delivery options are displayed to customers. * customer Customer The [customer](https://help.shopify.com/manual/customers/manage-customers) that's interacting with the cart. * amount​Spent Money​V2! non-null The total amount that the customer has spent on orders. The amount is converted from the shop's currency to the currency of the cart using a market rate. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * display​Name String! non-null The full name of the customer, based on the values for `firstName` and `lastName`. If `firstName` and `lastName` aren't specified, then the value is the customer's email address. If the email address isn't specified, then the value is the customer's phone number. * email String The customer's email address. * first​Name String The customer's first name. * has​Any​Tag Boolean! non-null Whether the customer is associated with any of the specified tags. The customer must have at least one tag from the list to return `true`. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the customer. For example, `"VIP, Gold"` returns customers with either the `VIP` or `Gold` tag. *** * has​Tags \[Has​Tag​Response!]! non-null Whether the customer is associated with the specified tags. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the customer. For example, `"VIP, Gold"` returns customers with both the `VIP` and `Gold` tags. *** * has​Tag Boolean! non-null ### Fields Whether the Shopify resource has the tag. * tag String! non-null A searchable keyword that's associated with a Shopify resource, such as a product or customer. For example, a merchant might apply the `sports` and `summer` tags to products that are associated with sportswear for summer. * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the customer. * last​Name String The customer's last name. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * number​Of​Orders Int! non-null The total number of orders that the customer has made at the store. * email String The email address of the customer that's interacting with the cart. * is​Authenticated Boolean! non-null Whether the customer is authenticated through their [customer account](https://help.shopify.com/manual/customers/customer-accounts). * phone String The phone number of the customer that's interacting with the cart. * purchasing​Company Purchasing​Company The company of a B2B customer that's interacting with the cart. Used to manage and track purchases made by businesses rather than individual customers. * company Company! non-null The company associated to the order or draft order. * created​At Date​Time! non-null The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company was created in Shopify. * external​Id String A unique externally-supplied ID for the company. * id ID! non-null The ID of the company. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * name String! non-null The name of the company. * updated​At Date​Time! non-null The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company was last modified. * contact Company​Contact The company contact associated to the order or draft order. * created​At Date​Time! non-null The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company contact was created in Shopify. * id ID! non-null The ID of the company. * locale String The company contact's locale (language). * title String The company contact's job title. * updated​At Date​Time! non-null The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company contact was last modified. * location Company​Location! non-null The company location associated to the order or draft order. * created​At Date​Time! non-null The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company location was created in Shopify. * external​Id String A unique externally-supplied ID for the company. * id ID! non-null The ID of the company. * locale String The preferred locale of the company location. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * name String! non-null The name of the company location. * updated​At Date​Time! non-null The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company location was last modified. * cost Cart​Cost! non-null A breakdown of the costs that the customer will pay at checkout. It includes the total amount, the subtotal before taxes and duties, the tax amount, and duty charges. * subtotal​Amount Money​V2! non-null The amount, before taxes and cart-level discounts, for the customer to pay. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * total​Amount Money​V2! non-null The total amount for the customer to pay at checkout. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * total​Duty​Amount Money​V2 The duty charges for a customer to pay at checkout. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * total​Tax​Amount Money​V2 The total tax amount for the customer to pay at checkout. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * deliverable​Lines \[Deliverable​Cart​Line!]! non-null The items in a cart that are eligible for fulfillment and can be delivered to the customer. * attribute Attribute The custom attributes associated with a cart to store additional information. Cart attributes allow you to collect specific information from customers on the **Cart** page, such as order notes, gift wrapping requests, or custom product details. Attributes are stored as key-value pairs. Cart line attributes are equivalent to the [`line_item`](https://shopify.dev/docs/apps/build/purchase-options/subscriptions/selling-plans) object in Liquid. * key String ### Arguments The key of the cart attribute to retrieve. For example, `"gift_wrapping"`. *** * key String! non-null ### Fields The key or name of the attribute. For example, `"customer_first_order"`. * value String The value of the attribute. For example, `"true"`. * id ID! non-null The ID of the cart line. * merchandise Merchandise! non-null The item that the customer intends to purchase. * Custom​Product OBJECT A custom product represents a product that doesn't map to Shopify's [standard product categories](https://help.shopify.com/manual/products/details/product-type). For example, you can use a custom product to manage gift cards, shipping requirements, localized product information, or weight measurements and conversions. * is​Gift​Card Boolean! non-null Whether the merchandise is a gift card. * requires​Shipping Boolean! non-null Whether the item needs to be shipped to the customer. For example, a digital gift card doesn't need to be shipped, but a t-shirt does need to be shipped. * title String! non-null The localized name for the product that displays to customers. The title is used to construct the product's handle, which is a unique, human-readable string of the product's title. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * weight Float The product variant's weight, in the system of measurement set in the `weightUnit` field. * weight​Unit Weight​Unit! non-null The unit of measurement for weight. * GRAMS, KILOGRAMS, OUNCES, POUNDS * Product​Variant OBJECT A specific version of a product that comes in more than one option, such as size or color. For example, if a merchant sells t-shirts with options for size and color, then a small, blue t-shirt would be one product variant and a large, blue t-shirt would be another. * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the product variant. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * product Product! non-null The product associated with the product variant. For example, if a merchant sells t-shirts with options for size and color, then a small, blue t-shirt would be one product variant and a large, blue t-shirt would be another. The product associated with the product variant would be the t-shirt itself. * handle Handle! non-null A unique, human-readable string of the product's title. A handle can contain letters, hyphens (`-`), and numbers, but not spaces. The handle is used in the online store URL for the product. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * has​Any​Tag Boolean! non-null Whether the product is associated with any of the specified tags. The product must have at least one tag from the list to return `true`. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the product. For example, `"sports, summer"` returns products with either the `sports` or `summer` tag. *** * has​Tags \[Has​Tag​Response!]! non-null Whether the product is associated with the specified tags. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the product. For example, `"sports, summer"` returns products with both the `sports` and `summer` tags. *** * has​Tag Boolean! non-null ### Fields Whether the Shopify resource has the tag. * tag String! non-null A searchable keyword that's associated with a Shopify resource, such as a product or customer. For example, a merchant might apply the `sports` and `summer` tags to products that are associated with sportswear for summer. * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the product. * in​Any​Collection Boolean! non-null Whether the product is in any of the specified collections. The product must be in at least one collection from the list to return `true`. A collection is a group of products that can be displayed in online stores and other sales channels in categories, which makes it easy for customers to find them. For example, an athletics store might create different collections for running attire and accessories. * ids \[ID!]! requiredDefault:\[] ### Arguments A comma-separated list of [globally-unique collection IDs](https://shopify.dev/docs/api/usage/gids) that are associated with the product. For example, `gid://shopify/Collection/123`, `gid://shopify/Collection/456`. *** * in​Collections \[Collection​Membership!]! non-null Whether the product is in the specified collections. The product must be in all of the collections in the list to return `true`. A collection is a group of products that can be displayed in online stores and other sales channels in categories, which makes it easy for customers to find them. For example, an athletics store might create different collections for running attire and accessories. * ids \[ID!]! requiredDefault:\[] ### Arguments A comma-separated list of [globally-unique collection IDs](https://shopify.dev/docs/api/usage/gids) that are associated with the product. For example, `gid://shopify/Collection/123`, `gid://shopify/Collection/456`. *** * collection​Id ID! non-null ### Fields A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the collection. * is​Member Boolean! non-null Whether the product is in the specified collection. * is​Gift​Card Boolean! non-null Whether the product is a gift card. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * product​Type String A custom category for a product. Product types allow merchants to define categories other than the ones available in Shopify's [standard product categories](https://help.shopify.com/manual/products/details/product-type). * title String! non-null The localized name for the product that displays to customers. The title is used to construct the product's handle, which is a unique, human-readable string of the product's title. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * vendor String The name of the product's vendor. * requires​Shipping Boolean! non-null Whether the item needs to be shipped to the customer. For example, a digital gift card doesn't need to be shipped, but a t-shirt does need to be shipped. * sku String A case-sensitive identifier for the product variant in the merchant's store. For example, `"BBC-1"`. A product variant must have a SKU to be connected to a [fulfillment service](https://shopify.dev/docs/apps/build/orders-fulfillment/fulfillment-service-apps/build-for-fulfillment-services). * title String The localized name for the product variant that displays to customers. * weight Float The product variant's weight, in the system of measurement set in the `weightUnit` field. * weight​Unit Weight​Unit! non-null The unit of measurement for weight. * GRAMS, KILOGRAMS, OUNCES, POUNDS * quantity Int! non-null The quantity of the item that the customer intends to purchase. * delivery​Groups \[Cart​Delivery​Group!]! non-null A collection of items that are grouped by shared delivery characteristics. Delivery groups streamline fulfillment by organizing items that can be shipped together, based on the customer's shipping address. For example, if a customer orders a t-shirt and a pair of shoes that can be shipped together, then the items are included in the same delivery group. In the [Order Discount](https://shopify.dev/docs/api/functions/reference/order-discounts) and [Product Discount](https://shopify.dev/docs/api/functions/reference/product-discounts) legacy APIs, the `cart.deliveryGroups` input is always an empty array. This means you can't access delivery groups when creating Order Discount or Product Discount Functions. If you need to apply discounts to shipping costs, then use the [Discount Function API](https://shopify.dev/docs/api/functions/reference/discount) instead. * cart​Lines \[Cart​Line!]! non-null Information about items in a cart that a customer intends to purchase. A cart line is an entry in the customer's cart that represents a single unit of a product variant. For example, if a customer adds two different sizes of the same t-shirt to their cart, then each size is represented as a separate cart line. * attribute Attribute The custom attributes associated with a cart to store additional information. Cart attributes allow you to collect specific information from customers on the **Cart** page, such as order notes, gift wrapping requests, or custom product details. Attributes are stored as key-value pairs. Cart line attributes are equivalent to the [`line_item`](https://shopify.dev/docs/apps/build/purchase-options/subscriptions/selling-plans) object in Liquid. * key String ### Arguments The key of the cart attribute to retrieve. For example, `"gift_wrapping"`. *** * key String! non-null ### Fields The key or name of the attribute. For example, `"customer_first_order"`. * value String The value of the attribute. For example, `"true"`. * cost Cart​Line​Cost! non-null The cost of an item in a cart that the customer intends to purchase. Cart lines are entries in the customer's cart that represent a single unit of a product variant. For example, if a customer adds two different sizes of the same t-shirt to their cart, then each size is represented as a separate cart line. * amount​Per​Quantity Money​V2! non-null The cost of a single unit. For example, if a customer purchases three units of a product that are priced at $10 each, then the `amountPerQuantity` is $10. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * compare​At​Amount​Per​Quantity Money​V2 The cost of a single unit before any discounts are applied. This field is used to calculate and display savings for customers. For example, if a product's `compareAtAmountPerQuantity` is $25 and its current price is $20, then the customer sees a $5 discount. This value can change based on the buyer's identity and is `null` when the value is hidden from buyers. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * subtotal​Amount Money​V2! non-null The cost of items in the cart before applying any discounts to certain items. This amount serves as the starting point for calculating any potential savings customers might receive through promotions or discounts. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * total​Amount Money​V2! non-null The total cost of items in a cart. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * id ID! non-null The ID of the cart line. * merchandise Merchandise! non-null The item that the customer intends to purchase. * Custom​Product OBJECT A custom product represents a product that doesn't map to Shopify's [standard product categories](https://help.shopify.com/manual/products/details/product-type). For example, you can use a custom product to manage gift cards, shipping requirements, localized product information, or weight measurements and conversions. * is​Gift​Card Boolean! non-null Whether the merchandise is a gift card. * requires​Shipping Boolean! non-null Whether the item needs to be shipped to the customer. For example, a digital gift card doesn't need to be shipped, but a t-shirt does need to be shipped. * title String! non-null The localized name for the product that displays to customers. The title is used to construct the product's handle, which is a unique, human-readable string of the product's title. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * weight Float The product variant's weight, in the system of measurement set in the `weightUnit` field. * weight​Unit Weight​Unit! non-null The unit of measurement for weight. * GRAMS, KILOGRAMS, OUNCES, POUNDS * Product​Variant OBJECT A specific version of a product that comes in more than one option, such as size or color. For example, if a merchant sells t-shirts with options for size and color, then a small, blue t-shirt would be one product variant and a large, blue t-shirt would be another. * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the product variant. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * product Product! non-null The product associated with the product variant. For example, if a merchant sells t-shirts with options for size and color, then a small, blue t-shirt would be one product variant and a large, blue t-shirt would be another. The product associated with the product variant would be the t-shirt itself. * handle Handle! non-null A unique, human-readable string of the product's title. A handle can contain letters, hyphens (`-`), and numbers, but not spaces. The handle is used in the online store URL for the product. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * has​Any​Tag Boolean! non-null Whether the product is associated with any of the specified tags. The product must have at least one tag from the list to return `true`. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the product. For example, `"sports, summer"` returns products with either the `sports` or `summer` tag. *** * has​Tags \[Has​Tag​Response!]! non-null Whether the product is associated with the specified tags. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the product. For example, `"sports, summer"` returns products with both the `sports` and `summer` tags. *** * has​Tag Boolean! non-null ### Fields Whether the Shopify resource has the tag. * tag String! non-null A searchable keyword that's associated with a Shopify resource, such as a product or customer. For example, a merchant might apply the `sports` and `summer` tags to products that are associated with sportswear for summer. * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the product. * in​Any​Collection Boolean! non-null Whether the product is in any of the specified collections. The product must be in at least one collection from the list to return `true`. A collection is a group of products that can be displayed in online stores and other sales channels in categories, which makes it easy for customers to find them. For example, an athletics store might create different collections for running attire and accessories. * ids \[ID!]! requiredDefault:\[] ### Arguments A comma-separated list of [globally-unique collection IDs](https://shopify.dev/docs/api/usage/gids) that are associated with the product. For example, `gid://shopify/Collection/123`, `gid://shopify/Collection/456`. *** * in​Collections \[Collection​Membership!]! non-null Whether the product is in the specified collections. The product must be in all of the collections in the list to return `true`. A collection is a group of products that can be displayed in online stores and other sales channels in categories, which makes it easy for customers to find them. For example, an athletics store might create different collections for running attire and accessories. * ids \[ID!]! requiredDefault:\[] ### Arguments A comma-separated list of [globally-unique collection IDs](https://shopify.dev/docs/api/usage/gids) that are associated with the product. For example, `gid://shopify/Collection/123`, `gid://shopify/Collection/456`. *** * collection​Id ID! non-null ### Fields A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the collection. * is​Member Boolean! non-null Whether the product is in the specified collection. * is​Gift​Card Boolean! non-null Whether the product is a gift card. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * product​Type String A custom category for a product. Product types allow merchants to define categories other than the ones available in Shopify's [standard product categories](https://help.shopify.com/manual/products/details/product-type). * title String! non-null The localized name for the product that displays to customers. The title is used to construct the product's handle, which is a unique, human-readable string of the product's title. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * vendor String The name of the product's vendor. * requires​Shipping Boolean! non-null Whether the item needs to be shipped to the customer. For example, a digital gift card doesn't need to be shipped, but a t-shirt does need to be shipped. * sku String A case-sensitive identifier for the product variant in the merchant's store. For example, `"BBC-1"`. A product variant must have a SKU to be connected to a [fulfillment service](https://shopify.dev/docs/apps/build/orders-fulfillment/fulfillment-service-apps/build-for-fulfillment-services). * title String The localized name for the product variant that displays to customers. * weight Float The product variant's weight, in the system of measurement set in the `weightUnit` field. * weight​Unit Weight​Unit! non-null The unit of measurement for weight. * GRAMS, KILOGRAMS, OUNCES, POUNDS * quantity Int! non-null The quantity of the item that the customer intends to purchase. * selling​Plan​Allocation Selling​Plan​Allocation The [selling plan](https://shopify.dev/docs/apps/build/purchase-options/subscriptions/selling-plans) associated with the cart line, including information about how a product variant can be sold and purchased. * price​Adjustments \[Selling​Plan​Allocation​Price​Adjustment!]! non-null A list of price adjustments, with a maximum of two. When there are two, the first price adjustment goes into effect at the time of purchase, while the second one starts after a certain number of orders. A price adjustment represents how a selling plan affects pricing when a variant is purchased with a selling plan. Prices display in the customer's currency if the shop is configured for it. * per​Delivery​Price Money​V2! non-null The effective price for a single delivery. For example, for a prepaid subscription plan that includes 6 deliveries at the price of $48.00, the per delivery price is $8.00. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * price Money​V2! non-null The price of the variant when it's purchased with a selling plan For example, for a prepaid subscription plan that includes 6 deliveries of $10.00 granola, where the customer gets 20% off, the price is 6 x $10.00 x 0.80 = $48.00. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * selling​Plan Selling​Plan! non-null A representation of how products and variants can be sold and purchased. For example, an individual selling plan could be '6 weeks of prepaid granola, delivered weekly'. * description String The description of the selling plan. * id ID! non-null A globally-unique identifier. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * name String! non-null The name of the selling plan. For example, '6 weeks of prepaid granola, delivered weekly'. * recurring​Deliveries Boolean! non-null Whether purchasing the selling plan will result in multiple deliveries. * delivery​Address Mailing​Address The shipping or destination address associated with the delivery group. * address1 String The first line of the address. Typically the street address or PO Box number. * address2 String The second line of the address. Typically the number of the apartment, suite, or unit. * city String The name of the city, district, village, or town. * company String The name of the customer's company or organization. * country​Code Country​Code The two-letter code for the country of the address. For example, US. * AC, AD, AE, AF, AG, AI, AL, AM, AN, AO, AR, AT, AU, AW, AX, AZ, BA, BB, BD, BE, BF, BG, BH, BI, BJ, BL, BM, BN, BO, BQ, BR, BS, BT, BV, BW, BY, BZ, CA, CC, CD, CF, CG, CH, CI, CK, CL, CM, CN, CO, CR, CU, CV, CW, CX, CY, CZ, DE, DJ, DK, DM, DO, DZ, EC, EE, EG, EH, ER, ES, ET, FI, FJ, FK, FO, FR, GA, GB, GD, GE, GF, GG, GH, GI, GL, GM, GN, GP, GQ, GR, GS, GT, GW, GY, HK, HM, HN, HR, HT, HU, ID, IE, IL, IM, IN, IO, IQ, IR, IS, IT, JE, JM, JO, JP, KE, KG, KH, KI, KM, KN, KP, KR, KW, KY, KZ, LA, LB, LC, LI, LK, LR, LS, LT, LU, LV, LY, MA, MC, MD, ME, MF, MG, MK, ML, MM, MN, MO, MQ, MR, MS, MT, MU, MV, MW, MX, MY, MZ, NA, NC, NE, NF, NG, NI, NL, NO, NP, NR, NU, NZ, OM, PA, PE, PF, PG, PH, PK, PL, PM, PN, PS, PT, PY, QA, RE, RO, RS, RU, RW, SA, SB, SC, SD, SE, SG, SH, SI, SJ, SK, SL, SM, SN, SO, SR, SS, ST, SV, SX, SY, SZ, TA, TC, TD, TF, TG, TH, TJ, TK, TL, TM, TN, TO, TR, TT, TV, TW, TZ, UA, UG, UM, US, UY, UZ, VA, VC, VE, VG, VN, VU, WF, WS, XK, YE, YT, ZA, ZM, ZW, ZZ * first​Name String The first name of the customer. * last​Name String The last name of the customer. * latitude Float The approximate latitude of the address. * longitude Float The approximate longitude of the address. * name String The full name of the customer, based on firstName and lastName. * phone String A unique phone number for the customer. Formatted using E.164 standard. For example, +16135551111. * province​Code String The alphanumeric code for the region. For example, ON. * zip String The zip or postal code of the address. * market Market Deprecated * handle Handle! non-null A human-readable unique string for the market automatically generated from its title. * id ID! non-null A globally-unique identifier. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * regions \[Market​Region!]! non-null A geographic region which comprises a market. * name String The name of the region in the language of the current localization. * delivery​Options \[Cart​Delivery​Option!]! non-null The delivery options available for the delivery group. Delivery options are the different ways that customers can choose to have their orders shipped. Examples include express shipping or standard shipping. * code String A unique identifier that represents the delivery option offered to customers. For example, `Canada Post Expedited`. * cost Money​V2! non-null The amount that the customer pays if they select the delivery option. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * delivery​Method​Type Delivery​Method! non-null The delivery method associated with the delivery option. A delivery method is a way that merchants can fulfill orders from their online stores. Delivery methods include shipping to an address, [local pickup](https://help.shopify.com/manual/fulfillment/setup/delivery-methods/pickup-in-store), and shipping to a [pickup point](https://help.shopify.com/manual/fulfillment/shopify-shipping/pickup-points), all of which are natively supported by Shopify checkout. * LOCAL, NONE, PICK_UP, PICKUP_POINT, RETAIL, SHIPPING * description String A single-line description of the delivery option, with HTML tags removed. * handle Handle! non-null A unique, human-readable identifier of the delivery option's title. A handle can contain letters, hyphens (`-`), and numbers, but not spaces. For example, `standard-shipping`. * title String The name of the delivery option that displays to customers. The title is used to construct the delivery option's handle. For example, if a delivery option is titled "Standard Shipping", then the handle is `standard-shipping`. * group​Type Cart​Delivery​Group​Type! non-null The type of merchandise in the delivery group. * ONE_TIME_PURCHASE, SUBSCRIPTION * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the delivery group. * selected​Delivery​Option Cart​Delivery​Option Information about the delivery option that the customer has selected. * code String A unique identifier that represents the delivery option offered to customers. For example, `Canada Post Expedited`. * cost Money​V2! non-null The amount that the customer pays if they select the delivery option. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * delivery​Method​Type Delivery​Method! non-null The delivery method associated with the delivery option. A delivery method is a way that merchants can fulfill orders from their online stores. Delivery methods include shipping to an address, [local pickup](https://help.shopify.com/manual/fulfillment/setup/delivery-methods/pickup-in-store), and shipping to a [pickup point](https://help.shopify.com/manual/fulfillment/shopify-shipping/pickup-points), all of which are natively supported by Shopify checkout. * LOCAL, NONE, PICK_UP, PICKUP_POINT, RETAIL, SHIPPING * description String A single-line description of the delivery option, with HTML tags removed. * handle Handle! non-null A unique, human-readable identifier of the delivery option's title. A handle can contain letters, hyphens (`-`), and numbers, but not spaces. For example, `standard-shipping`. * title String The name of the delivery option that displays to customers. The title is used to construct the delivery option's handle. For example, if a delivery option is titled "Standard Shipping", then the handle is `standard-shipping`. * lines \[Cart​Line!]! non-null The items in a cart that the customer intends to purchase. A cart line is an entry in the customer's cart that represents a single unit of a product variant. For example, if a customer adds two different sizes of the same t-shirt to their cart, then each size is represented as a separate cart line. * attribute Attribute The custom attributes associated with a cart to store additional information. Cart attributes allow you to collect specific information from customers on the **Cart** page, such as order notes, gift wrapping requests, or custom product details. Attributes are stored as key-value pairs. Cart line attributes are equivalent to the [`line_item`](https://shopify.dev/docs/apps/build/purchase-options/subscriptions/selling-plans) object in Liquid. * key String ### Arguments The key of the cart attribute to retrieve. For example, `"gift_wrapping"`. *** * key String! non-null ### Fields The key or name of the attribute. For example, `"customer_first_order"`. * value String The value of the attribute. For example, `"true"`. * cost Cart​Line​Cost! non-null The cost of an item in a cart that the customer intends to purchase. Cart lines are entries in the customer's cart that represent a single unit of a product variant. For example, if a customer adds two different sizes of the same t-shirt to their cart, then each size is represented as a separate cart line. * amount​Per​Quantity Money​V2! non-null The cost of a single unit. For example, if a customer purchases three units of a product that are priced at $10 each, then the `amountPerQuantity` is $10. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * compare​At​Amount​Per​Quantity Money​V2 The cost of a single unit before any discounts are applied. This field is used to calculate and display savings for customers. For example, if a product's `compareAtAmountPerQuantity` is $25 and its current price is $20, then the customer sees a $5 discount. This value can change based on the buyer's identity and is `null` when the value is hidden from buyers. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * subtotal​Amount Money​V2! non-null The cost of items in the cart before applying any discounts to certain items. This amount serves as the starting point for calculating any potential savings customers might receive through promotions or discounts. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * total​Amount Money​V2! non-null The total cost of items in a cart. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * id ID! non-null The ID of the cart line. * merchandise Merchandise! non-null The item that the customer intends to purchase. * Custom​Product OBJECT A custom product represents a product that doesn't map to Shopify's [standard product categories](https://help.shopify.com/manual/products/details/product-type). For example, you can use a custom product to manage gift cards, shipping requirements, localized product information, or weight measurements and conversions. * is​Gift​Card Boolean! non-null Whether the merchandise is a gift card. * requires​Shipping Boolean! non-null Whether the item needs to be shipped to the customer. For example, a digital gift card doesn't need to be shipped, but a t-shirt does need to be shipped. * title String! non-null The localized name for the product that displays to customers. The title is used to construct the product's handle, which is a unique, human-readable string of the product's title. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * weight Float The product variant's weight, in the system of measurement set in the `weightUnit` field. * weight​Unit Weight​Unit! non-null The unit of measurement for weight. * GRAMS, KILOGRAMS, OUNCES, POUNDS * Product​Variant OBJECT A specific version of a product that comes in more than one option, such as size or color. For example, if a merchant sells t-shirts with options for size and color, then a small, blue t-shirt would be one product variant and a large, blue t-shirt would be another. * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the product variant. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * product Product! non-null The product associated with the product variant. For example, if a merchant sells t-shirts with options for size and color, then a small, blue t-shirt would be one product variant and a large, blue t-shirt would be another. The product associated with the product variant would be the t-shirt itself. * handle Handle! non-null A unique, human-readable string of the product's title. A handle can contain letters, hyphens (`-`), and numbers, but not spaces. The handle is used in the online store URL for the product. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * has​Any​Tag Boolean! non-null Whether the product is associated with any of the specified tags. The product must have at least one tag from the list to return `true`. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the product. For example, `"sports, summer"` returns products with either the `sports` or `summer` tag. *** * has​Tags \[Has​Tag​Response!]! non-null Whether the product is associated with the specified tags. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the product. For example, `"sports, summer"` returns products with both the `sports` and `summer` tags. *** * has​Tag Boolean! non-null ### Fields Whether the Shopify resource has the tag. * tag String! non-null A searchable keyword that's associated with a Shopify resource, such as a product or customer. For example, a merchant might apply the `sports` and `summer` tags to products that are associated with sportswear for summer. * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the product. * in​Any​Collection Boolean! non-null Whether the product is in any of the specified collections. The product must be in at least one collection from the list to return `true`. A collection is a group of products that can be displayed in online stores and other sales channels in categories, which makes it easy for customers to find them. For example, an athletics store might create different collections for running attire and accessories. * ids \[ID!]! requiredDefault:\[] ### Arguments A comma-separated list of [globally-unique collection IDs](https://shopify.dev/docs/api/usage/gids) that are associated with the product. For example, `gid://shopify/Collection/123`, `gid://shopify/Collection/456`. *** * in​Collections \[Collection​Membership!]! non-null Whether the product is in the specified collections. The product must be in all of the collections in the list to return `true`. A collection is a group of products that can be displayed in online stores and other sales channels in categories, which makes it easy for customers to find them. For example, an athletics store might create different collections for running attire and accessories. * ids \[ID!]! requiredDefault:\[] ### Arguments A comma-separated list of [globally-unique collection IDs](https://shopify.dev/docs/api/usage/gids) that are associated with the product. For example, `gid://shopify/Collection/123`, `gid://shopify/Collection/456`. *** * collection​Id ID! non-null ### Fields A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the collection. * is​Member Boolean! non-null Whether the product is in the specified collection. * is​Gift​Card Boolean! non-null Whether the product is a gift card. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * product​Type String A custom category for a product. Product types allow merchants to define categories other than the ones available in Shopify's [standard product categories](https://help.shopify.com/manual/products/details/product-type). * title String! non-null The localized name for the product that displays to customers. The title is used to construct the product's handle, which is a unique, human-readable string of the product's title. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * vendor String The name of the product's vendor. * requires​Shipping Boolean! non-null Whether the item needs to be shipped to the customer. For example, a digital gift card doesn't need to be shipped, but a t-shirt does need to be shipped. * sku String A case-sensitive identifier for the product variant in the merchant's store. For example, `"BBC-1"`. A product variant must have a SKU to be connected to a [fulfillment service](https://shopify.dev/docs/apps/build/orders-fulfillment/fulfillment-service-apps/build-for-fulfillment-services). * title String The localized name for the product variant that displays to customers. * weight Float The product variant's weight, in the system of measurement set in the `weightUnit` field. * weight​Unit Weight​Unit! non-null The unit of measurement for weight. * GRAMS, KILOGRAMS, OUNCES, POUNDS * quantity Int! non-null The quantity of the item that the customer intends to purchase. * selling​Plan​Allocation Selling​Plan​Allocation The [selling plan](https://shopify.dev/docs/apps/build/purchase-options/subscriptions/selling-plans) associated with the cart line, including information about how a product variant can be sold and purchased. * price​Adjustments \[Selling​Plan​Allocation​Price​Adjustment!]! non-null A list of price adjustments, with a maximum of two. When there are two, the first price adjustment goes into effect at the time of purchase, while the second one starts after a certain number of orders. A price adjustment represents how a selling plan affects pricing when a variant is purchased with a selling plan. Prices display in the customer's currency if the shop is configured for it. * per​Delivery​Price Money​V2! non-null The effective price for a single delivery. For example, for a prepaid subscription plan that includes 6 deliveries at the price of $48.00, the per delivery price is $8.00. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * price Money​V2! non-null The price of the variant when it's purchased with a selling plan For example, for a prepaid subscription plan that includes 6 deliveries of $10.00 granola, where the customer gets 20% off, the price is 6 x $10.00 x 0.80 = $48.00. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * selling​Plan Selling​Plan! non-null A representation of how products and variants can be sold and purchased. For example, an individual selling plan could be '6 weeks of prepaid granola, delivered weekly'. * description String The description of the selling plan. * id ID! non-null A globally-unique identifier. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * name String! non-null The name of the selling plan. For example, '6 weeks of prepaid granola, delivered weekly'. * recurring​Deliveries Boolean! non-null Whether purchasing the selling plan will result in multiple deliveries. * localized​Fields \[Localized​Field!]! non-null The additional fields on the **Cart** page that are required for international orders in specific countries, such as customs information or tax identification numbers. * keys \[Localized​Field​Key!]! requiredDefault:\[] ### Arguments The keys of the localized fields to retrieve. * SHIPPING_CREDENTIAL_BR, SHIPPING_CREDENTIAL_CL, SHIPPING_CREDENTIAL_CN, SHIPPING_CREDENTIAL_CO, SHIPPING_CREDENTIAL_CR, SHIPPING_CREDENTIAL_EC, SHIPPING_CREDENTIAL_ES, SHIPPING_CREDENTIAL_GT, SHIPPING_CREDENTIAL_ID, SHIPPING_CREDENTIAL_KR, SHIPPING_CREDENTIAL_MX, SHIPPING_CREDENTIAL_MY, SHIPPING_CREDENTIAL_PE, SHIPPING_CREDENTIAL_PT, SHIPPING_CREDENTIAL_PY, SHIPPING_CREDENTIAL_TR, SHIPPING_CREDENTIAL_TW, SHIPPING_CREDENTIAL_TYPE_CO, TAX_CREDENTIAL_BR, TAX_CREDENTIAL_CL, TAX_CREDENTIAL_CO, TAX_CREDENTIAL_CR, TAX_CREDENTIAL_EC, TAX_CREDENTIAL_ES, TAX_CREDENTIAL_GT, TAX_CREDENTIAL_ID, TAX_CREDENTIAL_IT, TAX_CREDENTIAL_MX, TAX_CREDENTIAL_MY, TAX_CREDENTIAL_PE, TAX_CREDENTIAL_PT, TAX_CREDENTIAL_PY, TAX_CREDENTIAL_TR, TAX_CREDENTIAL_TYPE_CO, TAX_CREDENTIAL_TYPE_MX, TAX_CREDENTIAL_USE_MX, TAX_EMAIL_IT *** * key Localized​Field​Key! non-null ### Fields The key of the localized field. * SHIPPING_CREDENTIAL_BR, SHIPPING_CREDENTIAL_CL, SHIPPING_CREDENTIAL_CN, SHIPPING_CREDENTIAL_CO, SHIPPING_CREDENTIAL_CR, SHIPPING_CREDENTIAL_EC, SHIPPING_CREDENTIAL_ES, SHIPPING_CREDENTIAL_GT, SHIPPING_CREDENTIAL_ID, SHIPPING_CREDENTIAL_KR, SHIPPING_CREDENTIAL_MX, SHIPPING_CREDENTIAL_MY, SHIPPING_CREDENTIAL_PE, SHIPPING_CREDENTIAL_PT, SHIPPING_CREDENTIAL_PY, SHIPPING_CREDENTIAL_TR, SHIPPING_CREDENTIAL_TW, SHIPPING_CREDENTIAL_TYPE_CO, TAX_CREDENTIAL_BR, TAX_CREDENTIAL_CL, TAX_CREDENTIAL_CO, TAX_CREDENTIAL_CR, TAX_CREDENTIAL_EC, TAX_CREDENTIAL_ES, TAX_CREDENTIAL_GT, TAX_CREDENTIAL_ID, TAX_CREDENTIAL_IT, TAX_CREDENTIAL_MX, TAX_CREDENTIAL_MY, TAX_CREDENTIAL_PE, TAX_CREDENTIAL_PT, TAX_CREDENTIAL_PY, TAX_CREDENTIAL_TR, TAX_CREDENTIAL_TYPE_CO, TAX_CREDENTIAL_TYPE_MX, TAX_CREDENTIAL_USE_MX, TAX_EMAIL_IT * title String! non-null The title of the localized field. * value String The value of the localized field. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * retail​Location Location The physical location where a retail order is created or completed. * address Location​Address! non-null The address of this location. * address1 String The first line of the address for the location. * address2 String The second line of the address for the location. * city String The city of the location. * country String The country of the location. * country​Code String The country code of the location. * formatted \[String!]! non-null A formatted version of the address for the location. * latitude Float The approximate latitude coordinates of the location. * longitude Float The approximate longitude coordinates of the location. * phone String The phone number of the location. * province String The province of the location. * province​Code String The code for the province, state, or district of the address of the location. * zip String The ZIP code of the location. * handle Handle! non-null The location handle. * id ID! non-null The location id. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * name String! non-null The name of the location. * discount Discount! non-null The discount node that owns the [Shopify Function](https://shopify.dev/docs/apps/build/functions). Discounts are a way for merchants to promote sales and special offers, or as customer loyalty rewards. A single discount can be automatic or code-based, and can be applied to a cart lines, orders, and delivery. * discount​Classes \[Discount​Class!]! non-null The [discount classes](https://shopify.dev/docs/apps/build/discounts/#discount-classes)) that the [discountNode](https://shopify.dev/docs/api/admin-graphql/latest/queries/discountNode)) supports. * ORDER, PRODUCT, SHIPPING * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * fetch​Result Http​Response The result of the fetch target. Refer to [network access](https://shopify.dev/apps/build/functions/input-output/network-access/graphql) for Shopify Functions. This input is only available in the `cart.lines.discounts.generate.run` and `cart.delivery-options.discounts.generate.run` extension targets. * body String The HTTP response body as a plain string. Use this field when the body is not in JSON format. * header Http​Response​Header An HTTP header. * name String! required ### Arguments A case-insensitive header name. *** * name String! non-null ### Fields Header name. * value String! non-null Header value. * json​Body JSON The HTTP response body parsed as JSON. If the body is valid JSON, it will be parsed and returned as a JSON object. If parsing fails, then raw body is returned as a string. Use this field when you expect the response to be JSON, or when you're dealing with mixed response types, meaning both JSON and non-JSON. Using this field reduces function instruction consumption and ensures that the data is formatted in logs. To prevent increasing the function target input size unnecessarily, avoid querying both `body` and `jsonBody` simultaneously. * status Int! non-null The HTTP status code. * headers \[Http​Response​Header!]! non-nullDeprecated * name String! non-null Header name. * value String! non-null Header value. * localization Localization! non-null The regional and language settings that determine how the Function handles currency, numbers, dates, and other locale-specific values during discount calculations. These settings are based on the store's configured [localization practices](https://shopify.dev/docs/apps/build/functions/localization-practices-shopify-functions). * country Country! non-null The country for which the store is customized, reflecting local preferences and regulations. Localization might influence the language, currency, and product offerings available in a store to enhance the shopping experience for customers in that region. * iso​Code Country​Code! non-null The ISO code of the country. * AC, AD, AE, AF, AG, AI, AL, AM, AN, AO, AR, AT, AU, AW, AX, AZ, BA, BB, BD, BE, BF, BG, BH, BI, BJ, BL, BM, BN, BO, BQ, BR, BS, BT, BV, BW, BY, BZ, CA, CC, CD, CF, CG, CH, CI, CK, CL, CM, CN, CO, CR, CU, CV, CW, CX, CY, CZ, DE, DJ, DK, DM, DO, DZ, EC, EE, EG, EH, ER, ES, ET, FI, FJ, FK, FO, FR, GA, GB, GD, GE, GF, GG, GH, GI, GL, GM, GN, GP, GQ, GR, GS, GT, GW, GY, HK, HM, HN, HR, HT, HU, ID, IE, IL, IM, IN, IO, IQ, IR, IS, IT, JE, JM, JO, JP, KE, KG, KH, KI, KM, KN, KP, KR, KW, KY, KZ, LA, LB, LC, LI, LK, LR, LS, LT, LU, LV, LY, MA, MC, MD, ME, MF, MG, MK, ML, MM, MN, MO, MQ, MR, MS, MT, MU, MV, MW, MX, MY, MZ, NA, NC, NE, NF, NG, NI, NL, NO, NP, NR, NU, NZ, OM, PA, PE, PF, PG, PH, PK, PL, PM, PN, PS, PT, PY, QA, RE, RO, RS, RU, RW, SA, SB, SC, SD, SE, SG, SH, SI, SJ, SK, SL, SM, SN, SO, SR, SS, ST, SV, SX, SY, SZ, TA, TC, TD, TF, TG, TH, TJ, TK, TL, TM, TN, TO, TR, TT, TV, TW, TZ, UA, UG, UM, US, UY, UZ, VA, VC, VE, VG, VN, VU, WF, WS, XK, YE, YT, ZA, ZM, ZW, ZZ * language Language! non-null The language for which the store is customized, ensuring content is tailored to local customers. This includes product descriptions and customer communications that resonate with the target audience. * iso​Code Language​Code! non-null The ISO code. * AF, AK, AM, AR, AS, AZ, BE, BG, BM, BN, BO, BR, BS, CA, CE, CKB, CS, CU, CY, DA, DE, DZ, EE, EL, EN, EO, ES, ET, EU, FA, FF, FI, FIL, FO, FR, FY, GA, GD, GL, GU, GV, HA, HE, HI, HR, HU, HY, IA, ID, IG, II, IS, IT, JA, JV, KA, KI, KK, KL, KM, KN, KO, KS, KU, KW, KY, LB, LG, LN, LO, LT, LU, LV, MG, MI, MK, ML, MN, MR, MS, MT, MY, NB, ND, NE, NL, NN, NO, OM, OR, OS, PA, PL, PS, PT, PT_BR, PT_PT, QU, RM, RN, RO, RU, RW, SA, SC, SD, SE, SG, SI, SK, SL, SN, SO, SQ, SR, SU, SV, SW, TA, TE, TG, TH, TI, TK, TO, TR, TT, UG, UK, UR, UZ, VI, VO, WO, XH, YI, YO, ZH, ZH_CN, ZH_TW, ZU * market Market! non-nullDeprecated * handle Handle! non-null A human-readable unique string for the market automatically generated from its title. * id ID! non-null A globally-unique identifier. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * regions \[Market​Region!]! non-null A geographic region which comprises a market. * name String The name of the region in the language of the current localization. * presentment​Currency​Rate Decimal! non-null The exchange rate used to convert discounts between the shop's default currency and the currency that displays to the customer during checkout. For example, if a store operates in USD but a customer is viewing discounts in EUR, then the presentment currency rate handles this conversion for accurate pricing. * shop Shop! non-null Information about the shop where the Function is running, including the shop's timezone setting and associated [metafields](https://shopify.dev/docs/apps/build/custom-data). * local​Time Local​Time! non-null The current time based on the [store's timezone setting](https://help.shopify.com/manual/intro-to-shopify/initial-setup/setup-business-settings). * date Date! non-null The current date relative to the parent object. * date​Time​After Boolean! non-null Returns true if the current date and time is at or past the given date and time, and false otherwise. * date​Time Date​Time​Without​Timezone! required ### Arguments The date and time to compare against, assumed to be in the timezone of the parent object. *** * date​Time​Before Boolean! non-null Returns true if the current date and time is before the given date and time, and false otherwise. * date​Time Date​Time​Without​Timezone! required ### Arguments The date and time to compare against, assumed to be in the timezone of the parent timezone. *** * date​Time​Between Boolean! non-null Returns true if the current date and time is between the two given date and times, and false otherwise. * start​Date​Time Date​Time​Without​Timezone! required ### Arguments The lower bound time to compare against, assumed to be in the timezone of the parent timezone. * end​Date​Time Date​Time​Without​Timezone! required The upper bound time to compare against, assumed to be in the timezone of the parent timezone. *** * time​After Boolean! non-null Returns true if the current time is at or past the given time, and false otherwise. * time Time​Without​Timezone! required ### Arguments The time to compare against, assumed to be in the timezone of the parent timezone. *** * time​Before Boolean! non-null Returns true if the current time is at or past the given time, and false otherwise. * time Time​Without​Timezone! required ### Arguments The time to compare against, assumed to be in the timezone of the parent timezone. *** * time​Between Boolean! non-null Returns true if the current time is between the two given times, and false otherwise. * start​Time Time​Without​Timezone! required ### Arguments The lower bound time to compare against, assumed to be in the timezone of the parent timezone. * end​Time Time​Without​Timezone! required The upper bound time to compare against, assumed to be in the timezone of the parent timezone. *** * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * triggering​Discount​Code String The discount code entered by a customer, which caused the [Discount Function](https://shopify.dev/docs/apps/build/discounts#build-with-shopify-functions) to run. This input is only available in the `cart.lines.discounts.generate.run` and `cart.delivery-options.discounts.generate.run` extension targets. #### Cart run function The function processes input schema data to calculate and allocate discounts across cart lines. The function handles both fixed and percentage-based discounts while respecting discount caps and generating any messages associated with the discount, such as error messages associated with [validation](#validations). This return must follow the schema defined in the `CartLinesDiscountsGenerateRunResult` object. * Cart​Lines​Discounts​Generate​Run​Result OBJECT The `CartLinesDiscountsGenerateRunResult` object is the output of the function run target. The object contains the operations to generate, validate, and apply discounts to the cart. * operations \[Cart​Operation!]! non-null The list of operations to apply discounts to the cart. * entered​Discount​Codes​Accept Entered​Discount​Codes​Accept​Operation An operation that selects which entered discount codes to accept. Use this to validate discount codes from external systems. * codes \[Discount​Code!]! non-null The list of discount codes to accept. * code String! non-null The discount code. * order​Discounts​Add Order​Discounts​Add​Operation An operation that applies order discounts to a cart that share a selection strategy. * candidates \[Order​Discount​Candidate!]! non-null The list of discounts that can be applied to an order. * associated​Discount​Code Associated​Discount​Code The discount code associated with this discount candidate, for code-based discounts. * code String! non-null The discount code. * conditions \[Condition!] The conditions that must be satisfied for an order to be eligible for a discount candidate. * cart​Line​Minimum​Quantity Cart​Line​Minimum​Quantity The condition for checking the minimum quantity of products across a group of cart lines. * ids \[ID!]! non-null Cart line IDs with a merchandise line price that's included to calculate the minimum quantity purchased to receive the discount. * minimum​Quantity Int! non-null The minimum quantity of a cart line to be eligible for a discount candidate. * cart​Line​Minimum​Subtotal Cart​Line​Minimum​Subtotal The condition for checking the minimum subtotal of products across a group of cart lines. * ids \[ID!]! non-null Cart line IDs with a merchandise line price that's included to calculate the minimum subtotal purchased to receive the discount. * minimum​Amount Decimal! non-null The minimum subtotal amount of the cart line to be eligible for a discount candidate in the shop's currency. * order​Minimum​Subtotal Order​Minimum​Subtotal The condition for checking the minimum subtotal amount of the order. * excluded​Cart​Line​Ids \[ID!]! non-null Cart line IDs with a merchandise line price that's excluded to calculate the minimum subtotal amount of the order. * minimum​Amount Decimal! non-null The minimum subtotal amount of the order to be eligible for the discount in the shop's currency. * message String A notification on the **Cart** page informs customers about available discounts. If an automatic discount applies, the notification displays this message, such as "Save 20% on all t-shirts." If a discount code is entered, the notification displays the code instead. * targets \[Order​Discount​Candidate​Target!]! non-null The targets of the order discount candidate. * order​Subtotal Order​Subtotal​Target A method for applying a discount to the entire order subtotal. The subtotal is the total amount of the order before any taxes, shipping fees, or discounts are applied. For example, if a customer places an order for a t-shirt and a pair of shoes, then the subtotal is the sum of the prices of those items. * excluded​Cart​Line​Ids \[ID!]! non-null The list of excluded cart line IDs. These cart lines are excluded from the order subtotal calculation when calculating the maximum value of the discount. * value Order​Discount​Candidate​Value! non-null The value of the order discount candidate. * fixed​Amount Fixed​Amount A fixed amount value. * amount Decimal! non-null The fixed amount value of the discount, in the currency of the cart. The amount must be greater than or equal to 0. * percentage Percentage A percentage value. * value Decimal! non-null The percentage value. The value is validated against: >= 0 and <= 100. * selection​Strategy Order​Discount​Selection​Strategy! non-null The strategy that's applied to the list of discounts. * FIRST, MAXIMUM * product​Discounts​Add Product​Discounts​Add​Operation An operation that applies product discounts to a cart that share a selection strategy. * candidates \[Product​Discount​Candidate!]! non-null The list of products that are eligible for the discount. * associated​Discount​Code Associated​Discount​Code The discount code associated with this discount candidate, for code-based discounts. * code String! non-null The discount code. * message String A notification on the **Cart** page informs customers about available discounts. If an automatic discount applies, the notification displays this message, such as "Save 20% on all t-shirts." If a discount code is entered, the notification displays the code instead. * targets \[Product​Discount​Candidate​Target!]! non-null The targets of the discount to be applied to a cart line. * cart​Line Cart​Line​Target A method for applying a discount to a specific line item in the cart. A cart line is an entry in the customer's cart that represents a single unit of a product variant. For example, if a customer adds two different sizes of the same t-shirt to their cart, then each size is represented as a separate cart line. * id ID! non-null The ID of the targeted cart line. * quantity Int The number of line items that are being discounted. The default value is `null`, which represents the quantity of the matching line items. The value is validated against: > 0. * value Product​Discount​Candidate​Value! non-null The value of the discount to be applied to a cart line. For example, a fixed amount of $5 off or percentage value of 20% off. * fixed​Amount Product​Discount​Candidate​Fixed​Amount The [fixed-amount](https://help.shopify.com/manual/international/pricing/discounts) value of the discount to be applied to a cart line. For example, if the cart total is $100 and the discount is $10, then the fixed amount is $10. * amount Decimal! non-null The [fixed-amount](https://help.shopify.com/manual/international/pricing/discounts) value of the discount to be applied to a cart line, in the currency of the cart. The amount must be greater than or equal to 0. * applies​To​Each​Item Boolean Whether to apply the value of each eligible discount to each eligible cart line. The default value is `false`, which causes the value to be applied once across the entitled items. When the value is `true`, the value will be applied to each of the entitled items. * percentage Percentage A percentage value. * value Decimal! non-null The percentage value. The value is validated against: >= 0 and <= 100. * selection​Strategy Product​Discount​Selection​Strategy! non-null The strategy that's applied to the list of products that are eligible for the cart line discount. * ALL, FIRST, MAXIMUM *** ### Delivery run target `cart.delivery-options.discounts.generate.run` The run target that's responsible for generating the discount on shipping costs using either Shopify data, hardcoded values, or fetch results from external providers. The target returns an ordered list of operations to be applied to the cart. The run target evaluates carts against discount rules, calculates applicable reductions, and returns the final discount. This target generates and returns a shipping discount to potentially apply to the cart. * Input OBJECT The `Input` object is the complete GraphQL schema that your function receives to generate discounts for a delivery option or delivery group. Your function only receives the fields that you request in the input query. To optimize performance, we highly recommend that you request only the fields that your function requires. * cart Cart! non-null The cart where the Function is running. A cart contains the merchandise that a customer intends to purchase and information about the customer, such as the customer's email address and phone number. * attribute Attribute The custom attributes associated with a cart to store additional information. Cart attributes allow you to collect specific information from customers on the **Cart** page, such as order notes, gift wrapping requests, or custom product details. Attributes are stored as key-value pairs. * key String ### Arguments The key of the cart attribute to retrieve. For example, `"gift_wrapping"`. *** * key String! non-null ### Fields The key or name of the attribute. For example, `"customer_first_order"`. * value String The value of the attribute. For example, `"true"`. * buyer​Identity Buyer​Identity Information about the customer that's interacting with the cart. It includes details such as the customer's email and phone number, and the total amount of money the customer has spent in the store. This information helps personalize the checkout experience and ensures that accurate pricing and delivery options are displayed to customers. * customer Customer The [customer](https://help.shopify.com/manual/customers/manage-customers) that's interacting with the cart. * amount​Spent Money​V2! non-null The total amount that the customer has spent on orders. The amount is converted from the shop's currency to the currency of the cart using a market rate. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * display​Name String! non-null The full name of the customer, based on the values for `firstName` and `lastName`. If `firstName` and `lastName` aren't specified, then the value is the customer's email address. If the email address isn't specified, then the value is the customer's phone number. * email String The customer's email address. * first​Name String The customer's first name. * has​Any​Tag Boolean! non-null Whether the customer is associated with any of the specified tags. The customer must have at least one tag from the list to return `true`. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the customer. For example, `"VIP, Gold"` returns customers with either the `VIP` or `Gold` tag. *** * has​Tags \[Has​Tag​Response!]! non-null Whether the customer is associated with the specified tags. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the customer. For example, `"VIP, Gold"` returns customers with both the `VIP` and `Gold` tags. *** * has​Tag Boolean! non-null ### Fields Whether the Shopify resource has the tag. * tag String! non-null A searchable keyword that's associated with a Shopify resource, such as a product or customer. For example, a merchant might apply the `sports` and `summer` tags to products that are associated with sportswear for summer. * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the customer. * last​Name String The customer's last name. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * number​Of​Orders Int! non-null The total number of orders that the customer has made at the store. * email String The email address of the customer that's interacting with the cart. * is​Authenticated Boolean! non-null Whether the customer is authenticated through their [customer account](https://help.shopify.com/manual/customers/customer-accounts). * phone String The phone number of the customer that's interacting with the cart. * purchasing​Company Purchasing​Company The company of a B2B customer that's interacting with the cart. Used to manage and track purchases made by businesses rather than individual customers. * company Company! non-null The company associated to the order or draft order. * created​At Date​Time! non-null The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company was created in Shopify. * external​Id String A unique externally-supplied ID for the company. * id ID! non-null The ID of the company. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * name String! non-null The name of the company. * updated​At Date​Time! non-null The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company was last modified. * contact Company​Contact The company contact associated to the order or draft order. * created​At Date​Time! non-null The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company contact was created in Shopify. * id ID! non-null The ID of the company. * locale String The company contact's locale (language). * title String The company contact's job title. * updated​At Date​Time! non-null The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company contact was last modified. * location Company​Location! non-null The company location associated to the order or draft order. * created​At Date​Time! non-null The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company location was created in Shopify. * external​Id String A unique externally-supplied ID for the company. * id ID! non-null The ID of the company. * locale String The preferred locale of the company location. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * name String! non-null The name of the company location. * updated​At Date​Time! non-null The date and time ([ISO 8601 format](http://en.wikipedia.org/wiki/ISO_8601)) at which the company location was last modified. * cost Cart​Cost! non-null A breakdown of the costs that the customer will pay at checkout. It includes the total amount, the subtotal before taxes and duties, the tax amount, and duty charges. * subtotal​Amount Money​V2! non-null The amount, before taxes and cart-level discounts, for the customer to pay. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * total​Amount Money​V2! non-null The total amount for the customer to pay at checkout. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * total​Duty​Amount Money​V2 The duty charges for a customer to pay at checkout. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * total​Tax​Amount Money​V2 The total tax amount for the customer to pay at checkout. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * deliverable​Lines \[Deliverable​Cart​Line!]! non-null The items in a cart that are eligible for fulfillment and can be delivered to the customer. * attribute Attribute The custom attributes associated with a cart to store additional information. Cart attributes allow you to collect specific information from customers on the **Cart** page, such as order notes, gift wrapping requests, or custom product details. Attributes are stored as key-value pairs. Cart line attributes are equivalent to the [`line_item`](https://shopify.dev/docs/apps/build/purchase-options/subscriptions/selling-plans) object in Liquid. * key String ### Arguments The key of the cart attribute to retrieve. For example, `"gift_wrapping"`. *** * key String! non-null ### Fields The key or name of the attribute. For example, `"customer_first_order"`. * value String The value of the attribute. For example, `"true"`. * id ID! non-null The ID of the cart line. * merchandise Merchandise! non-null The item that the customer intends to purchase. * Custom​Product OBJECT A custom product represents a product that doesn't map to Shopify's [standard product categories](https://help.shopify.com/manual/products/details/product-type). For example, you can use a custom product to manage gift cards, shipping requirements, localized product information, or weight measurements and conversions. * is​Gift​Card Boolean! non-null Whether the merchandise is a gift card. * requires​Shipping Boolean! non-null Whether the item needs to be shipped to the customer. For example, a digital gift card doesn't need to be shipped, but a t-shirt does need to be shipped. * title String! non-null The localized name for the product that displays to customers. The title is used to construct the product's handle, which is a unique, human-readable string of the product's title. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * weight Float The product variant's weight, in the system of measurement set in the `weightUnit` field. * weight​Unit Weight​Unit! non-null The unit of measurement for weight. * GRAMS, KILOGRAMS, OUNCES, POUNDS * Product​Variant OBJECT A specific version of a product that comes in more than one option, such as size or color. For example, if a merchant sells t-shirts with options for size and color, then a small, blue t-shirt would be one product variant and a large, blue t-shirt would be another. * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the product variant. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * product Product! non-null The product associated with the product variant. For example, if a merchant sells t-shirts with options for size and color, then a small, blue t-shirt would be one product variant and a large, blue t-shirt would be another. The product associated with the product variant would be the t-shirt itself. * handle Handle! non-null A unique, human-readable string of the product's title. A handle can contain letters, hyphens (`-`), and numbers, but not spaces. The handle is used in the online store URL for the product. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * has​Any​Tag Boolean! non-null Whether the product is associated with any of the specified tags. The product must have at least one tag from the list to return `true`. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the product. For example, `"sports, summer"` returns products with either the `sports` or `summer` tag. *** * has​Tags \[Has​Tag​Response!]! non-null Whether the product is associated with the specified tags. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the product. For example, `"sports, summer"` returns products with both the `sports` and `summer` tags. *** * has​Tag Boolean! non-null ### Fields Whether the Shopify resource has the tag. * tag String! non-null A searchable keyword that's associated with a Shopify resource, such as a product or customer. For example, a merchant might apply the `sports` and `summer` tags to products that are associated with sportswear for summer. * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the product. * in​Any​Collection Boolean! non-null Whether the product is in any of the specified collections. The product must be in at least one collection from the list to return `true`. A collection is a group of products that can be displayed in online stores and other sales channels in categories, which makes it easy for customers to find them. For example, an athletics store might create different collections for running attire and accessories. * ids \[ID!]! requiredDefault:\[] ### Arguments A comma-separated list of [globally-unique collection IDs](https://shopify.dev/docs/api/usage/gids) that are associated with the product. For example, `gid://shopify/Collection/123`, `gid://shopify/Collection/456`. *** * in​Collections \[Collection​Membership!]! non-null Whether the product is in the specified collections. The product must be in all of the collections in the list to return `true`. A collection is a group of products that can be displayed in online stores and other sales channels in categories, which makes it easy for customers to find them. For example, an athletics store might create different collections for running attire and accessories. * ids \[ID!]! requiredDefault:\[] ### Arguments A comma-separated list of [globally-unique collection IDs](https://shopify.dev/docs/api/usage/gids) that are associated with the product. For example, `gid://shopify/Collection/123`, `gid://shopify/Collection/456`. *** * collection​Id ID! non-null ### Fields A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the collection. * is​Member Boolean! non-null Whether the product is in the specified collection. * is​Gift​Card Boolean! non-null Whether the product is a gift card. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * product​Type String A custom category for a product. Product types allow merchants to define categories other than the ones available in Shopify's [standard product categories](https://help.shopify.com/manual/products/details/product-type). * title String! non-null The localized name for the product that displays to customers. The title is used to construct the product's handle, which is a unique, human-readable string of the product's title. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * vendor String The name of the product's vendor. * requires​Shipping Boolean! non-null Whether the item needs to be shipped to the customer. For example, a digital gift card doesn't need to be shipped, but a t-shirt does need to be shipped. * sku String A case-sensitive identifier for the product variant in the merchant's store. For example, `"BBC-1"`. A product variant must have a SKU to be connected to a [fulfillment service](https://shopify.dev/docs/apps/build/orders-fulfillment/fulfillment-service-apps/build-for-fulfillment-services). * title String The localized name for the product variant that displays to customers. * weight Float The product variant's weight, in the system of measurement set in the `weightUnit` field. * weight​Unit Weight​Unit! non-null The unit of measurement for weight. * GRAMS, KILOGRAMS, OUNCES, POUNDS * quantity Int! non-null The quantity of the item that the customer intends to purchase. * delivery​Groups \[Cart​Delivery​Group!]! non-null A collection of items that are grouped by shared delivery characteristics. Delivery groups streamline fulfillment by organizing items that can be shipped together, based on the customer's shipping address. For example, if a customer orders a t-shirt and a pair of shoes that can be shipped together, then the items are included in the same delivery group. In the [Order Discount](https://shopify.dev/docs/api/functions/reference/order-discounts) and [Product Discount](https://shopify.dev/docs/api/functions/reference/product-discounts) legacy APIs, the `cart.deliveryGroups` input is always an empty array. This means you can't access delivery groups when creating Order Discount or Product Discount Functions. If you need to apply discounts to shipping costs, then use the [Discount Function API](https://shopify.dev/docs/api/functions/reference/discount) instead. * cart​Lines \[Cart​Line!]! non-null Information about items in a cart that a customer intends to purchase. A cart line is an entry in the customer's cart that represents a single unit of a product variant. For example, if a customer adds two different sizes of the same t-shirt to their cart, then each size is represented as a separate cart line. * attribute Attribute The custom attributes associated with a cart to store additional information. Cart attributes allow you to collect specific information from customers on the **Cart** page, such as order notes, gift wrapping requests, or custom product details. Attributes are stored as key-value pairs. Cart line attributes are equivalent to the [`line_item`](https://shopify.dev/docs/apps/build/purchase-options/subscriptions/selling-plans) object in Liquid. * key String ### Arguments The key of the cart attribute to retrieve. For example, `"gift_wrapping"`. *** * key String! non-null ### Fields The key or name of the attribute. For example, `"customer_first_order"`. * value String The value of the attribute. For example, `"true"`. * cost Cart​Line​Cost! non-null The cost of an item in a cart that the customer intends to purchase. Cart lines are entries in the customer's cart that represent a single unit of a product variant. For example, if a customer adds two different sizes of the same t-shirt to their cart, then each size is represented as a separate cart line. * amount​Per​Quantity Money​V2! non-null The cost of a single unit. For example, if a customer purchases three units of a product that are priced at $10 each, then the `amountPerQuantity` is $10. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * compare​At​Amount​Per​Quantity Money​V2 The cost of a single unit before any discounts are applied. This field is used to calculate and display savings for customers. For example, if a product's `compareAtAmountPerQuantity` is $25 and its current price is $20, then the customer sees a $5 discount. This value can change based on the buyer's identity and is `null` when the value is hidden from buyers. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * subtotal​Amount Money​V2! non-null The cost of items in the cart before applying any discounts to certain items. This amount serves as the starting point for calculating any potential savings customers might receive through promotions or discounts. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * total​Amount Money​V2! non-null The total cost of items in a cart. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * id ID! non-null The ID of the cart line. * merchandise Merchandise! non-null The item that the customer intends to purchase. * Custom​Product OBJECT A custom product represents a product that doesn't map to Shopify's [standard product categories](https://help.shopify.com/manual/products/details/product-type). For example, you can use a custom product to manage gift cards, shipping requirements, localized product information, or weight measurements and conversions. * is​Gift​Card Boolean! non-null Whether the merchandise is a gift card. * requires​Shipping Boolean! non-null Whether the item needs to be shipped to the customer. For example, a digital gift card doesn't need to be shipped, but a t-shirt does need to be shipped. * title String! non-null The localized name for the product that displays to customers. The title is used to construct the product's handle, which is a unique, human-readable string of the product's title. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * weight Float The product variant's weight, in the system of measurement set in the `weightUnit` field. * weight​Unit Weight​Unit! non-null The unit of measurement for weight. * GRAMS, KILOGRAMS, OUNCES, POUNDS * Product​Variant OBJECT A specific version of a product that comes in more than one option, such as size or color. For example, if a merchant sells t-shirts with options for size and color, then a small, blue t-shirt would be one product variant and a large, blue t-shirt would be another. * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the product variant. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * product Product! non-null The product associated with the product variant. For example, if a merchant sells t-shirts with options for size and color, then a small, blue t-shirt would be one product variant and a large, blue t-shirt would be another. The product associated with the product variant would be the t-shirt itself. * handle Handle! non-null A unique, human-readable string of the product's title. A handle can contain letters, hyphens (`-`), and numbers, but not spaces. The handle is used in the online store URL for the product. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * has​Any​Tag Boolean! non-null Whether the product is associated with any of the specified tags. The product must have at least one tag from the list to return `true`. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the product. For example, `"sports, summer"` returns products with either the `sports` or `summer` tag. *** * has​Tags \[Has​Tag​Response!]! non-null Whether the product is associated with the specified tags. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the product. For example, `"sports, summer"` returns products with both the `sports` and `summer` tags. *** * has​Tag Boolean! non-null ### Fields Whether the Shopify resource has the tag. * tag String! non-null A searchable keyword that's associated with a Shopify resource, such as a product or customer. For example, a merchant might apply the `sports` and `summer` tags to products that are associated with sportswear for summer. * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the product. * in​Any​Collection Boolean! non-null Whether the product is in any of the specified collections. The product must be in at least one collection from the list to return `true`. A collection is a group of products that can be displayed in online stores and other sales channels in categories, which makes it easy for customers to find them. For example, an athletics store might create different collections for running attire and accessories. * ids \[ID!]! requiredDefault:\[] ### Arguments A comma-separated list of [globally-unique collection IDs](https://shopify.dev/docs/api/usage/gids) that are associated with the product. For example, `gid://shopify/Collection/123`, `gid://shopify/Collection/456`. *** * in​Collections \[Collection​Membership!]! non-null Whether the product is in the specified collections. The product must be in all of the collections in the list to return `true`. A collection is a group of products that can be displayed in online stores and other sales channels in categories, which makes it easy for customers to find them. For example, an athletics store might create different collections for running attire and accessories. * ids \[ID!]! requiredDefault:\[] ### Arguments A comma-separated list of [globally-unique collection IDs](https://shopify.dev/docs/api/usage/gids) that are associated with the product. For example, `gid://shopify/Collection/123`, `gid://shopify/Collection/456`. *** * collection​Id ID! non-null ### Fields A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the collection. * is​Member Boolean! non-null Whether the product is in the specified collection. * is​Gift​Card Boolean! non-null Whether the product is a gift card. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * product​Type String A custom category for a product. Product types allow merchants to define categories other than the ones available in Shopify's [standard product categories](https://help.shopify.com/manual/products/details/product-type). * title String! non-null The localized name for the product that displays to customers. The title is used to construct the product's handle, which is a unique, human-readable string of the product's title. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * vendor String The name of the product's vendor. * requires​Shipping Boolean! non-null Whether the item needs to be shipped to the customer. For example, a digital gift card doesn't need to be shipped, but a t-shirt does need to be shipped. * sku String A case-sensitive identifier for the product variant in the merchant's store. For example, `"BBC-1"`. A product variant must have a SKU to be connected to a [fulfillment service](https://shopify.dev/docs/apps/build/orders-fulfillment/fulfillment-service-apps/build-for-fulfillment-services). * title String The localized name for the product variant that displays to customers. * weight Float The product variant's weight, in the system of measurement set in the `weightUnit` field. * weight​Unit Weight​Unit! non-null The unit of measurement for weight. * GRAMS, KILOGRAMS, OUNCES, POUNDS * quantity Int! non-null The quantity of the item that the customer intends to purchase. * selling​Plan​Allocation Selling​Plan​Allocation The [selling plan](https://shopify.dev/docs/apps/build/purchase-options/subscriptions/selling-plans) associated with the cart line, including information about how a product variant can be sold and purchased. * price​Adjustments \[Selling​Plan​Allocation​Price​Adjustment!]! non-null A list of price adjustments, with a maximum of two. When there are two, the first price adjustment goes into effect at the time of purchase, while the second one starts after a certain number of orders. A price adjustment represents how a selling plan affects pricing when a variant is purchased with a selling plan. Prices display in the customer's currency if the shop is configured for it. * per​Delivery​Price Money​V2! non-null The effective price for a single delivery. For example, for a prepaid subscription plan that includes 6 deliveries at the price of $48.00, the per delivery price is $8.00. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * price Money​V2! non-null The price of the variant when it's purchased with a selling plan For example, for a prepaid subscription plan that includes 6 deliveries of $10.00 granola, where the customer gets 20% off, the price is 6 x $10.00 x 0.80 = $48.00. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * selling​Plan Selling​Plan! non-null A representation of how products and variants can be sold and purchased. For example, an individual selling plan could be '6 weeks of prepaid granola, delivered weekly'. * description String The description of the selling plan. * id ID! non-null A globally-unique identifier. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * name String! non-null The name of the selling plan. For example, '6 weeks of prepaid granola, delivered weekly'. * recurring​Deliveries Boolean! non-null Whether purchasing the selling plan will result in multiple deliveries. * delivery​Address Mailing​Address The shipping or destination address associated with the delivery group. * address1 String The first line of the address. Typically the street address or PO Box number. * address2 String The second line of the address. Typically the number of the apartment, suite, or unit. * city String The name of the city, district, village, or town. * company String The name of the customer's company or organization. * country​Code Country​Code The two-letter code for the country of the address. For example, US. * AC, AD, AE, AF, AG, AI, AL, AM, AN, AO, AR, AT, AU, AW, AX, AZ, BA, BB, BD, BE, BF, BG, BH, BI, BJ, BL, BM, BN, BO, BQ, BR, BS, BT, BV, BW, BY, BZ, CA, CC, CD, CF, CG, CH, CI, CK, CL, CM, CN, CO, CR, CU, CV, CW, CX, CY, CZ, DE, DJ, DK, DM, DO, DZ, EC, EE, EG, EH, ER, ES, ET, FI, FJ, FK, FO, FR, GA, GB, GD, GE, GF, GG, GH, GI, GL, GM, GN, GP, GQ, GR, GS, GT, GW, GY, HK, HM, HN, HR, HT, HU, ID, IE, IL, IM, IN, IO, IQ, IR, IS, IT, JE, JM, JO, JP, KE, KG, KH, KI, KM, KN, KP, KR, KW, KY, KZ, LA, LB, LC, LI, LK, LR, LS, LT, LU, LV, LY, MA, MC, MD, ME, MF, MG, MK, ML, MM, MN, MO, MQ, MR, MS, MT, MU, MV, MW, MX, MY, MZ, NA, NC, NE, NF, NG, NI, NL, NO, NP, NR, NU, NZ, OM, PA, PE, PF, PG, PH, PK, PL, PM, PN, PS, PT, PY, QA, RE, RO, RS, RU, RW, SA, SB, SC, SD, SE, SG, SH, SI, SJ, SK, SL, SM, SN, SO, SR, SS, ST, SV, SX, SY, SZ, TA, TC, TD, TF, TG, TH, TJ, TK, TL, TM, TN, TO, TR, TT, TV, TW, TZ, UA, UG, UM, US, UY, UZ, VA, VC, VE, VG, VN, VU, WF, WS, XK, YE, YT, ZA, ZM, ZW, ZZ * first​Name String The first name of the customer. * last​Name String The last name of the customer. * latitude Float The approximate latitude of the address. * longitude Float The approximate longitude of the address. * name String The full name of the customer, based on firstName and lastName. * phone String A unique phone number for the customer. Formatted using E.164 standard. For example, +16135551111. * province​Code String The alphanumeric code for the region. For example, ON. * zip String The zip or postal code of the address. * market Market Deprecated * handle Handle! non-null A human-readable unique string for the market automatically generated from its title. * id ID! non-null A globally-unique identifier. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * regions \[Market​Region!]! non-null A geographic region which comprises a market. * name String The name of the region in the language of the current localization. * delivery​Options \[Cart​Delivery​Option!]! non-null The delivery options available for the delivery group. Delivery options are the different ways that customers can choose to have their orders shipped. Examples include express shipping or standard shipping. * code String A unique identifier that represents the delivery option offered to customers. For example, `Canada Post Expedited`. * cost Money​V2! non-null The amount that the customer pays if they select the delivery option. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * delivery​Method​Type Delivery​Method! non-null The delivery method associated with the delivery option. A delivery method is a way that merchants can fulfill orders from their online stores. Delivery methods include shipping to an address, [local pickup](https://help.shopify.com/manual/fulfillment/setup/delivery-methods/pickup-in-store), and shipping to a [pickup point](https://help.shopify.com/manual/fulfillment/shopify-shipping/pickup-points), all of which are natively supported by Shopify checkout. * LOCAL, NONE, PICK_UP, PICKUP_POINT, RETAIL, SHIPPING * description String A single-line description of the delivery option, with HTML tags removed. * handle Handle! non-null A unique, human-readable identifier of the delivery option's title. A handle can contain letters, hyphens (`-`), and numbers, but not spaces. For example, `standard-shipping`. * title String The name of the delivery option that displays to customers. The title is used to construct the delivery option's handle. For example, if a delivery option is titled "Standard Shipping", then the handle is `standard-shipping`. * group​Type Cart​Delivery​Group​Type! non-null The type of merchandise in the delivery group. * ONE_TIME_PURCHASE, SUBSCRIPTION * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the delivery group. * selected​Delivery​Option Cart​Delivery​Option Information about the delivery option that the customer has selected. * code String A unique identifier that represents the delivery option offered to customers. For example, `Canada Post Expedited`. * cost Money​V2! non-null The amount that the customer pays if they select the delivery option. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * delivery​Method​Type Delivery​Method! non-null The delivery method associated with the delivery option. A delivery method is a way that merchants can fulfill orders from their online stores. Delivery methods include shipping to an address, [local pickup](https://help.shopify.com/manual/fulfillment/setup/delivery-methods/pickup-in-store), and shipping to a [pickup point](https://help.shopify.com/manual/fulfillment/shopify-shipping/pickup-points), all of which are natively supported by Shopify checkout. * LOCAL, NONE, PICK_UP, PICKUP_POINT, RETAIL, SHIPPING * description String A single-line description of the delivery option, with HTML tags removed. * handle Handle! non-null A unique, human-readable identifier of the delivery option's title. A handle can contain letters, hyphens (`-`), and numbers, but not spaces. For example, `standard-shipping`. * title String The name of the delivery option that displays to customers. The title is used to construct the delivery option's handle. For example, if a delivery option is titled "Standard Shipping", then the handle is `standard-shipping`. * lines \[Cart​Line!]! non-null The items in a cart that the customer intends to purchase. A cart line is an entry in the customer's cart that represents a single unit of a product variant. For example, if a customer adds two different sizes of the same t-shirt to their cart, then each size is represented as a separate cart line. * attribute Attribute The custom attributes associated with a cart to store additional information. Cart attributes allow you to collect specific information from customers on the **Cart** page, such as order notes, gift wrapping requests, or custom product details. Attributes are stored as key-value pairs. Cart line attributes are equivalent to the [`line_item`](https://shopify.dev/docs/apps/build/purchase-options/subscriptions/selling-plans) object in Liquid. * key String ### Arguments The key of the cart attribute to retrieve. For example, `"gift_wrapping"`. *** * key String! non-null ### Fields The key or name of the attribute. For example, `"customer_first_order"`. * value String The value of the attribute. For example, `"true"`. * cost Cart​Line​Cost! non-null The cost of an item in a cart that the customer intends to purchase. Cart lines are entries in the customer's cart that represent a single unit of a product variant. For example, if a customer adds two different sizes of the same t-shirt to their cart, then each size is represented as a separate cart line. * amount​Per​Quantity Money​V2! non-null The cost of a single unit. For example, if a customer purchases three units of a product that are priced at $10 each, then the `amountPerQuantity` is $10. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * compare​At​Amount​Per​Quantity Money​V2 The cost of a single unit before any discounts are applied. This field is used to calculate and display savings for customers. For example, if a product's `compareAtAmountPerQuantity` is $25 and its current price is $20, then the customer sees a $5 discount. This value can change based on the buyer's identity and is `null` when the value is hidden from buyers. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * subtotal​Amount Money​V2! non-null The cost of items in the cart before applying any discounts to certain items. This amount serves as the starting point for calculating any potential savings customers might receive through promotions or discounts. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * total​Amount Money​V2! non-null The total cost of items in a cart. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * id ID! non-null The ID of the cart line. * merchandise Merchandise! non-null The item that the customer intends to purchase. * Custom​Product OBJECT A custom product represents a product that doesn't map to Shopify's [standard product categories](https://help.shopify.com/manual/products/details/product-type). For example, you can use a custom product to manage gift cards, shipping requirements, localized product information, or weight measurements and conversions. * is​Gift​Card Boolean! non-null Whether the merchandise is a gift card. * requires​Shipping Boolean! non-null Whether the item needs to be shipped to the customer. For example, a digital gift card doesn't need to be shipped, but a t-shirt does need to be shipped. * title String! non-null The localized name for the product that displays to customers. The title is used to construct the product's handle, which is a unique, human-readable string of the product's title. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * weight Float The product variant's weight, in the system of measurement set in the `weightUnit` field. * weight​Unit Weight​Unit! non-null The unit of measurement for weight. * GRAMS, KILOGRAMS, OUNCES, POUNDS * Product​Variant OBJECT A specific version of a product that comes in more than one option, such as size or color. For example, if a merchant sells t-shirts with options for size and color, then a small, blue t-shirt would be one product variant and a large, blue t-shirt would be another. * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the product variant. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * product Product! non-null The product associated with the product variant. For example, if a merchant sells t-shirts with options for size and color, then a small, blue t-shirt would be one product variant and a large, blue t-shirt would be another. The product associated with the product variant would be the t-shirt itself. * handle Handle! non-null A unique, human-readable string of the product's title. A handle can contain letters, hyphens (`-`), and numbers, but not spaces. The handle is used in the online store URL for the product. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * has​Any​Tag Boolean! non-null Whether the product is associated with any of the specified tags. The product must have at least one tag from the list to return `true`. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the product. For example, `"sports, summer"` returns products with either the `sports` or `summer` tag. *** * has​Tags \[Has​Tag​Response!]! non-null Whether the product is associated with the specified tags. * tags \[String!]! requiredDefault:\[] ### Arguments A comma-separated list of searchable keywords that are associated with the product. For example, `"sports, summer"` returns products with both the `sports` and `summer` tags. *** * has​Tag Boolean! non-null ### Fields Whether the Shopify resource has the tag. * tag String! non-null A searchable keyword that's associated with a Shopify resource, such as a product or customer. For example, a merchant might apply the `sports` and `summer` tags to products that are associated with sportswear for summer. * id ID! non-null A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the product. * in​Any​Collection Boolean! non-null Whether the product is in any of the specified collections. The product must be in at least one collection from the list to return `true`. A collection is a group of products that can be displayed in online stores and other sales channels in categories, which makes it easy for customers to find them. For example, an athletics store might create different collections for running attire and accessories. * ids \[ID!]! requiredDefault:\[] ### Arguments A comma-separated list of [globally-unique collection IDs](https://shopify.dev/docs/api/usage/gids) that are associated with the product. For example, `gid://shopify/Collection/123`, `gid://shopify/Collection/456`. *** * in​Collections \[Collection​Membership!]! non-null Whether the product is in the specified collections. The product must be in all of the collections in the list to return `true`. A collection is a group of products that can be displayed in online stores and other sales channels in categories, which makes it easy for customers to find them. For example, an athletics store might create different collections for running attire and accessories. * ids \[ID!]! requiredDefault:\[] ### Arguments A comma-separated list of [globally-unique collection IDs](https://shopify.dev/docs/api/usage/gids) that are associated with the product. For example, `gid://shopify/Collection/123`, `gid://shopify/Collection/456`. *** * collection​Id ID! non-null ### Fields A [globally-unique ID](https://shopify.dev/docs/api/usage/gids) for the collection. * is​Member Boolean! non-null Whether the product is in the specified collection. * is​Gift​Card Boolean! non-null Whether the product is a gift card. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * product​Type String A custom category for a product. Product types allow merchants to define categories other than the ones available in Shopify's [standard product categories](https://help.shopify.com/manual/products/details/product-type). * title String! non-null The localized name for the product that displays to customers. The title is used to construct the product's handle, which is a unique, human-readable string of the product's title. For example, if a product is titled "Black Sunglasses", then the handle is `black-sunglasses`. * vendor String The name of the product's vendor. * requires​Shipping Boolean! non-null Whether the item needs to be shipped to the customer. For example, a digital gift card doesn't need to be shipped, but a t-shirt does need to be shipped. * sku String A case-sensitive identifier for the product variant in the merchant's store. For example, `"BBC-1"`. A product variant must have a SKU to be connected to a [fulfillment service](https://shopify.dev/docs/apps/build/orders-fulfillment/fulfillment-service-apps/build-for-fulfillment-services). * title String The localized name for the product variant that displays to customers. * weight Float The product variant's weight, in the system of measurement set in the `weightUnit` field. * weight​Unit Weight​Unit! non-null The unit of measurement for weight. * GRAMS, KILOGRAMS, OUNCES, POUNDS * quantity Int! non-null The quantity of the item that the customer intends to purchase. * selling​Plan​Allocation Selling​Plan​Allocation The [selling plan](https://shopify.dev/docs/apps/build/purchase-options/subscriptions/selling-plans) associated with the cart line, including information about how a product variant can be sold and purchased. * price​Adjustments \[Selling​Plan​Allocation​Price​Adjustment!]! non-null A list of price adjustments, with a maximum of two. When there are two, the first price adjustment goes into effect at the time of purchase, while the second one starts after a certain number of orders. A price adjustment represents how a selling plan affects pricing when a variant is purchased with a selling plan. Prices display in the customer's currency if the shop is configured for it. * per​Delivery​Price Money​V2! non-null The effective price for a single delivery. For example, for a prepaid subscription plan that includes 6 deliveries at the price of $48.00, the per delivery price is $8.00. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * price Money​V2! non-null The price of the variant when it's purchased with a selling plan For example, for a prepaid subscription plan that includes 6 deliveries of $10.00 granola, where the customer gets 20% off, the price is 6 x $10.00 x 0.80 = $48.00. * amount Decimal! non-null A monetary value in decimal format, allowing for precise representation of cents or fractional currency. For example, 12.99. * currency​Code Currency​Code! non-null The three-letter currency code that represents a world currency used in a store. Currency codes include standard [standard ISO 4217 codes](https://en.wikipedia.org/wiki/ISO_4217), legacy codes, and non-standard codes. For example, USD. * AED, AFN, ALL, AMD, ANG, AOA, ARS, AUD, AWG, AZN, BAM, BBD, BDT, BGN, BHD, BIF, BMD, BND, BOB, BRL, BSD, BTN, BWP, BYN, BZD, CAD, CDF, CHF, CLP, CNY, COP, CRC, CVE, CZK, DJF, DKK, DOP, DZD, EGP, ERN, ETB, EUR, FJD, FKP, GBP, GEL, GHS, GIP, GMD, GNF, GTQ, GYD, HKD, HNL, HRK, HTG, HUF, IDR, ILS, INR, IQD, IRR, ISK, JEP, JMD, JOD, JPY, KES, KGS, KHR, KID, KMF, KRW, KWD, KYD, KZT, LAK, LBP, LKR, LRD, LSL, LTL, LVL, LYD, MAD, MDL, MGA, MKD, MMK, MNT, MOP, MRU, MUR, MVR, MWK, MXN, MYR, MZN, NAD, NGN, NIO, NOK, NPR, NZD, OMR, PAB, PEN, PGK, PHP, PKR, PLN, PYG, QAR, RON, RSD, RUB, RWF, SAR, SBD, SCR, SDG, SEK, SGD, SHP, SLL, SOS, SRD, SSP, STN, SYP, SZL, THB, TJS, TMT, TND, TOP, TRY, TTD, TWD, TZS, UAH, UGX, USD, USDC, UYU, UZS, VED, VES, VND, VUV, WST, XAF, XCD, XOF, XPF, XXX, YER, ZAR, ZMW, BYR, STD, VEF * selling​Plan Selling​Plan! non-null A representation of how products and variants can be sold and purchased. For example, an individual selling plan could be '6 weeks of prepaid granola, delivered weekly'. * description String The description of the selling plan. * id ID! non-null A globally-unique identifier. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * name String! non-null The name of the selling plan. For example, '6 weeks of prepaid granola, delivered weekly'. * recurring​Deliveries Boolean! non-null Whether purchasing the selling plan will result in multiple deliveries. * localized​Fields \[Localized​Field!]! non-null The additional fields on the **Cart** page that are required for international orders in specific countries, such as customs information or tax identification numbers. * keys \[Localized​Field​Key!]! requiredDefault:\[] ### Arguments The keys of the localized fields to retrieve. * SHIPPING_CREDENTIAL_BR, SHIPPING_CREDENTIAL_CL, SHIPPING_CREDENTIAL_CN, SHIPPING_CREDENTIAL_CO, SHIPPING_CREDENTIAL_CR, SHIPPING_CREDENTIAL_EC, SHIPPING_CREDENTIAL_ES, SHIPPING_CREDENTIAL_GT, SHIPPING_CREDENTIAL_ID, SHIPPING_CREDENTIAL_KR, SHIPPING_CREDENTIAL_MX, SHIPPING_CREDENTIAL_MY, SHIPPING_CREDENTIAL_PE, SHIPPING_CREDENTIAL_PT, SHIPPING_CREDENTIAL_PY, SHIPPING_CREDENTIAL_TR, SHIPPING_CREDENTIAL_TW, SHIPPING_CREDENTIAL_TYPE_CO, TAX_CREDENTIAL_BR, TAX_CREDENTIAL_CL, TAX_CREDENTIAL_CO, TAX_CREDENTIAL_CR, TAX_CREDENTIAL_EC, TAX_CREDENTIAL_ES, TAX_CREDENTIAL_GT, TAX_CREDENTIAL_ID, TAX_CREDENTIAL_IT, TAX_CREDENTIAL_MX, TAX_CREDENTIAL_MY, TAX_CREDENTIAL_PE, TAX_CREDENTIAL_PT, TAX_CREDENTIAL_PY, TAX_CREDENTIAL_TR, TAX_CREDENTIAL_TYPE_CO, TAX_CREDENTIAL_TYPE_MX, TAX_CREDENTIAL_USE_MX, TAX_EMAIL_IT *** * key Localized​Field​Key! non-null ### Fields The key of the localized field. * SHIPPING_CREDENTIAL_BR, SHIPPING_CREDENTIAL_CL, SHIPPING_CREDENTIAL_CN, SHIPPING_CREDENTIAL_CO, SHIPPING_CREDENTIAL_CR, SHIPPING_CREDENTIAL_EC, SHIPPING_CREDENTIAL_ES, SHIPPING_CREDENTIAL_GT, SHIPPING_CREDENTIAL_ID, SHIPPING_CREDENTIAL_KR, SHIPPING_CREDENTIAL_MX, SHIPPING_CREDENTIAL_MY, SHIPPING_CREDENTIAL_PE, SHIPPING_CREDENTIAL_PT, SHIPPING_CREDENTIAL_PY, SHIPPING_CREDENTIAL_TR, SHIPPING_CREDENTIAL_TW, SHIPPING_CREDENTIAL_TYPE_CO, TAX_CREDENTIAL_BR, TAX_CREDENTIAL_CL, TAX_CREDENTIAL_CO, TAX_CREDENTIAL_CR, TAX_CREDENTIAL_EC, TAX_CREDENTIAL_ES, TAX_CREDENTIAL_GT, TAX_CREDENTIAL_ID, TAX_CREDENTIAL_IT, TAX_CREDENTIAL_MX, TAX_CREDENTIAL_MY, TAX_CREDENTIAL_PE, TAX_CREDENTIAL_PT, TAX_CREDENTIAL_PY, TAX_CREDENTIAL_TR, TAX_CREDENTIAL_TYPE_CO, TAX_CREDENTIAL_TYPE_MX, TAX_CREDENTIAL_USE_MX, TAX_EMAIL_IT * title String! non-null The title of the localized field. * value String The value of the localized field. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * retail​Location Location The physical location where a retail order is created or completed. * address Location​Address! non-null The address of this location. * address1 String The first line of the address for the location. * address2 String The second line of the address for the location. * city String The city of the location. * country String The country of the location. * country​Code String The country code of the location. * formatted \[String!]! non-null A formatted version of the address for the location. * latitude Float The approximate latitude coordinates of the location. * longitude Float The approximate longitude coordinates of the location. * phone String The phone number of the location. * province String The province of the location. * province​Code String The code for the province, state, or district of the address of the location. * zip String The ZIP code of the location. * handle Handle! non-null The location handle. * id ID! non-null The location id. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * name String! non-null The name of the location. * discount Discount! non-null The discount node that owns the [Shopify Function](https://shopify.dev/docs/apps/build/functions). Discounts are a way for merchants to promote sales and special offers, or as customer loyalty rewards. A single discount can be automatic or code-based, and can be applied to a cart lines, orders, and delivery. * discount​Classes \[Discount​Class!]! non-null The [discount classes](https://shopify.dev/docs/apps/build/discounts/#discount-classes)) that the [discountNode](https://shopify.dev/docs/api/admin-graphql/latest/queries/discountNode)) supports. * ORDER, PRODUCT, SHIPPING * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * fetch​Result Http​Response The result of the fetch target. Refer to [network access](https://shopify.dev/apps/build/functions/input-output/network-access/graphql) for Shopify Functions. This input is only available in the `cart.lines.discounts.generate.run` and `cart.delivery-options.discounts.generate.run` extension targets. * body String The HTTP response body as a plain string. Use this field when the body is not in JSON format. * header Http​Response​Header An HTTP header. * name String! required ### Arguments A case-insensitive header name. *** * name String! non-null ### Fields Header name. * value String! non-null Header value. * json​Body JSON The HTTP response body parsed as JSON. If the body is valid JSON, it will be parsed and returned as a JSON object. If parsing fails, then raw body is returned as a string. Use this field when you expect the response to be JSON, or when you're dealing with mixed response types, meaning both JSON and non-JSON. Using this field reduces function instruction consumption and ensures that the data is formatted in logs. To prevent increasing the function target input size unnecessarily, avoid querying both `body` and `jsonBody` simultaneously. * status Int! non-null The HTTP status code. * headers \[Http​Response​Header!]! non-nullDeprecated * name String! non-null Header name. * value String! non-null Header value. * localization Localization! non-null The regional and language settings that determine how the Function handles currency, numbers, dates, and other locale-specific values during discount calculations. These settings are based on the store's configured [localization practices](https://shopify.dev/docs/apps/build/functions/localization-practices-shopify-functions). * country Country! non-null The country for which the store is customized, reflecting local preferences and regulations. Localization might influence the language, currency, and product offerings available in a store to enhance the shopping experience for customers in that region. * iso​Code Country​Code! non-null The ISO code of the country. * AC, AD, AE, AF, AG, AI, AL, AM, AN, AO, AR, AT, AU, AW, AX, AZ, BA, BB, BD, BE, BF, BG, BH, BI, BJ, BL, BM, BN, BO, BQ, BR, BS, BT, BV, BW, BY, BZ, CA, CC, CD, CF, CG, CH, CI, CK, CL, CM, CN, CO, CR, CU, CV, CW, CX, CY, CZ, DE, DJ, DK, DM, DO, DZ, EC, EE, EG, EH, ER, ES, ET, FI, FJ, FK, FO, FR, GA, GB, GD, GE, GF, GG, GH, GI, GL, GM, GN, GP, GQ, GR, GS, GT, GW, GY, HK, HM, HN, HR, HT, HU, ID, IE, IL, IM, IN, IO, IQ, IR, IS, IT, JE, JM, JO, JP, KE, KG, KH, KI, KM, KN, KP, KR, KW, KY, KZ, LA, LB, LC, LI, LK, LR, LS, LT, LU, LV, LY, MA, MC, MD, ME, MF, MG, MK, ML, MM, MN, MO, MQ, MR, MS, MT, MU, MV, MW, MX, MY, MZ, NA, NC, NE, NF, NG, NI, NL, NO, NP, NR, NU, NZ, OM, PA, PE, PF, PG, PH, PK, PL, PM, PN, PS, PT, PY, QA, RE, RO, RS, RU, RW, SA, SB, SC, SD, SE, SG, SH, SI, SJ, SK, SL, SM, SN, SO, SR, SS, ST, SV, SX, SY, SZ, TA, TC, TD, TF, TG, TH, TJ, TK, TL, TM, TN, TO, TR, TT, TV, TW, TZ, UA, UG, UM, US, UY, UZ, VA, VC, VE, VG, VN, VU, WF, WS, XK, YE, YT, ZA, ZM, ZW, ZZ * language Language! non-null The language for which the store is customized, ensuring content is tailored to local customers. This includes product descriptions and customer communications that resonate with the target audience. * iso​Code Language​Code! non-null The ISO code. * AF, AK, AM, AR, AS, AZ, BE, BG, BM, BN, BO, BR, BS, CA, CE, CKB, CS, CU, CY, DA, DE, DZ, EE, EL, EN, EO, ES, ET, EU, FA, FF, FI, FIL, FO, FR, FY, GA, GD, GL, GU, GV, HA, HE, HI, HR, HU, HY, IA, ID, IG, II, IS, IT, JA, JV, KA, KI, KK, KL, KM, KN, KO, KS, KU, KW, KY, LB, LG, LN, LO, LT, LU, LV, MG, MI, MK, ML, MN, MR, MS, MT, MY, NB, ND, NE, NL, NN, NO, OM, OR, OS, PA, PL, PS, PT, PT_BR, PT_PT, QU, RM, RN, RO, RU, RW, SA, SC, SD, SE, SG, SI, SK, SL, SN, SO, SQ, SR, SU, SV, SW, TA, TE, TG, TH, TI, TK, TO, TR, TT, UG, UK, UR, UZ, VI, VO, WO, XH, YI, YO, ZH, ZH_CN, ZH_TW, ZU * market Market! non-nullDeprecated * handle Handle! non-null A human-readable unique string for the market automatically generated from its title. * id ID! non-null A globally-unique identifier. * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * regions \[Market​Region!]! non-null A geographic region which comprises a market. * name String The name of the region in the language of the current localization. * presentment​Currency​Rate Decimal! non-null The exchange rate used to convert discounts between the shop's default currency and the currency that displays to the customer during checkout. For example, if a store operates in USD but a customer is viewing discounts in EUR, then the presentment currency rate handles this conversion for accurate pricing. * shop Shop! non-null Information about the shop where the Function is running, including the shop's timezone setting and associated [metafields](https://shopify.dev/docs/apps/build/custom-data). * local​Time Local​Time! non-null The current time based on the [store's timezone setting](https://help.shopify.com/manual/intro-to-shopify/initial-setup/setup-business-settings). * date Date! non-null The current date relative to the parent object. * date​Time​After Boolean! non-null Returns true if the current date and time is at or past the given date and time, and false otherwise. * date​Time Date​Time​Without​Timezone! required ### Arguments The date and time to compare against, assumed to be in the timezone of the parent object. *** * date​Time​Before Boolean! non-null Returns true if the current date and time is before the given date and time, and false otherwise. * date​Time Date​Time​Without​Timezone! required ### Arguments The date and time to compare against, assumed to be in the timezone of the parent timezone. *** * date​Time​Between Boolean! non-null Returns true if the current date and time is between the two given date and times, and false otherwise. * start​Date​Time Date​Time​Without​Timezone! required ### Arguments The lower bound time to compare against, assumed to be in the timezone of the parent timezone. * end​Date​Time Date​Time​Without​Timezone! required The upper bound time to compare against, assumed to be in the timezone of the parent timezone. *** * time​After Boolean! non-null Returns true if the current time is at or past the given time, and false otherwise. * time Time​Without​Timezone! required ### Arguments The time to compare against, assumed to be in the timezone of the parent timezone. *** * time​Before Boolean! non-null Returns true if the current time is at or past the given time, and false otherwise. * time Time​Without​Timezone! required ### Arguments The time to compare against, assumed to be in the timezone of the parent timezone. *** * time​Between Boolean! non-null Returns true if the current time is between the two given times, and false otherwise. * start​Time Time​Without​Timezone! required ### Arguments The lower bound time to compare against, assumed to be in the timezone of the parent timezone. * end​Time Time​Without​Timezone! required The upper bound time to compare against, assumed to be in the timezone of the parent timezone. *** * metafield Metafield A [custom field](https://shopify.dev/docs/apps/build/custom-data) that stores additional information about a Shopify resource, such as products, orders, and [many more](https://shopify.dev/docs/api/admin-graphql/latest/enums/MetafieldOwnerType). Using [metafields with Shopify Functions](https://shopify.dev/docs/apps/build/functions/input-output/metafields-for-input-queries) enables you to customize the checkout experience. * namespace String ### Arguments A category that organizes a group of metafields. Namespaces are used to prevent naming conflicts between different apps or different parts of the same app. If omitted, then the [app-reserved namespace](https://shopify.dev/docs/apps/build/custom-data/ownership) is used. * key String! required The unique identifier for the metafield within its namespace. A metafield is composed of a namespace and a key, in the format `namespace.key`. *** * json​Value JSON! non-null ### Fields The data that's stored in the metafield, using JSON format. * type String! non-null The [type of data](https://shopify.dev/apps/metafields/types) that the metafield stores in the `value` field. * value String! non-null The data that's stored in the metafield. The data is always stored as a string, regardless of the [metafield's type](https://shopify.dev/apps/metafields/types). * triggering​Discount​Code String The discount code entered by a customer, which caused the [Discount Function](https://shopify.dev/docs/apps/build/discounts#build-with-shopify-functions) to run. This input is only available in the `cart.lines.discounts.generate.run` and `cart.delivery-options.discounts.generate.run` extension targets. ### Delivery run function The function processes input schema data to calculate and allocate shipping discounts across cart lines, handling both fixed and percentage-based discounts while respecting discount caps and displaying messages associated with the discount. This return must follow the schema defined in the `CartDeliveryOptionsDiscountsGenerateRunResult` object. * Cart​Delivery​Options​Discounts​Generate​Run​Result OBJECT The `CartDeliveryOptionsDiscountsGenerateRunResult` object is the output of the function run target. The object contains the operations to generate, validate, and apply shipping discounts to the cart. * operations \[Delivery​Operation!]! non-null An ordered list of operations to generate delivery discounts, such as validating and applying discounts to the cart. * delivery​Discounts​Add Delivery​Discounts​Add​Operation Applies delivery discounts to a cart that share a method for determining which shipping and delivery discounts to apply when multiple discounts are eligible. * candidates \[Delivery​Discount​Candidate!]! non-null The list of discounts that are eligible to be applied to a delivery. * associated​Discount​Code Associated​Discount​Code The discount code that's eligible to be applied to a delivery. * code String! non-null The discount code. * message String A notification on the **Cart** page informs customers about available discounts. If an automatic discount applies, the notification displays this message, such as "Save 20% on all t-shirts." If a discount code is entered, the notification displays the code instead. * targets \[Delivery​Discount​Candidate​Target!]! non-null The targets of the discount that are eligible to be applied to a delivery. * delivery​Group Delivery​Group​Target A method for applying a discount to a delivery group. Delivery groups streamline fulfillment by organizing items that can be shipped together, based on the customer's shipping address. For example, if a customer orders a t-shirt and a pair of shoes that can be shipped together, then the items are included in the same delivery group. * id ID! non-null The ID of the target delivery group. * delivery​Option Delivery​Option​Target A method for applying a discount to a delivery option within a delivery group. Delivery options are the different ways that customers can choose to have their orders shipped. Examples of delivery options include express shipping or standard shipping. * handle Handle! non-null The handle of the target delivery option. * value Delivery​Discount​Candidate​Value! non-null The value of the discount that's eligible to be applied to a delivery. * fixed​Amount Fixed​Amount A fixed amount value. * amount Decimal! non-null The fixed amount value of the discount, in the currency of the cart. The amount must be greater than or equal to 0. * percentage Percentage A percentage value. * value Decimal! non-null The percentage value. The value is validated against: >= 0 and <= 100. * selection​Strategy Delivery​Discount​Selection​Strategy! non-null The method for determining which shipping and delivery discounts to apply when multiple discounts are eligible. For example, when the "ALL" strategy is selected, every shipping and delivery discount that qualifies is applied to the cart (for example, free shipping on orders over $50 and $5 off express shipping). This controls how shipping and delivery discounts interact when multiple conditions are satisfied simultaneously. * ALL * entered​Discount​Codes​Accept Entered​Discount​Codes​Accept​Operation An operation that selects which entered discount codes to accept. Use this to validate discount codes from external systems. * codes \[Discount​Code!]! non-null The list of discount codes to accept. * code String! non-null The discount code. Examples * ### Apply a percentage-off shipping discount. This function implements a shipping discount function that applies a percentage discount to the cheapest shipping method based on the cart subtotal. #### cart.delivery-options.discounts.generate.run ##### Input Query ```graphql query Input { cart { cost { subtotalAmount { amount } } deliveryGroups { deliveryOptions { handle cost { amount } } } } discount { metafield(namespace: "$app:delivery-discounts", key: "configuration") { jsonValue } } } ``` ##### Input Object ```json { "cart": { "cost": { "subtotalAmount": { "amount": "120.00" } }, "lines": [ { "id": "gid://shopify/CartLine/0", "cost": { "subtotalAmount": { "amount": "120.00" } }, "quantity": 1 } ], "deliveryGroups": [ { "deliveryOptions": [ { "handle": "standard", "cost": { "amount": "10.00" } }, { "handle": "express", "cost": { "amount": "20.00" } } ] } ] }, "discount": { "metafield": { "jsonValue": { "tiers": [ { "threshold": 50.0, "percentage": 10.0 }, { "threshold": 100.0, "percentage": 15.0 } ] } } } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize, Default)] pub struct DiscountTier { threshold: f64, percentage: f64, } #[derive(Deserialize, Default)] pub struct Configuration { tiers: Vec, } #[shopify_function] fn cart_delivery_options_discounts_generate_run(input: schema::cart_delivery_options_discounts_generate_run::Input) -> Result { // Parse configuration from metafield let config: &Configuration = match input.discount().metafield() { Some(metafield) => metafield.json_value(), None => return Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![] }), }; // Get cart subtotal let subtotal = input.cart().cost().subtotal_amount().amount().0; // Find the highest applicable tier let applicable_tier = config.tiers.iter() .filter(|tier| subtotal >= tier.threshold) .max_by(|a, b| a.threshold.partial_cmp(&b.threshold).unwrap_or(std::cmp::Ordering::Equal)); // If no tier applies, return empty operations let Some(tier) = applicable_tier else { return Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![] }); }; let mut operations = vec![]; // Process each delivery group for delivery_group in input.cart().delivery_groups() { // Find the cheapest delivery option if let Some(cheapest_option) = delivery_group.delivery_options().iter() .min_by(|a, b| { let a_cost = a.cost().amount().0; let b_cost = b.cost().amount().0; a_cost.partial_cmp(&b_cost).unwrap_or(std::cmp::Ordering::Equal) }) { // Add discount operation for the cheapest option operations.push(schema::DeliveryOperation::DeliveryDiscountsAdd(schema::DeliveryDiscountsAddOperation { selection_strategy: schema::DeliveryDiscountSelectionStrategy::All, candidates: vec![schema::DeliveryDiscountCandidate { targets: vec![schema::DeliveryDiscountCandidateTarget::DeliveryOption( schema::DeliveryOptionTarget { handle: cheapest_option.handle().clone(), }, )], value: schema::DeliveryDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(tier.percentage), }), message: Some(format!("{}% off shipping", tier.percentage)), associated_discount_code: None, }], })); } } Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { DeliveryDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {Object} DiscountTier * @property {number} threshold * @property {number} percentage */ /** * @typedef {Object} Configuration * @property {DiscountTier[]} tiers */ /** * @typedef {import('../generated/api').DeliveryInput} DeliveryInput * @typedef {import('../generated/api').DeliveryOperation} DeliveryOperation * @typedef {import('../generated/api').DeliveryDiscountCandidate} DeliveryDiscountCandidate */ /** * cartDeliveryOptionsDiscountsGenerateRun * @param {DeliveryInput} input - The DeliveryInput * @returns {{operations: DeliveryOperation[]}} - The function result with discounts. */ export function cartDeliveryOptionsDiscountsGenerateRun(input) { // Parse configuration from metafield let config; try { config = input.discount?.metafield ? JSON.parse(JSON.stringify(input.discount.metafield.jsonValue)) : { tiers: [] }; } catch (e) { return { operations: [] }; } // If no config or invalid tiers, return empty operations if (!config || !Array.isArray(config.tiers)) { return { operations: [] }; } // Get cart subtotal const subtotal = input.cart?.cost?.subtotalAmount?.amount || 0; // Find the highest applicable tier const applicableTier = config.tiers .filter(tier => subtotal >= tier.threshold) .reduce((highest, current) => !highest || current.threshold > highest.threshold ? current : highest, null); // If no tier applies, return empty operations if (!applicableTier) { console.log('no tier applies'); return { operations: [] }; } const operations = []; // Process each delivery group for (const deliveryGroup of input.cart.deliveryGroups) { if (!deliveryGroup.deliveryOptions?.length) { continue; } // Find the cheapest delivery option let cheapestOption = deliveryGroup.deliveryOptions[0]; for (let i = 1; i < deliveryGroup.deliveryOptions.length; i++) { const option = deliveryGroup.deliveryOptions[i]; if (option.cost.amount < cheapestOption.cost.amount) { cheapestOption = option; } } /** @type {DeliveryOperation} */ const operation = { deliveryDiscountsAdd: { candidates: [{ message: `${applicableTier.percentage}% off shipping`, targets: [{ deliveryOption: { handle: cheapestOption.handle, }, }], value: { percentage: { value: String(applicableTier.percentage.toFixed(1)), }, }, }], selectionStrategy: DeliveryDiscountSelectionStrategy.All, }, }; operations.push(operation); } return { operations }; } ``` ##### Output JSON ```json { "operations": [ { "deliveryDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "15% off shipping", "targets": [ { "deliveryOption": { "handle": "standard" } } ], "value": { "percentage": { "value": "15.0" } } } ], "selectionStrategy": "ALL" } } ] } ``` #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id cost { subtotalAmount { amount } } } } } ``` ##### Input Object ```json { "cart": { "cost": { "subtotalAmount": { "amount": "120.00" } }, "lines": [ { "id": "gid://shopify/CartLine/0", "cost": { "subtotalAmount": { "amount": "120.00" } }, "quantity": 1 } ], "deliveryGroups": [ { "deliveryOptions": [ { "handle": "standard", "cost": { "amount": "10.00" } }, { "handle": "express", "cost": { "amount": "20.00" } } ] } ] }, "discount": { "metafield": { "jsonValue": { "tiers": [ { "threshold": 50.0, "percentage": 10.0 }, { "threshold": 100.0, "percentage": 15.0 } ] } } } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_lines_discounts_generate_run(input: schema::cart_lines_discounts_generate_run::Input) -> Result { let max_cart_line = input .cart() .lines() .iter() .max_by(|a, b| { a.cost() .subtotal_amount() .amount() .partial_cmp(b.cost().subtotal_amount().amount()) .unwrap_or(std::cmp::Ordering::Equal) }) .ok_or("No cart lines found")?; Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![ schema::CartOperation::OrderDiscountsAdd(schema::OrderDiscountsAddOperation { selection_strategy: schema::OrderDiscountSelectionStrategy::First, candidates: vec![schema::OrderDiscountCandidate { targets: vec![schema::OrderDiscountCandidateTarget::OrderSubtotal( schema::OrderSubtotalTarget { excluded_cart_line_ids: vec![], }, )], message: Some("10% OFF ORDER".to_string()), value: schema::OrderDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(10.0), }), conditions: None, associated_discount_code: None, }], }), schema::CartOperation::ProductDiscountsAdd(schema::ProductDiscountsAddOperation { selection_strategy: schema::ProductDiscountSelectionStrategy::First, candidates: vec![schema::ProductDiscountCandidate { targets: vec![schema::ProductDiscountCandidateTarget::CartLine(schema::CartLineTarget { id: max_cart_line.id().clone(), quantity: None, })], message: Some("20% OFF PRODUCT".to_string()), value: schema::ProductDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(20.0), }), associated_discount_code: None, }], }), ], }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { OrderDiscountSelectionStrategy, ProductDiscountSelectionStrategy, } from '../generated/api'; /** * @typedef {import("../generated/api").Input} CartInput * @typedef {import("../generated/api").CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * cartLinesDiscountsGenerateRun * @param {CartInput} input - The CartInput * @returns {CartLinesDiscountsGenerateRunResult} - The function result with discounts. */ export function cartLinesDiscountsGenerateRun(input) { if (!input.cart.lines.length) { throw new Error('No cart lines found'); } const maxCartLine = input.cart.lines.reduce((maxLine, line) => { if (line.cost.subtotalAmount.amount > maxLine.cost.subtotalAmount.amount) { return line; } return maxLine; }, input.cart.lines[0]); return { operations: [ { orderDiscountsAdd: { candidates: [ { message: '10% OFF ORDER', targets: [ { orderSubtotal: { excludedCartLineIds: [], }, }, ], value: { percentage: { value: "10.0", }, }, }, ], selectionStrategy: OrderDiscountSelectionStrategy.First, }, }, { productDiscountsAdd: { candidates: [ { message: '20% OFF PRODUCT', targets: [ { cartLine: { id: maxCartLine.id, }, }, ], value: { percentage: { value: "20.0", }, }, }, ], selectionStrategy: ProductDiscountSelectionStrategy.First, }, }, ], }; } ``` ##### Output JSON ```json { "operations": [ { "orderDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "conditions": null, "message": "10% OFF ORDER", "targets": [ { "orderSubtotal": { "excludedCartLineIds": [] } } ], "value": { "percentage": { "value": "10.0" } } } ], "selectionStrategy": "FIRST" } }, { "productDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "20% OFF PRODUCT", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/0", "quantity": null } } ], "value": { "percentage": { "value": "20.0" } } } ], "selectionStrategy": "FIRST" } } ] } ``` * ### Create a tiered discount based on line subtotals A Shopify Discount Function that implements tiered fixed-amount discounts for cart lines based on their individual subtotals. It applies progressively larger discounts as line subtotals increase: $10 off for lines totaling $100+, $20 off for lines totaling $200+, and $30 off for lines totaling $300+. The discount is applied as a fixed amount per line rather than per item, creating effective volume discounts for higher-value purchases. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id cost { subtotalAmount { amount } } } } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/1", "cost": { "subtotalAmount": { "amount": "50.00" } } }, { "id": "gid://shopify/CartLine/2", "cost": { "subtotalAmount": { "amount": "150.00" } } }, { "id": "gid://shopify/CartLine/3", "cost": { "subtotalAmount": { "amount": "250.00" } } }, { "id": "gid://shopify/CartLine/4", "cost": { "subtotalAmount": { "amount": "350.00" } } } ] } } ``` ##### Function Code (Rust) ```rust use crate::schema; use shopify_function::prelude::*; use shopify_function::Result; const TIERS: [(Decimal, i32); 3] = [ (Decimal(100.0), 10), (Decimal(200.0), 40), (Decimal(300.0), 60), ]; #[shopify_function] fn cart_lines_discounts_generate_run(input: schema::cart_lines_discounts_generate_run::Input) -> Result { let mut operations = vec![]; for line in input.cart().lines() { let cost = line.cost().subtotal_amount().amount(); if let Some(tier) = get_tier(&cost) { let discount = tier.1; operations.push(schema::CartOperation::ProductDiscountsAdd(schema::ProductDiscountsAddOperation { candidates: vec![schema::ProductDiscountCandidate { targets: vec![schema::ProductDiscountCandidateTarget::CartLine(schema::CartLineTarget { id: line.id().clone(), quantity: None, })], value: schema::ProductDiscountCandidateValue::FixedAmount(schema::ProductDiscountCandidateFixedAmount { amount: Decimal(discount.into()), applies_to_each_item: Some(false), }), message: Some(format!("{}$ off", discount)), associated_discount_code: None, }], selection_strategy: schema::ProductDiscountSelectionStrategy::All, })); } } Ok( schema::CartLinesDiscountsGenerateRunResult { operations, }, ) } fn get_tier(cost: &Decimal) -> Option<(Decimal, i32)> { TIERS .iter() .rev() .find(|(threshold, _)| cost.ge(threshold)) .copied() } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import {ProductDiscountSelectionStrategy} from "../generated/api"; /** * @typedef {import("../generated/api").Input} CartInput * @typedef {import("../generated/api").CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * @typedef {Object} Tier * @property {number} threshold - The threshold of the tier * @property {number} discount - The discount of the tier */ const TIERS = [ {threshold: 100, discount: 10}, {threshold: 200, discount: 20}, {threshold: 300, discount: 30}, ]; /** * generateCartRun * @param {CartInput} input - The CartInput * @returns {CartLinesDiscountsGenerateRunResult} - The function result with discounts. */ export function cartLinesDiscountsGenerateRun(input) { if (!input.cart.lines.length) { throw new Error("No cart lines found"); } return input.cart.lines.reduce((runResult, cartLine) => { const tier = getTier(cartLine.cost.subtotalAmount.amount); if (tier) { runResult.operations.push({ productDiscountsAdd: { candidates: [ { message: `${tier.discount}$ off`, targets: [ { cartLine: { id: cartLine.id, }, }, ], value: { fixedAmount: { amount: tier.discount, appliesToEachItem: false, }, }, }, ], selectionStrategy: ProductDiscountSelectionStrategy.First, }, }); } return runResult; }, /** @type {CartLinesDiscountsGenerateRunResult} */ ({operations: []})); } /** * getTier * @param {number} cost - The cost of the cart line * @returns {Tier | undefined} - The tier */ function getTier(cost) { return [...TIERS].reverse().find(tier => cost >= tier.threshold); } ``` ##### Output JSON ```json { "operations": [ { "productDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "10$ off", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/2", "quantity": null } } ], "value": { "fixedAmount": { "amount": "10.0", "appliesToEachItem": false } } } ], "selectionStrategy": "ALL" } }, { "productDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "40$ off", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/3", "quantity": null } } ], "value": { "fixedAmount": { "amount": "40.0", "appliesToEachItem": false } } } ], "selectionStrategy": "ALL" } }, { "productDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "60$ off", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/4", "quantity": null } } ], "value": { "fixedAmount": { "amount": "60.0", "appliesToEachItem": false } } } ], "selectionStrategy": "ALL" } } ] } ``` * ### Create a dynamic discount from discount codes A Shopify Discount Function that parses entered discount codes with the format "X%OFF" to extract and apply the specified percentage discount to the entire order if a discount code associated to this function exists. For example, entering "10%OFF" applies a 10% discount, while "25%OFF" applies a 25% discount. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { discount { discountClasses } triggeringDiscountCode } ``` ##### Input Object ```json { "discount": { "discountClasses": ["ORDER"] }, "triggeringDiscountCode": "20%OFF" } ``` ##### Function Code (Rust) ```rust use crate::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_lines_discounts_generate_run( input: schema::cart_lines_discounts_generate_run::Input, ) -> Result { if !input .discount() .discount_classes() .contains(&schema::DiscountClass::Order) { return Ok( schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }, ); } if let Some(percentage_off) = get_percentage_off(&input.triggering_discount_code()) { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![schema::CartOperation::OrderDiscountsAdd( schema::OrderDiscountsAddOperation { selection_strategy: schema::OrderDiscountSelectionStrategy::First, candidates: vec![schema::OrderDiscountCandidate { conditions: None, targets: vec![schema::OrderDiscountCandidateTarget::OrderSubtotal( schema::OrderSubtotalTarget { excluded_cart_line_ids: vec![], }, )], value: schema::OrderDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(percentage_off as f64), }), message: Some(format!("{}% off order", percentage_off)), associated_discount_code: None, }], }, )], }); } Ok( schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }, ) } fn get_percentage_off(code: &Option<&String>) -> Option { code.as_ref().and_then(|discount_code| { discount_code .strip_suffix("%OFF") .filter(|digits| !digits.is_empty()) .and_then(|digits| digits.parse::().ok()) }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import {OrderDiscountSelectionStrategy, DiscountClass} from "../generated/api"; /** * @typedef {import("../generated/api").Input} CartInput * @typedef {import("../generated/api").CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * generateCartRun * @param {CartInput} input - The CartInput * @returns {CartLinesDiscountsGenerateRunResult} - The function result with discounts. */ export function cartLinesDiscountsGenerateRun(input) { const percentageOff = getPercentageOff(input.triggeringDiscountCode); const hasOrderDiscount = input.discount.discountClasses.includes( DiscountClass.Order, ); if (!hasOrderDiscount || !percentageOff) { return { operations: [], }; } return { operations: [ { orderDiscountsAdd: { candidates: [ { message: `${percentageOff}% off order`, targets: [ { orderSubtotal: { excludedCartLineIds: [], }, }, ], value: { percentage: { value: percentageOff, }, }, }, ], selectionStrategy: OrderDiscountSelectionStrategy.First, }, }, ], }; } function getPercentageOff(code) { const percentageOff = code.match(/([\d]{1,2})%OFF/); return percentageOff ? parseInt(percentageOff[1], 10) : null; } ``` ##### Output JSON ```json { "operations": [ { "orderDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "conditions": null, "message": "20% off order", "targets": [ { "orderSubtotal": { "excludedCartLineIds": [] } } ], "value": { "percentage": { "value": "20.0" } } } ], "selectionStrategy": "FIRST" } } ] } ``` #### cart.delivery-options.discounts.generate.run ##### Input Query ```graphql query Input { discount { discountClasses } triggeringDiscountCode cart { deliveryGroups { id } } } ``` ##### Input Object ```json { "discount": { "discountClasses": ["SHIPPING"] }, "triggeringDiscountCode": "50%OFF", "cart": { "deliveryGroups": [ { "id": "gid://shopify/CartDeliveryGroup/1" } ] } } ``` ##### Function Code (Rust) ```rust use crate::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_delivery_options_discounts_generate_run( input: schema::cart_delivery_options_discounts_generate_run::Input, ) -> Result{ if !input .discount() .discount_classes() .contains(&schema::DiscountClass::Shipping) { return Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![] }); } if let Some(percentage_off) = get_percentage_off(&input.triggering_discount_code()) { return Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: input .cart() .delivery_groups() .iter() .map(|group| { schema::DeliveryOperation::DeliveryDiscountsAdd(schema::DeliveryDiscountsAddOperation { selection_strategy: schema::DeliveryDiscountSelectionStrategy::All, candidates: vec![schema::DeliveryDiscountCandidate { targets: vec![schema::DeliveryDiscountCandidateTarget::DeliveryGroup( schema::DeliveryGroupTarget { id: group.id().clone(), }, )], value: schema::DeliveryDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(percentage_off as f64), }), message: Some(format!("{}% off shipping", percentage_off)), associated_discount_code: None, }], }) }) .collect(), }); } Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![] }) } fn get_percentage_off(code: &Option<&String>) -> Option { code.as_ref().and_then(|discount_code| { discount_code .strip_suffix("%OFF") .filter(|digits| !digits.is_empty()) .and_then(|digits| digits.parse::().ok()) }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { DeliveryDiscountSelectionStrategy, DiscountClass, } from "../generated/api"; /** * @typedef {import("../generated/api").Input} RunInput * @typedef {import("../generated/api").CartDeliveryOptionsDiscountsGenerateRunResult} CartDeliveryOptionsDiscountsGenerateRunResult */ /** * generateDeliveryRun * @param {RunInput} input - The DeliveryInput * @returns {CartDeliveryOptionsDiscountsGenerateRunResult} - The function result with discounts. */ export function cartDeliveryOptionsDiscountsGenerateRun(input) { const percentageOff = getPercentageOff(input.triggeringDiscountCode); const hasShippingDiscount = input.discount.discountClasses.includes( DiscountClass.Shipping, ); if (!hasShippingDiscount || !percentageOff) { return { operations: [], }; } const operations = input.cart.deliveryGroups.map(deliveryGroup => ({ deliveryDiscountsAdd: { candidates: [ { message: `${percentageOff}% off shipping`, targets: [ { deliveryGroup: { id: deliveryGroup.id, }, }, ], value: { percentage: { value: percentageOff, }, }, }, ], selectionStrategy: DeliveryDiscountSelectionStrategy.All, }, })); return {operations}; } function getPercentageOff(code) { const percentageOff = code.match(/([\d]{1,2})%OFF/); return percentageOff ? parseInt(percentageOff[1], 10) : null; } ``` ##### Output JSON ```json { "operations": [ { "deliveryDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "50% off shipping", "targets": [ { "deliveryGroup": { "id": "gid://shopify/CartDeliveryGroup/1" } } ], "value": { "percentage": { "value": "50.0" } } } ], "selectionStrategy": "ALL" } } ] } ``` * ### Apply a collection-based order discount Example implementation of a discounts function that applies a 10% discount to the order if the cart total is high enough and a product in the cart belongs to a specific collection. in this example the subtotal must be above $100 and there must be a product in the TORONTO collection. You can use this example to understand how to: \* Apply a percent discount to the if the order is worth enough money \* Apply a percent discount if its for a product in a certain collection \* Not apply a percent discount if the order is not for the right products \* Not apply a percent discount if the order does not contain products from a certain collection. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id merchandise { __typename ... on ProductVariant { product { inAnyCollection(ids: ["gid://shopify/Collection/452849795317"]) } } } } } discount { discountClasses } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/0", "merchandise": { "__typename": "ProductVariant", "product": { "inAnyCollection": true } } } ] }, "discount": { "discountClasses": ["PRODUCT", "ORDER", "SHIPPING"] } } ``` ##### Function Code (Rust) ```rust use crate::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_lines_discounts_generate_run( input: schema::cart_lines_discounts_generate_run::Input, ) -> Result { if input.cart().lines().is_empty() { return Err("No cart lines found".into()); } // Check if the discount has the ORDER class let has_order_discount_class = input .discount() .discount_classes() .contains(&schema::DiscountClass::Order); // If the order cannot be discounted, return early if !has_order_discount_class { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] }); } // Check if there are any products in the collection let products_in_collection = input.cart().lines().iter().any(|line| { let merchandise = &line.merchandise(); if let schema::cart_lines_discounts_generate_run::input::cart::lines::Merchandise::ProductVariant(variant) = merchandise { return *variant.product().in_any_collection(); } false }); // If there are products in the collection, add the order discount if products_in_collection { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![schema::CartOperation::OrderDiscountsAdd( schema::OrderDiscountsAddOperation { selection_strategy: schema::OrderDiscountSelectionStrategy::First, candidates: vec![schema::OrderDiscountCandidate { targets: vec![schema::OrderDiscountCandidateTarget::OrderSubtotal( schema::OrderSubtotalTarget { excluded_cart_line_ids: vec![], }, )], message: Some("10% OFF ORDER".to_string()), value: schema::OrderDiscountCandidateValue::Percentage( schema::Percentage { value: Decimal(10.0), }, ), conditions: None, associated_discount_code: None, }], }, )], }); } Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] }) } ``` ##### Function Code (JavaScript) ```javascript import { DiscountClass, OrderDiscountSelectionStrategy, } from "../generated/api"; /** * @typedef {import("../generated/api").CartInput} RunInput * @typedef {import("../generated/api").CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * @param {RunInput} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { if (!input.cart.lines.length) { throw new Error("No cart lines found"); } const discountClasses = input.discount.discountClasses || []; const canDiscountOrder = discountClasses.includes(DiscountClass.Order); // If the order cannot be discounted, return early if (!canDiscountOrder) { return { operations: [] }; } // Check if there are any products in the collection const productsInCollection = input.cart.lines.some( (line) => line.merchandise.__typename === "ProductVariant" && line.merchandise.product?.inAnyCollection ); // If there are products in the collection, add the order discount if (productsInCollection) { return { operations: [ { orderDiscountsAdd: { candidates: [ { message: "10% OFF ORDER", targets: [{ orderSubtotal: { excludedCartLineIds: [] } }], value: { percentage: { value: 10 } }, }, ], selectionStrategy: OrderDiscountSelectionStrategy.First, }, }, ], }; } return { operations: [] }; } ``` ##### Output JSON ```json { "operations": [ { "orderDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "conditions": null, "message": "10% OFF ORDER", "targets": [ { "orderSubtotal": { "excludedCartLineIds": [] } } ], "value": { "percentage": { "value": "10.0" } } } ], "selectionStrategy": "FIRST" } } ] } ``` * ### Apply a discount to custom products This example demonstrates how to create a discount function that applies a 20% discount to all custom products. Custom products are identified by a metafield on the product. This example demonstrates: \* Creating a discount function \* Checking the metafield on the products in the cart \* Applying a discount to the cart lines that have the custom product metafield set to true \* Returning the discount application result \* Using `ProductDiscountSelectionStrategy.All` to ensure all eligible products receive the discount #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id merchandise { __typename ... on ProductVariant { product { metafield(namespace: "custom", key: "isCustom") { value } } } } } } discount { discountClasses } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/0", "merchandise": { "__typename": "ProductVariant", "product": { "metafield": { "value": "true" } } } } ] }, "discount": { "discountClasses": [ "PRODUCT" ] } } ``` ##### Function Code (Rust) ```rust use crate::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_lines_discounts_generate_run( input: schema::cart_lines_discounts_generate_run::Input, ) -> Result { if input.cart().lines().is_empty() { return Err("No cart lines found".into()); } let has_product_discount_class = input .discount() .discount_classes() .contains(&schema::DiscountClass::Product); if !has_product_discount_class { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] }); } let mut operations = vec![]; // Find products with isCustom metafield set to true let custom_product_lines: Vec<_> = input .cart() .lines() .iter() .filter(|line| { // Check if the line has a product with isCustom metafield if let schema::cart_lines_discounts_generate_run::input::cart::lines::Merchandise::ProductVariant(variant) = &line.merchandise() { if let Some(metafield) = &variant.product().metafield() { return *metafield.value() == "true"; } } false }) .collect(); if !custom_product_lines.is_empty() { // Apply 20% discount to all custom products let candidates = custom_product_lines .iter() .map(|line| schema::ProductDiscountCandidate { targets: vec![schema::ProductDiscountCandidateTarget::CartLine( schema::CartLineTarget { id: line.id().to_string(), quantity: None, }, )], message: Some("20% OFF CUSTOM PRODUCT".to_string()), value: schema::ProductDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(20.0), }), associated_discount_code: None, }) .collect::>(); operations.push(schema::CartOperation::ProductDiscountsAdd( schema::ProductDiscountsAddOperation { selection_strategy: schema::ProductDiscountSelectionStrategy::All, candidates, }, )); } Ok(schema::CartLinesDiscountsGenerateRunResult { operations }) } ``` ##### Function Code (JavaScript) ```javascript import { DiscountClass, ProductDiscountSelectionStrategy, } from '../generated/api'; /** * @typedef {import("../generated/api").CartInput} RunInput * @typedef {import("../generated/api").CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * @param {RunInput} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { if (!input.cart.lines.length) { throw new Error('No cart lines found'); } const hasProductDiscountClass = input.discount.discountClasses.includes( DiscountClass.Product, ); const operations = []; if (hasProductDiscountClass) { // Find products with isCustom metafield set to true const customProductLines = input.cart.lines.filter(line => { // Check if the line has a product with isCustom metafield if (line.merchandise.__typename !== 'ProductVariant') return false; const metafield = line.merchandise.product?.metafield; return metafield && metafield.value === 'true'; }); if (customProductLines.length > 0) { // Apply 20% discount to all custom products operations.push({ productDiscountsAdd: { candidates: customProductLines.map(line => ({ message: '20% OFF CUSTOM PRODUCT', targets: [ { cartLine: { id: line.id, }, }, ], value: { percentage: { value: 20, }, }, })), selectionStrategy: ProductDiscountSelectionStrategy.All, }, }); } } return { operations, }; } ``` ##### Output JSON ```json { "operations": [ { "productDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "20% OFF CUSTOM PRODUCT", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/0", "quantity": null } } ], "value": { "percentage": { "value": "20.0" } } } ], "selectionStrategy": "ALL" } } ] } ``` * ### Apply a discount to orders with no sale items This example implements a Shopify function that gives a configurable discount to any order whose product variants do not have a compare-at price higher than its current price. The discount percentage is stored in an app-owned metafield. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id quantity cost { amountPerQuantity { amount } compareAtAmountPerQuantity { amount } } } } discount { metafield(namespace: "$app:order-discount", key: "function-configuration") { jsonValue } } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/1", "quantity": 2, "cost": { "amountPerQuantity": { "amount": "50.00" }, "compareAtAmountPerQuantity": null } } ] }, "discount": { "metafield": { "jsonValue": { "percentage": 10.0 } } } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize, Default, PartialEq)] pub struct Configuration { percentage: f64, } #[shopify_function] fn cart_lines_discounts_generate_run(input: schema::cart_lines_discounts_generate_run::Input) -> Result { let config= match input.discount().metafield() { Some(metafield) => metafield.json_value(), None => return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }), }; // Check if any product has a compare-at price greater than the current price let has_higher_compare_at_price = input.cart().lines().iter().any(|line| { if let Some(compare_at_amount) = &line.cost().compare_at_amount_per_quantity() { let current_price = line.cost().amount_per_quantity().amount().0; let compare_at_price = compare_at_amount.amount().0; compare_at_price > current_price } else { false } }); if has_higher_compare_at_price { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }); } // Apply the discount to the entire order Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![ schema::CartOperation::OrderDiscountsAdd(schema::OrderDiscountsAddOperation { selection_strategy: schema::OrderDiscountSelectionStrategy::First, candidates: vec![schema::OrderDiscountCandidate { conditions: None, value: schema::OrderDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(config.percentage), }), targets: vec![schema::OrderDiscountCandidateTarget::OrderSubtotal( schema::OrderSubtotalTarget { excluded_cart_line_ids: vec![], }, )], message: Some(format!("{}% off your order!", config.percentage)), associated_discount_code: None, }], }), ], }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { OrderDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {import('../generated/api').Input} Input * @typedef {import('../generated/api').CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * @param {Input} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { // Parse configuration or return empty discount if no metafield const configuration = input.discount?.metafield?.jsonValue || { percentage: 0 }; if (!configuration.percentage) { return { operations: [] }; } // Check if any product has a compare-at price greater than the current price const hasHigherCompareAtPrice = input.cart.lines.some(line => { const compareAtAmount = line.cost.compareAtAmountPerQuantity?.amount; const currentPrice = line.cost.amountPerQuantity.amount; return compareAtAmount > currentPrice; }); if (hasHigherCompareAtPrice) { return { operations: [] }; } // Apply the discount to the entire order return { operations: [ { orderDiscountsAdd: { candidates: [ { value: { percentage: { value: configuration.percentage.toFixed(1) } }, targets: [ { orderSubtotal: { excludedCartLineIds: [] } } ], message: `${configuration.percentage}% off your order!` } ], selectionStrategy: OrderDiscountSelectionStrategy.First } } ] }; } ``` ##### Output JSON ```json { "operations": [ { "orderDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "conditions": null, "message": "10% off your order!", "targets": [ { "orderSubtotal": { "excludedCartLineIds": [] } } ], "value": { "percentage": { "value": "10.0" } } } ], "selectionStrategy": "FIRST" } } ] } ``` * ### Apply tiered discounts based on order subtotal This function implements tiered discounting based on order subtotal setting a minimum order subtotal for each tier, and storing the tier in an app owned metafield. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { cost { subtotalAmount { amount currencyCode } } } discount { metafield(namespace: "order-discount", key: "function-configuration") { jsonValue } } } ``` ##### Input Object ```json { "cart": { "cost": { "subtotalAmount": { "amount": "150.00", "currencyCode": "USD" } } }, "discount": { "metafield": { "jsonValue": { "tiers": [ { "threshold": 100.0, "percentage": 10.0 }, { "threshold": 200.0, "percentage": 15.0 } ] } } } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize, Default, PartialEq)] struct Tier { threshold: f64, percentage: f64, } #[derive(Deserialize, Default, PartialEq)] pub struct Configuration { tiers: Vec, } #[shopify_function] fn cart_lines_discounts_generate_run(input: schema::cart_lines_discounts_generate_run::Input) -> Result { let config = match input.discount().metafield() { Some(metafield) => metafield.json_value(), None => { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }) } }; let subtotal = input.cart().cost().subtotal_amount().amount().0; // Get all applicable discount tiers let applicable_tiers: Vec<&Tier> = config .tiers .iter() .filter(|tier| subtotal >= tier.threshold) .collect(); if !applicable_tiers.is_empty() { let candidates = applicable_tiers .into_iter() .map(|tier| schema::OrderDiscountCandidate { value: schema::OrderDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal::from(tier.percentage), }), targets: vec![schema::OrderDiscountCandidateTarget::OrderSubtotal( schema::OrderSubtotalTarget { excluded_cart_line_ids: vec![], }, )], message: Some(format!("{}% off your order", tier.percentage)), conditions: Some(vec![schema::Condition::OrderMinimumSubtotal( schema::OrderMinimumSubtotal { minimum_amount: Decimal::from(tier.threshold), excluded_cart_line_ids: vec![], }, )]), associated_discount_code: None, }) .collect(); Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![ schema::CartOperation::OrderDiscountsAdd(schema::OrderDiscountsAddOperation { selection_strategy: schema::OrderDiscountSelectionStrategy::Maximum, candidates, }), ], }) } else { Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }) } } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { OrderDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {import('../generated/api').Input} Input * @typedef {import('../generated/api').CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult * @typedef {import('../generated/api').OrderDiscountCandidate} OrderDiscountCandidate */ /** * @typedef {Object} Tier * @property {number} threshold * @property {number} percentage */ /** * @typedef {Object} Configuration * @property {Tier[]} tiers */ /** * @param {Input} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { // Return empty operations if no cart or metafield if (!input?.discount?.metafield) { return { operations: [] }; } // Parse configuration from metafield /** @type {Configuration} */ const configuration = input.discount.metafield?.jsonValue ?? { tiers: [] }; const subtotal = parseFloat(input.cart.cost.subtotalAmount?.amount ?? "0"); // Get all applicable discount tiers const applicableTiers = configuration.tiers?.filter(tier => subtotal >= tier.threshold) ?? []; if (applicableTiers.length === 0) { return { operations: [] }; } /** @type {OrderDiscountCandidate[]} */ const candidates = applicableTiers.map(tier => ({ value: { percentage: { value: tier.percentage.toFixed(1) } }, targets: [{ orderSubtotal: { excludedCartLineIds: [] } }], message: `${tier.percentage}% off your order`, conditions: [{ orderMinimumSubtotal: { excludedCartLineIds: [], minimumAmount: tier.threshold.toFixed(1).toString() } }] })); return { operations: [ { orderDiscountsAdd: { candidates, selectionStrategy: OrderDiscountSelectionStrategy.Maximum } } ] }; } ``` ##### Output JSON ```json { "operations": [ { "orderDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "conditions": [ { "orderMinimumSubtotal": { "excludedCartLineIds": [], "minimumAmount": "100.0" } } ], "message": "10% off your order", "targets": [ { "orderSubtotal": { "excludedCartLineIds": [] } } ], "value": { "percentage": { "value": "10.0" } } } ], "selectionStrategy": "MAXIMUM" } } ] } ``` * ### Apply a fixed discount for collection-specific purchases Example implementation of a discount function that applies a discount to the order if the order total is high enough and a product in the cart belongs to a specific collection. In this example the order subtotal must be above $100 and there must be a product in the TORONTO collection. You can use this example to understand how to: \* Apply a discount to the order if the order is worth enough money \* Apply an order discount if its for a product in a certain collection \* Not apply a order discount if the order is not for the right products \* Not apply an order discount if the order does not contain products from a certain collection. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { merchandise { __typename ... on ProductVariant { product { inAnyCollection(ids: ["gid://shopify/Collection/452849795317"]) } } } } cost { subtotalAmount { amount } } } } ``` ##### Input Object ```json { "cart": { "cost": { "subtotalAmount": { "amount": "100.0" } }, "lines": [ { "merchandise": { "__typename": "ProductVariant", "product": { "inAnyCollection": true } } } ] } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_lines_discounts_generate_run(input: schema::cart_lines_discounts_generate_run::Input) -> Result { // Check if the cart contains a product from the Toronto Collection let mut is_in_collection = false; for line in input.cart().lines().iter() { let variant = match &line.merchandise() { schema::cart_lines_discounts_generate_run::input::cart::lines::Merchandise::ProductVariant(variant) => variant, _ => continue, // Do not select for CustomProduct unless it's selected in the input query }; let in_collection = variant.product().in_any_collection(); if *in_collection == true { is_in_collection = true; break; } } // If the cart does not contain a product from the Toronto collection, // then there should be no discount applied if !is_in_collection { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }); } // If the value of the order is not high enough, // don't apply any discount let amount = input.cart().cost().subtotal_amount().amount().0; let min_amount = Decimal::from(100.0); if amount < *min_amount { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }); } // If the cart contains a product from the Toronto Collection, // and the value of the order is high enough, // then we apply a $50 discount to the order Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![ schema::CartOperation::OrderDiscountsAdd(schema::OrderDiscountsAddOperation { selection_strategy: schema::OrderDiscountSelectionStrategy::First, candidates: vec![ schema::OrderDiscountCandidate { message: Some("$50 off the Toronto Collection!".to_string()), targets: vec![ schema::OrderDiscountCandidateTarget::OrderSubtotal( schema::OrderSubtotalTarget { excluded_cart_line_ids: vec![], } ), ], value: schema::OrderDiscountCandidateValue::FixedAmount( schema::FixedAmount { amount: Decimal::from(50.0), } ), conditions: None, associated_discount_code: None, } ], }), ], }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { OrderDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {import('../generated/api').Input} Input * @typedef {import('../generated/api').CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * @param {Input} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { // The cart is only eligible for the discount if it contains a product from the Toronto Collection const isInCollection = input.cart.lines.some( (line) => line.merchandise.__typename === "ProductVariant" && line.merchandise.product.inAnyCollection ); // If the cart does not contain a product from a the TORONTO collection, // then there should be no discount applied if (!isInCollection) { return { operations: [] }; } // If the value of the order is not high enough, // don't apply any discount, but inform the customer if (input.cart.cost.subtotalAmount.amount < 100) { return { operations: [] }; } // If the cart contains a product from the Toronto Collection, // and the value of the order is high enough, // then we apply a $50 discount to the order return { operations: [ { orderDiscountsAdd: { candidates: [ { message: "$50 off the Toronto Collection!", value: { fixedAmount: { amount: 50.0, }, }, targets: [ { orderSubtotal: { excludedCartLineIds: [], }, }, ], }, ], selectionStrategy: OrderDiscountSelectionStrategy.First, }, }, ], }; } ``` ##### Output JSON ```json { "operations": [ { "orderDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "conditions": null, "message": "$50 off the Toronto Collection!", "targets": [ { "orderSubtotal": { "excludedCartLineIds": [] } } ], "value": { "fixedAmount": { "amount": "50.0" } } } ], "selectionStrategy": "FIRST" } } ] } ``` * ### Apply a discount to orders containing only new collection items This function checks if all products in the order have a specific product tag. If so, it applies a percent off discount to the order. This example demonstrates \* Creating a discount function \* Checking the tags on the products in the order \* Applying a discount to the order #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { merchandise { __typename ... on ProductVariant { id product { hasAnyTag(tags: ["new_collection"]) } } } } } } ``` ##### Input Object ```json { "cart": { "lines": [ { "merchandise": { "__typename": "ProductVariant", "id": "gid://shopify/ProductVariant/46711460495653", "product": { "hasAnyTag": true } } } ] } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_lines_discounts_generate_run(input: schema::cart_lines_discounts_generate_run::Input) -> Result { // Get cart lines from input let cart_lines = &input.cart().lines(); // Check if there are any cart lines if cart_lines.is_empty() { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }); } // Check if ALL products have "new_collection" tag let all_products_new_collection = cart_lines.iter().all(|line| { if let schema::cart_lines_discounts_generate_run::input::cart::lines::Merchandise::ProductVariant(variant) = &line.merchandise() { let product = &variant.product(); return *product.has_any_tag(); } false }); // If all products have "new_collection" tag, apply 10% discount if all_products_new_collection { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![ schema::CartOperation::OrderDiscountsAdd(schema::OrderDiscountsAddOperation { selection_strategy: schema::OrderDiscountSelectionStrategy::Maximum, candidates: vec![ schema::OrderDiscountCandidate { conditions: None, message: Some("10% off your new collection order!".to_string()), targets: vec![ schema::OrderDiscountCandidateTarget::OrderSubtotal( schema::OrderSubtotalTarget { excluded_cart_line_ids: vec![], } ), ], value: schema::OrderDiscountCandidateValue::Percentage( schema::Percentage { value: Decimal(10.0), } ), associated_discount_code: None, }, ], }), ], }); } Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { OrderDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {import('../generated/api').Input} Input * @typedef {import('../generated/api').CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * @param {Input} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { // Get cart lines from input const cartLines = input.cart?.lines || []; // Check if ALL products have "new_collection" tag const allProductsNewCollection = cartLines.length > 0 && cartLines.every(line => { const merchandise = line.merchandise; if (merchandise.__typename === 'ProductVariant') { return merchandise.product?.hasAnyTag; } return false; }); // If all products have "new_collection" tag, apply 10% discount if (allProductsNewCollection) { return { operations: [ { orderDiscountsAdd: { candidates: [ { message: "10% off your new collection order!", targets: [ { orderSubtotal: { excludedCartLineIds: [] } } ], value: { percentage: { value: "10.0" } } } ], selectionStrategy: OrderDiscountSelectionStrategy.Maximum } } ] }; } return { operations: [] }; } ``` ##### Output JSON ```json { "operations": [ { "orderDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "conditions": null, "message": "10% off your new collection order!", "targets": [ { "orderSubtotal": { "excludedCartLineIds": [] } } ], "value": { "percentage": { "value": "10.0" } } } ], "selectionStrategy": "MAXIMUM" } } ] } ``` * ### Apply a percentage discount to specific products This example implements a Shopify function that gives a configurable amount of discount off a number of product variants. The configuration is stored in an app owned metafield. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id quantity merchandise { __typename ... on ProductVariant { id title } } } } discount { metafield(namespace: "$app:product-discount", key: "function-configuration") { jsonValue } } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/1", "quantity": 2, "merchandise": { "__typename": "ProductVariant", "id": "gid://shopify/ProductVariant/1234567890", "title": "Small / Black" } }, { "id": "gid://shopify/CartLine/2", "quantity": 1, "merchandise": { "__typename": "ProductVariant", "id": "gid://shopify/ProductVariant/9876543210", "title": "Medium / Blue" } } ] }, "discount": { "metafield": { "jsonValue": { "percentage": 15, "target_variant_ids": [ "gid://shopify/ProductVariant/1234567890", "gid://shopify/ProductVariant/9876543210" ] } } } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize, Default, PartialEq)] pub struct Configuration { percentage: f64, target_variant_ids: Vec, } #[shopify_function] fn cart_lines_discounts_generate_run(input: schema::cart_lines_discounts_generate_run::Input) -> Result { let config: &Configuration = match input.discount().metafield() { Some(metafield) => metafield.json_value(), None => return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }), }; let mut candidates = vec![]; for line in input.cart().lines().iter() { let variant = match &line.merchandise() { schema::cart_lines_discounts_generate_run::input::cart::lines::Merchandise::ProductVariant(variant) => variant, _ => continue, }; if config.target_variant_ids.contains(&variant.id()) { let message = match &variant.title() { Some(title) => format!("{}% off {}!", config.percentage, title), None => format!("{}% off this product!", config.percentage), }; candidates.push(schema::ProductDiscountCandidate { value: schema::ProductDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal::from(config.percentage), }), targets: vec![schema::ProductDiscountCandidateTarget::ProductVariant( schema::ProductVariantTarget { id: variant.id().clone(), quantity: Some(*line.quantity()), }, )], message: Some(message), associated_discount_code: None, }); } } if candidates.is_empty() { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }); } Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![ schema::CartOperation::ProductDiscountsAdd(schema::ProductDiscountsAddOperation { selection_strategy: schema::ProductDiscountSelectionStrategy::First, candidates, }), ], }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { ProductDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {import('../generated/api').Input} Input * @typedef {import('../generated/api').CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * @param {Input} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { // Parse configuration from metafield const configuration = input?.discount?.metafield?.jsonValue ?? {}; // Return empty operations if no configuration if (!configuration || !configuration.target_variant_ids || !configuration.percentage) { return { operations: [] }; } const candidates = []; // Return empty operations if no cart or lines if (!input.cart.lines) { return { operations: [] }; } // Process each cart line for (const line of input.cart.lines) { // Skip if not a product variant if (line.merchandise.__typename !== "ProductVariant") { continue; } // Check if variant is in target list if (configuration.target_variant_ids.includes(line.merchandise.id)) { const message = line.merchandise.title ? `${configuration.percentage}% off ${line.merchandise.title}!` : `${configuration.percentage}% off this product!`; candidates.push({ value: { percentage: { value: configuration.percentage.toFixed(1).toString() } }, targets: [ { productVariant: { id: line.merchandise.id, quantity: line.quantity } } ], message }); } } if (candidates.length === 0) { return { operations: [] }; } return { operations: [ { productDiscountsAdd: { candidates, selectionStrategy: ProductDiscountSelectionStrategy.First } } ] }; } ``` ##### Output JSON ```json { "operations": [ { "productDiscountsAdd": { "selectionStrategy": "FIRST", "candidates": [ { "message": "15% off Small / Black!", "targets": [ { "productVariant": { "id": "gid://shopify/ProductVariant/1234567890", "quantity": 2 } } ], "value": { "percentage": { "value": "15.0" } } }, { "message": "15% off Medium / Blue!", "targets": [ { "productVariant": { "id": "gid://shopify/ProductVariant/9876543210", "quantity": 1 } } ], "value": { "percentage": { "value": "15.0" } } } ] } } ] } ``` * ### Apply a discount to the first cart line This example implements a Shopify function that gives a 20% off the first line in the cart. #### cart.delivery-options.discounts.generate.run ##### Input Query ```graphql query Input { cart { deliveryGroups { id } } } ``` ##### Input Object ```json { "cart": { "deliveryGroups": [ { "id": "gid://shopify/DeliveryGroup/1" } ] } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_delivery_options_discounts_generate_run( input: schema::cart_delivery_options_discounts_generate_run::Input, ) -> Result { let first_delivery_group = input .cart() .delivery_groups() .first() .ok_or("No delivery groups found")?; Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![schema::DeliveryOperation::DeliveryDiscountsAdd( schema::DeliveryDiscountsAddOperation { selection_strategy: schema::DeliveryDiscountSelectionStrategy::All, candidates: vec![schema::DeliveryDiscountCandidate { targets: vec![schema::DeliveryDiscountCandidateTarget::DeliveryGroup( schema::DeliveryGroupTarget { id: first_delivery_group.id().clone(), }, )], value: schema::DeliveryDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(100.0), }), message: Some("FREE DELIVERY".to_string()), associated_discount_code: None, }], }, )], }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { DeliveryDiscountSelectionStrategy} from '../generated/api'; /** * @typedef {import("../generated/api").Input} RunInput * @typedef {import("../generated/api").CartDeliveryOptionsDiscountsGenerateRunResult} CartDeliveryOptionsDiscountsGenerateRunResult */ /** * cartDeliveryOptionsDiscountsGenerateRun * @param {RunInput} input - The DeliveryInput * @returns {CartDeliveryOptionsDiscountsGenerateRunResult} - The function result with discounts. */ export function cartDeliveryOptionsDiscountsGenerateRun(input) { const firstDeliveryGroup = input.cart.deliveryGroups[0]; if (!firstDeliveryGroup) { throw new Error('No delivery groups found'); } return { operations: [ { deliveryDiscountsAdd: { candidates: [ { message: 'FREE DELIVERY', targets: [ { deliveryGroup: { id: firstDeliveryGroup.id, }, }, ], value: { percentage: { value: "100.0", }, }, }, ], selectionStrategy: DeliveryDiscountSelectionStrategy.All, }, }, ], }; } ``` ##### Output JSON ```json { "operations": [ { "deliveryDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "FREE DELIVERY", "targets": [ { "deliveryGroup": { "id": "gid://shopify/DeliveryGroup/1" } } ], "value": { "percentage": { "value": "100.0" } } } ], "selectionStrategy": "ALL" } } ] } ``` #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id quantity } } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/1", "quantity": 1 } ] } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_lines_discounts_generate_run(input: schema::cart_lines_discounts_generate_run::Input) -> Result { let mut operations = vec![]; let percentage = 20.0; // Check if there are any lines in the cart if let Some(first_line) = input.cart().lines().first() { operations.push(schema::CartOperation::ProductDiscountsAdd(schema::ProductDiscountsAddOperation { selection_strategy: schema::ProductDiscountSelectionStrategy::First, candidates: vec![schema::ProductDiscountCandidate { targets: vec![schema::ProductDiscountCandidateTarget::CartLine(schema::CartLineTarget { id: first_line.id().clone(), quantity: None, })], message: Some(format!("{}% off first item", percentage)), value: schema::ProductDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(percentage), }), associated_discount_code: None, }], })); } Ok(schema::CartLinesDiscountsGenerateRunResult { operations }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { ProductDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {import("../generated/api").Input} Input * @typedef {import("../generated/api").CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * cartLinesDiscountsGenerateRun * @param {Input} input - The CartInput * @returns {CartLinesDiscountsGenerateRunResult} - The function result with discounts. */ export function cartLinesDiscountsGenerateRun(input) { const percentage = 20; const operations = []; // Check if there are any lines in the cart if (input.cart.lines.length > 0) { const firstLine = input.cart.lines[0]; operations.push({ productDiscountsAdd: { candidates: [ { message: `${percentage}% off first item`, targets: [ { cartLine: { id: firstLine.id, }, }, ], value: { percentage: { value: percentage.toFixed(1), }, }, }, ], selectionStrategy: ProductDiscountSelectionStrategy.First, }, }); } return { operations }; } ``` ##### Output JSON ```json { "operations": [ { "productDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "20% off first item", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/1", "quantity": null } } ], "value": { "percentage": { "value": "20.0" } } } ], "selectionStrategy": "FIRST" } } ] } ``` * ### Apply a per-item discount to a product with quantity limits This example implements a Shopify function that gives a configurable amount of discount off an item. The configuration is stored in an app owned metafield. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id quantity merchandise { __typename ... on ProductVariant { id title product { id } } } } } discount { metafield(namespace: "$app:product-discount", key: "function-configuration") { jsonValue } } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/1", "quantity": 3, "merchandise": { "__typename": "ProductVariant", "id": "gid://shopify/ProductVariant/1", "product": { "id": "gid://shopify/Product/1" } } } ] }, "discount": { "metafield": { "jsonValue": { "discount_amount": 10.0, "max_quantity": 2, "product_id": "gid://shopify/Product/1" } } } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize, Default, PartialEq)] pub struct Configuration { discount_amount: f64, max_quantity: i32, product_id: String, } #[shopify_function] fn cart_lines_discounts_generate_run(input: schema::cart_lines_discounts_generate_run::Input) -> Result { let config: &Configuration = match input.discount().metafield() { Some(metafield) => metafield.json_value(), None => return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }), }; let mut candidates = vec![]; let mut remaining_quantity = config.max_quantity; for line in input.cart().lines().iter() { let variant = match &line.merchandise() { schema::cart_lines_discounts_generate_run::input::cart::lines::Merchandise::ProductVariant(variant) => variant, _ => continue, }; if *variant.product().id() == config.product_id && remaining_quantity > 0 { let line_quantity = line.quantity(); let discount_quantity = remaining_quantity.min(*line_quantity); remaining_quantity -= discount_quantity; candidates.push(schema::ProductDiscountCandidate { value: schema::ProductDiscountCandidateValue::FixedAmount(schema::FixedAmount { amount: config.discount_amount.into(), applies_to_each_item: Some(true), }), targets: vec![schema::ProductDiscountCandidateTarget::ProductVariant(schema::ProductVariantTarget { id: variant.id().clone(), quantity: Some(discount_quantity), })], message: Some("Discount applied".to_string()), associated_discount_code: None, }); } } if candidates.is_empty() { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }); } Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![ schema::CartOperation::ProductDiscountsAdd(schema::ProductDiscountsAddOperation { selection_strategy: schema::ProductDiscountSelectionStrategy::First, candidates, }), ], }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { ProductDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {import('../generated/api').Input} Input * @typedef {import('../generated/api').CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult * @typedef {{ * discount_amount: number, * max_quantity: number, * product_id: string * }} Configuration */ /** * @param {Input} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { // Parse configuration from metafield /** @type {Configuration} */ const configuration = input.discount?.metafield?.jsonValue ?? {}; if (!configuration.discount_amount || !configuration.max_quantity || !configuration.product_id) { return { operations: [] }; } const candidates = []; let remainingQuantity = configuration.max_quantity; // Iterate through cart lines for (const line of input.cart.lines) { if (line.merchandise.__typename !== "ProductVariant") { continue; } if (line.merchandise.product.id === configuration.product_id && remainingQuantity > 0) { const lineQuantity = line.quantity; const discountQuantity = Math.min(remainingQuantity, lineQuantity); remainingQuantity -= discountQuantity; candidates.push({ value: { fixedAmount: { amount: configuration.discount_amount.toFixed(1).toString(), appliesToEachItem: true } }, targets: [{ productVariant: { id: line.merchandise.id, quantity: discountQuantity } }], message: "Discount applied" }); } } if (candidates.length === 0) { return { operations: [] }; } return { operations: [ { productDiscountsAdd: { candidates, selectionStrategy: ProductDiscountSelectionStrategy.First } } ] }; } ``` ##### Output JSON ```json { "operations": [ { "productDiscountsAdd": { "selectionStrategy": "FIRST", "candidates": [ { "message": "Discount applied", "targets": [ { "productVariant": { "id": "gid://shopify/ProductVariant/1", "quantity": 2 } } ], "value": { "fixedAmount": { "amount": "10.0", "appliesToEachItem": true } } } ] } } ] } ``` * ### Apply a per-item discount to a product with quantity limits This example implements a Shopify function that gives a configurable fixed amount discount off a cart line with a maximum quantity limit. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id quantity merchandise { __typename ... on ProductVariant { id product { id } } } } } discount { metafield(namespace: "$app:product-discount", key: "function-configuration") { jsonValue } } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/1", "quantity": 2, "merchandise": { "__typename": "ProductVariant", "id": "gid://shopify/ProductVariant/1234567890", "product": { "id": "gid://shopify/Product/123" } } }, { "id": "gid://shopify/CartLine/2", "quantity": 1, "merchandise": { "__typename": "ProductVariant", "id": "gid://shopify/ProductVariant/9876543210", "product": { "id": "gid://shopify/Product/456" } } } ] }, "discount": { "metafield": { "jsonValue": { "discount_amount": 10.0, "max_quantity": 1, "product_id": "gid://shopify/Product/123" } } } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize)] pub struct Configuration { discount_amount: f64, max_quantity: i32, product_id: String, } #[shopify_function] fn cart_lines_discounts_generate_run(input: schema::cart_lines_discounts_generate_run::Input) -> Result { // Extract configuration from metafield let config = match input.discount().metafield() { Some(metafield) => metafield.json_value(), None => return Ok(empty_discount()), }; let mut candidates = Vec::new(); let mut remaining_quantity = config.max_quantity; // Process each cart line for line in input.cart().lines() { if let schema::cart_lines_discounts_generate_run::input::cart::lines::Merchandise::ProductVariant(variant) = line.merchandise() { if *variant.product().id() == config.product_id && remaining_quantity > 0 { let discount_quantity = std::cmp::min(remaining_quantity, *line.quantity()); remaining_quantity -= discount_quantity; candidates.push(schema::ProductDiscountCandidate { value: schema::ProductDiscountCandidateValue::FixedAmount(schema::FixedAmount { amount: Decimal::from(config.discount_amount), applies_to_each_item: Some(true), }), targets: vec![schema::ProductDiscountCandidateTarget::CartLine(schema::CartLineTarget { id: line.id().to_string(), quantity: Some(discount_quantity), })], message: Some("Discount applied".to_string()), associated_discount_code: None, }); } } } if candidates.is_empty() { return Ok(empty_discount()); } Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![ schema::CartOperation::ProductDiscountsAdd(schema::ProductDiscountsAddOperation { selection_strategy: schema::ProductDiscountSelectionStrategy::First, candidates, }), ], }) } fn empty_discount() -> schema::CartLinesDiscountsGenerateRunResult { schema::CartLinesDiscountsGenerateRunResult { operations: Vec::new(), } } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { ProductDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {import('../generated/api').Input} Input * @typedef {import('../generated/api').CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * @param {Input} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { const configuration = input.discount?.metafield?.jsonValue ?? {}; if (!configuration.discount_amount || !configuration.max_quantity || !configuration.product_id) { return { operations: [] }; } const candidates = []; let remainingQuantity = configuration.max_quantity; for (const line of input.cart.lines) { if (line.merchandise.__typename !== "ProductVariant") { continue; } if (line.merchandise.product.id === configuration.product_id && remainingQuantity > 0) { const discountQuantity = Math.min(remainingQuantity, line.quantity); remainingQuantity -= discountQuantity; candidates.push({ value: { fixedAmount: { amount: configuration.discount_amount.toFixed(1).toString(), appliesToEachItem: true, }, }, targets: [ { cartLine: { id: line.id, quantity: discountQuantity, } }, ], message: "Discount applied", }); } } if (candidates.length === 0) { return { operations: [] }; } return { operations: [ { productDiscountsAdd: { candidates, selectionStrategy: ProductDiscountSelectionStrategy.First } } ] }; } ``` ##### Output JSON ```json { "operations": [ { "productDiscountsAdd": { "selectionStrategy": "FIRST", "candidates": [ { "message": "Discount applied", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/1", "quantity": 1 } } ], "value": { "fixedAmount": { "amount": "10.0", "appliesToEachItem": true } } } ] } } ] } ``` * ### Apply a percentage discount to products with specific SKUs This example implements a Shopify function that gives a configurable discount to any cart line whose product variant has one of the specified SKUs. The SKUs and discount percentage are stored in an app-owned metafield. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id quantity merchandise { __typename ... on ProductVariant { id sku } } } } discount { metafield(namespace: "$app:product-discount", key: "function-configuration") { jsonValue } } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/1", "quantity": 2, "merchandise": { "__typename": "ProductVariant", "id": "gid://shopify/ProductVariant/1", "sku": "DISC-SKU1" } } ] }, "discount": { "metafield": { "jsonValue": { "percentage": 15.0, "skus": [ "DISC-SKU1", "DISC-SKU2", "SALE-SKU" ] } } } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize, Default, PartialEq)] pub struct Configuration { percentage: f64, skus: Vec, } #[shopify_function] fn cart_lines_discounts_generate_run(input: schema::cart_lines_discounts_generate_run::Input) -> Result { let config: &Configuration = match input.discount().metafield() { Some(metafield) => metafield.json_value(), None => return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }), }; let mut candidates = vec![]; for line in input.cart().lines() { let variant = match &line.merchandise() { schema::cart_lines_discounts_generate_run::input::cart::lines::Merchandise::ProductVariant(variant) => variant, _ => continue, }; // Check if the variant has a SKU and if it's in our target list if let Some(sku) = variant.sku() { if config.skus.contains(sku) { candidates.push(schema::ProductDiscountCandidate { value: schema::ProductDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(config.percentage), }), targets: vec![schema::ProductDiscountCandidateTarget::CartLine(schema::CartLineTarget { id: line.id().to_string(), quantity: None, })], message: Some(format!("{}% off!", config.percentage)), associated_discount_code: None, }); } } } if candidates.is_empty() { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }); } Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![ schema::CartOperation::ProductDiscountsAdd(schema::ProductDiscountsAddOperation { selection_strategy: schema::ProductDiscountSelectionStrategy::First, candidates, }), ], }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { ProductDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {import('../generated/api').Input} Input * @typedef {import('../generated/api').CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * @param {Input} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { // Parse configuration from metafield const configuration = input.discount?.metafield?.jsonValue ?? {}; if (!configuration.percentage || !configuration.skus || configuration.skus.length === 0) { return { operations: [] }; } const candidates = []; // Check each cart line for matching SKUs for (const line of input.cart.lines) { if (line.merchandise.__typename !== "ProductVariant") { continue; } if (line.merchandise.sku && configuration.skus.includes(line.merchandise.sku)) { candidates.push({ value: { percentage: { value: configuration.percentage.toFixed(1) } }, targets: [{ cartLine: { id: line.id } }], message: `${configuration.percentage}% off!` }); } } if (candidates.length === 0) { return { operations: [] }; } return { operations: [ { productDiscountsAdd: { candidates, selectionStrategy: ProductDiscountSelectionStrategy.First } } ] }; } ``` ##### Output JSON ```json { "operations": [ { "productDiscountsAdd": { "selectionStrategy": "FIRST", "candidates": [ { "message": "15% off!", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/1", "quantity": null } } ], "value": { "percentage": { "value": "15.0" } } } ] } } ] } ``` * ### Apply an extra discount to sale items This example implements a Shopify function that gives a configurable discount to any cart line whose product variant has a compare-at price higher than its current price. The discount percentage is stored in an app-owned metafield. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id quantity cost { amountPerQuantity { amount } compareAtAmountPerQuantity { amount } } } } discount { metafield(namespace: "$app:product-discount", key: "function-configuration") { jsonValue } } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/1", "quantity": 1, "cost": { "amountPerQuantity": { "amount": "80.00" }, "compareAtAmountPerQuantity": { "amount": "100.00" } } } ] }, "discount": { "metafield": { "jsonValue": { "percentage": 10.0 } } } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize, Default, PartialEq)] pub struct Configuration { percentage: f64, } #[shopify_function] fn cart_lines_discounts_generate_run(input: schema::cart_lines_discounts_generate_run::Input) -> Result { let config: &Configuration = match input.discount().metafield() { Some(metafield) => metafield.json_value(), None => return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }), }; let mut candidates = vec![]; for line in input.cart().lines() { // Check if there's a compare-at price and if it's higher than the current price if let Some(compare_at_amount) = &line.cost().compare_at_amount_per_quantity() { let current_price = line.cost().amount_per_quantity().amount().0; let compare_at_price = compare_at_amount.amount().0; if compare_at_price > current_price { candidates.push(schema::ProductDiscountCandidate { value: schema::ProductDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(config.percentage), }), targets: vec![schema::ProductDiscountCandidateTarget::CartLine(schema::CartLineTarget { id: line.id().to_string(), quantity: None, })], message: Some(format!("{}% off sale item!", config.percentage)), associated_discount_code: None, }); } } } if candidates.is_empty() { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }); } Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![ schema::CartOperation::ProductDiscountsAdd(schema::ProductDiscountsAddOperation { selection_strategy: schema::ProductDiscountSelectionStrategy::First, candidates, }), ], }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { ProductDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {import('../generated/api').Input} Input * @typedef {import('../generated/api').CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * @param {Input} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { // Parse configuration from metafield const configuration = input.discount?.metafield?.jsonValue || { percentage: 0 }; if (!configuration.percentage) { return { operations: [] }; } const candidates = []; // Check each cart line for compare-at prices for (const line of input.cart.lines) { const compareAtAmount = line.cost.compareAtAmountPerQuantity?.amount; const currentPrice = line.cost.amountPerQuantity.amount; // Apply discount if compare-at price is higher than current price if (compareAtAmount && compareAtAmount > currentPrice) { candidates.push({ value: { percentage: { value: configuration.percentage.toFixed(1) } }, targets: [{ cartLine: { id: line.id } }], message: `${configuration.percentage}% off sale item!` }); } } if (candidates.length === 0) { return { operations: [] }; } return { operations: [ { productDiscountsAdd: { candidates, selectionStrategy: ProductDiscountSelectionStrategy.First } } ] }; } ``` ##### Output JSON ```json { "operations": [ { "productDiscountsAdd": { "selectionStrategy": "FIRST", "candidates": [ { "message": "10% off sale item!", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/1", "quantity": null } } ], "value": { "percentage": { "value": "10.0" } } } ] } } ] } ``` * ### Apply a percentage discount for VIP customers This example implements a Shopify function that gives a configurable discount to customers with a "VIP" tag. The discount percentage is stored in an app-owned metafield and the tags are stored in a function-owned metafield. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id quantity } buyerIdentity { customer { hasAnyTag(tags: ["VIP"]) } } } discount { metafield(namespace: "$app:product-discount", key: "function-configuration") { jsonValue } } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/1", "quantity": 2 } ], "buyerIdentity": { "customer": { "hasAnyTag": true } } }, "discount": { "metafield": { "jsonValue": { "percentage": 10.0 } } } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize, Default, PartialEq)] pub struct Configuration { percentage: f64, } #[shopify_function] fn cart_lines_discounts_generate_run(input: schema::cart_lines_discounts_generate_run::Input) -> Result { // Get configuration or return early if no metafield is set let config: &Configuration = match input.discount().metafield() { Some(metafield) => metafield.json_value(), None => return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }), }; // Check if customer exists and has the VIP tag let has_vip_tag = input.cart() .buyer_identity() .as_ref() .and_then(|identity| identity.customer()) .map(|customer| *customer.has_any_tag()) .unwrap_or(false); if !has_vip_tag { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }); } // Create discount for all cart lines let candidates: Vec<_> = input.cart() .lines() .iter() .map(|line| { schema::ProductDiscountCandidate { value: schema::ProductDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(config.percentage), }), targets: vec![schema::ProductDiscountCandidateTarget::CartLine(schema::CartLineTarget { id: line.id().clone(), quantity: None, })], message: Some(format!("{}% VIP discount!", config.percentage)), associated_discount_code: None, } }).collect(); if candidates.is_empty() { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }); } Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![ schema::CartOperation::ProductDiscountsAdd(schema::ProductDiscountsAddOperation { selection_strategy: schema::ProductDiscountSelectionStrategy::First, candidates, }), ], }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { ProductDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {import('../generated/api').Input} Input * @typedef {import('../generated/api').CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * @param {Input} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { // Parse configuration from metafield const configuration = input.discount?.metafield?.jsonValue || { percentage: 0 }; if (!configuration.percentage) { return { operations: [] }; } // Check if customer has VIP tag const hasVipTag = input.cart.buyerIdentity?.customer?.hasAnyTag || false; if (!hasVipTag) { return { operations: [] }; } const candidates = []; // Apply discount to all cart lines for (const line of input.cart.lines) { candidates.push({ value: { percentage: { value: configuration.percentage.toFixed(1) } }, targets: [{ cartLine: { id: line.id } }], message: `${configuration.percentage}% VIP discount!` }); } if (candidates.length === 0) { return { operations: [] }; } return { operations: [ { productDiscountsAdd: { candidates, selectionStrategy: ProductDiscountSelectionStrategy.First } } ] }; } ``` ##### Output JSON ```json { "operations": [ { "productDiscountsAdd": { "selectionStrategy": "FIRST", "candidates": [ { "message": "10% VIP discount!", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/1", "quantity": null } } ], "value": { "percentage": { "value": "10.0" } } } ] } } ] } ``` * ### Apply tiered shipping discounts based on cart subtotal This function implements a discount function that applies a percentage discount to the cheapest shipping method based on the cart subtotal. #### cart.delivery-options.discounts.generate.run ##### Input Query ```graphql query Input { cart { cost { subtotalAmount { amount } } deliveryGroups { deliveryOptions { handle cost { amount } } } } discount { metafield(namespace: "$app:delivery-discounts", key: "configuration") { jsonValue } } } ``` ##### Input Object ```json { "cart": { "cost": { "subtotalAmount": { "amount": "120.00" } }, "deliveryGroups": [ { "deliveryOptions": [ { "handle": "standard", "cost": { "amount": "10.00" } }, { "handle": "express", "cost": { "amount": "20.00" } } ] } ] }, "discount": { "metafield": { "jsonValue": { "tiers": [ { "threshold": 50.0, "percentage": 10.0 }, { "threshold": 100.0, "percentage": 15.0 } ] } } } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize, Default, PartialEq)] struct DiscountTier { threshold: f64, percentage: f64, } #[derive(Deserialize, Default, PartialEq)] pub struct Configuration { tiers: Vec, } #[shopify_function] fn cart_delivery_options_discounts_generate_run(input: schema::cart_delivery_options_discounts_generate_run::Input) -> Result { let config = match input.discount().metafield() { Some(metafield) => metafield.json_value(), None => return Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![], }), }; // Get cart subtotal let subtotal = input.cart().cost().subtotal_amount().amount().0; // Find the highest applicable tier let applicable_tier = config.tiers.iter() .filter(|tier| subtotal >= tier.threshold) .max_by(|a, b| a.threshold.partial_cmp(&b.threshold).unwrap_or(std::cmp::Ordering::Equal)); // If no tier applies, return empty operations let Some(tier) = applicable_tier else { return Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![], }); }; let mut operations = vec![]; // Process each delivery group for delivery_group in input.cart().delivery_groups() { // Find the cheapest delivery option if let Some(cheapest_option) = delivery_group.delivery_options().iter() .min_by(|a, b| { let a_cost = a.cost().amount().0; let b_cost = b.cost().amount().0; a_cost.partial_cmp(&b_cost).unwrap_or(std::cmp::Ordering::Equal) }) { // Add discount operation for the cheapest option operations.push(schema::DeliveryOperation::DeliveryDiscountsAdd(schema::DeliveryDiscountsAddOperation { selection_strategy: schema::DeliveryDiscountSelectionStrategy::All, candidates: vec![schema::DeliveryDiscountCandidate { targets: vec![schema::DeliveryDiscountCandidateTarget::DeliveryOption( schema::DeliveryOptionTarget { handle: cheapest_option.handle().clone(), }, )], value: schema::DeliveryDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(tier.percentage), }), message: Some(format!("{}% off shipping", tier.percentage)), associated_discount_code: None, }], })); } } Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { DeliveryDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {import('../generated/api').DeliveryInput} DeliveryInput * @typedef {import('../generated/api').CartDeliveryOptionsDiscountsGenerateRunResult} CartDeliveryOptionsDiscountsGenerateRunResult */ /** * @typedef {Object} DiscountTier * @property {number} threshold * @property {number} percentage */ /** * @typedef {Object} Configuration * @property {DiscountTier[]} tiers */ /** * @param {DeliveryInput} input * @returns {CartDeliveryOptionsDiscountsGenerateRunResult} */ export function cartDeliveryOptionsDiscountsGenerateRun(input) { // Parse configuration from metafield const config = input?.discount?.metafield?.jsonValue ?? { tiers: [] }; // If no config or invalid tiers, return empty operations if (!config || !Array.isArray(config.tiers)) { return { operations: [] }; } // Get cart subtotal const subtotal = input.cart.cost.subtotalAmount.amount; // Find the highest applicable tier const applicableTier = config.tiers .filter(tier => subtotal >= tier.threshold) .reduce((highest, current) => !highest || current.threshold > highest.threshold ? current : highest, null); // If no tier applies, return empty operations if (!applicableTier) { return { operations: [] }; } const operations = []; // Process each delivery group for (const deliveryGroup of input.cart.deliveryGroups) { if (!deliveryGroup.deliveryOptions?.length) { continue; } // Find the cheapest delivery option const cheapestOption = deliveryGroup.deliveryOptions.reduce( (cheapest, current) => current.cost.amount < cheapest.cost.amount ? current : cheapest, deliveryGroup.deliveryOptions[0] ); operations.push({ deliveryDiscountsAdd: { candidates: [{ value: { percentage: { value: applicableTier.percentage.toFixed(1) } }, targets: [{ deliveryOption: { handle: cheapestOption.handle } }], message: `${applicableTier.percentage}% off shipping` }], selectionStrategy: DeliveryDiscountSelectionStrategy.All } }); } return { operations }; } ``` ##### Output JSON ```json { "operations": [ { "deliveryDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "15% off shipping", "targets": [ { "deliveryOption": { "handle": "standard" } } ], "value": { "percentage": { "value": "15.0" } } } ], "selectionStrategy": "ALL" } } ] } ``` * ### Apply a shipping discount based on location A discount function that applies a discount to a specific shipping method if the delivery address is in a specific city. This example applies a 50% shipping discount to the express shipping method. Use this example to understand: - How to apply percent discounts to shipping using the discount API - How to check the delivery address for an order - How to only apply shipping discounts depending on the customers location #### cart.delivery-options.discounts.generate.run ##### Input Query ```graphql query Input { cart { deliveryGroups { id deliveryAddress { city } deliveryOptions { handle title cost { amount } } } } } ``` ##### Input Object ```json { "cart": { "deliveryGroups": [ { "id": "gid://shopify/CartDeliveryGroup/0", "deliveryAddress": { "city": "Ottawa" }, "deliveryOptions": [ { "handle": "0d8a74c6e309668ff67eef9d765741ec-b1a2fe47040bfe8f971ccb0abbcf8ea1", "title": "Standard", "cost": { "amount": "0.0" } }, { "handle": "0d8a74c6e309668ff67eef9d765741ec-71c568b7bd38c0bc23d9e7457ab6aa3b", "title": "Express", "cost": { "amount": "21.9" } } ] } ] } } ``` ##### Function Code (Rust) ```rust use crate::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_delivery_options_discounts_generate_run(input: schema::cart_delivery_options_discounts_generate_run::Input) -> Result { let mut operations = Vec::new(); // Process each delivery group for group in input.cart().delivery_groups() { // Check if the delivery address city is Ottawa (case-insensitive) let city = group.delivery_address() .and_then(|addr| addr.city()) .map(|city| city.to_lowercase()); // Only apply a discount if delivering to Ottawa if city.as_deref() != Some("ottawa") { continue; } let mut candidates = Vec::new(); // Check each delivery option for option in group.delivery_options() { // Only apply a discount if the shipping option is express (case-insensitive) if let Some(title) = option.title() { if title.to_lowercase().contains("express") { // Create a discount for express shipping to Ottawa let candidate = schema::DeliveryDiscountCandidate { message: Some(String::from("50% off express shipping for Ottawa")), targets: vec![ schema::DeliveryDiscountCandidateTarget::DeliveryOption( schema::DeliveryOptionTarget { handle: option.handle().clone(), } ) ], value: schema::DeliveryDiscountCandidateValue::Percentage( schema::Percentage { value: Decimal(50.0), } ), associated_discount_code: None, }; candidates.push(candidate); break; } } } if !candidates.is_empty() { operations.push(schema::CartOperation::DeliveryDiscountsAdd( schema::DeliveryDiscountsAddOperation { selection_strategy: schema::DeliveryDiscountSelectionStrategy::All, candidates, } )); } } Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { DeliveryDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {import('../generated/api').DeliveryInput} DeliveryInput * @typedef {import('../generated/api').CartDeliveryOptionsDiscountsGenerateRunResult} CartDeliveryOptionsDiscountsGenerateRunResult */ /** * @param {DeliveryInput} input * @returns {CartDeliveryOptionsDiscountsGenerateRunResult} */ export function cartDeliveryOptionsDiscountsGenerateRun(input) { const { cart } = input; const operations = []; const deliveryGroups = cart.deliveryGroups || []; for (const group of deliveryGroups) { const city = group.deliveryAddress?.city?.toLowerCase(); // Only apply a discount if delivering to a specific city if (city !== "ottawa") continue; const candidates = []; for (const option of group.deliveryOptions) { // Only apply a discount if the shipping option is express if (option.title?.toLowerCase().includes("express")) { // Apply a 50% discount to shipping candidates.push({ message: "50% off express shipping for Ottawa", targets: [{ deliveryOption: { handle: option.handle } }], value: { percentage: { value: "50.0" } }, }); break; } } if (candidates.length > 0) { operations.push({ deliveryDiscountsAdd: { candidates, selectionStrategy: DeliveryDiscountSelectionStrategy.All } }); } } return { operations }; } ``` ##### Output JSON ```json { "operations": [ { "deliveryDiscountsAdd": { "selectionStrategy": "ALL", "candidates": [ { "message": "50% off express shipping for Ottawa", "targets": [ { "deliveryOption": { "handle": "0d8a74c6e309668ff67eef9d765741ec-71c568b7bd38c0bc23d9e7457ab6aa3b" } } ], "value": { "percentage": { "value": "50.0" } } } ] } } ] } ``` * ### Apply tiered shipping discounts for loyal customers buying from a collection Example implementation of a Discount function. This function provides a discount on shipping for loyal customers, that are buying multiple products from a specific collection. Loyal customers are defined by a tag on the customer. This example demonstrates how to \* Check if products are in a specific collection \* Check if line items are in a specific collection \* Apply a discount on shipping \* Apply a different discount on shipping for different delivery options \* Apply a discount on shipping for multiple line items \* Check if the customer has any tags #### cart.delivery-options.discounts.generate.run ##### Input Query ```graphql query Input { cart { buyerIdentity { customer { hasAnyTag(tags: ["member"]) } } lines { quantity merchandise { __typename ... on ProductVariant { product { inCollections(ids: ["gid://shopify/Collection/spring2025"]) { collectionId isMember } } } } } deliveryGroups { id deliveryOptions { handle cost { amount } } } } } ``` ##### Input Object ```json { "cart": { "buyerIdentity": { "customer": { "hasAnyTag": true } }, "lines": [ { "quantity": 4, "merchandise": { "__typename": "ProductVariant", "product": { "inCollections": [ { "collectionId": "gid://shopify/Collection/spring2025", "isMember": true } ] } } } ], "deliveryGroups": [ { "id": "gid://shopify/CartDeliveryGroup/0", "deliveryOptions": [ { "handle": "cae179072e1b0a565f51700b666b62c5-95e685b97e091ac14c1f4905f7c610a9", "cost": { "amount": "0.0" } }, { "handle": "cae179072e1b0a565f51700b666b62c5-b514e01af8655a9229f7a04405396118", "cost": { "amount": "1.0" } }, { "handle": "cae179072e1b0a565f51700b666b62c5-fbcaff8dd39a68820109eb990460be0a", "cost": { "amount": "15.0" } } ] } ] } } ``` ##### Function Code (Rust) ```rust use crate::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_delivery_options_discounts_generate_run(input: schema::cart_delivery_options_discounts_generate_run::Input) -> Result { let no_discount = schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![] }; // Check if the customer has the "member" tag let is_member = input.cart().buyer_identity() .and_then(|buyer| buyer.customer()) .map(|customer| *customer.has_any_tag()) .unwrap_or(false); // If not a member, return no discounts if !is_member { return Ok(no_discount); } // Count items from the spring2025 collection let spring2025_items = input.cart().lines().iter().fold(0, |count, line| { // Check if it's a product variant if let schema::cart_delivery_options_discounts_generate_run::input::cart::lines::Merchandise::ProductVariant(variant) = line.merchandise() { // Check if product is from spring2025 collection let in_collection = variant.product().in_collections().iter() .any(|collection| *collection.is_member()); if in_collection { return count + line.quantity(); } } count }); // Only apply discount if customer has at least 3 items from the spring2025 collection if spring2025_items < 3 { return Ok(no_discount); } let mut operations = vec![]; // Apply discounts to each delivery option for delivery_group in input.cart().delivery_groups() { let mut candidates = vec![]; for delivery_option in delivery_group.delivery_options() { let shipping_cost = delivery_option.cost().amount().0; // For shipping that costs $5 or less, make it free // For shipping that costs more than $5, apply a $5 discount let discount_amount = if shipping_cost <= 5.0 { shipping_cost } else { 5.0 }; if discount_amount > 0.0 { let message = if shipping_cost <= 5.0 { "Free shipping for members".to_string() } else { "$5 off shipping for members".to_string() }; candidates.push(schema::DeliveryDiscountCandidate { message: Some(message), targets: vec![ schema::DeliveryDiscountCandidateTarget::DeliveryOption(schema::DeliveryOptionTarget { handle: delivery_option.handle().clone() }) ], value: schema::DeliveryDiscountCandidateValue::FixedAmount(schema::FixedAmount { amount: Decimal(discount_amount), applies_to_each_item: None, }), associated_discount_code: None, }); } } if !candidates.is_empty() { operations.push(schema::CartOperation::DeliveryDiscountsAdd( schema::DeliveryDiscountsAddOperation { selection_strategy: schema::DeliveryDiscountSelectionStrategy::All, candidates, } )); } } Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { DeliveryDiscountSelectionStrategy } from '../generated/api'; /** * @typedef {import('../generated/api').DeliveryInput} DeliveryInput * @typedef {import('../generated/api').CartDeliveryOptionsDiscountsGenerateRunResult} CartDeliveryOptionsDiscountsGenerateRunResult */ /** * @param {DeliveryInput} input * @returns {CartDeliveryOptionsDiscountsGenerateRunResult} */ export function cartDeliveryOptionsDiscountsGenerateRun(input) { const { cart } = input; const operations = []; // Check if the customer has the 'member' tag const isMember = cart.buyerIdentity?.customer?.hasAnyTag || false; if (!isMember) { return { operations: [] }; } // Count how many items are from the spring collection let springCollectionCount = 0; for (const line of cart.lines) { if (line.merchandise.__typename === "ProductVariant" && line.merchandise.product.inAnyCollection) { springCollectionCount += line.quantity; } } // Apply discount only if there are 3 or more spring collection items if (springCollectionCount < 3) { return { operations: [] }; } // Apply shipping discounts for (const deliveryGroup of cart.deliveryGroups) { const candidates = []; for (const option of deliveryGroup.deliveryOptions) { const cost = parseFloat(option.cost.amount); if (cost <= 5.0) { // Make shipping free for options under $5 candidates.push({ message: "Free shipping for loyal customers!", targets: [{ deliveryOption: { handle: option.handle } }], value: { percentage: { value: "100.0" } }, }); } else { // Apply $5 off for options over $5 candidates.push({ message: "$5 off shipping for loyal customers!", targets: [{ deliveryOption: { handle: option.handle } }], value: { fixedAmount: { amount: "5.0" } }, }); } } if (candidates.length > 0) { operations.push({ deliveryDiscountsAdd: { candidates, selectionStrategy: DeliveryDiscountSelectionStrategy.All } }); } } return { operations }; } ``` ##### Output JSON ```json { "operations": [ { "deliveryDiscountsAdd": { "selectionStrategy": "ALL", "candidates": [ { "message": "Free shipping for members", "targets": [ { "deliveryOption": { "handle": "cae179072e1b0a565f51700b666b62c5-b514e01af8655a9229f7a04405396118" } } ], "value": { "fixedAmount": { "amount": "1.0" } } }, { "message": "$5 off shipping for members", "targets": [ { "deliveryOption": { "handle": "cae179072e1b0a565f51700b666b62c5-fbcaff8dd39a68820109eb990460be0a" } } ], "value": { "fixedAmount": { "amount": "5.0" } } } ] } } ] } ``` * ### Create a Buy X get Y discount A Shopify Discount Function that implements a "buy one, get discount on another" promotion. When customers add a specified product (ID 123456) to their cart, they receive a 10% discount on a companion product (ID 123457) if it's also in the cart. The discount applies to only one unit of the companion product. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id merchandise { __typename ... on ProductVariant { product { id } } } } } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/1", "merchandise": { "__typename": "ProductVariant", "product": { "id": "gid://shopify/Product/123456" } } }, { "id": "gid://shopify/CartLine/2", "merchandise": { "__typename": "ProductVariant", "product": { "id": "gid://shopify/Product/123457" } } } ] } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_lines_discounts_generate_run( input: schema::cart_lines_discounts_generate_run::Input, ) -> Result { let customer_buys_id = "gid://shopify/Product/123456"; let customer_gets_id = "gid://shopify/Product/123457"; let mut customer_buys_cart_line = None; let mut customer_gets_cart_line = None; input.cart().lines().iter().for_each(|line| { if let schema::cart_lines_discounts_generate_run::input::cart::lines::Merchandise::ProductVariant( variant, ) = &line.merchandise() { let product_id = variant.product().id().as_str(); if product_id == customer_buys_id { customer_buys_cart_line = Some(line.id().clone()); } else if product_id == customer_gets_id { customer_gets_cart_line = Some(line.id().clone()); } } }); if customer_buys_cart_line.is_none() || customer_gets_cart_line.is_none() { return Ok( schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }, ); } Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![ schema::CartOperation::ProductDiscountsAdd(schema::ProductDiscountsAddOperation{ candidates: vec![ schema::ProductDiscountCandidate { targets: vec![ schema::ProductDiscountCandidateTarget::CartLine(schema::CartLineTarget { id: customer_gets_cart_line.unwrap(), quantity: Some(1), }), ], message: Some("10% off on Y when buying X".to_string()), associated_discount_code: None, value: schema::ProductDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(10.0), }), } ], selection_strategy: schema::ProductDiscountSelectionStrategy::First, }), ]}) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import {ProductDiscountSelectionStrategy} from "../generated/api"; /** * @typedef {import("../generated/api").Input} CartInput * @typedef {import("../generated/api").CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult * @typedef {import("../generated/api").CartLine} CartLine */ /** * generateCartRun * @param {CartInput} input - The CartInput * @returns {CartLinesDiscountsGenerateRunResult} - The function result with discounts. */ export function cartLinesDiscountsGenerateRun(input) { const customer_buys_id = "gid://shopify/Product/123456"; const customer_gets_id = "gid://shopify/Product/123457"; /** @type {CartLine | null} */ let customer_buys_cart_line = null; /** @type {CartLine | null} */ let customer_gets_cart_line = null; for (const line of input.cart.lines) { const productId = "product" in line.merchandise ? line.merchandise.product.id : null; if (productId === customer_buys_id) { customer_buys_cart_line = line; } else if (productId === customer_gets_id) { customer_gets_cart_line = line; } } if (!customer_buys_cart_line || !customer_gets_cart_line) { return { operations: [], }; } return { operations: [ { productDiscountsAdd: { candidates: [ { message: "10% off on Y when buying X", targets: [ { cartLine: { id: customer_gets_cart_line.id, quantity: 1, }, }, ], value: { percentage: { value: 10, }, }, }, ], selectionStrategy: ProductDiscountSelectionStrategy.First, }, }, ], }; } ``` ##### Output JSON ```json { "operations": [ { "productDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "10% off on Y when buying X", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/2", "quantity": 1 } } ], "value": { "percentage": { "value": "10.0" } } } ], "selectionStrategy": "FIRST" } } ] } ``` #### cart.delivery-options.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id merchandise { __typename ... on ProductVariant { product { id } } } } deliveryGroups { id } } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/1", "merchandise": { "__typename": "ProductVariant", "product": { "id": "gid://shopify/Product/123456" } } }, { "id": "gid://shopify/CartLine/2", "merchandise": { "__typename": "ProductVariant", "product": { "id": "gid://shopify/Product/123457" } } } ], "deliveryGroups": [ { "id": "gid://shopify/CartDeliveryGroup/1" } ] } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_delivery_options_discounts_generate_run( input: schema::cart_delivery_options_discounts_generate_run::Input, ) -> Result { let customer_buys_id = "gid://shopify/Product/123456"; let customer_gets_id = "gid://shopify/Product/123457"; let mut customer_buys_cart_line = None; let mut customer_gets_cart_line = None; input.cart().lines().iter().for_each(|line| { if let schema::cart_delivery_options_discounts_generate_run::input::cart::lines::Merchandise::ProductVariant(variant) = &line.merchandise() { let product_id = variant.product().id().as_str(); if product_id == customer_buys_id { customer_buys_cart_line = Some(line.id().clone()); } else if product_id == customer_gets_id { customer_gets_cart_line = Some(line.id().clone()); } } }); let first_delivery_group = input .cart() .delivery_groups() .first() .ok_or("No delivery groups found")?; if customer_buys_cart_line.is_none() || customer_gets_cart_line.is_none() { return Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![] }); } Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![schema::DeliveryOperation::DeliveryDiscountsAdd( schema::DeliveryDiscountsAddOperation { selection_strategy: schema::DeliveryDiscountSelectionStrategy::All, candidates: vec![schema::DeliveryDiscountCandidate { targets: vec![schema::DeliveryDiscountCandidateTarget::DeliveryGroup( schema::DeliveryGroupTarget { id: first_delivery_group.id().clone(), }, )], value: schema::DeliveryDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(100.0), }), message: Some("Free delivery when buying X and Y".to_string()), associated_discount_code: None, }], }, )], }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import {DeliveryDiscountSelectionStrategy} from "../generated/api"; /** * @typedef {import("../generated/api").Input} RunInput * @typedef {import("../generated/api").CartDeliveryOptionsDiscountsGenerateRunResult} CartDeliveryOptionsDiscountsGenerateRunResult * @typedef {import("../generated/api").CartLine} CartLine */ /** * generateDeliveryRun * @param {RunInput} input - The DeliveryInput * @returns {CartDeliveryOptionsDiscountsGenerateRunResult} - The function result with discounts. */ export function cartDeliveryOptionsDiscountsGenerateRun(input) { const customer_buys_id = "gid://shopify/Product/123456"; const customer_gets_id = "gid://shopify/Product/123457"; let customer_buys_cart_line_present = false; let customer_gets_cart_line_present = false; for (const line of input.cart.lines) { const productId = "product" in line.merchandise ? line.merchandise.product.id : null; if (productId === customer_buys_id) { customer_buys_cart_line_present = true; } else if (productId === customer_gets_id) { customer_gets_cart_line_present = true; } } if (!customer_buys_cart_line_present || !customer_gets_cart_line_present) { return { operations: [], }; } const firstDeliveryGroup = input.cart.deliveryGroups[0]; if (!firstDeliveryGroup) { throw new Error("No delivery groups found"); } return { operations: [ { deliveryDiscountsAdd: { candidates: [ { message: "Free delivery when buying X and Y", targets: [ { deliveryGroup: { id: firstDeliveryGroup.id, }, }, ], value: { percentage: { value: 100, }, }, }, ], selectionStrategy: DeliveryDiscountSelectionStrategy.All, }, }, ], }; } ``` ##### Output JSON ```json { "operations": [ { "deliveryDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "Free delivery when buying X and Y", "targets": [ { "deliveryGroup": { "id": "gid://shopify/CartDeliveryGroup/1" } } ], "value": { "percentage": { "value": "100.0" } } } ], "selectionStrategy": "ALL" } } ] } ``` * ### Create loyalty program discounts A Shopify Discount Function that implements a loyalty program by detecting customer tags. The Function returns three discounts to tagged customers: a $10 fixed amount discount on the last item in the cart, a 10% percentage discount on the entire order subtotal, and free shipping on all available delivery options. Each type of discount is only applied when the corresponding discount class is enabled. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { buyerIdentity { customer { hasAnyTag(tags: ["loyalty-member"]) } } lines { id cost { totalAmount { amount currencyCode } } } deliveryGroups { id deliveryOptions { handle cost { amount currencyCode } } } cost { subtotalAmount { amount currencyCode } } } discount { discountClasses } } ``` ##### Input Object ```json { "cart": { "buyerIdentity": { "customer": { "hasAnyTag": true } }, "lines": [ { "id": "gid://shopify/CartLine/1", "cost": { "totalAmount": { "amount": "50.00", "currencyCode": "USD" } } }, { "id": "gid://shopify/CartLine/2", "cost": { "totalAmount": { "amount": "75.00", "currencyCode": "USD" } } } ], "deliveryGroups": [], "cost": { "subtotalAmount": { "amount": "125.00", "currencyCode": "USD" } } }, "discount": { "discountClasses": ["PRODUCT", "ORDER"] } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_lines_discounts_generate_run( input: schema::cart_lines_discounts_generate_run::Input, ) -> Result { let mut operations = vec![]; let discount_classes = &input.discount().discount_classes(); let has_product_discounts = discount_classes .contains(&schema::DiscountClass::Product); let has_order_discounts = discount_classes.contains(&schema::DiscountClass::Order); if let Some(buyer_identity) = input.cart().buyer_identity() { if let Some(customer) = buyer_identity.customer() { if *customer.has_any_tag() { // Apply $10 off the last cart line (product discount) if has_product_discounts { if let Some(last_line) = input.cart().lines().last() { operations.push(schema::CartOperation::ProductDiscountsAdd( schema::ProductDiscountsAddOperation { candidates: vec![schema::ProductDiscountCandidate { targets: vec![schema::ProductDiscountCandidateTarget::CartLine( schema::CartLineTarget { id: last_line.id().clone(), quantity: Some(1), }, )], value: schema::ProductDiscountCandidateValue::FixedAmount( schema::ProductDiscountCandidateFixedAmount { amount: Decimal::from(10.0), applies_to_each_item: Some(false), }, ), message: Some( "Loyalty member discount: $10 off last item".to_string(), ), associated_discount_code: None, }], selection_strategy: schema::ProductDiscountSelectionStrategy::First, }, )); } } // Apply 10% off the order (order discount) if has_order_discounts { operations.push(schema::CartOperation::OrderDiscountsAdd( schema::OrderDiscountsAddOperation { candidates: vec![schema::OrderDiscountCandidate { value: schema::OrderDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal::from(10.0), }), targets: vec![schema::OrderDiscountCandidateTarget::OrderSubtotal( schema::OrderSubtotalTarget { excluded_cart_line_ids: vec![], }, )], message: Some("Loyalty member discount: 10% off order".to_string()), conditions: None, associated_discount_code: None, }], selection_strategy: schema::OrderDiscountSelectionStrategy::First, }, )); } } } } Ok(schema::CartLinesDiscountsGenerateRunResult { operations }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { DiscountClass, OrderDiscountSelectionStrategy, ProductDiscountSelectionStrategy, } from "../generated/api"; /** * @typedef {import("../generated/api").Input} Input * @typedef {import("../generated/api").CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * generateCartRun * @param {Input} input - The Input * @returns {CartLinesDiscountsGenerateRunResult} - The function result with discounts. */ export function cartLinesDiscountsGenerateRun(input) { const operations = []; const discountClasses = input.discount.discountClasses; const hasProductDiscounts = discountClasses.includes(DiscountClass.Product); const hasOrderDiscounts = discountClasses.includes(DiscountClass.Order); // Check if customer has any tag const buyerIdentity = input.cart.buyerIdentity; if (buyerIdentity?.customer?.hasAnyTag) { // Apply $10 off the last cart line (product discount) if (hasProductDiscounts && input.cart.lines.length > 0) { const lastLine = input.cart.lines[input.cart.lines.length - 1]; operations.push({ productDiscountsAdd: { candidates: [ { targets: [ { cartLine: { id: lastLine.id, quantity: 1, }, }, ], value: { fixedAmount: { amount: "10.0", appliesToEachItem: false, }, }, message: "Loyalty member discount: $10 off last item", }, ], selectionStrategy: ProductDiscountSelectionStrategy.First, }, }); } // Apply 10% off the order (order discount) if (hasOrderDiscounts) { operations.push({ orderDiscountsAdd: { candidates: [ { value: { percentage: { value: "10.0", }, }, targets: [ { orderSubtotal: { excludedCartLineIds: [], }, }, ], message: "Loyalty member discount: 10% off order", }, ], selectionStrategy: OrderDiscountSelectionStrategy.First, }, }); } } return { operations, }; } ``` ##### Output JSON ```json { "operations": [ { "productDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "Loyalty member discount: $10 off last item", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/2", "quantity": 1 } } ], "value": { "fixedAmount": { "amount": "10.0", "appliesToEachItem": false } } } ], "selectionStrategy": "FIRST" } }, { "orderDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "conditions": null, "message": "Loyalty member discount: 10% off order", "targets": [ { "orderSubtotal": { "excludedCartLineIds": [] } } ], "value": { "percentage": { "value": "10.0" } } } ], "selectionStrategy": "FIRST" } } ] } ``` #### cart.delivery-options.discounts.generate.run ##### Input Query ```graphql query Input { cart { buyerIdentity { customer { hasAnyTag(tags: ["loyalty-member"]) } } lines { id cost { totalAmount { amount currencyCode } } } deliveryGroups { id deliveryOptions { handle cost { amount currencyCode } } } cost { subtotalAmount { amount currencyCode } } } discount { discountClasses } } ``` ##### Input Object ```json { "cart": { "buyerIdentity": { "customer": { "hasAnyTag": true } }, "lines": [ { "id": "gid://shopify/CartLine/1", "cost": { "totalAmount": { "amount": "50.00", "currencyCode": "USD" } } } ], "deliveryGroups": [ { "id": "gid://shopify/CartDeliveryGroup/1", "deliveryOptions": [ { "handle": "standard-shipping", "cost": { "amount": "5.00", "currencyCode": "USD" } }, { "handle": "express-shipping", "cost": { "amount": "10.00", "currencyCode": "USD" } } ] } ], "cost": { "subtotalAmount": { "amount": "50.00", "currencyCode": "USD" } } }, "discount": { "discountClasses": ["SHIPPING"] } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_delivery_options_discounts_generate_run( input: schema::cart_delivery_options_discounts_generate_run::Input, ) -> Result { let mut operations = vec![]; let discount_classes = &input.discount().discount_classes(); let has_shipping_discounts = discount_classes .contains(&schema::DiscountClass::Shipping); // Only proceed if SHIPPING discounts are allowed if !has_shipping_discounts { return Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations }); } if let Some(buyer_identity) = input.cart().buyer_identity() { if let Some(customer) = buyer_identity.customer() { if *customer.has_any_tag() { // Apply free shipping for group in input.cart().delivery_groups() { for option in group.delivery_options() { if *option.cost().amount() != Decimal::from(0.0) { operations.push(schema::DeliveryOperation::DeliveryDiscountsAdd( schema::DeliveryDiscountsAddOperation { candidates: vec![schema::DeliveryDiscountCandidate { targets: vec![ schema::DeliveryDiscountCandidateTarget::DeliveryOption( schema::DeliveryOptionTarget { handle: option.handle().clone(), }, ), ], value: schema::DeliveryDiscountCandidateValue::FixedAmount( schema::FixedAmount { amount: *option.cost().amount(), }, ), message: Some( "Loyalty member discount: Free shipping".to_string(), ), associated_discount_code: None, }], selection_strategy: schema::DeliveryDiscountSelectionStrategy::All, }, )); } } } } } } Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { DeliveryDiscountSelectionStrategy, DiscountClass, } from "../generated/api"; /** * @typedef {import("../generated/api").Input} Input * @typedef {import("../generated/api").CartDeliveryOptionsDiscountsGenerateRunResult} DeliveryResult */ /** * @param {Input} input * @returns {DeliveryResult} */ export function cartDeliveryOptionsDiscountsGenerateRun(input) { const operations = []; const discountClasses = input.discount.discountClasses; const hasShippingDiscounts = discountClasses.includes(DiscountClass.Shipping); // Only proceed if SHIPPING discounts are allowed if (!hasShippingDiscounts) { return {operations}; } // Check if customer has any tag const buyerIdentity = input.cart.buyerIdentity; if (buyerIdentity?.customer?.hasAnyTag) { // Apply free shipping for (const group of input.cart.deliveryGroups) { for (const option of group.deliveryOptions) { // Check if shipping cost is not already free if (option.cost.amount !== "0") { operations.push({ deliveryDiscountsAdd: { candidates: [ { targets: [ { deliveryOption: { handle: option.handle, }, }, ], value: { fixedAmount: { amount: option.cost.amount, }, }, message: "Loyalty member discount: Free shipping", }, ], selectionStrategy: DeliveryDiscountSelectionStrategy.All, }, }); } } } } return {operations}; } ``` ##### Output JSON ```json { "operations": [ { "deliveryDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "Loyalty member discount: Free shipping", "targets": [ { "deliveryOption": { "handle": "standard-shipping" } } ], "value": { "fixedAmount": { "amount": "5.0" } } } ], "selectionStrategy": "ALL" } }, { "deliveryDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "Loyalty member discount: Free shipping", "targets": [ { "deliveryOption": { "handle": "express-shipping" } } ], "value": { "fixedAmount": { "amount": "10.0" } } } ], "selectionStrategy": "ALL" } } ] } ``` * ### Create an order discount with exclusions A Shopify Discount Function that applies a 10% order discount while intentionally excluding the first item in the cart from the discount calculation. This approach enables creating "second item discount" promotions or selective discounting where certain high-value or non-discountable items remain at full price while the rest of the order receives the discount. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id } deliveryGroups { id deliveryOptions { handle } } } discount { discountClasses metafield(namespace: "$app:ex-excludedline-rs", key: "function-configuration") { jsonValue } } } ``` ##### Input Object ```json { "cart": { "lines": [ {"id": "gid://shopify/CartLine/1"}, {"id": "gid://shopify/CartLine/2"}, {"id": "gid://shopify/CartLine/3"} ], "deliveryGroups": [] }, "discount": { "discountClasses": ["ORDER"] } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize, Default)] pub struct Configuration {} #[shopify_function] fn cart_lines_discounts_generate_run( input: schema::cart_lines_discounts_generate_run::Input, ) -> Result { let first_cart_line_id = input.cart().lines().first().map(|line| line.id().clone()); let order_discount = schema::OrderDiscountCandidate { value: schema::OrderDiscountCandidateValue::Percentage( schema::Percentage { value: Decimal::from(10.0), }, ), targets: vec![ schema::OrderDiscountCandidateTarget::OrderSubtotal( schema::OrderSubtotalTarget { excluded_cart_line_ids: first_cart_line_id.into_iter().collect(), }, ), ], message: Some("10% off your order".to_string()), conditions: None, associated_discount_code: None, }; Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![schema::CartOperation::OrderDiscountsAdd( schema::OrderDiscountsAddOperation { candidates: vec![order_discount], selection_strategy: schema::OrderDiscountSelectionStrategy::First, }, )], }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { OrderDiscountSelectionStrategy, ProductDiscountSelectionStrategy, } from "../generated/api"; /** * @typedef {import("../generated/api").Input} CartInput * @typedef {import("../generated/api").CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * Generates cart discounts that exclude the first cart line from the order discount * @param {CartInput} input - The CartInput * @returns {CartLinesDiscountsGenerateRunResult} - The function result with discounts. */ export function cartLinesDiscountsGenerateRun(input) { if (!input.cart.lines.length) { throw new Error("No cart lines found"); } // Get the first cart line ID to exclude it from the discount const firstCartLine = input.cart.lines[0]; const firstCartLineId = firstCartLine.id; const maxCartLine = input.cart.lines.reduce((maxLine, line) => { if (line.cost.subtotalAmount.amount > maxLine.cost.subtotalAmount.amount) { return line; } return maxLine; }, input.cart.lines[0]); return { operations: [ { orderDiscountsAdd: { candidates: [ { message: "10% off your order", targets: [ { orderSubtotal: { excludedCartLineIds: [firstCartLineId], }, }, ], value: { percentage: { value: 10, }, }, }, ], selectionStrategy: OrderDiscountSelectionStrategy.First, }, }, { productDiscountsAdd: { candidates: [ { message: "20% OFF PRODUCT", targets: [ { cartLine: { id: maxCartLine.id, }, }, ], value: { percentage: { value: 20, }, }, }, ], selectionStrategy: ProductDiscountSelectionStrategy.First, }, }, ], }; } ``` ##### Output JSON ```json { "operations": [ { "orderDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "conditions": null, "message": "10% off your order", "targets": [ { "orderSubtotal": { "excludedCartLineIds": ["gid://shopify/CartLine/1"] } } ], "value": { "percentage": { "value": "10.0" } } } ], "selectionStrategy": "FIRST" } } ] } ``` #### cart.delivery-options.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id } deliveryGroups { id deliveryOptions { handle } } } discount { discountClasses metafield(namespace: "$app:ex-excludedline-rs", key: "function-configuration") { jsonValue } } } ``` ##### Input Object ```json { "cart": { "lines": [ {"id": "gid://shopify/CartLine/1"}, {"id": "gid://shopify/CartLine/2"} ], "deliveryGroups": [ { "id": "gid://shopify/CartDeliveryGroup/1", "deliveryOptions": [ {"handle": "standard-shipping"}, {"handle": "express-shipping"} ] } ] }, "discount": { "discountClasses": ["SHIPPING"] } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize, Default)] pub struct Configuration {} #[shopify_function] fn cart_delivery_options_discounts_generate_run( input: schema::cart_delivery_options_discounts_generate_run::Input, ) -> Result { let free_shipping = schema::DeliveryDiscountCandidate { value: schema::DeliveryDiscountCandidateValue::FixedAmount(schema::FixedAmount { amount: Decimal::from(0.0), }), targets: input .cart() .delivery_groups() .iter() .flat_map(|group| { group.delivery_options() .iter() .map(|option| { schema::DeliveryDiscountCandidateTarget::DeliveryOption( schema::DeliveryOptionTarget { handle: option.handle().clone(), }, ) }) }) .collect(), message: Some("Free Shipping".to_string()), associated_discount_code: None, }; Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![schema::DeliveryOperation::DeliveryDiscountsAdd( schema::DeliveryDiscountsAddOperation { candidates: vec![free_shipping], selection_strategy: schema::DeliveryDiscountSelectionStrategy::All, }, )], }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import {DeliveryDiscountSelectionStrategy} from "../generated/api"; /** * @typedef {import("../generated/api").Input} DeliveryInput * @typedef {import("../generated/api").CartDeliveryOptionsDiscountsGenerateRunResult} CartDeliveryOptionsDiscountsGenerateRunResult */ /** * Generates delivery discounts for free shipping on all delivery options * @param {DeliveryInput} input - The DeliveryInput * @returns {CartDeliveryOptionsDiscountsGenerateRunResult} - The function result with discounts. */ export function cartDeliveryOptionsDiscountsGenerateRun(input) { // Check if there are delivery groups and options if (!input.cart.deliveryGroups.length) { return {operations: []}; } // Create targets for all delivery options const targets = []; for (const group of input.cart.deliveryGroups) { for (const option of group.deliveryOptions) { targets.push({ deliveryOption: { handle: option.handle, }, }); } } // If no delivery options found, return empty operations if (targets.length === 0) { return {operations: []}; } return { operations: [ { deliveryDiscountsAdd: { candidates: [ { message: "Free Shipping", targets: targets, value: { percentage: { value: 100, }, }, }, ], selectionStrategy: DeliveryDiscountSelectionStrategy.All, }, }, ], }; } ``` ##### Output JSON ```json { "operations": [ { "deliveryDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "Free Shipping", "targets": [ { "deliveryOption": { "handle": "standard-shipping" } }, { "deliveryOption": { "handle": "express-shipping" } } ], "value": { "fixedAmount": { "amount": "0.0" } } } ], "selectionStrategy": "ALL" } } ] } ``` * ### Create combined multi-type discounts A Shopify Discount Function offers, product, order and shipping discounts. When order discounts are enabled, it applies a 10% percentage discount to the entire order subtotal. When product discounts are enabled, it applies a 20% discount specifically to the most expensive item in the cart. When shipping discounts are enabled, it makes delivery options free by applying a 100% discount. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { cart { lines { id cost { subtotalAmount { amount } } } } discount { discountClasses } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/1", "cost": { "subtotalAmount": { "amount": "50.00" } } }, { "id": "gid://shopify/CartLine/2", "cost": { "subtotalAmount": { "amount": "100.00" } } }, { "id": "gid://shopify/CartLine/3", "cost": { "subtotalAmount": { "amount": "75.00" } } } ] }, "discount": { "discountClasses": ["PRODUCT", "ORDER"] } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_lines_discounts_generate_run( input: schema::cart_lines_discounts_generate_run::Input, ) -> Result { let max_cart_line = input .cart() .lines() .iter() .max_by(|a, b| { a.cost() .subtotal_amount() .amount() .partial_cmp(&b.cost().subtotal_amount().amount()) .unwrap_or(std::cmp::Ordering::Equal) }) .ok_or("No cart lines found")?; let has_order_discount_class = input .discount() .discount_classes() .contains(&schema::DiscountClass::Order); let has_product_discount_class = input .discount() .discount_classes() .contains(&schema::DiscountClass::Product); if !has_order_discount_class && !has_product_discount_class { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] }); } let mut operations = vec![]; // Check if the discount has the ORDER class if has_order_discount_class { operations.push(schema::CartOperation::OrderDiscountsAdd( schema::OrderDiscountsAddOperation { selection_strategy: schema::OrderDiscountSelectionStrategy::First, candidates: vec![schema::OrderDiscountCandidate { targets: vec![schema::OrderDiscountCandidateTarget::OrderSubtotal( schema::OrderSubtotalTarget { excluded_cart_line_ids: vec![], }, )], message: Some("10% OFF ORDER".to_string()), value: schema::OrderDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(10.0), }), conditions: None, associated_discount_code: None, }], }, )); } // Check if the discount has the PRODUCT class if has_product_discount_class { operations.push(schema::CartOperation::ProductDiscountsAdd( schema::ProductDiscountsAddOperation { selection_strategy: schema::ProductDiscountSelectionStrategy::First, candidates: vec![schema::ProductDiscountCandidate { targets: vec![schema::ProductDiscountCandidateTarget::CartLine( schema::CartLineTarget { id: max_cart_line.id().clone(), quantity: None, }, )], message: Some("20% OFF PRODUCT".to_string()), value: schema::ProductDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(20.0), }), associated_discount_code: None, }], }, )); } Ok(schema::CartLinesDiscountsGenerateRunResult { operations }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { DiscountClass, OrderDiscountSelectionStrategy, ProductDiscountSelectionStrategy, } from "../generated/api"; /** * @typedef {import("../generated/api").CartInput} RunInput * @typedef {import("../generated/api").CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * @param {RunInput} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { if (!input.cart.lines.length) { throw new Error("No cart lines found"); } const hasOrderDiscountClass = input.discount.discountClasses.includes( DiscountClass.Order, ); const hasProductDiscountClass = input.discount.discountClasses.includes( DiscountClass.Product, ); if (!hasOrderDiscountClass && !hasProductDiscountClass) { return {operations: []}; } const maxCartLine = input.cart.lines.reduce((maxLine, line) => { if (line.cost.subtotalAmount.amount > maxLine.cost.subtotalAmount.amount) { return line; } return maxLine; }, input.cart.lines[0]); const operations = []; if (hasOrderDiscountClass) { operations.push({ orderDiscountsAdd: { candidates: [ { message: "10% OFF ORDER", targets: [ { orderSubtotal: { excludedCartLineIds: [], }, }, ], value: { percentage: { value: 10, }, }, }, ], selectionStrategy: OrderDiscountSelectionStrategy.First, }, }); } if (hasProductDiscountClass) { operations.push({ productDiscountsAdd: { candidates: [ { message: "20% OFF PRODUCT", targets: [ { cartLine: { id: maxCartLine.id, }, }, ], value: { percentage: { value: 20, }, }, }, ], selectionStrategy: ProductDiscountSelectionStrategy.First, }, }); } return { operations, }; } ``` ##### Output JSON ```json { "operations": [ { "orderDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "conditions": null, "message": "10% OFF ORDER", "targets": [ { "orderSubtotal": { "excludedCartLineIds": [] } } ], "value": { "percentage": { "value": "10.0" } } } ], "selectionStrategy": "FIRST" } }, { "productDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "20% OFF PRODUCT", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/2", "quantity": null } } ], "value": { "percentage": { "value": "20.0" } } } ], "selectionStrategy": "FIRST" } } ] } ``` #### cart.delivery-options.discounts.generate.run ##### Input Query ```graphql query Input { cart { deliveryGroups { id } } discount { discountClasses } } ``` ##### Input Object ```json { "cart": { "deliveryGroups": [ { "id": "gid://shopify/CartDeliveryGroup/1" } ] }, "discount": { "discountClasses": ["SHIPPING"] } } ``` ##### Function Code (Rust) ```rust use super::schema; use shopify_function::prelude::*; use shopify_function::Result; #[shopify_function] fn cart_delivery_options_discounts_generate_run( input: schema::cart_delivery_options_discounts_generate_run::Input, ) -> Result { let has_shipping_discount_class = input .discount() .discount_classes() .contains(&schema::DiscountClass::Shipping); if !has_shipping_discount_class { return Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![] }); } let first_delivery_group = input .cart() .delivery_groups() .first() .ok_or("No delivery groups found")?; Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![schema::DeliveryOperation::DeliveryDiscountsAdd( schema::DeliveryDiscountsAddOperation { selection_strategy: schema::DeliveryDiscountSelectionStrategy::All, candidates: vec![schema::DeliveryDiscountCandidate { targets: vec![schema::DeliveryDiscountCandidateTarget::DeliveryGroup( schema::DeliveryGroupTarget { id: first_delivery_group.id().clone(), }, )], value: schema::DeliveryDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(100.0), }), message: Some("FREE DELIVERY".to_string()), associated_discount_code: None, }], }, )], }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { DeliveryDiscountSelectionStrategy, DiscountClass, } from "../generated/api"; /** * @typedef {import("../generated/api").DeliveryInput} RunInput * @typedef {import("../generated/api").CartDeliveryOptionsDiscountsGenerateRunResult} CartDeliveryOptionsDiscountsGenerateRunResult */ /** * @param {RunInput} input * @returns {CartDeliveryOptionsDiscountsGenerateRunResult} */ export function cartDeliveryOptionsDiscountsGenerateRun(input) { const firstDeliveryGroup = input.cart.deliveryGroups[0]; if (!firstDeliveryGroup) { throw new Error("No delivery groups found"); } const hasShippingDiscountClass = input.discount.discountClasses.includes( DiscountClass.Shipping, ); if (!hasShippingDiscountClass) { return {operations: []}; } return { operations: [ { deliveryDiscountsAdd: { candidates: [ { message: "FREE DELIVERY", targets: [ { deliveryGroup: { id: firstDeliveryGroup.id, }, }, ], value: { percentage: { value: 100, }, }, }, ], selectionStrategy: DeliveryDiscountSelectionStrategy.All, }, }, ], }; } ``` ##### Output JSON ```json { "operations": [ { "deliveryDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "FREE DELIVERY", "targets": [ { "deliveryGroup": { "id": "gid://shopify/CartDeliveryGroup/1" } } ], "value": { "percentage": { "value": "100.0" } } } ], "selectionStrategy": "ALL" } } ] } ``` * ### Create a configurable discount with metafields A Shopify Discount Function that reads its configuration from a discount metafield, enabling merchant-configurable promotions. The Function parses the metafield JSON to retrieve product discount percentage, order discount percentage, eligible collection IDs and shipping discount percentage. It can selectively apply percentage discounts to products within specified collections and/or offer a separate percentage discount on the entire order or apply a shipping discount, with all values configurable through the metafield. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input($collectionIds: [ID!]) { cart { lines { id cost { subtotalAmount { amount } } merchandise { __typename ... on ProductVariant { product { inAnyCollection(ids: $collectionIds) } } } } } discount { discountClasses metafield( namespace: "$app:example-discounts--ui-extension" key: "function-configuration" ) { jsonValue } } } ``` ##### Input Object ```json { "cart": { "lines": [ { "id": "gid://shopify/CartLine/1", "cost": { "subtotalAmount": { "amount": "100.00" } }, "merchandise": { "__typename": "ProductVariant", "product": { "inAnyCollection": true } } }, { "id": "gid://shopify/CartLine/2", "cost": { "subtotalAmount": { "amount": "50.00" } }, "merchandise": { "__typename": "ProductVariant", "product": { "inAnyCollection": false } } } ] }, "discount": { "discountClasses": ["PRODUCT", "ORDER"], "metafield": { "jsonValue": { "cartLinePercentage": 15.0, "orderPercentage": 10.0, "collectionIds": ["gid://shopify/Collection/123"] } } } } ``` ##### Function Code (Rust) ```rust use crate::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize)] #[shopify_function(rename_all = "camelCase")] pub struct Configuration { cart_line_percentage: f64, order_percentage: f64, collection_ids: Vec, } #[shopify_function] fn cart_lines_discounts_generate_run( input: schema::cart_lines_discounts_generate_run::Input, ) -> Result { let configuration = match input.discount().metafield() { Some(metafield) => metafield.json_value(), None => return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] }), }; let discount_classes = input.discount().discount_classes(); let has_order_discount_class = discount_classes.contains(&schema::DiscountClass::Order); let has_product_discount_class = discount_classes.contains(&schema::DiscountClass::Product); if !has_order_discount_class && !has_product_discount_class { return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] }); } let mut operations = vec![]; // Add product discounts first if available and allowed if has_product_discount_class && configuration.cart_line_percentage > 0.0 { let mut cart_line_targets = vec![]; for line in input.cart().lines() { if let schema::cart_lines_discounts_generate_run::input::cart::lines::Merchandise::ProductVariant(variant) = &line.merchandise() { if *variant.product().in_any_collection() || configuration.collection_ids.is_empty() { cart_line_targets.push(schema::ProductDiscountCandidateTarget::CartLine( schema::CartLineTarget { id: line.id().clone(), quantity: None, }, )); } } } if !cart_line_targets.is_empty() { operations.push(schema::CartOperation::ProductDiscountsAdd( schema::ProductDiscountsAddOperation { selection_strategy: schema::ProductDiscountSelectionStrategy::First, candidates: vec![schema::ProductDiscountCandidate { targets: cart_line_targets, message: Some(format!( "{}% OFF PRODUCT", configuration.cart_line_percentage )), value: schema::ProductDiscountCandidateValue::Percentage( schema::Percentage { value: Decimal(configuration.cart_line_percentage), }, ), associated_discount_code: None, }], }, )); } } // Then add order discounts if available and allowed if has_order_discount_class && configuration.order_percentage > 0.0 { operations.push(schema::CartOperation::OrderDiscountsAdd( schema::OrderDiscountsAddOperation { selection_strategy: schema::OrderDiscountSelectionStrategy::First, candidates: vec![schema::OrderDiscountCandidate { targets: vec![schema::OrderDiscountCandidateTarget::OrderSubtotal( schema::OrderSubtotalTarget { excluded_cart_line_ids: vec![], }, )], message: Some(format!("{}% OFF ORDER", configuration.order_percentage)), value: schema::OrderDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(configuration.order_percentage), }), conditions: None, associated_discount_code: None, }], }, )); } Ok(schema::CartLinesDiscountsGenerateRunResult { operations }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { OrderDiscountSelectionStrategy, ProductDiscountSelectionStrategy, DiscountClass, } from "../generated/api"; /** * @typedef {import("../generated/api").CartInput} RunInput * @typedef {import("../generated/api").CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult * @typedef {import("../generated/api").ProductDiscountCandidateTarget} ProductDiscountCandidateTarget */ /** * @param {RunInput} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { if (!input.cart.lines.length) { throw new Error("No cart lines found"); } const {cartLinePercentage, orderPercentage, collectionIds} = parseMetafield( input.discount.metafield, ); const hasOrderDiscountClass = input.discount.discountClasses.includes( DiscountClass.Order, ); const hasProductDiscountClass = input.discount.discountClasses.includes( DiscountClass.Product, ); if (!hasOrderDiscountClass && !hasProductDiscountClass) { return {operations: []}; } const operations = []; // Add product discounts first if available and allowed if (hasProductDiscountClass && cartLinePercentage > 0) { const cartLineTargets = input.cart.lines.reduce((targets, line) => { if ( "product" in line.merchandise && (line.merchandise.product.inAnyCollection || collectionIds.length === 0) ) { targets.push({ cartLine: { id: line.id, }, }); } return targets; }, /** @type {ProductDiscountCandidateTarget[]} */ ([])); if (cartLineTargets.length > 0) { operations.push({ productDiscountsAdd: { candidates: [ { message: `${cartLinePercentage}% OFF PRODUCT`, targets: cartLineTargets, value: { percentage: { value: cartLinePercentage, }, }, }, ], selectionStrategy: ProductDiscountSelectionStrategy.First, }, }); } } // Then add order discounts if available and allowed if (hasOrderDiscountClass && orderPercentage > 0) { operations.push({ orderDiscountsAdd: { candidates: [ { message: `${orderPercentage}% OFF ORDER`, targets: [ { orderSubtotal: { excludedCartLineIds: [], }, }, ], value: { percentage: { value: orderPercentage, }, }, }, ], selectionStrategy: OrderDiscountSelectionStrategy.First, }, }); } return {operations}; } function parseMetafield(metafield) { try { const value = JSON.parse(metafield.value); return { cartLinePercentage: value.cartLinePercentage || 0, orderPercentage: value.orderPercentage || 0, collectionIds: value.collectionIds || [], }; } catch (error) { console.error("Error parsing metafield", error); return { cartLinePercentage: 0, orderPercentage: 0, collectionIds: [], }; } } ``` ##### Output JSON ```json { "operations": [ { "productDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "15% OFF PRODUCT", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/1", "quantity": null } } ], "value": { "percentage": { "value": "15.0" } } } ], "selectionStrategy": "FIRST" } }, { "orderDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "conditions": null, "message": "10% OFF ORDER", "targets": [ { "orderSubtotal": { "excludedCartLineIds": [] } } ], "value": { "percentage": { "value": "10.0" } } } ], "selectionStrategy": "FIRST" } } ] } ``` #### cart.delivery-options.discounts.generate.run ##### Input Query ```graphql query Input { cart { deliveryGroups { id } } discount { discountClasses metafield( namespace: "$app:example-discounts--ui-extension" key: "function-configuration" ) { jsonValue } } } ``` ##### Input Object ```json { "cart": { "deliveryGroups": [ { "id": "gid://shopify/CartDeliveryGroup/1" } ] }, "discount": { "discountClasses": ["SHIPPING"], "metafield": { "jsonValue": { "deliveryPercentage": 100.0 } } } } ``` ##### Function Code (Rust) ```rust use crate::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize)] #[shopify_function(rename_all = "camelCase")] pub struct Configuration { delivery_percentage: f64, } #[shopify_function] fn cart_delivery_options_discounts_generate_run( input: schema::cart_delivery_options_discounts_generate_run::Input, ) -> Result { let configuration = match input.discount().metafield() { Some(metafield) => metafield.json_value(), None => { return Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![] }) } }; let first_delivery_group = input .cart() .delivery_groups() .first() .ok_or("No delivery groups found")?; let discount_classes = input.discount().discount_classes(); let has_shipping_discount_class = discount_classes.contains(&schema::DiscountClass::Shipping); if !has_shipping_discount_class { return Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![] }); } let mut operations = vec![]; // Only add delivery discount if both the class is allowed and percentage is set if configuration.delivery_percentage > 0.0 { operations.push(schema::DeliveryOperation::DeliveryDiscountsAdd( schema::DeliveryDiscountsAddOperation { selection_strategy: schema::DeliveryDiscountSelectionStrategy::All, candidates: vec![schema::DeliveryDiscountCandidate { targets: vec![schema::DeliveryDiscountCandidateTarget::DeliveryGroup( schema::DeliveryGroupTarget { id: first_delivery_group.id().clone(), }, )], value: schema::DeliveryDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal(configuration.delivery_percentage), }), message: Some(format!( "{}% OFF DELIVERY", configuration.delivery_percentage )), associated_discount_code: None, }], }, )); } Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations }) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import { DeliveryDiscountSelectionStrategy, DiscountClass, } from "../generated/api"; /** * @typedef {import("../generated/api").DeliveryInput} RunInput * @typedef {import("../generated/api").CartDeliveryOptionsDiscountsGenerateRunResult} CartDeliveryOptionsDiscountsGenerateRunResult */ /** * @param {RunInput} input * @returns {CartDeliveryOptionsDiscountsGenerateRunResult} */ export function cartDeliveryOptionsDiscountsGenerateRun(input) { const firstDeliveryGroup = input.cart.deliveryGroups[0]; if (!firstDeliveryGroup) { throw new Error("No delivery groups found"); } const {deliveryPercentage} = parseMetafield(input.discount.metafield); const hasShippingDiscountClass = input.discount.discountClasses.includes( DiscountClass.Shipping, ); if (!hasShippingDiscountClass) { return {operations: []}; } const operations = []; if (hasShippingDiscountClass && deliveryPercentage > 0) { operations.push({ deliveryDiscountsAdd: { candidates: [ { message: `${deliveryPercentage}% OFF DELIVERY`, targets: [ { deliveryGroup: { id: firstDeliveryGroup.id, }, }, ], value: { percentage: { value: deliveryPercentage, }, }, }, ], selectionStrategy: DeliveryDiscountSelectionStrategy.All, }, }); } return {operations}; } function parseMetafield(metafield) { try { const value = JSON.parse(metafield.value); return {deliveryPercentage: value.deliveryPercentage || 0}; } catch (error) { console.error("Error parsing metafield", error); return {deliveryPercentage: 0}; } } ``` ##### Output JSON ```json { "operations": [ { "deliveryDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "100% OFF DELIVERY", "targets": [ { "deliveryGroup": { "id": "gid://shopify/CartDeliveryGroup/1" } } ], "value": { "percentage": { "value": "100.0" } } } ], "selectionStrategy": "ALL" } } ] } ``` * ### Create discounts managed by external services A Shopify Discount Function that implements network connectivity to retrieve data from external services for discount calculations. Through its fetch operations, it sends discount code data to an external API endpoint and receives discount operations in response. The operations received from the external API are then applied, enabling integration with existing promotion systems or third-party discount logic. #### cart.lines.discounts.generate.run ##### Input Query ```graphql query Input { fetchResult { jsonBody } cart { buyerIdentity { email } lines { id cost { subtotalAmount { amount } } } } discount { discountClasses } } ``` ##### Input Object ```json { "fetchResult": { "jsonBody": [ { "enteredDiscountCodesAccept": { "codes": [{"code": "SUMMER10"}] } }, { "productDiscountsAdd": { "selectionStrategy": "FIRST", "candidates": [ { "value": { "percentage": { "value": "10.0" } }, "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/123" } } ], "message": "10% off with SUMMER10 code" } ] } }, { "orderDiscountsAdd": { "selectionStrategy": "MAXIMUM", "candidates": [ { "value": { "percentage": { "value": "15.0" } }, "targets": [ { "orderSubtotal": { "excludedCartLineIds": [] } } ], "message": "15% off entire order" } ] } } ] }, "cart": { "buyerIdentity": { "email": "customer@example.com" }, "lines": [ { "id": "gid://shopify/CartLine/123", "cost": { "subtotalAmount": { "amount": "100.00" } } }, { "id": "gid://shopify/CartLine/456", "cost": { "subtotalAmount": { "amount": "50.00" } } } ] }, "discount": { "discountClasses": ["PRODUCT", "ORDER"] } } ``` ##### Function Code (Rust) ```rust use crate::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize)] #[shopify_function(rename_all = "camelCase")] pub struct OperationItem { product_discounts_add: Option, order_discounts_add: Option, entered_discount_codes_accept: Option, } pub type OperationsList = Vec; #[shopify_function] fn cart_lines_discounts_generate_run( input: schema::cart_lines_discounts_generate_run::Input, ) -> Result { let fetch_result = input.fetch_result().ok_or("Missing fetch result")?; let discount_classes = &input.discount().discount_classes(); let has_order_discount_class = discount_classes.contains(&schema::DiscountClass::Order); let has_product_discount_class = discount_classes .contains(&schema::DiscountClass::Product); // If no relevant discount class is set, return empty operations if !has_order_discount_class && !has_product_discount_class { return Ok( schema::CartLinesDiscountsGenerateRunResult { operations: vec![], }, ); } // Use the json_body which is the available property let operation_items = match fetch_result.json_body() { Some(json_body) => json_body, None => return Ok(schema::CartLinesDiscountsGenerateRunResult { operations: vec![] }), }; // Convert the response into operations let mut operations = Vec::new(); // Process each operation item for item in operation_items { // Always include discount code operations if let Some(validations) = &item.entered_discount_codes_accept { operations.push(schema::CartOperation::EnteredDiscountCodesAccept(validations.clone())); } // Include product discounts only if that class is set if has_product_discount_class { if let Some(product_discounts_add_operation) = &item.product_discounts_add { operations.push( schema::CartOperation::ProductDiscountsAdd(product_discounts_add_operation.clone()), ); } } // Include order discounts only if that class is set if has_order_discount_class { if let Some(order_discounts_add_operation) = &item.order_discounts_add { operations.push( schema::CartOperation::OrderDiscountsAdd( order_discounts_add_operation.clone(), ), ); } } // Ignore delivery discounts for cart operations } Ok( schema::CartLinesDiscountsGenerateRunResult { operations, }, ) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import {DiscountClass} from "../generated/api"; /** * @typedef {import("../generated/api").InputCartRun} InputCartRun * @typedef {import("../generated/api").CartLinesDiscountsGenerateRunResult} CartLinesDiscountsGenerateRunResult */ /** * * @param {InputCartRun} input * @returns {CartLinesDiscountsGenerateRunResult} */ export function cartLinesDiscountsGenerateRun(input) { const { fetchResult, discount: {discountClasses}, } = input; const body = fetchResult?.jsonBody; if (!body) { throw new Error("Missing response body"); } const operations = body; const hasOrderDiscountClass = discountClasses.includes(DiscountClass.Order); const hasProductDiscountClass = discountClasses.includes( DiscountClass.Product, ); // If no relevant discount classes are set, return an empty operations array if (!hasOrderDiscountClass && !hasProductDiscountClass) { return {operations: []}; } // Filter operations to include appropriate discounts based on set discount classes const filteredOperations = operations.filter(operation => { // Always include discount code operations if (operation.enteredDiscountCodesAccept) { return true; } // Include order discounts only if that class is set if (operation.orderDiscountsAdd) { return hasOrderDiscountClass; } // Include product discounts only if that class is set if (operation.productDiscountsAdd) { return hasProductDiscountClass; } return false; }); return {operations: filteredOperations}; } ``` ##### Output JSON ```json { "operations": [ { "enteredDiscountCodesAccept": { "codes": [ { "code": "SUMMER10" } ] } }, { "productDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "10% off with SUMMER10 code", "targets": [ { "cartLine": { "id": "gid://shopify/CartLine/123", "quantity": null } } ], "value": { "percentage": { "value": "10.0" } } } ], "selectionStrategy": "FIRST" } }, { "orderDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "conditions": null, "message": "15% off entire order", "targets": [ { "orderSubtotal": { "excludedCartLineIds": [] } } ], "value": { "percentage": { "value": "15.0" } } } ], "selectionStrategy": "MAXIMUM" } } ] } ``` #### cart.delivery-options.discounts.generate.run ##### Input Query ```graphql query Input { fetchResult { jsonBody } cart { buyerIdentity { email } deliveryGroups { id } } discount { discountClasses } } ``` ##### Input Object ```json { "fetchResult": { "jsonBody": [ { "enteredDiscountCodesAccept": { "codes": [{"code": "FREESHIP"}] } }, { "deliveryDiscountsAdd": { "selectionStrategy": "ALL", "candidates": [ { "value": { "percentage": { "value": "100.0" } }, "targets": [ { "deliveryOption": { "handle": "standard-shipping" } } ], "message": "Free standard shipping" } ] } } ] }, "cart": { "buyerIdentity": { "email": "customer@example.com" }, "deliveryGroups": [ { "id": "gid://shopify/CartDeliveryGroup/1" } ] }, "discount": { "discountClasses": ["SHIPPING"] } } ``` ##### Function Code (Rust) ```rust use crate::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize)] #[shopify_function(rename_all = "camelCase")] pub struct OperationItem { delivery_discounts_add: Option, entered_discount_codes_accept: Option, } pub type OperationsList = Vec; #[shopify_function] fn cart_delivery_options_discounts_generate_run( input: schema::cart_delivery_options_discounts_generate_run::Input, ) -> Result{ let fetch_result = input.fetch_result().ok_or("Missing fetch result")?; let discount_classes = &input.discount().discount_classes(); // Check if shipping discount class is set let has_shipping_discount_class = discount_classes .contains(&schema::DiscountClass::Shipping); // If shipping discount class is not set, return empty operations if !has_shipping_discount_class { return Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![] }); } // Use the json_body which is the available property let operation_items = match fetch_result.json_body() { Some(json_body) => json_body, None => return Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![] }), }; // Convert the response into operations let mut operations = Vec::new(); // Process each operation item for item in operation_items { // Always include discount code operations if let Some(validations) = &item.entered_discount_codes_accept { operations.push(schema::DeliveryOperation::EnteredDiscountCodesAccept(validations.clone())); } // Include delivery discounts (shipping discount class is already verified) if let Some(delivery_discounts_add_operation) = &item.delivery_discounts_add { operations.push(schema::DeliveryOperation::DeliveryDiscountsAdd( delivery_discounts_add_operation.clone(), )); } // Ignore cart/order discounts for delivery operations } Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations }) } ``` ##### Function Code (JavaScript) ```javascript //@ts-check import {DiscountClass} from "../generated/api"; /** * @typedef {import("../generated/api").InputDeliveryRun} InputDeliveryRun * @typedef {import("../generated/api").CartDeliveryOptionsDiscountsGenerateRunResult} CartDeliveryOptionsDiscountsGenerateRunResult */ /** * * @param {InputDeliveryRun} input * @returns {CartDeliveryOptionsDiscountsGenerateRunResult} */ export function cartDeliveryOptionsDiscountsGenerateRun(input) { const { fetchResult, discount: {discountClasses}, } = input; const body = fetchResult?.jsonBody; if (!body) { throw new Error("Missing response body"); } const operations = body; const hasShippingDiscountClass = discountClasses.includes( DiscountClass.Shipping, ); // If shipping discount class is not set, return an empty operations array if (!hasShippingDiscountClass) { return {operations: []}; } // Filter operations to only include enteredDiscountCodesAccept and delivery operations const filteredOperations = operations.filter(operation => { return ( operation.enteredDiscountCodesAccept || operation.deliveryDiscountsAdd ); }); return {operations: filteredOperations}; } ``` ##### Output JSON ```json { "operations": [ { "enteredDiscountCodesAccept": { "codes": [ { "code": "FREESHIP" } ] } }, { "deliveryDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "Free standard shipping", "targets": [ { "deliveryOption": { "handle": "standard-shipping" } } ], "value": { "percentage": { "value": "100.0" } } } ], "selectionStrategy": "ALL" } } ] } ``` #### cart.lines.discounts.generate.fetch ##### Input Query ```graphql query Input { enteredDiscountCodes cart { buyerIdentity { email } } } ``` ##### Input Object ```json { "enteredDiscountCodes": ["SUMMER10", "WELCOME20"], "cart": { "buyerIdentity": { "email": "customer@example.com" } } } ``` ##### Function Code (Rust) ```rust use crate::schema; use shopify_function::Result; use shopify_function; use shopify_function::prelude::*; use serde_json::json; #[shopify_function] fn cart_lines_discounts_generate_fetch( input: schema::cart_lines_discounts_generate_fetch::Input, ) -> Result { let entered_discount_codes = &input.entered_discount_codes(); let json_body = json!({ "enteredDiscountCodes": entered_discount_codes }); let request = schema::HttpRequest { headers: vec![ schema::HttpRequestHeader { name: "accept".to_string(), value: "application/json".to_string(), }, schema::HttpRequestHeader { name: "Content-Type".to_string(), value: "application/json".to_string(), }, ], method: schema::HttpRequestMethod::Post, policy: schema::HttpRequestPolicy { read_timeout_ms: 2000, }, url: "/api".to_string(), body: Some(json_body.to_string()), json_body: None, }; Ok( schema::CartLinesDiscountsGenerateFetchResult { request: Some(request), }, ) } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import {HttpRequestMethod} from "../generated/api"; /** * @typedef {import("../generated/api").InputCartFetch} InputCartFetch * @typedef {import("../generated/api").CartLinesDiscountsGenerateFetchResult} CartLinesDiscountsGenerateFetchResult */ /** * * @param {InputCartFetch} input * @returns {CartLinesDiscountsGenerateFetchResult} */ export function cartLinesDiscountsGenerateFetch(input) { const {enteredDiscountCodes} = input; const jsonBody = {enteredDiscountCodes}; const request = { headers: [ { name: "accept", value: "application/json", }, { name: "Content-Type", value: "application/json", }, ], method: HttpRequestMethod.Post, policy: { readTimeoutMs: 2000, }, url: "/api", body: JSON.stringify(jsonBody), jsonBody, }; return {request}; } ``` ##### Output JSON ```json { "request": { "body": "{\"enteredDiscountCodes\":[\"SUMMER10\",\"WELCOME20\"]}", "headers": [ { "name": "accept", "value": "application/json" }, { "name": "Content-Type", "value": "application/json" } ], "jsonBody": null, "method": "POST", "policy": { "readTimeoutMs": 2000 }, "url": "/api" } } ``` #### cart.delivery-options.discounts.generate.fetch ##### Input Query ```graphql query Input { enteredDiscountCodes cart { buyerIdentity { email } } } ``` ##### Input Object ```json { "enteredDiscountCodes": ["FREESHIP"], "cart": { "buyerIdentity": { "email": "customer@example.com" } } } ``` ##### Function Code (Rust) ```rust use crate::schema; use shopify_function; use shopify_function::prelude::*; use shopify_function::Result; use serde_json::json; use schema::cart_delivery_options_discounts_generate_fetch::Input as DeliveryFetchResponseData; #[shopify_function] fn cart_delivery_options_discounts_generate_fetch( input: DeliveryFetchResponseData, ) -> Result { let entered_discount_codes = &input.entered_discount_codes(); let json_body = json!({ "enteredDiscountCodes": entered_discount_codes }); let request = schema::HttpRequest { headers: vec![ schema::HttpRequestHeader { name: "accept".to_string(), value: "application/json".to_string(), }, schema::HttpRequestHeader { name: "Content-Type".to_string(), value: "application/json".to_string(), }, ], method: schema::HttpRequestMethod::Post, policy: schema::HttpRequestPolicy { read_timeout_ms: 2000, }, url: "/api".to_string(), body: Some(json_body.to_string()), json_body: None, }; Ok(schema::CartDeliveryOptionsDiscountsGenerateFetchResult { request: Some(request), }) } ``` ##### Function Code (JavaScript) ```javascript //@ts-check import {HttpRequestMethod} from "../generated/api"; /** * @typedef {import("../generated/api").InputDeliveryFetch} InputDeliveryFetch * @typedef {import("../generated/api").CartDeliveryOptionsDiscountsGenerateFetchResult} CartDeliveryOptionsDiscountsGenerateFetchResult */ /** * * @param {InputDeliveryFetch} input * @returns {CartDeliveryOptionsDiscountsGenerateFetchResult} */ export function cartDeliveryOptionsDiscountsGenerateFetch(input) { const {enteredDiscountCodes} = input; const jsonBody = {enteredDiscountCodes}; const request = { headers: [ { name: "accept", value: "application/json", }, { name: "Content-Type", value: "application/json", }, ], method: HttpRequestMethod.Post, policy: { readTimeoutMs: 2000, }, url: "/api", body: JSON.stringify(jsonBody), jsonBody, }; return {request}; } ``` ##### Output JSON ```json { "request": { "body": "{\"enteredDiscountCodes\":[\"FREESHIP\"]}", "headers": [ { "name": "accept", "value": "application/json" }, { "name": "Content-Type", "value": "application/json" } ], "jsonBody": null, "method": "POST", "policy": { "readTimeoutMs": 2000 }, "url": "/api" } } ``` * ### Create a free shipping discount with currency thresholds A Shopify Discount Function that provides free shipping when the cart subtotal exceeds configurable thresholds. Using shop metafields to store configuration, it supports multiple currency-specific thresholds (such as $100 USD or €80 EUR), automatically detecting the cart's currency and applying the appropriate threshold. When the threshold is met, the function offers free shipping on all available delivery options. #### cart.delivery-options.discounts.generate.run ##### Input Query ```graphql query Input { cart { cost { subtotalAmount { amount currencyCode } } deliveryGroups { id deliveryOptions { handle } } } shop { metafield(namespace: "shipping", key: "free_shipping_thresholds") { jsonValue } } } ``` ##### Input Object ```json { "cart": { "cost": { "subtotalAmount": { "amount": "150.00", "currencyCode": "USD" } }, "deliveryGroups": [ { "id": "gid://Shopify/CartDeliveryGroup/1", "deliveryOptions": [ { "handle": "standard-shipping" }, { "handle": "express-shipping" } ] } ] }, "shop": { "metafield": { "jsonValue": { "thresholds": [ {"currency": "USD", "minimum_subtotal": 100.0}, {"currency": "CAD", "minimum_subtotal": 120.0}, {"currency": "EUR", "minimum_subtotal": 80.0} ] } } } } ``` ##### Function Code (Rust) ```rust use crate::schema; use shopify_function::prelude::*; use shopify_function::Result; #[derive(Deserialize, Default, PartialEq)] struct FreeShippingThreshold { currency: String, minimum_subtotal: f64, } #[derive(Deserialize, Default, PartialEq)] pub struct Configuration { thresholds: Vec, } #[shopify_function] fn cart_delivery_options_discounts_generate_run( input: schema::cart_delivery_options_discounts_generate_run::Input, ) -> Result{ let config: &Configuration = match input.shop().metafield() { Some(metafield) => metafield.json_value(), None => return Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![] }), }; let subtotal = input.cart().cost().subtotal_amount().amount().as_f64(); let currency = &input.cart().cost().subtotal_amount().currency_code(); let applicable_threshold = config.thresholds.iter().find(|threshold| { &threshold.currency == *currency && subtotal >= threshold.minimum_subtotal }); if applicable_threshold.is_some() { let candidates: Vec = input .cart() .delivery_groups() .iter() .flat_map(|group| { group .delivery_options() .iter() .map(|option| schema::DeliveryDiscountCandidate { targets: vec![schema::DeliveryDiscountCandidateTarget::DeliveryOption( schema::DeliveryOptionTarget { handle: option.handle().to_string(), }, )], value: schema::DeliveryDiscountCandidateValue::Percentage(schema::Percentage { value: Decimal::from(100.0), }), message: Some("Free Shipping".to_string()), associated_discount_code: None, }) }) .collect(); Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![schema::DeliveryOperation::DeliveryDiscountsAdd( schema::DeliveryDiscountsAddOperation { candidates, selection_strategy: schema::DeliveryDiscountSelectionStrategy::All, }, )], }) } else { Ok(schema::CartDeliveryOptionsDiscountsGenerateRunResult { operations: vec![] }) } } ``` ##### Function Code (JavaScript) ```javascript // @ts-check import {DeliveryDiscountSelectionStrategy} from "../generated/api"; /** * @typedef {import("../generated/api").Input} RunInput * @typedef {import("../generated/api").CartDeliveryOptionsDiscountsGenerateRunResult} CartDeliveryOptionsDiscountsGenerateRunResult */ /** * Configuration for free shipping thresholds * @typedef {Object} FreeShippingThreshold * @property {string} currency - The currency code * @property {number} minimum_subtotal - The minimum subtotal required for free shipping */ /** * generateDeliveryRun * @param {RunInput} input - The DeliveryInput * @returns {CartDeliveryOptionsDiscountsGenerateRunResult} - The function result with discounts. */ export function cartDeliveryOptionsDiscountsGenerateRun(input) { // Parse configuration from metafield (namespace: shipping, key: free_shipping_thresholds) const config = input.shop.metafield?.jsonValue ?? {thresholds: []}; const subtotal = parseFloat(input.cart.cost.subtotalAmount.amount); const currency = input.cart.cost.subtotalAmount.currencyCode; // Find applicable threshold const applicableThreshold = config.thresholds.find( threshold => threshold.currency === currency && subtotal >= threshold.minimum_subtotal, ); if (!applicableThreshold) { return { operations: [], }; } // Collect all delivery options into candidates const candidates = input.cart.deliveryGroups.flatMap(group => group.deliveryOptions.map(option => ({ targets: [ { deliveryOption: { handle: option.handle, }, }, ], value: { percentage: { value: 100, }, }, message: "Free Shipping", })), ); // Return single operation with all candidates return { operations: [ { deliveryDiscountsAdd: { candidates, selectionStrategy: DeliveryDiscountSelectionStrategy.All, }, }, ], }; } ``` ##### Output JSON ```json { "operations": [ { "deliveryDiscountsAdd": { "candidates": [ { "associatedDiscountCode": null, "message": "Free Shipping", "targets": [ { "deliveryOption": { "handle": "standard-shipping" } } ], "value": { "percentage": { "value": "100.0" } } }, { "associatedDiscountCode": null, "message": "Free Shipping", "targets": [ { "deliveryOption": { "handle": "express-shipping" } } ], "value": { "percentage": { "value": "100.0" } } } ], "selectionStrategy": "ALL" } } ] } ``` *** ## Validations The following is a summary of validations that are run on function results. Violating any of the following checks will yield an error when the function runs: * There can only be one of each operation (`enteredDiscountCodesAccept`, `deliveryDiscountsAdd`, `orderDiscountsAdd`, or `productDiscountsAdd`) in a single function result. * `enteredDiscountCodesAccept.codes` must only contain discount codes that are a subset of `enteredDiscountCodes`. * The `associatedDiscountCode.code` field in the `productDiscountsAdd`, `orderDiscountsAdd` and `deliveryDiscountsAdd` operations must only contain discount codes that are a subset of `enteredDiscountCodesAccept.codes`. *** ## Migrate from deprecated Discount Function APIs The following sections outline the changes to the [Product Discount](https://shopify.dev/docs/api/functions/latest/product-discount), [Order Discount](https://shopify.dev/docs/api/functions/latest/order-discount), and [Shipping Discount](https://shopify.dev/docs/api/functions/latest/shipping-discount) Function APIs, and how you can migrate from Shopify Scripts to Discount Functions. ### Product Discount Function API and Order Discount Function API The Product Discount Function API and Order Discount Function API are now merged into the Discount Function API in the `cart.lines.discounts.generate.run` target. The target returns a `CartLinesDiscountsGenerateRunResult` object, which returns an `operations` field that includes fields that aren't present in the deprecated `FunctionRunResult` object. The following table outlines key changes: ### Input query | Product Discount Function API and Order Discount Function API | Discount Function API | Description | Available in run target | Available in fetch target | | - | - | - | - | - | | `discounts` | `operations` | Lists of discount operations to be applied | Yes | No | | `discountApplicationStrategy` | `ProductDiscountSelectionStrategy` or `OrderDiscountSelectionStrategy` | Specifies which outputs to apply `FIRST`, `MAXIMUM`, or `ALL` (product discounts only) | No | Yes | | N/A | `candidates` | The list of product or order discount candidates to be applied. | Yes | No | | N/A | `associatedDiscountCode` | A list of valid discount codes that correspond to external discounts. This can only be used by Functions with network access. | No | Yes | | N/A | `orderDiscountsAdd` | A group of order discounts that share a selection strategy. | Yes | No | | N/A | `productDiscountsAdd` | A group of product discounts that share a selection strategy. | Yes | No | #### Cart​Lines​Discounts​Generate​Run​Result output | Product Discount Function API and Order Discount Function API | Discount Function API | Description | Available in run target | Available in fetch target | | - | - | - | - | - | | `discounts` | `operations` | Lists of discount operations to be applied | Yes | No | | `discountApplicationStrategy` | `ProductDiscountSelectionStrategy` or `OrderDiscountSelectionStrategy` | Specifies which outputs to apply FIRST, MAXIMUM, or ALL (product discounts only) | No | Yes | | N/A | `candidates` | The list of product or order discount candidates to be applied. | Yes | No | | N/A | `associatedDiscountCode` | A list of valid discount codes that correspond to external discounts. This can only be used by Functions with network access. | No | Yes | | N/A | `orderDiscountsAdd` | A group of order discounts that share a selection strategy. | Yes | No | | N/A | `productDiscountsAdd` | A group of product discounts that share a selection strategy. | Yes | No | ### Shipping Discount Function API The Shipping Discount Function API is now merged into the Discount Function API in the `cart.delivery-options.discounts.generate.run` target. The target returns a `CartDeliveryOptionsDiscountsGenerateRunResult` object, which includes fields that aren't present in the deprecated `FunctionRunResult` object. The following table outlines key changes: ### Input query | Shipping Discount Function API | Discount Function API | Description | Available in run target | Available in fetch target | | - | - | - | - | - | | N/A | `enteredDiscountCodes` | The discounts entered at checkout by the buyer | No | Yes | | `discountNode` | `discount` | The discount associated to the Function that can be queried by the input query | Yes | Yes | | N/A | `triggeringDiscountCode` | The discount code that triggered the Function | Yes | Yes | #### Cart​Delivery​Options​Discounts​Generate​Run​Result | Shipping Discount Function API | Discount Function API | Description | Available in run target | Available in fetch target | | - | - | - | - | - | | `discounts` | `operations` | Lists of discount operations to be applied | Yes | No | | N/A | `deliveryDiscountsAdd` | A group of delivery discounts that share a selection strategy. | Yes | No | | N/A | `enteredDiscountCodesAccept` | A list of valid discount codes that correspond to external discounts. | No | Yes | | N/A | `candidates` | The list of delivery discount candidates to be applied. | Yes | No | | N/A | `selectionStrategy` | The strategy that's applied to the list of discounts. | Yes | No | | `productVariant` | `cartLineIds` | Target identifiers for the discount application | Yes | No | ### Migrate from line item scripts to discount functions If you want to migrate an existing [line item script](https://help.shopify.com/manual/checkout-settings/script-editor/shopify-scripts) to Shopify Functions, then you can use the following mappings: | Shopify Scripts method | Description | Shopify Functions target | Additional context | | - | - | - | - | | `change_line_price` | Applies a discount to a cart line such as a loyalty discount on a product by specifying a new reduced price, and a message either set by the developer or the merchant in the Function's configuration. | [Discount](#cart-run-target) | Apply [order discounts](#CartLinesDiscountsGenerateRunResult.fields.operations.orderDiscountsAdd) or [product discounts](#CartLinesDiscountsGenerateRunResult.fields.operations.productDiscountsAdd) by specifying the `OrderDiscountCandidateValue` or `ProductDiscountCandidateValue` (`percentage` or `fixedAmount` off), and an optional message. | | `split` | Splits a product into multiple lines so that you can apply discounts to partial quantities. For example, if a customer has five t-shirts in their cart, you can apply a discount to only two items while keeping the other three at full price | [Discount](#cart-run-target) | Use the optional `quantity` field in the `ProductDiscountCandidateTarget` object to limit the number of units the discount may be applied to. | | `change_properties` | Adds or changes a line item property | Not available | Refer to [applyAttributeChange](https://shopify.dev/docs/api/checkout-ui-extensions/latest/apis) in the checkout UI extensions API to apply attribute changes. | | `reject` | Disallows a discounts code from being applied at checkout | Not available | Use a [discount](#cart-run-target) function that contains the necessary logic. For example, you can use conditions to exclude a discount from applying, such as preventing a discount code when cart value is below $50 or when specific products are in the cart. | ### Migrate from shipping scripts to discount functions To migrate an existing [shipping script](https://help.shopify.com/manual/checkout-settings/script-editor/shopify-scripts) to Shopify Functions, then you can use the following mapping: | Shopify Scripts method | Description | Shopify Functions target | | - | - | - | | `apply_discount` | Applies a discount to a shipping rate | [Shipping discounts](#delivery-run-target) | *** ## Additional resources Explore comprehensive guides and references to help you build, deploy, and optimize your Shopify Functions. ### Working with Functions These guides cover essential concepts for building Shopify Functions effectively. Learn how functions process data, execute during checkout, and handle versioning, localization, and external APIs. [![](https://shopify.dev/images/icons/48/pickaxe-3.png)![](https://shopify.dev/images/icons/48/pickaxe-3-dark.png)](https://shopify.dev/docs/api/functions/current#function-anatomy) [Function anatomy](https://shopify.dev/docs/api/functions/current#function-anatomy) [Explore how functions process input data and generate operations.](https://shopify.dev/docs/api/functions/current#function-anatomy) [![](https://shopify.dev/images/icons/48/hearts.png)![](https://shopify.dev/images/icons/48/hearts-dark.png)](https://shopify.dev/docs/api/functions/current#function-execution-order-in-checkout) [Execution order in checkout](https://shopify.dev/docs/api/functions/current#function-execution-order-in-checkout) [Learn when function APIs execute during the checkout process.](https://shopify.dev/docs/api/functions/current#function-execution-order-in-checkout) [![](https://shopify.dev/images/icons/48/graphql.png)![](https://shopify.dev/images/icons/48/graphql-dark.png)](https://shopify.dev/docs/api/functions/current#graphql-schema-and-versioning) [Schema and versioning](https://shopify.dev/docs/api/functions/current#graphql-schema-and-versioning) [Understand schema versioning, release and upgrade requirements.](https://shopify.dev/docs/api/functions/current#graphql-schema-and-versioning) [![](https://shopify.dev/images/icons/48/growth.png)![](https://shopify.dev/images/icons/48/growth-dark.png)](https://shopify.dev/docs/api/functions/current#api-availability) [API availability](https://shopify.dev/docs/api/functions/current#api-availability) [Check which Shopify plans support functions in custom apps.](https://shopify.dev/docs/api/functions/current#api-availability) [![](https://shopify.dev/images/icons/48/globe.png)![](https://shopify.dev/images/icons/48/globe-dark.png)](https://shopify.dev/docs/apps/build/functions/localization-practices-shopify-functions) [Localization practices](https://shopify.dev/docs/apps/build/functions/localization-practices-shopify-functions) [Localize functions for international markets.](https://shopify.dev/docs/apps/build/functions/localization-practices-shopify-functions) [![](https://shopify.dev/images/icons/48/key.png)![](https://shopify.dev/images/icons/48/key-dark.png)](https://shopify.dev/docs/apps/build/functions/network-access) [Understand network access](https://shopify.dev/docs/apps/build/functions/network-access) [Configure functions to fetch data from external APIs.](https://shopify.dev/docs/apps/build/functions/network-access) ### Performance and troubleshooting Optimize function performance and ensure reliable operation from development through production deployment. [![](https://shopify.dev/images/icons/48/gear.png)![](https://shopify.dev/images/icons/48/gear-dark.png)](https://shopify.dev/docs/api/functions/current#resource-limits-and-performance) [Resource limits and performance](https://shopify.dev/docs/api/functions/current#resource-limits-and-performance) [Understand function performance requirements and resource limitations for optimal execution.](https://shopify.dev/docs/api/functions/current#resource-limits-and-performance) [![](https://shopify.dev/images/icons/48/industries.png)![](https://shopify.dev/images/icons/48/industries-dark.png)](https://shopify.dev/docs/apps/build/functions/test-debug-functions) [Test and debug Shopify Functions](https://shopify.dev/docs/apps/build/functions/test-debug-functions) [Explore comprehensive testing workflows from local development to production deployment.](https://shopify.dev/docs/apps/build/functions/test-debug-functions) [![](https://shopify.dev/images/icons/48/clicode.png)![](https://shopify.dev/images/icons/48/clicode-dark.png)](https://shopify.dev/docs/apps/build/functions/programming-languages) [Considerations for programming languages](https://shopify.dev/docs/apps/build/functions/programming-languages) [Choose languages that compile to WebAssembly for optimal function performance.](https://shopify.dev/docs/apps/build/functions/programming-languages) [![](https://shopify.dev/images/icons/48/flag.png)![](https://shopify.dev/images/icons/48/flag-dark.png)](https://shopify.dev/docs/apps/build/functions/monitoring-and-errors) [Monitoring and handling errors in production](https://shopify.dev/docs/apps/build/functions/monitoring-and-errors) [Master testing and debugging workflows for reliable function development.](https://shopify.dev/docs/apps/build/functions/monitoring-and-errors)