For discussing the development and usage of Checkout UI extensions, post-purchase extensions, web pixels, Customer Accounts UI extensions, and POS UI extensions
// @ts-check /* A straightforward example of a function that expands a bundle into its component parts. The parts of a bundle are stored in a metafield on the product parent value with a specific format, specifying each part's quantity and variant. The function reads the cart. Any item containing the metafield that specifies the bundle parts will return an Expand operation containing the parts. */ /** * @typedef {import("../generated/api").RunInput} RunInput * @typedef {import("../generated/api").FunctionRunResult} FunctionRunResult * @typedef {import("../generated/api").CartOperation} CartOperation */ /** * @type {FunctionRunResult} */ const NO_CHANGES = { operations: [], }; /** * @param {RunInput} input * @returns {FunctionRunResult} */ export function run(input) { const operations = input.cart.lines.reduce( /** @param {CartOperation[]} acc */ (acc, cartLine) => { const expandOperation = optionallyBuildExpandOperation(cartLine, input); if (expandOperation) { return [...acc, { expand: expandOperation }]; } return acc; }, [] ); return operations.length > 0 ? { operations } : NO_CHANGES; } /** * @param {RunInput['cart']['lines'][number]} cartLine * @param {RunInput} input */ function optionallyBuildExpandOperation( { id: cartLineId, merchandise, cost, addonsAdded }, { cartTransform: { addonsVariantID }, presentmentCurrencyRate } ) { const hasWarrantyMetafields = merchandise.__typename === "ProductVariant" && !!merchandise.discountPercentage && !!addonsVariantID; const shouldAddWarranty = addonsAdded?.value === "Yes"; const discountPercentage = merchandise.__typename === "ProductVariant" && merchandise.discountPercentage?.value ? parseFloat(merchandise.discountPercentage.value) : 0; if ( merchandise.__typename === "ProductVariant" && hasWarrantyMetafields && shouldAddWarranty ) { return { cartLineId, title: `${merchandise.title} with discount`, // Optionally override the image for line item // image: { url: "https://cdn.shopify.com/.../something.png" }, expandedCartItems: [ { merchandiseId: addonsVariantID.value, quantity: 1, price: { adjustment: { fixedPricePerUnit: { amount: ( cost.amountPerQuantity.amount * ((100 - discountPercentage) / 100) * presentmentCurrencyRate ).toFixed(2), }, }, }, }, { merchandiseId: merchandise.id, quantity: 1, price: { adjustment: { fixedPricePerUnit: { amount: ( cost.amountPerQuantity.amount * ((100 - discountPercentage * 2) / 100) * presentmentCurrencyRate ).toFixed(2), }, }, }, }, ], }; } return null; }
query RunInput { presentmentCurrencyRate cart { lines { id quantity cost { amountPerQuantity { amount currencyCode } } # Access the cart line attribute to decide if we should add a warranty addonsAdded: attribute(key: "addons_added") { value } merchandise { __typename ... on ProductVariant { id title discountPercentage: metafield(namespace: "$app:add-ons", key: "add_ons") { value } } } } } cartTransform { # Access the variant ID that represents the warranty product addonsVariantID: metafield(namespace: "$app:add-ons", key: "add_ons") { value } } }
the output
{ "operations": [ { "expand": { "cartLineId": "gid://shopify/CartLine/6227da72-02f3-4dc5-b4e1-1ccdbaf9a176", "title": "Selling Plans Ski Wax with discount", "expandedCartItems": [ { "merchandiseId": "gid://shopify/ProductVariant/49268939260200", "quantity": 1, "price": { "adjustment": { "fixedPricePerUnit": { "amount": "22.50" } } } }, { "merchandiseId": "gid://shopify/ProductVariant/49268939227432", "quantity": 1, "price": { "adjustment": { "fixedPricePerUnit": { "amount": "20.00" } } } } ] } } ] }
I picked one with id=49268939227432 and then added it to the cart, in the cart I expect another one with id=49268939260200 as I process in function but I can't see