ce-catalog について
Commerce Engine storefront SDK のカタログメソッドを使うためのスキルガイドです。商品やバリアントの取得、検索、価格、在庫、ストアフロント表示のパターンを、EC開発者向けに説明します。
主な機能
- 01商品、バリアント、SKU の一覧取得
- 02フィルター、ソート、ファセット検索
- 03商品詳細とレビューの取得
- 04バリアント選択と URL 状態の処理
- 05在庫と顧客グループ別価格への対応
活用シーン
- 01絞り込み付き商品一覧ページの構築
- 02商品詳細とバリアント選択の実装
- 03在庫状況と価格の表示
- 04ストアフロントへの商品レビュー追加
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ commercengine/ skills --skill ce-catalogインストール後、Claude Code で/ce-catalogを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
.claude-plugin/plugin.json.cursor-plugin/plugin.jsonreferences/pdp-option-model.md詳細
LLM Docs ヘッダー:
https://llm-docs.commercengine.ioへのすべてのリクエストには、Accept: text/markdownヘッダーを必ず含めてください(または URL パスの末尾に.mdを追加してください)。含めない場合、解析可能な Markdown ではなく HTML が返されます。
商品とカタログ
前提条件:SDK の初期化と匿名認証が完了していること。
setup/を参照してください。
クイックリファレンス
| タスク | SDK メソッド |
|---|---|
| 商品を一覧表示 | sdk.catalog.listProducts({ page, limit, category_id }) |
| 商品の詳細を取得 | sdk.catalog.getProductDetail({ product_id }) |
| バリエーションを一覧表示 | sdk.catalog.listProductVariants({ product_id }) |
| バリエーションの詳細を取得 | sdk.catalog.getVariantDetail({ product_id, variant_id }) |
| SKU を一覧表示(フラット形式) | sdk.catalog.listSkus() |
| カテゴリを一覧表示 | sdk.catalog.listCategories() |
| 商品を検索 | sdk.catalog.searchProducts({ query: searchTerm, filter?, sort?, facets? }) |
| レビューを取得 | sdk.catalog.listProductReviews({ product_id }) |
| レビューを投稿 | sdk.catalog.createProductReview({ product_id }, { ... }) |
| 類似商品 | sdk.catalog.listSimilarProducts({ product_id }) |
| アップセル商品 | sdk.catalog.listUpSellProducts({ product_id }) |
| クロスセル商品 | sdk.catalog.listCrossSellProducts({ product_id }) |
商品階層
商品 → バリエーション → SKU の関係を理解することが重要です。
Product (has_variant: false)
└─ A simple product with one SKU, one price
Product (has_variant: true)
├─ Variant A (Color: Red, Size: M) → SKU: "RED-M-001"
├─ Variant B (Color: Red, Size: L) → SKU: "RED-L-001"
└─ Variant C (Color: Blue, Size: M) → SKU: "BLU-M-001"
| 概念 | 戻り値の型 | 説明 | 使用する場面 |
|---|---|---|---|
| 商品 | Product | variants 配列をネストして持つ基本アイテム | 商品ごとに1枚のカードを表示する PLP(例:「Tシャツ」のカードに色/サイズのセレクターを表示) |
| バリエーション | — | 特定のオプションの組み合わせ(色 + サイズ) | PDP、カート内の商品 — listProductVariants() で取得するか、Product にネストされたものを使用 |
| SKU/アイテム | Item | 販売可能なフラット形式の単位 — 各バリエーションが個別のレコード | フラットなグリッドを表示する PLP(色/サイズの組み合わせごとに別のカード)、またはフィルター/並べ替え/検索を使うページ |
判断フロー
User Request
│
├─ "Show products" / "Product list"
│ ├─ With filters/sorting/search? → sdk.catalog.searchProducts({ query, filter, sort, facets })
│ │ → Returns Item[] (flat SKUs) + facet_distribution + facet_stats
│ ├─ Flat grid (no filters)? → sdk.catalog.listSkus()
│ │ → Returns Item[] (flat SKUs)
│ └─ One card per product (group variants)? → sdk.catalog.listProducts()
│ → Returns Product[] (with nested variants)
│
├─ "Product detail page"
│ ├─ sdk.catalog.getProductDetail({ product_id })
│ └─ If has_variant → sdk.catalog.listProductVariants({ product_id })
│
├─ "Search" / "Filter" / "Sort"
│ └─ sdk.catalog.searchProducts({ query, filter, sort, facets })
│ → Returns Item[] + facet_distribution + facet_stats
│
├─ "Categories" / "Navigation"
│ └─ sdk.catalog.listCategories()
│
├─ "Reviews"
│ ├─ Read → sdk.catalog.listProductReviews({ product_id })
│ └─ Write → sdk.catalog.createProductReview({ product_id }, body)
│
└─ "Recommendations"
├─ Similar → sdk.catalog.listSimilarProducts()
├─ Upsell → sdk.catalog.listUpSellProducts()
└─ Cross-sell → sdk.catalog.listCrossSellProducts()
主なパターン
商品一覧ページ(PLP)
フィルター、並べ替え、検索を使う PLP には、searchProducts を使用してください(推奨)。Item[](フラット形式の SKU)に加えて、フィルター UI の構築に使える facet_distribution と facet_stats が返されます。
const { data, error } = await sdk.catalog.searchProducts({
query: "running shoes",
filter: "pricing.selling_price 50 TO 200 AND categories.name = footwear",
sort: ["pricing.selling_price:asc"],
facets: ["categories.name", "product_type", "tags"],
page: 1,
limit: 20,
});
// data.skus → Item[] (flat list — each variant is its own record)
// Each Item includes product_slug and variant_slug for building SEO-friendly URLs
// data.facet_distribution → { [attribute]: { [value]: count } }
// data.facet_stats → { [attribute]: { min, max } } (e.g. price range)
// data.pagination → { page, limit, total, total_pages }
// filter also accepts arrays — conditions are AND'd:
// filter: ["product_type = physical", "rating >= 4"]
//
// Nested arrays express OR within AND:
// filter: ["pricing.selling_price 50 TO 200", ["categories.name = footwear", "categories.name = apparel"]]
フィルターを使わず、商品ごとに1枚のカードを表示する PLP の場合(バリエーションを1枚のカードにまとめる場合):
const { data, error } = await sdk.catalog.listProducts({
page: 1,
limit: 20,
category_id: ["cat_123"], // Optional: filter by category
});
// data.products → Product[] (each product may contain a variants array)
// Check product.has_variant to know if options exist
フィルターを使わず、フラットなグリッドを表示する場合(バリエーションごとに別のカードを表示):
const { data, error } = await sdk.catalog.listSkus();
// Returns Item[] — same flat type as searchProducts
// Each Item includes product_slug and variant_slug for building SEO-friendly URLs
商品詳細ページ(PDP)
const { data, error } = await sdk.catalog.getProductDetail({
product_id: "blue-running-shoes", // Accepts product ID or slug
});
const product = data?.product;
// Prefer product.variants from getProductDetail.
// Fetch separately only if variants are missing or you specifically need the variants endpoint.
if (product?.has_variant && (!product.variants || product.variants.length === 0)) {
const { data: variantData } = await sdk.catalog.listProductVariants({
product_id: product.id,
});
// variantData.variants contains all options with pricing and stock
}
PDP から商品をカートに追加
PDP でバリエーションを特定した後、getProductDetail のレスポンスから product.id と variant.id を使用します。
// product = data.product from getProductDetail()
// resolvedVariant = the variant matched from product.variants via option selection
if (product.has_variant) {
// Variant product — must specify both product_id and variant_id
await sdk.cart.addDeleteCartItem(
{ id: cartId },
{ product_id: product.id, variant_id: resolvedVariant.id, quantity: 1 }
);
} else {
// Simple product — variant_id is null
await sdk.cart.addDeleteCartItem(
{ id: cartId },
{ product_id: product.id, variant_id: null, quantity: 1 }
);
}
Hosted Checkout を使用する場合は、代わりに addToCart を使用してください。
const { addToCart } = useCheckout();
addToCart(product.id, product.has_variant ? resolvedVariant.id : null, 1);
標準的なバリアント URL 状態(PDP)
バリアントのある商品では、オプションのクエリパラメーターを信頼できる情報源として使用します:?size=large&color=blue。
- クエリーキーには、プレフィックスを付けずに
option.keyの値をそのまま使用します。 - オプショングループは
variant_optionsの順序で表示します(バリアントを反復処理してオプショングループを導出しないでください)。 - すべてのオプションキーが
variant.associated_optionsと一致する場合にのみ、バリアントを特定します。 - 比較前にオプションの値を一貫した方法で正規化します:
color→option.value.nameと比較します(スウォッチ UI にはoption.value.hexcodeを使用します)。single-select→option.valueと比較します。
variantクエリパラメーターは、派生状態として任意で使用できます:- オプションからバリアントを1つに特定できた場合、設定または更新します。
- 選択が不完全または無効な場合は削除します。
- URL に
variantしかない場合は、そのバリアントからオプションパラメーターを補完します。 - URL に一部のオプションと有効な
variantがある場合は、そのバリアントから不足しているオプションのみを補完します。 variantが無効な場合は、デフォルト(is_default、なければ最初のバリアント)にフォールバックします。
- 必須オプションが選択され、特定されたバリアントが購入可能(
stock_availableまたはbackorder)になるまで、「カートに追加」を無効にします。 - 現在の部分的な選択状態では購入可能なバリアントにつながらないオプション値を無効にします。
標準の SDK 型を直接使用します:
import type {
AssociatedOption,
Product,
Variant,
VariantOption,
} from "@commercengine/storefront";
これらのアプリレベルの型を OpenAPI スキーマから導出しないでください。
実装例:
references/pdp-option-model.md(URL 状態+バリアントの特定+attribute/variantOption UI の統一)
Attribute と VariantOption(PDP の一貫性)
variant_options は、バリアントを決定する属性キー(通常は single-select と color)として扱い、完全に別の表示領域として扱わないでください。
- バリアントのない商品でも、同じキーの
ProductAttribute値を公開できます。 - 商品にバリアントがない場合でも、ブランドによっては PDP でこれらのキーに同じ UI 表現を使用したい場合があります。
- 正規化された単一のオプション表示モデルを維持します:
- バリアントのある商品:
variant_optionsとvariant.associated_optionsから選択可能なオプションを表示します。 - バリアントのない商品:ブランドがオプション風の表示にしたいキー/型について、
attributesから読み取り専用のオプション形式のグループを表示します。
- バリアントのある商品:
- バリアントのある商品で
attribute.keyとvariant_option.keyが重複する場合は、variant-option UI のみを表示し、重複する attribute の行は表示しないでください。 - 主な判断基準として、
attribute.keyの対応と attribute のtype(single-select/color)を使用します。 - カートのルールは厳格に維持します。「カートに追加」の前にバリアントの特定が必要なのは、バリアントのある商品のみです。
商品タイプ
| タイプ | 説明 | 主なフィールド |
|---|---|---|
physical | 配送が必要な有形商品 | shipping、inventory |
digital | ダウンロード可能または仮想の商品 | 配送不要 |
bundle | まとめて販売される商品グループ | サブアイテムを含む |
在庫と販売可能状況
stock_available— ブール値で、Product、Variant、SKU のスキーマに必ず存在します。falseの場合は、「カートに追加」を無効にするか、「在庫切れ」と表示します。backorder— 商品ごとに Admin で設定するブール値です。trueの場合、在庫切れでも注文を受け付けます。ビジネスでバックオーダーを許可する場合は、stock_availableがfalseでもbackorderがtrueならボタンを有効にします。- 在庫数 — カタログ API(
listProducts、listSkusなど)は、レスポンスに在庫データを含めることができます。これを使用して、UI に在庫数を表示します。
顧客グループと価格設定
管理者が顧客グループ(小売業者、販売店、卸売業者など)を設定している B2B ストアフロント向けの高度な機能です。API リクエストで customer_group_id を送信すると、該当するグループの商品一覧、価格、プロモーションが返されます。
リクエストごとにヘッダーを渡さないでください。 SDK の設定で defaultHeaders を使って一度だけ設定します(setup/ §「デフォルトヘッダー」を参照)。ユーザーのログイン後、SDK インスタンスをそのユーザーのグループ ID で更新すると、それ以降の SDK 呼び出しにはすべて自動的にその ID が含まれます。
ウィッシュリスト
Commerce Engine は、SDK メソッドを通じてウィッシュリスト(追加、削除、取得)をサポートしています。これらのスキルでは、ストアフロントの主なフローを扱います。ウィッシュリストやその他の副次的な機能については、LLM API リファレンスまたはCE ドキュメントを参照してください。
よくある落とし穴
| レベル | 問題 | 解決策 |
|---|---|---|
| CRITICAL | listProducts() を使ってフィルター付きの PLP を構築する | searchProducts({ query, filter, sort, facets }) を使用してください。data.skus(Item[])と data.facet_distribution、data.facet_stats が返されます。listProducts() はファセットを含まない Product[] を返します。Meilisearch のフィルター構文(例:"rating > 4 AND product_type = physical")を使用します。 |
| CRITICAL | Product と Item の型を混同する | listProducts() は Product[](バリアント配列を含むグループ化されたデータ)を返します。listSkus() と searchProducts() は Item[](フラットなデータ。各バリアントが個別のレコード)を返します。 |
| CRITICAL | 複数のオプションがある商品で、PDP の URL の信頼できる情報源として variant を使う | オプションのパラメーター(size、color など)を正規の値として保持し、variant は派生値/バックフィル専用として扱います。 |
| HIGH | 1 つのオプション、または variant_options のみを使ってバリアントを解決する | すべてのオプションキーにわたって variant.associated_options を照合してください。 |
| HIGH | アプリコードで生成されたスキーマからオプション/バリアントの型を導出する | SDK の型を @commercengine/storefront から直接インポートしてください(AssociatedOption、VariantOption、Variant、Product)。 |
| MEDIUM | attributes と variant_options を別々の PDP UI として扱う | バリアント商品と非バリアント商品の両方で、共通のキー(例:metal)を一貫して表示できるよう、統合されたオプション表示モデルを構築してください。 |
| HIGH | has_variant フラグを無視する | バリアントデータにアクセスする前に、必ず has_variant を確認してください。 |
| HIGH | バリアントではなく商品をカートに追加する | has_variant: true の場合は、商品ではなく特定のバリアントを追加する必要があります。 |
| MEDIUM | URL に slug を使わない | SEO に適した URL には slug フィールドを使用してください。カタログエンドポイントの product_id パラメーターは、ID とスラッグの両方を受け付けます。 |
| MEDIUM | ページネーションを見落とす | すべてのリストエンドポイントは pagination を返します。page と limit パラメーターを使用してください。 |
| LOW | カテゴリーを再取得する | カテゴリーはほとんど変更されないため、クライアント側でキャッシュしてください。 |
関連項目
setup/- 最初に SDK の初期化が必要ですcart-checkout/- 商品をカートに追加する方法orders/- 注文のコンテキストにおける商品ssr-patterns/- 商品ページの SSG/事前レンダリング(Next.js のgenerateStaticParams()、TanStack Start の事前レンダリング)