N.Hayashida

作らないという判断
ECを作り直す前に、売上を分解した

データ分析 / 意思決定分析 / 設計検討 / 意思決定2025年10月〜2026年7月2026-07-04

妻が営むフラワーショップのECを、全面的に作り直す計画を立てていました。設計はほぼ固まっていましたが、着手前に売上データを分解したところ、ボトルネックはサイトではないと分かりました。作らずに済ませた判断の記録です。

9,047件

再集計した注文データ

Technologies

PythonSQLiteSQLEC-CUBENext.js(設計のみ)

プロジェクト概要

妻が営むフラワーショップのオンラインショップについて、既存のECプラットフォームから Next.js + Supabase への全面リプレイスを計画していました。アーキテクチャの検討はかなり進み、あとは着手するだけという状態でした。

結論から書くと、作りませんでした。

着手する前に売上データを分解したところ、解決すべき問題はサイトの作りではなかったからです。この記事は、その判断に至るまでの記録です。

きっかけ
決済だけが通ってしまう

発端は、在庫にまつわる不具合でした。

このショップの商品はすべて一点ものです。同じものが二つとありません。そして販売方法にも特徴があって、月に2回、決まった時刻に販売を開始し、1時間ほどでほぼ完売します。数十点の商品を、200人ほどのお客さんが同時に取り合う形になります。

この条件で、まれに事故が起きました。決済は完了しているのに、商品を確保できていない。つまりお客さんは支払ったのに商品が届かないという、小売として最も避けたい状態です。

原因を追うと、構造的な問題に行き着きました。在庫の引き当てが決済処理より後になっていて、しかも両者がひとつのトランザクションになっていない。同時アクセスが集中すれば、すり抜けが起きます。

既存プラットフォームの設定変更でどうにかならないか、いくつか案を検討しました。在庫確保を前倒しする、決済前のチェックを強化する、といった方向です。しかしどれも対症療法で、根本的な解決には届かないという判断になりました。

全面リプレイスの設計まで進めた

そこで、作り直す前提で設計を始めました。

中心に据えたのは段階的なロックです。カートに入れた時点で一定時間だけ在庫を仮押さえし、決済が完了したら確定、時間切れなら自動的に解放する。同時に、在庫の状態をリアルタイムで画面に反映させて、そもそも売り切れたものをカートに入れられないようにする。

販売開始直後のアクセス集中に耐える構成、注文管理を楽にする管理画面、40〜60代のお客さんが多いことを踏まえた画面設計。このあたりまで、具体的に詰めていきました。

ロックの保持時間をどうするかは最後まで悩みました。短すぎると、ゆっくり選びたいお客さんが決済中に商品を失う。長すぎると、買う気のない人が在庫を握り続ける。ここは正解のない設計判断で、複数の案を並べたまま止まっていました。

着手前に、データを見ることにした

設計が固まってきた頃、ふと引っかかったことがあります。

この不具合は、確かに深刻です。でも、年に数件です。

一方でこれから作ろうとしているのは、決済も在庫も会員も含めた全面的な作り直しです。本業のかたわら、夜と週末で進める規模ではありません。

そもそも、なぜ作り直そうとしているのか。売上が落ちてきているから、なんとかしたい。その「なんとか」の中身を、私は検証していませんでした。サイトを作り直せば売上が戻る、という仮説を一度も疑っていなかったわけです。

作る前に測ろう、と決めました。

匿名化してから分析する

まず困ったのは、本番のデータには当然ながら顧客の個人情報が含まれていることです。氏名も住所も連絡先も入っています。これを分析用のPCに持ってきて、そのまま集計するのは避けたい。

そこで、本番のダンプを読み込んで、匿名化した分析用データベースを出力する変換スクリプトを書きました。個人情報の列は破棄し、同一人物の判定に必要な識別子だけを一方向ハッシュに置き換えます。ハッシュから元には戻せませんが、「この注文とこの注文は同じ人」という判定はできる。リピート構造を見るにはこれで十分でした。

出力先はSQLiteの単一ファイルです。取り回しが軽く、集計クエリをそのまま書けます。月次で更新する手順も整理して、5分で最新のレポートに差し替えられる状態にしました。

分析の対象になったのは、9,047件の注文です。

分解して分かったこと

年別に分解して、指標ごとに並べてみました。すると、思っていたのと違う絵が出てきました。

指標傾向判定
客単価ピーク時から**+26%**健全
カゴ落ち率65% → 49% に改善健全
リピート由来の売上比率ほぼ0%から 約50% へ健全

