Paketi bileşenlerine ayırma

Standart bileşen metafield’larını kullanarak sepetteki bir paket ürünü bileşen varyantlarına ayıran Shopify cart transform Function’ı.

Function API
Cart Transform
Hedef (target)
cart.transform.run
İşlem (operation)
lineExpand
Plan
Herkese açık uygulamada her plan; özel uygulamada Shopify Plus
Uygulama yetkisi
write_cart_transforms
API sürümü
2026-10
Son kontrol

Kısaca

Bu cart transform Function’ı, sepette ve checkout’ta bir paket varyantını bileşen ürünlerine ayırır; böylece stok ve gönderim gerçek ürünler üzerinden yürür. Bileşenler custom.component_reference ve custom.component_quantities varyant metafield’larından gelir. Cart Transform API’nin cart.transform.run hedefindeki lineExpand işlemini kullanır (2026-10); herkese açık uygulamada her planda çalışır.

Nasıl kullanılır

  1. custom.component_reference (ürün varyantı listesi) ve custom.component_quantities (tam sayı listesi) varyant metafield tanımlarını oluşturun.
  2. Her paket varyantında bileşen varyantlarını ve adetlerini aynı sırayla girin.
  3. Shopify CLI ile bir uygulama oluşturun, uzantıyı ekleyin (shopify app generate extension --template cart_transform) ve dosyalarını aşağıdakilerle değiştirin.
  4. Testleri shopify app function run ile çalıştırın, deploy edin ve Function’ı cartTransformCreate ile etkinleştirin.

Kod

shopify.extension.toml
api_version = "2026-10"

[[extensions]]
name = "Expand a bundle into its components"
handle = "expand-bundle-components"
type = "function"

  [[extensions.targeting]]
  target = "cart.transform.run"
  input_query = "src/cart_transform_run.graphql"
  export = "cart-transform-run"

  [extensions.build]
  command = ""
  path = "dist/function.wasm"
src/cart_transform_run.graphql
query CartTransformRunInput {
  cart {
    lines {
      id
      merchandise {
        __typename
        ... on ProductVariant {
          componentReference: metafield(namespace: "custom", key: "component_reference") {
            jsonValue
          }
          componentQuantities: metafield(namespace: "custom", key: "component_quantities") {
            jsonValue
          }
        }
      }
    }
  }
}
src/cart_transform_run.js
// @ts-check

/**
 * @typedef {import("../generated/api").CartTransformRunInput} CartTransformRunInput
 * @typedef {import("../generated/api").CartTransformRunResult} CartTransformRunResult
 */

/**
 * The bundle variant lists its components in two variant metafields, the
 * definitions Shopify's bundle guide uses: custom.component_reference (list of
 * variants) and custom.component_quantities (list of integers, same order).
 * Quantities are for one bundle.
 */

/**
 * @param {CartTransformRunInput["cart"]["lines"][number]} line
 * @returns {CartTransformRunResult["operations"][number] | null}
 */
function expandOperation(line) {
  if (line.merchandise.__typename !== "ProductVariant") return null;
  const variantIds = line.merchandise.componentReference?.jsonValue;
  const quantities = line.merchandise.componentQuantities?.jsonValue;
  if (!Array.isArray(variantIds) || variantIds.length === 0) return null;
  // Mismatched lists mean a half-edited bundle; leave the line as it is
  // rather than expand it into the wrong items.
  if (!Array.isArray(quantities) || quantities.length !== variantIds.length) return null;

  // No price on the items: Shopify splits the bundle price across the
  // components by their own prices (its weight price algorithm).
  return {
    lineExpand: {
      cartLineId: line.id,
      expandedCartItems: variantIds.map((merchandiseId, index) => ({ merchandiseId, quantity: quantities[index] })),
    },
  };
}

/**
 * @param {CartTransformRunInput} input
 * @returns {CartTransformRunResult}
 */
