CONTENT
ここから
第15章では、EC管理画面の基本として、注文一覧、注文詳細、ステータス変更、CSV出力などを整理しました。
この章では、管理画面の中でも特に重要な商品管理機能を作ります。
商品管理機能とは、店舗側が商品を登録したり、価格を変更したり、在庫数を調整したりするための機能です。
ECでは、商品ページが表の顔です。
そして商品管理画面は、その商品ページを支える裏側の作業場です。
購入者が見る画面:
商品一覧
商品詳細
購入ボタン
店舗が使う画面:
商品登録
商品編集
画像管理
価格変更
在庫変更
公開・非公開
攻略本風に言えば、第16章は**「商品を売り場に並べるための管理ステージ」**です。
16.1 商品登録フォーム
商品登録フォームは、新しい商品をECサイトに追加するための画面です。
最初から複雑なフォームを作る必要はありません。
小規模ECで最低限必要な項目は、次の通りです。
・商品名
・商品説明
・価格
・商品画像
・在庫数
・公開状態
・カテゴリ
・スラッグ
スラッグとは、URLに使う商品ごとの名前です。
たとえば、次のようなURLの最後の部分です。
/products/classic-bushi-gift
この場合、classic-bushi-giftがスラッグです。
商品登録フォームの画面イメージは、次のようになります。
商品登録
商品名:
[ クラシック節ギフトセット ]
スラッグ:
[ classic-bushi-gift ]
価格:
[ 5400 ]
在庫数:
[ 20 ]
カテゴリ:
[ ギフト ]
公開状態:
[ 下書き ▼ ]
商品説明:
[ 商品説明を入力 ]
商品画像:
[ 画像をアップロード ]
[ 保存する ]
最初は、登録時にいきなり公開しない設計がおすすめです。
まずはdraft、つまり下書きとして保存します。
draft:
下書き。購入者には表示しない
published:
公開中。購入者に表示する
private:
非公開。管理画面だけで確認する
商品登録時の基本フローは、次の通りです。
商品情報を入力
↓
下書きで保存
↓
内容を確認
↓
問題なければ公開
TypeScriptで商品登録の入力型を考えると、次のようになります。
type ProductStatus = 'draft' | 'published' | 'private';
type CreateProductInput = {
name: string;
slug: string;
description: string;
price: number;
stock: number;
categoryId: string | null;
status: ProductStatus;
};
/**
* 役割: 管理画面から新しい商品を登録する
* 入力: 商品名、スラッグ、説明、価格、在庫数、カテゴリ、公開状態
* 出力: 作成された商品のID
*/
async function createProduct(input: CreateProductInput): Promise<string> {
// 実際の実装では、ここでDBに商品情報を保存する
// 入力値の検証を必ず行う
return 'new_product_id';
}
商品登録フォームで大切なのは、入力ミスを防ぐことです。
特に次の項目は必ず検証します。
・商品名が空ではないか
・価格が0円未満ではないか
・在庫数が0未満ではないか
・スラッグが重複していないか
・公開する商品に画像があるか
商品登録は、ECの入口です。
ここが雑だと、商品ページ、決済、在庫、SEOまですべてに影響します。
16.2 商品編集フォーム
商品編集フォームは、すでに登録した商品を修正するための画面です。
商品登録フォームと似ていますが、編集ではさらに注意が必要です。
なぜなら、すでに販売中の商品を変更する可能性があるからです。
商品登録:
新しく商品を作る
商品編集:
すでに存在する商品を変更する
商品編集でよく変更する項目は、次の通りです。
・商品名
・商品説明
・価格
・画像
・在庫数
・カテゴリ
・公開状態
・おすすめ表示
・並び順
編集画面では、現在の状態が分かるようにします。
商品名:クラシック節ギフトセット
現在の価格:5,400円
現在の在庫:20個
公開状態:公開中
最終更新:2026年7月6日 15:30
特に、価格や在庫を変更する場合は注意が必要です。
商品ページを見ているユーザーがいる可能性があるからです。
ユーザーA:
5,400円の商品ページを見ている
管理者:
価格を6,000円に変更する
ユーザーA:
古い価格のまま購入ボタンを押す可能性がある
そのため、最終的な金額は必ずサーバー側で計算します。
画面に表示されている価格だけを信用してはいけません。
商品編集フォームの保存処理では、入力値を確認してから更新します。
type UpdateProductInput = {
productId: string;
name: string;
slug: string;
description: string;
price: number;
stock: number;
categoryId: string | null;
status: ProductStatus;
};
/**
* 役割: 既存の商品情報を更新する
* 入力: 商品IDと更新後の商品情報
* 出力: 更新が成功したかどうか
*/
async function updateProduct(input: UpdateProductInput): Promise<boolean> {
// 実際の実装では、更新前の商品が存在するか確認する
// 価格や在庫など重要項目は変更履歴を残すと安全
return true;
}
編集時におすすめなのは、変更履歴を残すことです。
2026-07-06 15:30
価格を5,400円から6,000円に変更
実行者:admin@example.com
履歴があると、あとから「いつ、誰が、何を変えたか」を確認できます。
特に価格変更と在庫変更は、必ず履歴を残す設計にします。
16.3 商品画像アップロード
商品画像は、ECの売上に大きく影響します。
購入者は、実物を手に取れないため、画像を見て判断します。
そのため、商品管理画面では、画像を登録・変更できるようにします。
商品画像で最低限必要な機能は、次の通りです。
・画像アップロード
・メイン画像の設定
・複数画像の登録
・画像の並び替え
・画像の削除
・代替テキストの入力
画像の役割を分けると分かりやすくなります。
メイン画像:
商品一覧やOGPに使う代表画像
詳細画像:
商品詳細ページで見せる補足画像
説明画像:
使い方、サイズ感、内容量などを説明する画像
画像登録画面のイメージです。
商品画像
メイン画像:
[ 画像を選択 ]
追加画像:
[ 画像を追加 ]
画像の説明:
[ 商品パッケージ正面 ]
[ 保存する ]
画像アップロードで注意することは、画像サイズです。
重すぎる画像をそのまま表示すると、商品ページの読み込みが遅くなります。
悪い例:
スマホで撮影した大きな画像をそのまま表示
よい例:
表示に適したサイズへ変換して使う
管理画面では、アップロード時に次のルールを決めておくと安全です。
・対応形式はjpg、png、webpなどに限定する
・ファイルサイズ上限を決める
・画像の縦横比をある程度そろえる
・画像の代替テキストを入れられるようにする
代替テキストとは、画像の内容を説明するテキストです。
SEOやアクセシビリティのためにも大切です。
悪い例:
image1
よい例:
クラシック節ギフトセットの外箱と中身
商品画像は、見た目だけでなく、表示速度や検索評価にも関係します。
画像管理は、商品管理機能の中でも重要な部分です。
16.4 価格変更
価格変更は、商品管理の中でも特に慎重に扱うべき操作です。
価格は購入者の判断に直結します。
また、決済金額にも関わります。
商品ページの表示価格
↓
カート内の金額
↓
Squareへ送る決済金額
↓
注文DBの合計金額
この流れがズレると、トラブルになります。
価格変更で大切なのは、表示価格と決済金額をサーバー側で一致させることです。
ユーザーのブラウザから送られてきた金額をそのまま信用してはいけません。
危険な設計:
ブラウザから送られた価格で決済する
安全な設計:
商品IDを受け取り、サーバー側で現在価格を取得して決済する
価格変更時の管理画面では、変更前と変更後を表示します。
現在の価格:
5,400円
変更後の価格:
6,000円
[価格を変更する]
確認ダイアログも入れます。
価格を変更しますか?
変更前:5,400円
変更後:6,000円
この変更は商品ページと購入金額に反映されます。
価格変更履歴も残します。
価格変更履歴
2026-07-06 15:30
5,400円 → 6,000円
実行者:admin@example.com
価格を変更した直後は、キャッシュにも注意します。
商品ページを静的化している場合、古い価格が一時的に表示される可能性があります。
そのため、価格変更後には商品ページを再検証する設計が必要です。
価格変更
↓
DB更新
↓
商品ページのキャッシュを再検証
↓
新しい価格を表示
価格はECの信頼に直結します。
必ず、表示、注文、決済の金額が一致するようにします。
16.5 公開・非公開の切り替え
商品には、公開状態を持たせます。
すべての商品を常に表示するわけではありません。
たとえば、次のような商品があります。
・まだ準備中の商品
・販売終了した商品
・在庫切れの商品
・限定販売の商品
・催事専用の商品
・管理画面だけで確認したい商品
そのため、商品ステータスを用意します。
draft:
下書き。管理画面だけで確認する
published:
公開中。購入者に表示する
private:
非公開。URLを知っていても表示しない
archived:
販売終了。管理用に残す
公開・非公開を切り替えるときの考え方は、次の通りです。
公開中:
商品一覧に表示する
商品詳細ページを表示する
購入できる
下書き:
商品一覧に表示しない
商品詳細ページも公開しない
購入できない
販売終了:
商品一覧には出さない
必要に応じて販売終了ページを表示する
購入できない
商品を削除するのではなく、非公開や販売終了にする設計がおすすめです。
商品を削除:
過去の注文とのつながりが分からなくなる
商品を非公開:
購入者には見えないが、管理画面では残る
過去の注文には、商品情報が紐づいています。
商品を完全に削除すると、過去注文の確認が難しくなることがあります。
過去注文:
クラシック節ギフトセットを購入
商品マスターを削除:
どの商品だったか追いにくくなる
そのため、実務では削除よりも非公開を使います。
公開切り替えにも確認を入れます。
この商品を公開しますか?
公開すると購入者が商品ページを見られるようになります。
非公開にする場合も確認します。
この商品を非公開にしますか?
商品一覧や商品詳細ページから購入できなくなります。
公開状態は、売り場の入口です。
出す、隠す、残すをきちんと分けましょう。
16.6 在庫数の変更
在庫数の変更は、商品管理の中でも特に実務に近い機能です。
店舗では、次のような場面で在庫を変更します。
・商品が入荷した
・実店舗で売れた
・催事販売で在庫が減った
・破損や不良品が出た
・棚卸しで数が違っていた
在庫数の変更には、2つの方法があります。
A. 現在の在庫数を直接変更する
B. 増減数を入力して在庫を調整する
直接変更の例です。
現在の在庫:20個
変更後の在庫:15個
増減入力の例です。
現在の在庫:20個
調整:-5個
変更後の在庫:15個
実務では、増減入力の方が履歴を残しやすいです。
2026-07-06 16:00
在庫調整:-5
理由:催事販売
実行者:admin@example.com
在庫変更では、理由を選べるようにすると便利です。
・入荷
・実店舗販売
・催事販売
・破損
・棚卸し調整
・返品
・その他
TypeScriptで在庫調整の入力型を作ると、次のようになります。
type StockAdjustmentReason =
| 'restock'
| 'store_sale'
| 'event_sale'
| 'damage'
| 'inventory_check'
| 'return'
| 'other';
type AdjustStockInput = {
productId: string;
quantityChange: number;
reason: StockAdjustmentReason;
memo?: string;
};
/**
* 役割: 商品在庫を増減させ、在庫変更履歴を残す
* 入力: 商品ID、増減数、変更理由、メモ
* 出力: 更新後の在庫数
*/
async function adjustStock(input: AdjustStockInput): Promise<number> {
// 実際の実装では、在庫数が0未満にならないように検証する
// 同時更新に備えてDB側で安全に更新する
return 15;
}
在庫数は、0未満にならないようにします。
悪い例:
在庫数:-3
よい例:
在庫数:0
売り切れ表示
在庫は、EC、実店舗、催事販売が絡むとズレやすくなります。
そのため、在庫変更履歴を残すことがとても重要です。
16.7 カテゴリ管理
カテゴリは、商品を探しやすくするための分類です。
商品数が少ないうちはカテゴリなしでも問題ありません。
しかし、商品が増えると、カテゴリがないECは見づらくなります。
カテゴリなし:
すべての商品が一列に並ぶ
カテゴリあり:
ギフト
単品
セット
季節商品
定期便
カテゴリの例です。
食品EC:
だし
ギフト
セット商品
定期便
季節限定
工芸品EC:
器
布
一点もの
展示会作品
予約販売
カテゴリ管理で必要な項目は、次の通りです。
・カテゴリ名
・スラッグ
・説明文
・表示順
・公開状態
カテゴリにもスラッグを持たせます。
/categories/gift
/categories/limited
/categories/subscription
カテゴリページはSEOにも関係します。
たとえば、「ギフト商品一覧」のようなカテゴリページを作ると、検索流入の入口になります。
商品ページ:
1つの商品を詳しく見せる
カテゴリページ:
同じ目的の商品をまとめて見せる
カテゴリ管理では、1商品に複数カテゴリを付けるかどうかも考えます。
単一カテゴリ:
商品は1つのカテゴリにだけ属する
複数カテゴリ:
商品は複数カテゴリに属する
小規模ECでは、最初は単一カテゴリで十分です。
商品:
クラシック節ギフトセット
カテゴリ:
ギフト
将来的に商品数が増えたら、タグを追加する方法もあります。
カテゴリ:
ギフト
タグ:
母の日
お中元
高級
常温配送
カテゴリは売り場の棚です。
商品をどの棚に置くかで、購入者の見つけやすさが変わります。
16.8 おすすめ商品設定
おすすめ商品は、トップページや商品詳細ページで目立たせたい商品です。
すべての商品を同じように並べると、購入者はどれを選べばよいか迷います。
そこで、店舗側が特に見せたい商品を選びます。
おすすめ商品:
初めての人に買ってほしい商品
季節的に売りたい商品
ギフト向けの商品
利益率の高い商品
在庫を動かしたい商品
おすすめ商品は、次の場所に表示できます。
・トップページ
・商品一覧の上部
・商品詳細ページの下部
・ギフトページ
・初めての方向けページ
管理画面では、商品ごとにおすすめ設定を持たせます。
おすすめ商品にする:
[ ON ]
表示場所:
[ トップページ ]
[ ギフトページ ]
[ 関連商品 ]
最初は、シンプルにisFeaturedだけでも十分です。
type ProductFeatureSettings = {
productId: string;
isFeatured: boolean;
featuredSortOrder: number | null;
};
おすすめ商品で注意したいのは、数を増やしすぎないことです。
おすすめが多すぎると、結局どれが大事なのか分からなくなります。
悪い例:
20商品すべておすすめ
よい例:
おすすめは3〜5商品に絞る
おすすめ商品には、目的を持たせます。
初めての方向け:
定番商品
ギフト向け:
見栄えのよい商品
リピート向け:
消耗品や定期便
季節向け:
期間限定商品
おすすめ商品は、店舗側の売りたい気持ちだけで決めるのではなく、購入者が選びやすくなるかどうかで決めます。
16.9 並び順の管理
商品一覧では、並び順がとても重要です。
購入者は、上にある商品から見ていきます。
そのため、何を先に見せるかで売れ方が変わります。
上に表示する商品:
定番商品
売れ筋商品
おすすめ商品
季節商品
初めての人向け商品
並び順の管理方法はいくつかあります。
・登録日順
・価格順
・人気順
・在庫数順
・手動並び替え
小規模ECでは、最初は手動並び替えが分かりやすいです。
店舗側が「この商品を上に出したい」と決められるからです。
商品にsortOrderを持たせます。
type ProductSortSettings = {
productId: string;
sortOrder: number;
};
数字が小さいほど上に表示する、というルールにします。
sortOrder: 10
→ 上に表示
sortOrder: 20
→ 次に表示
sortOrder: 30
→ その次に表示
管理画面では、ドラッグ操作で並び替えられると便利です。
ただし、最初は数字入力でも問題ありません。
商品A:10
商品B:20
商品C:30
数字を10刻みにしておくと、あとから間に商品を入れやすくなります。
商品A:10
商品B:20
間に入れたい商品:
商品C:15
並び順を変更したら、商品一覧ページのキャッシュも更新します。
並び順変更
↓
DB更新
↓
商品一覧ページを再検証
↓
新しい並び順で表示
並び順は、店舗の販売戦略そのものです。
「何を先に見せるか」を管理できるだけで、ECの運用力が上がります。
16.10 商品マスターと販売ページの分離
最後に、商品管理でとても大切な考え方を扱います。
それが、商品マスターと販売ページの分離です。
初心者のうちは、商品情報と販売ページを同じものとして考えがちです。
しかし、実務では分けて考えた方が安全です。
商品マスター:
商品そのものの基本情報
販売ページ:
その商品をどう見せて売るか
商品マスターには、変わりにくい情報を持たせます。
・商品ID
・商品名
・基本価格
・在庫数
・SKU
・カテゴリ
・管理用メモ
販売ページには、見せ方に関する情報を持たせます。
・キャッチコピー
・商品説明
・画像
・おすすめ文
・ギフト訴求
・SEOタイトル
・メタディスクリプション
・公開状態
なぜ分けるのか。
理由は、同じ商品でも売り方が変わることがあるからです。
同じ商品:
クラシック節
販売ページA:
初めての方向け
販売ページB:
ギフト向け
販売ページC:
お中元向け
販売ページD:
催事限定
もし商品マスターと販売ページを一体にしていると、売り方を変えるたびに商品そのものの情報まで変更することになります。
これは管理が難しくなります。
商品マスター:
変えすぎない
販売ページ:
季節や導線に合わせて変える
最初の小規模ECでは、完全に分けなくても構いません。
ただし、設計思想としては分けて考えることが大切です。
最小構成では、次のようにします。
products:
商品の基本情報
product_pages:
商品ページの表示情報
シンプルに始めるなら、まずはproductsだけでも十分です。
ただし、将来的に次のようなことをしたい場合は、分離を検討します。
・同じ商品を複数ページで売りたい
・季節ごとに訴求を変えたい
・ギフトページ専用の説明を作りたい
・催事販売用ページを作りたい
・SEO用の記事と商品をつなげたい
商品マスターと販売ページを分けると、ECはただの販売画面ではなく、販売戦略を組み立てる場所になります。
第16章のまとめ
商品管理機能は、ECの売り場を作るための機能です。
購入者には見えない管理画面ですが、商品登録、価格変更、在庫変更、公開切り替えが整っていると、運用がとても楽になります。
この章で覚えておきたいポイントは、次の通りです。
1. 商品登録フォームでは、商品名、価格、在庫、画像、公開状態を管理する
2. 商品編集では、価格や在庫の変更履歴を残す
3. 商品画像は、見た目だけでなく表示速度やSEOにも関係する
4. 価格変更では、表示価格と決済金額を必ず一致させる
5. 商品は削除よりも非公開・販売終了で管理する
6. 在庫変更では、理由と履歴を残す
7. カテゴリは、購入者が商品を探しやすくする棚である
8. おすすめ商品は、購入者が選びやすくなるように絞る
9. 並び順は、何を先に見せるかを決める販売戦略である
10. 商品マスターと販売ページは分けて考えると拡張しやすい
最初から完璧な商品管理機能を作る必要はありません。
まずは、次の5つから始めれば十分です。
・商品登録
・商品編集
・画像登録
・価格変更
・公開・非公開の切り替え
そのあと、在庫管理、カテゴリ管理、おすすめ商品、並び順を追加していくと、実務で使いやすい管理画面になります。
第17章では、注文された商品を実際に届けるための配送管理機能を作っていきます。