TL;DR
- 筆者は一級建築士(40代)。プログラミング経験ゼロでリリースした割り勘アプリの奮闘記(第3弾)。
- UTMを泥臭く設定した結果、真の流入1位は「X(Twitter)」の170セッションだと判明。
- 新規313人のうち51人(16%)がイベント作成まで到達。デモを入れたのは正解だった。
- ReactとSupabase、VercelのSEOバグを踏み抜いた(詳細は付録)。
- 振り返ると、全部の根っこは同じだった。「AIにコードを書かせる前に、人間が考えるべきことをサボった」。
前回の記事はこちら。
プログラミング歴ゼロの個人開発者が、GA4・UTM・サーチコンソールと格闘した1ヶ月の記録
はじめに:前回の宿題の答え合わせ
FAMI-KANという割り勘計算のWebアプリ(Next.js + Supabase)をリリースして、気づけば2ヶ月が経った。
前回の記事の最後に、自分はこう書いた。
directが312セッション。名刺組がいるのかもしれないし、いないのかもしれない。永遠にわからない。
ほとんどのページがインデックスされない。お手上げ。
正直に言うと、マーケティングより先にやるべきことがある気がしている。でもそれが何なのかが見えていない。
あれから1ヶ月。3つとも答えが出た。
ただ、その答えは自分が期待していたものとは全然違った。
UTMを入れてわかった「本当のトラフィック」
まずはdirect地獄の話から。
前回の記事でも書いたとおり、リリース時にGA4のオプトアウト(自分自身のアクセスを除外する設定)を入れていなかった。
ブラウザにオプトアウトアドオンをインストールしたのが3月6日。さらに3月10日頃に /go/xxx というショートURLを自前で作り、すべてのリンクにUTMパラメータを自動付与するようにした。
以下は、その両方が機能し始めた3月10日〜31日の22日間のクリーンなデータだ。
| 参照元 | セッション | 平均滞在時間 |
|---|---|---|
| X(t.co + x/social 合算) | 170 | 約33秒 |
| (direct) | 64 | 1分35秒 |
| note / article | 51 | 39秒 |
| google / organic | 41 | 1分8秒 |
| line / community | 18 | 31秒 |
| qiita / article | 19 | 約1分 |
| 合計 | 403セッション / 新規313人 | — |
前回の記事でdirectが312セッションもあって「何が何だかわからない」と嘆いていたが、オプトアウトとUTMを入れた結果、directは64まで減った。
そしてようやく見えた本当の外部流入。
1位はX(Twitter)の170セッション。全体の42%を占めている。
個人アカウントと公式アカウントの両方で、「割り勘の幹事は辛い」というペインに向けた投稿を続けた結果が数字に表れた。
ただし、X経由の平均滞在時間は約33秒。
短く見えるかもしれないが、悲観はしていない。SNSからの流入は「今すぐ割り勘したい」需要ではなく、認知を広めるフェーズだ。33秒でも目に入れば、次に幹事になったとき思い出してもらえるかもしれない。
一方、Google検索からの流入は41セッション、平均1分8秒。
検索から来る人は「割り勘 アプリ 比較」のような明確な目的を持っているので、来たらちゃんと見てくれる。SEOが軌道に乗れば質の高いユーザーが増える手応えを感じている。
デモを入れたのは正解だった
今回の3月で一番「やってよかった」と思える判断がある。
アプリにデモ(サンプルデータ入りのイベント)を用意したことだ。
ページ別のアクセスデータを見てほしい。
| ページ | ユーザー数 | 平均滞在時間 |
|---|---|---|
/(トップページ) |
294 | 16秒 |
/demo(デモ入口) |
79 | 6秒 |
/event/de00...(デモイベント) |
81 | 35秒 |
トップページに来た294人のうち、79人(27%)がデモページまで到達している。
そしてデモイベントを開いた人は、平均35秒かけてサンプルの割り勘データを眺めてくれた。
割り勘アプリは飲み会やグループ旅行のときにしか使わない。今すぐの需要がないタイミングではピンとこないが、デモがあれば「なるほど、こうやって使うのか」と体験できる。
他の類似アプリを見ると、デモを用意していないものが多い。「使わせる」ではなく「触らせる」こと。デモを入れた判断は個人開発で数少ない正解だったと思う。
3月のコンバージョンファネルも載せておく(キーイベントの計測設定が3月途中からなので、厳密な数字ではない)。
新規ユーザー 313人
↓
CTA クリック 95人(30%)
↓
イベント作成 51人(16%)
↓
メンバー追加 18人
↓
支払い追加 14人
↓
精算画面閲覧 5人
新規313人のうち51人(16%)が実際にイベントを作成している。
無名の個人開発アプリとしては悪くない数字だと思いたい。ただ、精算画面まで到達した人は5人。ここから先の壁は高い。
3月に踏んだ2つの地雷
数字の裏で、アプリ内部では致命的なバグと格闘していた。
地雷①:モーダルが保存できないバグ
割り勘の個別設定を保存しようとすると、入力したデータが消える不具合が発生した。
原因はReactの「stale closure(古い状態のキャプチャ)」と、Supabase側のカラム追加忘れのダブルパンチ。フロントとデータベースの両方にそれぞれ別の原因がある複合バグで、切り分けに苦労した。
(技術的な詳細は付録Aへ)
地雷②:Googleにインデックスされない
前回「お手上げ」と書いたサーチコンソールの問題。原因の一つは特定できた。
Vercelに複数ドメインをProductionとして繋いだことで、Next.jsが出力するcanonical(正規URL)タグがリクエスト毎に変わる「ガチャ状態」になっていた。
コードは修正したが、この記事を書いている2026年4月時点でも、インデックスは一部しか進んでいない。
AIに原因を聞いても納得のいく答えが返ってこない。別の場所にまだ原因がある気がしている。
(技術的な詳細は付録Bへ)
全部の原因は「AIの前に人間が考えること」をサボったこと
3月の失敗を振り返って、ようやく前回の「マーケティングより先にやるべきことがある気がしている」の答えが見えた。
それは技術力の問題ではなかった。もっと上流の話だった。
自分は、人間が先に考えるべきことを、AIに丸投げしていた。
具体的に言うとこういうことだ。
-
事業設計をしていなかった。 リーンキャンバスのようなフレームワークで「誰の、何の課題を、なぜ自分が解決するのか」を整理してからコードを書き始めるべきだった。それをやらずに走り出したから、マーケティングの方針もSNSの発信軸もブレた。(リーンキャンバスについては付録Cで解説している)
-
ドメイン設計を人間が決めていなかった。 「メインドメインとルートドメインの関係はどうするか」「サブドメインは切るのか」——これはAIが勝手に決めてくれることではない。人間がインフラ構成として最初に定義すべきだった。それをやらなかった結果、Vercelの環境変数がガチャになり、canonicalタグが崩壊した。
-
画面遷移を人間が設計していなかった。 モーダルの開閉タイミング、どの画面でどのデータを保持するかといった状態管理を、設計図なしにAIへ「作って」と丸投げした。結果、stale closureのようなバグを踏んだ。
-
DBスキーマとフロントの対応表がなかった。 仕様書やスキーマ定義があれば、「フロントに項目を追加したらDBにもカラムを追加する」はチェック項目の一行で済んだはずだ。
AIの「コードを書く」能力は本当にすごい。プログラミング歴ゼロの自分でもアプリを2本リリースできたのは、紛れもなくAIのおかげだ。
でも、AIは「何を作るべきか」「なぜこの構成にするのか」までは考えてくれない。
人間がテキストで定義しない限り、AIの視界には入らない。
正直に書くと、仕様書に何を書けばいいのかは今もわかっていない。
ただ、少なくとも「人間が先に考える領域」と「AIに任せる領域」の線引きだけは、コードを書き始める前にやるべきだった。
おわりに:ローンチ後でも間に合うのか
今からでも仕様書を書くべきだと思っている。
ただ、正直に言うと億劫だ。動いているアプリに対して後から設計書を起こすのは、引っ越し後にダンボールを片づけるような気の重さがある。
サーチコンソールの問題もまだ全部は解決していない。
それでも、今月ようやく「自分が何を間違えていたのか」が言語化できた。
バイブコーディングでアプリは作れる。でも、その前に人間がやることがある。
同じフェーズで苦戦中の方、あるいは「ローンチ後に仕様書を整備し直した」経験のある方がいたら、コメントで教えてもらえると本当に助かります。
付録A:ReactとSupabaseの地雷 詳細
stale closure(古い状態のキャプチャ)とは
Reactの関数コンポーネントでは、イベントハンドラの中の関数が、定義された時点のstateの値をクロージャとして閉じ込めてしまうことがある。
たとえば、モーダルを開いた時点で payment というstateが {amount: 0} だったとする。
ユーザーが入力欄に 1000 と入力しても、保存ボタンの関数が古い {amount: 0} を掴んだままなので、保存すると入力値が消える。
// ❌ stale closure が発生するパターン
const handleSave = () => {
updatePayment(payment); // この payment は古い値
};
// ✅ 関数型更新で最新の値を使う
const handleSave = () => {
setPayment((prev) => ({
...prev,
amount: inputValue,
}));
};
(prev) => ({...prev}) という関数型更新を使えば、Reactが実行時点の最新のstateを prev として渡してくれる。
知っていれば一行の修正だが、知らないと「なぜ入力したのにデータが消えるのか」の原因にたどり着けない。
Supabaseのカラム追加忘れ
フロントエンドで新しいデータ項目(今回は負担割合の weights)を追加し、Supabaseに保存しようとすると 400 Bad Request が返る。
原因は単純で、SupabaseのTable Editorに対応するカラムが存在しなかった。フロント側のコードだけ直して、DB側の変更を忘れていた。
個人開発ではフロントもバックもインフラも一人で見ているので、こういう「片方だけ直して片方を忘れる」ミスは頻発する。
フロントの型定義とDBスキーマの対応表を作っておくのが本来の正解だ。だが、それこそが本文で書いた「仕様書を書いていなかった」問題そのものだった。
付録B:VercelとNext.jsのcanonical崩壊 詳細
canonicalタグとは
<link rel="canonical" href="https://example.com/page" /> という形でHTMLの <head> に埋め込むメタタグ。「このURLが、このページの正規のアドレスです」とGoogleに伝える役割を持つ。
同じ内容のページが複数のURLでアクセスできる場合、canonicalが統一されていないとGoogleは「重複コンテンツ」と判断し、どちらもインデックスから除外することがある。
なぜガチャ状態になったか
Next.jsの layout.tsx でメタデータのベースURLを以下のように設定していた。
// ❌ 環境変数に依存した動的生成
export const metadata: Metadata = {
metadataBase: new URL(
process.env.VERCEL_PROJECT_PRODUCTION_URL
? `https://${process.env.VERCEL_PROJECT_PRODUCTION_URL}`
: 'http://localhost:3000'
),
};
Vercelに複数のドメインをProductionとして向けていたこと(メインドメインに加え、別の用途で使っていたドメインも繋いでいた)が問題だった。
Vercelは両方とも「Production」と認識するため、VERCEL_PROJECT_PRODUCTION_URL がリクエストのたびにどちらかのドメインを返す。結果、canonicalタグがリクエスト毎にコロコロ変わり、Googleから「どっちが本物?」と判断されていた。
// ✅ ハードコードで解決
export const metadata: Metadata = {
metadataBase: new URL('https://famikan.tetras-ltd.com'),
};
解決策は本番ドメインの直書き。動的に解決しようとした設計が裏目に出た。
まだ解決していないこと
canonicalのブレは修正した。しかし、2026年4月時点でもサーチコンソール上の多くのページは「インデックス未登録」のままだ。
AIに原因を聞いても一般的なSEOのアドバイスが返ってくるだけで、自分のケースに効く回答は得られていない。AIは万能ではないと痛感した経験でもある。
付録C:事業設計フレームワーク一覧
本文で「リーンキャンバスのようなフレームワークを最初にやるべきだった」と書いた。
ここでは、個人開発で使える主なフレームワークを整理しておく。自分自身の備忘録でもある。
リーンキャンバスとは
アッシュ・マウリヤが提唱した、スタートアップ向けの事業計画を1枚にまとめるフレームワーク。以下の9つのブロックを埋めることで、事業の全体像を可視化する。
| ブロック | 問い | FAMI-KANに当てはめると |
|---|---|---|
| ① 課題 | ユーザーの上位3つの課題は? | 複雑な割り勘の計算が面倒、既存アプリでは大人と子供の比率設定ができない |
| ② 顧客セグメント | 誰のための製品か? | 家族旅行やグループ飲み会の幹事 |
| ③ 独自の価値提案 | 既存の解決策と何が違うか? | 傾斜配分(大人:子供 = 2:1)に対応したWebアプリ |
| ④ ソリューション | 課題をどう解決するか? | ブラウザだけで使える割り勘計算ツール |
| ⑤ チャネル | どうやって届けるか? | SEO、SNS、Qiita/note |
| ⑥ 収益の流れ | どう収益化するか? | アドセンス広告(他は検討中) |
| ⑦ コスト構造 | 運用コストは? | Vercel/Supabase無料枠、ドメイン代 |
| ⑧ 主要指標 | 成功を測る数字は? | MAU、イベント作成数、精算完了率 |
| ⑨ 圧倒的な優位性 | 簡単に真似できない強みは? | (正直、まだ見つかっていない) |
皮肉なことに、リーンキャンバスの存在自体は知っていた。でもやらなかった。
もしリリース前にこれを埋めてAIに渡していたら、⑤のチャネル設計を見たAIが「UTMを設定しましょう」「GA4のオプトアウトも必要です」と教えてくれたかもしれない。自分はUTMもオプトアウトも知らなかったが、AIは知っていた。自分が持っている知識(フレームワーク)を使わなかったせいで、AIが持っている知識(技術的な設定)を引き出せなかった。
他のフレームワーク
アプリ開発の上流工程で使えるフレームワークは他にもある。
| フレームワーク | 概要 | 向いているフェーズ |
|---|---|---|
| ビジネスモデルキャンバス | リーンキャンバスの原型。パートナー、リソース、収益構造など9ブロック。企業向け寄り | 企画 |
| バリュープロポジションキャンバス | 「顧客のジョブ(やりたいこと)・ペイン・ゲイン」と自分のプロダクトのフィットを可視化 | 企画 |
| ジョブ理論(JTBD) | 「顧客はプロダクトを"雇う"」という視点。どんな状況で、何のために使われるかを定義 | 企画・設計 |
| ユーザーストーリーマッピング | ユーザーの行動を時系列に並べ、MVP(最小限の製品)の範囲を決める | 設計 |
| PRD(プロダクト要求仕様書) | 機能要件、非機能要件、画面遷移、データ構造をまとめた設計ドキュメント | 設計 |
| デザインスプリント | Google Ventures発。5日間で課題定義→プロトタイプ→ユーザー検証を回す手法 | 検証 |
どれが正解かは自分にもわからない。ただ、「何も書かずにAIにコードを書かせ始める」よりは、どれか一つでもやっておいたほうがいい。
自分は今からでも、リーンキャンバスだけは書こうと思っている。