# lineUpdate ile kişiselleştirme ücreti

> Bir satır özelliği (line item property) doldurulduğunda satırın fiyatına ve adına gravür ücreti ekleyen Shopify cart transform Function’ı. Shopify Plus.

Sayfa: https://lintelagency.com/tr/kaynaklar/shopify-functions/kisisellestirme-ucretini-satira-ekleme

## Kısaca

Bu cart transform Function’ı, gravür bilgisi olan her satırın birim fiyatına bir kişiselleştirme ücreti (varsayılan olarak mağaza para biriminde 10) ekler ve adını işaretler. Gravür metni bir satır özelliğinden (line item property) gelir. Cart Transform API’nin cart.transform.run hedefindeki lineUpdate işlemini kullanır (2026-10); Shopify bu işleme yalnızca Plus ve geliştirme mağazalarında izin verir.

## Bilgiler

- **Function API:** Cart Transform
- **Hedef (target):** cart.transform.run
- **İşlem (operation):** lineUpdate
- **Plan:** Shopify Plus ya da geliştirme mağazası
- **Uygulama yetkisi:** write_cart_transforms
- **API sürümü:** 2026-10
- **Son kontrol:** 2 Kasım 2026

## Nasıl kullanılır

1. Ürün formuna bir metin alanı ekleyin: <input name="properties[Engraving]">.
2. 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.
3. Testleri shopify app function run --input tests/engraved-line.input.json ile çalıştırın, ardından deploy edin.
4. cartTransformCreate ile etkinleştirin; farklı değerler istiyorsanız metafield’ına {"fee": 10, "titleSuffix": " (gravürlü)"} yazın.
5. Yeni adın görünmesi için sepet şablonunda item.title’ı kullanın.

## Kod

### shopify.extension.toml

```toml
api_version = "2026-10"

[[extensions]]
name = "Personalization fee with lineUpdate"
handle = "personalization-fee-line-update"
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

```graphql
query CartTransformRunInput {
  presentmentCurrencyRate
  cart {
    lines {
      id
      engraving: attribute(key: "Engraving") {
        value
      }
      cost {
        amountPerQuantity {
          amount
        }
      }
      merchandise {
        __typename
        ... on ProductVariant {
          product {
            title
          }
        }
      }
    }
  }
  cartTransform {
    metafield(namespace: "$app", key: "function-configuration") {
      jsonValue
    }
  }
}
```

### src/cart_transform_run.js

```js
// @ts-check

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

/**
 * Settings stored as JSON in the cart transform's metafield. The engraving
 * text comes from a line item property named "Engraving" on the product form
 * (<input name="properties[Engraving]">); change the attribute key in the
 * query if your theme uses another name.
 */
const DEFAULT_CONFIG = {
  // Added to each engraved unit, in the store's currency.
  fee: 10,
  // Appended to the product title on engraved lines.
  titleSuffix: " (engraved)",
};

/**
 * @param {CartTransformRunInput} input
 * @returns {CartTransformRunResult}
 */
