プロモーション コードと割引の実装

このガイドでは、ユニバーサル コマース プロトコル(UCP)のバージョン 2026-04-08 でプロモーション コードと割引を処理するための技術的な API リファレンスとペイロード スキーマを提供します。

エンドポイントを構築する前に、プロモーション コードと割引の概要で、ハイレベルなコンセプト、数学的不変量、エラー処理ルールを確認してください。

ファインド

Google から割引コードを受け取るには、プロフィールで割引サポートを宣伝する必要があります。バージョン 2026-04-08 では、プラットフォームは割引コードを送信する前に、購入手続き機能が拡張されているかどうかを確認します。

{
  "ucp": {
    "version": "2026-04-08",
    "capabilities": {
      "dev.ucp.shopping.discount": [
        {
          "version": "2026-04-08",
          "extends": ["dev.ucp.shopping.checkout"],
          "spec": "https://ucp.dev/2026-04-08/specification/discount",
          "schema": "https://ucp.dev/2026-04-08/schemas/shopping/discount.json"
        }
      ]
    }
  }
}

広告申込情報と合計への影響

適用された割引は、2 つの異なる合計タイプを使用して、コアの購入手続きフィールドに反映されます。割引に広告申込情報を指す allocations がある場合、その割引は items_discount に反映されます。割り当てのない割引、または送料や手数料に割り当てられた割引は、discount に貢献します。

割引のタイプ 合計タイプ 反映される場所
広告申込情報の割引 items_discount line_items[].totals[type=items_discount]
注文レベルの割引 discount totals[type=discount]

バージョンの要件:

バージョン 2026-04-08 の場合、totals[]line_items[].totals[] の割引エントリでは、領収書での減算効果を反映するために負の値を使用する必要があります。discounts.applied 配列と allocations 配列内の金額は常に正の整数です。

自動適用されるプロモーションの API の例

次の例は、割引が自動的に適用されることを示しています。リクエスト ペイロードには discounts.codes 配列が含まれていませんが、レスポンスには "automatic": true が含まれ、code フィールドは省略されています。

自動適用される商品レベルの割引

特定の広告申込情報に自動的に適用されるサイト全体の 10% 割引。

リクエストの例:

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "title": "Sneakers", "price": 10000 },
      "quantity": 1
    }
  ]
}

レスポンスの例:

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "title": "Sneakers", "price": 10000 },
      "quantity": 1,
      "totals": [
        {"type": "subtotal", "amount": 10000},
        {"type": "items_discount", "amount": -1000},
        {"type": "total", "amount": 9000}
      ]
    }
  ],
  "discounts": {
    "applied": [
      {
        "title": "10% Off Sitewide Sale",
        "amount": 1000,
        "automatic": true,
        "method": "each",
        "allocations": [
          {"path": "$.line_items[0]", "amount": 1000}
        ]
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 10000},
    {"type": "items_discount", "display_text": "Item Discounts", "amount": -1000},
    {"type": "total", "display_text": "Total", "amount": 9000}
  ]
}

注文単位の自動適用割引

特定の広告申込情報への割り当てなしで、注文全体に適用されるプロモーション ルール(「50 ドル以上の注文で 10 ドル割引」など)。

リクエストの例:

{
  "line_items": [ ... ]
}

レスポンスの例:

{
  "line_items": [ ... ],
  "discounts": {
    "applied": [
      {
        "title": "$10 Off Orders Over $50",
        "amount": 1000,
        "automatic": true
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 6000},
    {"type": "discount", "display_text": "Order Promo", "amount": -1000},
    {"type": "total", "display_text": "Total", "amount": 5000}
  ]
}

ユーザーが適用したプロモーションの API の例

次の例は、ユーザーがプロモーション コードを入力したときにトリガーされる割引を示しています。リクエスト ペイロードにはリクエストされたコードが含まれ、レスポンスは適用された金額を割り当てながら、それらをエコーバックします。

注文単位の割引

注文の合計額に適用される一律の割引。割り当ては不要です。割引は注文全体に適用され、type: "discount" が使用されます。

リクエストの例:

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SAVE10"]
  }
}

