product-comparison について
product-comparisonは、オンラインストアの商品を並べて比較する機能を設計するスキルです。各プラットフォームでの設定や、URLで選択状態を保ち、固定ヘッダーと同一属性の非表示に対応する独自実装を扱います。
主な機能
- 012~4商品を表で比較
- 02属性が同じ行を非表示
- 03比較状態をURLに保存
- 04主要なECプラットフォームで比較機能を設定
- 05商品属性を整理して差異を強調
- 06モバイルでスクロール可能な表
活用シーン
- 01オンラインストアに商品比較を追加
- 02技術仕様の比較を購入者に促す
- 03B2B購入者が比較内容を共有
- 04ヘッドレスストア向けの比較ページを構築
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ finsilabs/ awesome-ecommerce-skills --skill product-comparisonインストール後、Claude Code で/product-comparisonを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
tile.jsonevals/accessible-comparison-table-with-attribu/criteria.jsontask.mdevals/compare-checkboxes-and-floating-comparis/criteria.jsontask.mdevals/url-state-management-and-attribute-norma/criteria.jsontask.md詳細
商品比較
概要
購入者が2~4点の商品を選択し、ヘッダーが固定されたテーブルで属性を確認できる、横並びの商品比較機能を構築します。選択したすべての商品で同一の属性行は、情報をすっきりさせるために非表示にできます。比較状態はURLに保存されるため、共有したりブックマークしたりできます。
このスキルを使用する場面
- 技術仕様が多い商品(電子機器、家電、カメラ)を販売している場合
- 購入前に複数の商品を検討している購入者が多いことが、コンバージョン調査で示されている場合
- 商品カタログの属性データが適切に構造化されており、比較に活用できる場合
- 購入者が関係者に購入の判断理由を説明する必要があるB2Bストアを構築する場合
- 商品一覧ページに「比較」チェックボックスを実装する場合
基本的な手順
ステップ1:マーチャントのプラットフォームを特定し、適切な方法を選択する
| プラットフォーム | 推奨する方法 | 理由 |
|---|---|---|
| Shopify | Comparify または Product Compare アプリをインストールする(どちらも無料プランを利用可能) | Shopifyには比較機能が組み込まれていません。これらのアプリを使うと、商品カードに比較ボタンを追加し、比較用のフローティングトレイや比較テーブルのページを作成できます。仕様データには商品メタフィールドを使用します |
| WooCommerce | YITH WooCommerce Compare(無料)または WooCommerce Products Compare をインストールする | YITH Compareは最も人気のある無料オプションです。商品カードへの比較チェックボックスの追加、WooCommerceの商品属性を使った比較テーブルページの作成、差異のみを表示する切り替え機能が利用できます |
| BigCommerce | Storefront → My Themes → Customize(Cornerstoneテーマ)で組み込みのCompare機能を有効にする | BigCommerceとCornerstoneにはネイティブの商品比較機能が含まれています。テーマエディターで有効にすると、商品カスタムフィールドが比較属性として使用されます |
| カスタム/ヘッドレス | 商品属性データを使って、URLの状態を保持する比較トレイと比較テーブルページを構築する | 属性の表示、差異の強調、テーブルレイアウトを完全に制御できます。実装については以下をご覧ください |
ステップ2:プラットフォームで比較機能を有効にして設定する
Shopify
Comparifyアプリを使用する場合:
- Shopify App StoreからComparify – Product Comparisonをインストールします(無料プランを利用可能)
- アプリの設定で、比較行として表示する商品メタフィールドを選択します(例:素材、重量、寸法、保証)
- まだメタフィールドを設定していない場合は、Settings → Custom data → Productsに移動し、仕様用のメタフィールドを作成します
- アプリによって、コレクションページの商品カードに「Compare」チェックボックスが自動的に追加されます
- 購入者が最大4点の商品を選択し、フローティングトレイで「Compare」をクリックすると、比較テーブルのページが表示されます
- アプリのTable Settingsで、行として表示する属性とその順序を設定します
商品データの準備:
- 仕様データは商品メタフィールドに追加することを推奨します。商品説明に追加する場合は、書式を統一してください
- バリエーションの仕様は、バリエーションのメタフィールドに追加します(例:サイズごとの重量)
WooCommerce
YITH WooCommerce Compare(無料)を使用する場合:
- WordPress.orgからインストールして有効化します
- YITH → Compare → Settingsに移動します
- Fields to compareで、行として表示するWooCommerceの商品属性とカスタムフィールドを選択します(例:色、素材、寸法、重量)
- Maximum productsを4に設定します
- Highlight differencesを有効にして、商品間で異なる行を視覚的に強調します
- プラグインによって、ショップページやアーカイブの商品カードに「Compare」ボタンが追加されます
- 購入者が商品を追加すると、ページ下部に比較用のフローティングバーが表示されます
商品データの準備:
- Products → Attributesから比較属性を追加します。「素材」、「保証」、「対応製品」などの属性を作成し、各商品に値を設定します
- 比較行を正しく揃えるには、商品間で同じ属性名を使用する必要があります
BigCommerce
組み込みの比較機能(Cornerstone テーマ):
- Storefront → My Themes → Customize に移動します
- Global → Product Compare(テーマのバージョンによっては Category Page → Product Compare)に移動します
- Enable product comparison をオンに切り替えます
- Maximum products を設定します(デフォルトは 4 です)
- 比較行として表示する Product Custom Fields を、Products → Product Custom Fields の設定で指定します
- 商品カードに「Compare」チェックボックスが表示され、フローティング比較トレイが自動的に表示されます
スペックデータの追加:
- Products → [product] → Custom Fields に移動し、名前と値のペアを追加します(例:「Screen Size: 15.6 inches」、「Battery Life: 10 hours」)
- 比較対象の商品で同じフィールド名を使用すると、比較表の項目が揃います
カスタム/ヘッドレス
比較トレイ(商品を選択すると表示されるフローティングバー):
// ComparisonTray.jsx
export function ComparisonTray({ selectedProducts, onRemove, onClear }) {
if (selectedProducts.length === 0) return null;
const compareUrl = `/compare?${selectedProducts.map(p => `compare=${p.id}`).join('&')}`;
return (
<div className="comparison-tray" aria-live="polite" aria-label="Products selected for comparison">
<div className="tray-products">
{selectedProducts.map(product => (
<div key={product.id} className="tray-product">
<img src={product.image} alt={product.name} width="48" height="48" />
<button onClick={() => onRemove(product.id)} aria-label={`Remove ${product.name} from comparison`}>×</button>
</div>
))}
{Array.from({ length: Math.max(0, 4 - selectedProducts.length) }).map((_, i) => (
<div key={`empty-${i}`} className="tray-placeholder" aria-hidden="true">+</div>
))}
</div>
<div className="tray-actions">
<a href={compareUrl} className="btn-primary" aria-disabled={selectedProducts.length < 2}>
Compare ({selectedProducts.length})
</a>
<button onClick={onClear}>Clear all</button>
</div>
</div>
);
}
固定ヘッダーと差分のハイライト表示に対応した比較表:
export function ProductComparisonTable({ products, attributeGroups, showOnlyDifferences }) {
function isRowIdentical(attrKey) {
const values = products.map(p => p.attributes[attrKey]);
return values.every(v => v === values[0]);
}
return (
<div className="comparison-wrapper" style={{ overflowX: 'auto' }}>
<table className="comparison-table">
<caption className="sr-only">
Side-by-side comparison of {products.map(p => p.name).join(', ')}
</caption>
<thead>
<tr>
<th scope="col" className="attr-col">Attribute</th>
{products.map(product => (
<th key={product.id} scope="col">
<img src={product.image} alt={product.name} width="80" height="80" />
<a href={product.url}>{product.name}</a>
<strong>${product.price}</strong>
<button className="btn-primary">Add to Cart</button>
</th>
))}
</tr>
</thead>
<tbody>
{attributeGroups.map(group => (
<>
<tr key={`group-${group.label}`}>
<th scope="rowgroup" colSpan={products.length + 1}>{group.label}</th>
</tr>
{group.attributes.map(attrKey => {
if (showOnlyDifferences && isRowIdentical(attrKey)) return null;
return (
<tr key={attrKey} className={isRowIdentical(attrKey) ? 'identical-row' : 'different-row'}>
<th scope="row">{attrKey.replace(/_/g, ' ')}</th>
{products.map(p => (
<td key={p.id}>{p.attributes[attrKey] ?? 'N/A'}</td>
))}
</tr>
);
})}
</>
))}
</tbody>
</table>
</div>
);
}
比較の URL 状態(戻るボタンの履歴が汚れないように replaceState を使用):
function toggleCompare(productId) {
const params = new URLSearchParams(window.location.search);
const current = params.getAll('compare');
if (current.includes(productId)) {
params.delete('compare');
current.filter(id => id !== productId).forEach(id => params.append('compare', id));
} else if (current.length < 4) {
params.append('compare', productId);
}
window.history.replaceState({}, '', `${window.location.pathname}?${params.toString()}`);
}
ベストプラクティス
- 比較対象を 2~4 商品に制限する — 4 列を超えるとほとんどの画面で表のレイアウトが崩れるため、UI で制限します
- 属性をカテゴリ別にまとめる — スペックをグループ(ディスプレイ、パフォーマンス、バッテリー)に整理し、50 行に及ぶフラットな表になるのを防ぎます
- 「違いのみ表示」トグルを用意する — すべての商品で値が同じ行は情報を見づらくするため、簡単に切り替えられるようにします
- モバイルでは表を横スクロール可能にする — ラッパーに
overflow-x: autoを使用します。小さな画面に合わせるために列を非表示にしてはいけません - 商品一覧ページから事前に選択状態を引き継ぐ — PLP で商品を選択した後、購入者が「Compare Now」をクリックした場合は、URL に ID を含めて遷移します
- 属性名を統一する — 表の行を揃えるには、商品間で同一のフィールド名(例:「Display Size」ではなく「Screen Size」)を使用する必要があります
よくある問題
| 問題 | 解決策 |
|---|---|
| モバイルで表がはみ出す | スクロール可能なコンテナーで囲み、最初の列(属性ラベル)には position: sticky を使用します |
| 一部の商品で属性が欠けている | 値に「N/A」を使用します。セルを省略すると列の位置がずれるため、省略しないでください |
| 比較トレイがページのコンテンツを覆う | トレイの表示中は、トレイの高さに合わせてページ本文に padding-bottom を追加します |
| 商品ごとに属性セットが異なる | 比較するすべての商品で属性キーを統一し、欠けている値には null を設定します |
関連スキル
- @product-page-design
- @faceted-navigation
- @accessibility-commerce
- @recently-viewed-products
コメント
Markdown 対応