export function cartTransformRun(input) {
  const config = { ...DEFAULT_CONFIG, ...input.cartTransform?.metafield?.jsonValue };
  // Prices in the input and output are in the customer's currency.
  const fee = config.fee * Number(input.presentmentCurrencyRate);

  const operations = input.cart.lines
    .filter((line) => line.merchandise.__typename === "ProductVariant" && (line.engraving?.value ?? "").trim() !== "")
    .map((line) => {
      const title = line.merchandise.__typename === "ProductVariant" ? line.merchandise.product.title : "";
      // A fixed unit price replaces the variant price, so it includes the fee.
      const unitPrice = Number(line.cost.amountPerQuantity.amount) + fee;
      return {
        lineUpdate: {
          cartLineId: line.id,
          title: `${title}${config.titleSuffix}`,
          price: { adjustment: { fixedPricePerUnit: { amount: unitPrice.toFixed(2) } } },
        },
      };
    });

  return { operations };
}
```

## Test girdisi ve beklenen çıktı

### tests/blank-engraving.input.json

```json
{
  "presentmentCurrencyRate": "1.0",
  "cart": {
    "lines": [
      {
        "id": "gid://shopify/CartLine/1",
        "engraving": { "value": "   " },
        "cost": { "amountPerQuantity": { "amount": "49.0" } },
        "merchandise": { "__typename": "ProductVariant", "product": { "title": "Brass Pocket Watch" } }
      }
    ]
  },
  "cartTransform": { "metafield": null }
}
```

### tests/blank-engraving.output.json

```json
{ "operations": [] }
```

### tests/converted-fee.input.json

```json
{
  "presentmentCurrencyRate": "1.25",
  "cart": {
    "lines": [
      {
        "id": "gid://shopify/CartLine/1",
        "engraving": { "value": "JS" },
        "cost": { "amountPerQuantity": { "amount": "80.0" } },
        "merchandise": { "__typename": "ProductVariant", "product": { "title": "Leather Wallet" } }
      }
    ]
  },
  "cartTransform": { "metafield": { "jsonValue": { "fee": 8, "titleSuffix": " · monogrammed" } } }
}
```

### tests/converted-fee.output.json

```json
{
  "operations": [
    {
      "lineUpdate": {
        "cartLineId": "gid://shopify/CartLine/1",
        "title": "Leather Wallet · monogrammed",
        "price": { "adjustment": { "fixedPricePerUnit": { "amount": "90.00" } } }
      }
    }
  ]
}
```

### tests/engraved-line.input.json

```json
{
  "presentmentCurrencyRate": "1.0",
  "cart": {
    "lines": [
      {
        "id": "gid://shopify/CartLine/1",
        "engraving": { "value": "For Ada, 2026" },
        "cost": { "amountPerQuantity": { "amount": "49.0" } },
        "merchandise": { "__typename": "ProductVariant", "product": { "title": "Brass Pocket Watch" } }
      },
      {
        "id": "gid://shopify/CartLine/2",
        "engraving": null,
        "cost": { "amountPerQuantity": { "amount": "49.0" } },
        "merchandise": { "__typename": "ProductVariant", "product": { "title": "Brass Pocket Watch" } }
      }
    ]
  },
  "cartTransform": { "metafield": null }
}
```

### tests/engraved-line.output.json

```json
{
  "operations": [
    {
      "lineUpdate": {
        "cartLineId": "gid://shopify/CartLine/1",
        "title": "Brass Pocket Watch (engraved)",
        "price": { "adjustment": { "fixedPricePerUnit": { "amount": "59.00" } } }
      }
    }
  ]
}
```

## Sınırlar ve özel durumlar

- Shopify Plus ya da geliştirme mağazası olmayan mağazalarda lineUpdate reddedilir.
- Aynı anda ayrılan (expand) ya da birleştirilen (merge) bir satır güncellenemez; Shopify lineUpdate’i yok sayar.
- Ücret presentmentCurrencyRate ile çevrilir; input ve output’taki fiyatlar müşterinin para birimindedir.
- Function’ın değiştirdiği adlar sepette, checkout’ta ve bildirim e-postalarında yalnızca şablon item.title ya da line.title kullanıyorsa görünür.

## Sorular

### Shopify’da gravür için nasıl ek ücret alınır?

Shopify Plus’ta, bu örnekteki gibi lineUpdate kullanan bir cart transform gravürlü satırın fiyatını artırabilir. Diğer planlarda sepete ayrı bir ücret ürünü ekleyin.

### Fiyatı neden temada değiştirmiyoruz?

Temadaki fiyatlar yalnızca gösterimdir. Müşterinin ödediği fiyat sunucu tarafında belirlenir; bir varyanttan, indirimden ya da cart transform’dan gelmelidir.

### Mağazam Shopify Plus değilse ne yapabilirim?

Tema tarafından gravürlü ürünle birlikte sepete eklenen ayrı bir “gravür ücreti” ürünü kullanın.

## Shopify belgeleri

- [Cart Transform Function API](https://shopify.dev/docs/api/functions/latest/cart-transform)

## İlgili içerikler

- [Shopify’da ürün sayfasından sepete kişiselleştirme](https://lintelagency.com/tr/blog/shopify-urun-kisisellestirme)
- [Hangi Shopify Functions özellikleri Shopify Plus gerektirir?](https://lintelagency.com/tr/blog/hangi-shopify-functions-ozellikleri-plus-gerektirir)
- [Shopify’da Cart Transform ile ürün paketleri: Plus ne zaman gerekir?](https://lintelagency.com/tr/blog/shopify-paketleri-ve-cart-transform)

Lisans: MIT. Kendi mağazanızda da müşteri işlerinizde de ücretsiz kullanabilirsiniz.
