バリエーションの価格変更時にバンドルの価格を自動同期する

Shopify)の**「Bundles」**アプリ()を使用して商品バンドルを作成する場合、構成商品のバリエーション価格を変更しても、バンドル商品のバリエーション価格は自動的に更新されません。Workflow Trigger Extensions)の「Product Variant Price Changed」トリガー()は、価格の変更を検知し、バンドルのバリエーション価格を自動的に再計算して更新することで、この問題を解決します。


**「商品バリエーションの価格変更」**トリガーを使用して、バンドル価格を同期させる方法を理解するために、以下のシナリオを想定します。

シナリオ:コンポーネントのバリエーション価格が変更された際に、バンドル価格を自動更新する

Shopifyの「Bundles」アプリを使用して作成されたバンドル商品(例:Tシャツのバンドル)があるとします。このバンドルには、「ブラックTシャツ」、「グレーTシャツ」、「ホワイトTシャツ」という3つの構成商品が含まれており、各バリエーションの価格は10.00ユーロです。 バンドルのバリエーション価格は30.00ユーロ(構成商品の価格の合計)です。構成商品のバリエーション価格を変更すると、このフローによって対応するバンドルのバリエーション価格が自動的に更新されます。

アプリの設定 → 「商品バリエーション」 → 「バリエーション価格の変更」から、このトリガーを有効にしてください。

商品のバリエーションの価格が変更されました

親バンドル商品を取得し、更新後のバリエーション価格を算出し、Admin API を通じてバンドルのバリエーション価格を一括更新する

動画ガイド

この動画でも手順を視覚的に確認できます(音声はありませんが、必要に応じて再生速度を調整できます)。

このプロセスをどのように進めるか

設定の理解

  • 当社には、S、M、L、XL、2XLというバリエーションがあり、それぞれ10.00ユーロで販売されている商品(例:グレーのTシャツ)があります。
  • Shopify Bundles」アプリを使用して作成したバンドル商品があります。このバンドルには3つの商品(黒のTシャツ、灰色のTシャツ、白のTシャツ)が含まれており、それぞれに5つのバリエーションがあります。バンドルのバリエーション価格は30.00ユーロです(構成商品の価格の合計:3 × 10.00ユーロ)。

ここをクリックすると、手順を視覚的に確認できます:

  • Workflow Trigger Extensions で**「トリガー」を開き、「価格**」を検索して、「商品バリエーションの価格変更」を有効にします。これには「商品」「バリエーション」「コレクション」へのデータアクセス権限が必要です。権限が不足している場合は、アプリから要求が表示されます。
  • 「Shopify Flow」アプリから新しい空白のワークフローを作成し、「Workflow Trigger Extensions」アプリから「**Product Variant Price Changed」**トリガーを選択します。
  • **「商品データを取得」**アクションを追加し、詳細クエリを使用して、「作成日時」の昇順で並べ替えられた変更後の商品を取得します。このステップでは、productParentsフィールドを介して商品の親バンドル情報を取得します。クエリは次のようになります:id:{{productVariant.product.id | split: "gid://shopify/Product/" | last}}
  • 「**コードを実行」**ステップを追加し、「getProductData」の結果から親バンドルの製品IDを抽出します。このコードは、productParents から親製品のIDを抽出し、クエリ用に idsCondition という文字列を生成します。

コードの実行」ステップでは、親製品のIDを取得するために、以下のGraphQL入力、JavaScriptコード、および出力を使用します:

GraphQLの入力、JavaScriptコード、およびプレビュー出力を表示する「コードの実行」ステップを実行する

「トリガー」ページで「価格」を検索し、「商品バリエーションの価格変更」がオンになっている状態
アプリ内の「トリガー」で「価格」を検索し、「商品バリエーションの価格変更」をオンにします。
Flowの「Product Variant Price Changed」用バリアブルピッカー(oldPrice、newPrice、delta、percentChange、direction に対応)
「どの商品バリエーションの価格が変更されたか」には、変更前後の価格、差額、変化率、および価格変動の方向が示されます。
bash
{
  getProductData {
    productParents {
      id
    }
  }
}
javascript
export default function main(input) {
  const productIds = input.getProductData[0]?.productParents?.map(p => p.id) ?? [];
  const productId = productIds[0] ?? null;

  const idsCondition = productIds
    .map(gid => "id:" + gid.split("gid://shopify/Product/").pop())
    .join(" OR ");

  return {
    productId: productId,
    productIds: productIds,
    idsCondition: idsCondition,
  };
}
typescript
type Output {
  productId: String
  productIds: [String!]!
  idsCondition: String!
}
  • 「Run」コードの出力「productId」が空ではなく、かつ存在するかを確認する「条件」ステップを追加します。これにより、変更された製品が実際にバンドルの一部である場合にのみ処理が進むようになります。
  • → バンドル価格の更新を継続する
  • False → 停止(この製品はバンドル構成要素ではありません)
  • 条件が「True」の場合、「**製品データの取得 (1)」**アクションをもう1つ追加し、「コードの実行」ステップのidsConditionを使用して、親バンドル製品のバリエーションおよび価格データを取得します。
  • 更新されたコンポーネント価格に基づいて、新しいバンドルバリエーションの価格を計算するために、2つ目の「**コードを実行(1)」**ステップを追加します。このステップは、各バンドルバリエーションの新しい価格を含むvariantPrices配列を出力します。