レスポンスの例:

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SAVE10"],
    "applied": [
      {
        "code": "SAVE10",
        "title": "$10 Off Your Order",
        "amount": 1000
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 5000},
    {"type": "discount", "display_text": "Order Discount", "amount": -1000},
    {"type": "total", "display_text": "Total", "amount": 4000}
  ]
}

複合割引(商品レベルと注文レベル)

この例では、商品ごとの割引(20% オフ)が広告申込情報に割り当てられ、注文レベルで送料が自動的に割引されるという、2 種類の割引が示されています。

リクエストの例:

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SUMMER20"]
  }
}

レスポンスの例:

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "title": "T-Shirt", "price": 2000 },
      "quantity": 2,
      "totals": [
        {"type": "subtotal", "amount": 4000},
        {"type": "items_discount", "amount": -800},
        {"type": "total", "amount": 3200}
      ]
    }
  ],
  "discounts": {
    "codes": ["SUMMER20"],
    "applied": [
      {
        "code": "SUMMER20",
        "title": "Summer Sale 20% Off",
        "amount": 800,
        "allocations": [
          {"path": "$.line_items[0]", "amount": 800}
        ]
      },
      {
        "title": "Free shipping on orders over $30",
        "amount": 599,
        "automatic": true
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 4000},
    {"type": "items_discount", "display_text": "Item Discounts", "amount": -800},
    {"type": "discount", "display_text": "Order Discounts", "amount": -599},
    {"type": "fulfillment", "display_text": "Shipping", "amount": 0},
    {"type": "total", "display_text": "Total", "amount": 2601}
  ]
}

割引コードが拒否された

コードが無効な場合、codes ではエコーされますが、applied では省略されます。拒否は、messages[] 配列の warning を使用して伝達されます。

リクエストの例:

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SAVE10", "EXPIRED50"]
  }
}

レスポンスの例:

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SAVE10", "EXPIRED50"],
    "applied": [
      {
        "code": "SAVE10",
        "title": "$10 Off Your Order",
        "amount": 1000
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 5000},
    {"type": "discount", "display_text": "Order Discount", "amount": -1000},
    {"type": "total", "display_text": "Total", "amount": 4000}
  ],
  "messages": [
    {
      "type": "warning",
      "code": "discount_code_expired",
      "path": "$.discounts.codes[1]",
      "content": "Code 'EXPIRED50' expired on December 1st"
    }
  ]
}

割り当てによる割引の積み重ね

複数の割引が適用され、割り当ての内訳が完全に表示されます。

リクエストの例:

{
  "line_items": [ ... ],
  "discounts": {
    "codes": ["SUMMER20", "EXTRA5"]
  }
}

レスポンスの例:

{
  "line_items": [
    {
      "id": "li_1",
      "item": { "title": "T-Shirt", "price": 6000 },
      "quantity": 1,
      "totals": [
        {"type": "subtotal", "amount": 6000},
        {"type": "items_discount", "amount": -1500},
        {"type": "total", "amount": 4500}
      ]
    },
    {
      "id": "li_2",
      "item": { "title": "Socks", "price": 4000 },
      "quantity": 1,
      "totals": [
        {"type": "subtotal", "amount": 4000},
        {"type": "items_discount", "amount": -1000},
        {"type": "total", "amount": 3000}
      ]
    }
  ],
  "discounts": {
    "codes": ["SUMMER20", "EXTRA5"],
    "applied": [
      {
        "code": "SUMMER20",
        "title": "Summer Sale 20% Off",
        "amount": 2000,
        "method": "each",
        "priority": 1,
        "allocations": [
          {"path": "$.line_items[0]", "amount": 1200},
          {"path": "$.line_items[1]", "amount": 800}
        ]
      },
      {
        "code": "EXTRA5",
        "title": "Extra $5 Off",
        "amount": 500,
        "method": "across",
        "priority": 2,
        "allocations": [
          {"path": "$.line_items[0]", "amount": 300},
          {"path": "$.line_items[1]", "amount": 200}
        ]
      }
    ]
  },
  "totals": [
    {"type": "subtotal", "display_text": "Subtotal", "amount": 10000},
    {"type": "items_discount", "display_text": "Item Discounts", "amount": -2500},
    {"type": "total", "display_text": "Total", "amount": 7500}
  ]
}