export function cartTransformRun(input) {
  const operations = input.cart.lines.map(expandOperation).filter((operation) => operation !== null);
  return { operations };
}
Test girdisi ve beklenen çıktı
tests/bundle-line.input.json
{
  "cart": {
    "lines": [
      {
        "id": "gid://shopify/CartLine/1",
        "merchandise": {
          "__typename": "ProductVariant",
          "componentReference": {
            "jsonValue": ["gid://shopify/ProductVariant/1111111111", "gid://shopify/ProductVariant/2222222222"]
          },
          "componentQuantities": { "jsonValue": [2, 1] }
        }
      },
      {
        "id": "gid://shopify/CartLine/2",
        "merchandise": { "__typename": "ProductVariant", "componentReference": null, "componentQuantities": null }
      }
    ]
  }
}
tests/bundle-line.output.json
{
  "operations": [
    {
      "lineExpand": {
        "cartLineId": "gid://shopify/CartLine/1",
        "expandedCartItems": [
          { "merchandiseId": "gid://shopify/ProductVariant/1111111111", "quantity": 2 },
          { "merchandiseId": "gid://shopify/ProductVariant/2222222222", "quantity": 1 }
        ]
      }
    }
  ]
}
tests/mismatched-lists.input.json
{
  "cart": {
    "lines": [
      {
        "id": "gid://shopify/CartLine/1",
        "merchandise": {
          "__typename": "ProductVariant",
          "componentReference": {
            "jsonValue": ["gid://shopify/ProductVariant/1111111111", "gid://shopify/ProductVariant/2222222222"]
          },
          "componentQuantities": { "jsonValue": [2] }
        }
      }
    ]
  }
}
tests/mismatched-lists.output.json
{ "operations": [] }
tests/no-bundles.input.json
{
  "cart": {
    "lines": [
      { "id": "gid://shopify/CartLine/1", "merchandise": { "__typename": "ProductVariant", "componentReference": null, "componentQuantities": null } }
    ]
  }
}
tests/no-bundles.output.json
{ "operations": [] }

Lintel tarafından yazıldı. MIT lisansı: kendi mağazanızda da müşteri işlerinizde de ücretsiz kullanabilirsiniz.

Sınırlar ve özel durumlar

  • Bileşen fiyatı gönderilmediği için Shopify paket fiyatını bileşenlere kendi fiyatları oranında dağıtır.
  • Satırda bir satış planı (abonelik, ön sipariş) varsa Shopify cart transform işlemlerini reddeder.
  • Ayrılan bir satır en fazla 150 bileşene sahip olabilir.
  • Mağaza başına uygulama başına bir cart transform Function’ı olur; iki işlem aynı satırı hedeflerse lineExpand kazanır.

Sık sorulan sorular

Ürün paketleri Shopify Functions ile nasıl çalışır?
Bir cart transform Function’ı sepet satırlarının nasıl sunulacağını değiştirir: lineExpand bir paket satırını bileşenlere ayırır, linesMerge bileşenleri tek bir paket satırında birleştirir. Siparişler, paket ana ürününe referansla bileşen satırlarını tutar.
Paketler için Shopify Plus gerekir mi?
Herkese açık bir uygulamada lineExpand ve linesMerge için gerekmez. Yalnızca lineUpdate (bir satırın fiyatını, adını ya da görselini değiştirme) Shopify Plus ya da geliştirme mağazası ister.
Cart transform neden etkinleşmiyor?
cartTransformCreate, write_cart_transforms yetkisi ister ve mağazanın Checkout Extensibility’ye geçmiş olması gerekir.
  • Function API sürümü 2026-10 için yazıldı ve gösterilen tarihte Shopify’ın başvuru belgeleriyle karşılaştırıldı. Shopify her çeyrekte yeni bir sürüm yayımlar.
  • Function içeren özel (custom) uygulamalar yalnızca Shopify Plus mağazalarında çalışır. Aynı Function herkese açık bir uygulamada, sayfada aksi yazmıyorsa her planda çalışır.
  • Her örnek test verileriyle gelir ve yayımlamadan önce bu testleri çalıştırırız. Kodu değiştirdikten sonra testleri tekrar çalıştırın: shopify app function run.
  • MIT lisansı. Kodu kendi mağazanızda da müşteri işlerinizde de kullanabilirsiniz.

Mağazanız için kurulmasını, test edilmesini ve bakımını isterseniz: Shopify Functions geliştirme.

Geliştirmek istediğiniz bir şey mi var? Gelin, birlikte konuşalım.

Aynı anda sınırlı sayıda proje alıyoruz.

Gencer KarakayaShopify mühendisi

Proje özetinizi bir mühendis okur; size e-postayla yanıt veririz.