売上が落ちているのだから、どこかに悪い数字があるはずだと思っていました。ところが、追いかけた指標はどれも健全でした。

客単価は上がっています。カゴ落ち率、つまり買い物かごに入れたのに買わずに離脱する割合は、むしろ改善していました。既存のお客さんは繰り返し買ってくれていて、売上の半分はリピートで成り立っています。全期間で2,174人が購入し、そのうち617人が2回以上、118人は5回以上のコアなお客さんでした。

つまり、来てくれた人はちゃんと買っている。

落ちていたのは、新規のお客さんの数だけでした。他の指標がどれも横ばいか改善しているなかで、ここだけが逆の動きをしていました。

さらに集客の経路を見ると、流入のほとんどがひとつのSNSに依存していました。そのSNS経由の外部リンクのタップ数が、前の期間と比べて28.5%減。タップした人のうち注文に至る割合は約2.9%で、こちらは安定しています。

入口の数が減っただけで、入ってきた人の通り方は悪くなっていなかったわけです。

Fig.01
直すべきは、サイトへ来る前だったSNS閲覧86,0002.2%プロフィール1,86544%外部リンク816前期間比 28.5%減約2.9%EC注文24サイト内は健全だった分析した注文9,047件購入者2,174人2回以上617人/5回以上118人売上のリピート約半分カゴ落ち率改善以前の水準に必要なタップ現在816必要2,400/月いまの約3倍サイトを作り直しても入口は増えない。だから、作らないと決めた。

結論
直すべきはサイトではなかった

ここまで来て、答えははっきりしました。

サイトを作り直しても、新規のお客さんは増えません。カゴ落ち率も客単価もリピート率も、すでに健全な数字です。改善の余地が大きい指標が見当たらない。つまり、私が数ヶ月かけて作ろうとしていたものは、事業の一番痛いところに効かない。

在庫の不具合は、確かに直すべき問題です。でもそれは**「全面リプレイスの理由」ではなく「運用でカバーすべき問題」でした。**順序を間違えていたのです。

全面リプレイスは見送りました。代わりに、リピートしてくれている617人に季節ごとの案内を届ける仕組みと、SNS以外の新規の入口をつくることに切り替えています。

学んだこと

作らない判断をした、というのがこのプロジェクトの成果です。

エンジニアとして一番危険だったのは、「作れる」ことと「作るべき」ことを混同していた点でした。設計は楽しかったし、技術的にも解けそうだった。だから疑わなかった。もし測らずに着手していたら、数ヶ月を投じたうえで「思ったほど売上が戻らない」という結果になっていたはずです。

もうひとつ、不具合の深刻さと事業インパクトの大きさは別の軸だと学びました。決済だけ通ってしまう事故は、体験としては最悪です。感情的には最優先で潰したくなる。でも件数で見れば年に数件で、売上の構造にはほとんど影響していませんでした。痛みの強さで優先順位を決めると、判断を誤ります。

そして、作らない判断を下すためにも、判断材料をつくる作業自体からは逃げられませんでした。匿名化のパイプラインを書いて、集計して、レポートにまとめる。結果的にこれが、このプロジェクトで唯一「作ったもの」になりました。作らないと決めるために作るという、少し不思議な順序でしたが、これがなければ今も設計を続けていたと思います。

Outcomes & Results

  • ✓本番データを匿名化する変換パイプラインを構築(個人情報は破棄、識別子は一方向ハッシュのみ)
  • ✓9,047件の注文を年別・カテゴリ別・リピート構造に分解
  • ✓ボトルネックが「サイトの作り」ではなく「新規顧客の入口」だと特定
  • ✓全面リプレイスを見送り、資源を集客施策へ振り替える判断
  • ✓月次でレポートを更新できる手順を整備(所要5分)

Challenges Overcome

  • 在庫の引き当てと決済処理が分離しており、まれに決済だけが成立する事象が発生した
  • 既存プラットフォーム側の設定変更では根本的な解決が難しかった
  • 販売開始からの1時間に注文が集中する、特殊なアクセス特性
  • 本番データに個人情報が含まれるため、そのままでは分析に使えなかった

Key Learnings

  • 作る前に測る。手を動かしたい欲求と、事業にとって必要なことは一致しない
  • 不具合の深刻さと、事業インパクトの大きさは別の軸で考える必要がある
  • 作らない判断を下すためにも、判断材料をつくる作業からは逃げられない
#データ分析#EC#意思決定#SQLite#個人開発#作らない判断