この「**コードを実行 (1)」**ステップでは、更新されたコンポーネント価格に基づいて、バンドルバリエーションの価格を再計算します。その処理内容は以下の通りです。まず、トリガーから2つの重要な情報を取得します:

  • changedVariantId 先ほど変更されたバリアント(...158920
  • newPrice そのバリエーションの新しい価格(11.00)**その後、すべてのバンドルバリエーションをループ処理し、合計価格を再計算します。**各バンドルバリエーションには、3つの構成バリエーション(黒のTシャツ、灰色のTシャツ、白のTシャツ)があります。 各構成品について、次のようにチェックします。「これは先ほど変更されたバリエーションか?」もし「はい」であれば、Shopify(10.00)にまだ保存されている古い価格の代わりに、newPrice(11.00)を使用します。もし「いいえ」であれば、既存のcomponent.productVariant.price.Itを使用します。構成品の価格を合計して、新しいバンドルバリエーションの価格を算出します。出力データでこれが機能していることが確認できます。 バリエーション ...088840 を確認してください。その構成要素には、...158920(変更されたバリエーション)が含まれています。したがって、その価格は 11 + 10 + 10 = 31 となりますが、他のすべてのバンドルバリエーションは、構成要素に変更がないため、合計が 30 のままです。これがこのステップの重要なポイントです。「Shopify」は、まだバンドルデータ内の構成商品の価格を更新していないため、コードは既存の価格を単純に合計するだけでは不十分であり、変更されたバリエーションの価格をその場で新しい価格に置き換える必要があります。 これを行わないと、すべてのバリエーションが依然として「30」と表示されてしまいます。出力されたvariantPrices配列は、For eachループに渡され、そこでproductVariantsBulkUpdateが呼び出されて、再計算された価格がバンドル商品に実際に書き戻されます。
bash
{
  productVariant {
    id
  }
  priceChange {
    oldPrice { amount }
    newPrice { amount }
  }
  getProductData1 {
    id
    variants {
      id
      productVariantComponents {
        productVariant {
          id
          price
        }
      }
    }
  }
}
javascript
export default function main(input) {
  const changedVariantId = input.productVariant.id;
  const newPrice = parseFloat(input.priceChange.newPrice.amount);

  const variantPrices = input.getProductData1.flatMap(product =>
    product.variants.map(variant => ({
      productId: product.id,
      id: variant.id,
      price: variant.productVariantComponents.reduce((sum, component) => {
        const p = component.productVariant.id === changedVariantId
          ? newPrice
          : parseFloat(component.productVariant.price);
        return sum + p;
      }, 0)
    }))
  );

  return { variantPrices };
}
yaml
type VariantPrice {
  productId: String!
  id: String!
  price: Float!
}
type Output {
  variantPrices: [VariantPrice!]!
}
  • runCode1.variantPrices 内の各項目を順に処理する **For each ループ(反復処理)**を追加します。各バリエーション価格について、productVariantsBulkUpdate ミューテーションを使用して Send Admin API リクエストを実行し、バンドルのバリエーション価格を更新します。 この入力を「Mutation」で使用できます:
json
{
  "variants": [
    {
      "id": "{{variantPricesForeachitem.id}}",
      "price": "{{variantPricesForeachitem.price}}"
    }
  ],
  "productId": "{{variantPricesForeachitem.productId}}",
  "allowPartialUpdates": true
}

全体としてどのように機能するのか

構成商品のバリエーション価格が変更された場合(例:「グレーのTシャツ S」のバリエーション価格を10.00ユーロから15.00ユーロに更新した場合):

  1. 商品バリエーションの価格が変更された」トリガーが発動します
  2. このフローは、productParents を使用して、その製品の親バンドルを取得します。
  3. 「Run code」ステップでは、バンドル製品のIDが抽出されます
  4. この商品がバンドルに含まれているかどうかを確認する条件です
  5. 「はい」の場合、バンドル商品のデータを取得します
  6. 2番目の「コードを実行」ステップでは、バンドルバリエーションの価格が再計算されます
  7. このループは各バリアントを順に処理し、productVariantsBulkUpdate Admin API ミューテーションを通じてバンドル価格を更新します。

これにより、バンドル「S」バージョンの価格は、30.00 ユーロから 35.00 ユーロ(15.00 ユーロ + 10.00 ユーロ + 10.00 ユーロ)に更新されます。