【LINE Harness完成編】1分診断+5日間ステップ配信を自前で組んだら、月3万が0円になった話

「LINE Harnessを組んだのはいいけど、診断とかステップ配信の中身どう作るの・・・?」

「Lステップ月3万、本気で自前に乗り換えるなら何が必要なんだろう」

そう思って検索してきたあなたへ、
結論からお伝えします。

2026年5月、
自前で1分5問診断+5日間ステップ配信を組み上げました。

配信通数は1友だちあたり4通だけ。
月200通の無料枠で50友だちまで完全無料です。

前回の構築編(=「LINE Harnessを丸1日で組んでみた」)の続編です。

今回は「中身を作る」ステージ。
5問×4択の診断 → 4タイプ自動振り分け → 5日間のステップ配信 までを、Claude Codeとペアで実装しました。

みけ

えっ、配信通数4通?
ステップ配信だと20通とか送らない?

アラン

みけ、ここが一番のポイントなんだ。
診断中の対話(=Q1〜Q5)と結果配信は、LINEの「応答メッセージ」を使うと完全無料になる。
翌日以降の Day 2〜5 配信だけがプッシュ送信で、これが4通分。

ロイ

「応答メッセージは無料」を活かして、5問対話を全部それで組んだのか。
これは月額固定費の前提を変える設計だな。

この記事は、実際に1日かけて診断ファネルを実装した作業ログです。

  • LINE Harnessを構築したけど中身が空っぽの人
  • Lステップ・エルメから自前に乗り換えたい中級者
  • 「自社・自店舗にも公式LINEで診断ファネルを導入したい」事業オーナー

このどれかに当てはまるなら、最後まで読む価値があります。


目次

何が完成したか?
(=結論を先に見せます)

手順の前に、「実際に何が動いてるか」を3つのスクショで先に見せます。これが見えないと「どうせ動かないんでしょ?」と疑いながら読むことになるので。

完成形①:LINEのトーク画面で対話型診断

友だち追加した瞬間に、こんなメッセージが届きます。

LINEトーク画面・診断スタート(Q1配信)

「登録ありがとうございます🌱 5つの質問で…」のあとに、4つのボタンが縦並びで表示されます。

ユーザーがボタンを押すと、0.5秒の間を置いて次の質問が届きます。

これがいわゆる「人間らしい間」=ボット感を消す演出です。
(LINE公式設定だとボット返信の“間”を空けることはできません)

LINEトーク画面・Q5回答後の診断結果メッセージ

5問全部答え終わると、2秒の「ためる間」のあと、診断結果が届きます。

完成形②:管理画面で5シナリオの自動振り分け

診断結果に応じて、自動でタグが付与されてシナリオが起動します。

管理画面・シナリオ一覧(5本)

5本のシナリオが並んでいます。

  • A型(バランス型):時間もお金もある人 → 事業×投資ハイブリッド
  • B型(時間あり・お金なし型):時間を価値に変換するストック資産
  • C型(時間なし・お金あり型):お金を働かせる投資メイン
  • D型(両方なし型):副業/転職+生活防衛資金
  • D-緊急(両方なし・6ヶ月生活不可):固定費圧縮+防衛資金最優先

診断結果のタイプによって、その人専用の5日間ステップ配信が自動で動き出します。

\今ならAIプロンプト5選配布中!/

完成形③:配信通数=4通/友だち
(=月200通枠で50友だち無料)

これが今回の設計の真の発見です。

スクロールできます
項目送信タイプLINE通数カウント
あいさつ + Q1配信応答メッセージ(reply)0通(無料)
Q2〜Q5の応答配信(4回)応答メッセージ(reply)0通(無料)
診断結果の即時配信応答メッセージ(reply)0通(無料)
Day 2〜Day 5(=翌日以降の追従配信)プッシュメッセージ(push)4通
合計4通/友だち

1友だちあたり4通だけ。
LINE公式アカウントのコミュニケーションプラン(=月200通までの無料枠)なら、月50友だちまで完全0円で運用可能です。

ロイ

50友だちまで月0円・・・
これはLステップ月3万円のロジックを根本から書き換える数字だな。

プッシュメッセージ(push)をなくせば、いつでも費用を0円にできます。


なぜLIFFフォームをやめたか?(=設計の本質)

正直に告白すると、当初はLIFFフォーム(=画面遷移型)で作るつもりでした

公式LINEに登録 → リッチメニューから「診断はこちら」 → LIFFアプリ起動 → 5問入力 → 送信 → 結果表示。

でも、設計を進める中で3つの発見があり、設計を大転換しました。

発見1:応答メッセージは配信通数カウント対象外(=完全無料)

LINE Messaging APIには「replyMessage」というメッセージ送信方法があります。

これはユーザーがメッセージを送ってきた直後に、その応答として返信する仕組み。

Webhookで受け取ったイベントに含まれる「replyToken」を使って、1分以内に1回だけ応答できます。

replyMessage は LINE公式アカウントの配信通数にカウントされません(=無料)。

ユーザーが何かを送ってきた → こちらが1分以内に返事をする、という構造なら、何度繰り返しても課金ゼロです。

発見2:LIFFアプリ起動の手間が消える

LIFFフォームの欠点は「LIFFアプリの読み込みに数秒かかる」こと。

ユーザーがリッチメニューを押す → ローディング画面 → LIFF起動 → フォーム入力。この最初の数秒で、診断モチベーションが下がる人が必ず出ます。

対話型なら、友だち追加した瞬間にQ1が届く
1秒のラグもなく、ユーザーは「答えればいいだけ」の状態に入れます。

発見3:「会話してる感」=親近感が出る

LIFFフォームは「アンケート」感。
対話型は「やり取りしてる」感。

特に重要なのが「人間らしい“間”」です。
ユーザーが回答を押した瞬間に次の質問が出るとボット感が出ます。

0.5秒の遅延を入れると、「人が読んで返信を打ってる」感じが出る。

診断結果配信は2秒の「ためる間」を入れることで、「結果が出たぞ」という期待感が高まります。

\今ならAIプロンプト5選配布中!/

みけ

0.5秒と2秒・・・
そんな細かい数字でユーザー体験変わるの?

アラン

変わるんだ。
0秒(即時)→ ボット感、AIが裏で動いてる感
0.5〜3秒 → 「人が打ってる」感
10秒以上 → 「待たされてる」感

このスペクトラムをシーンごとに使い分けるのがUX設計の核心。


Phase A:タグ設計(=9タグ・15分)

診断結果を友だちに紐づけるためのタグを作ります。
これがLINE運用の最小単位です。

なぜ4タイプじゃなく9タグなのか?

診断結果は4タイプ(A型・B型・C型・D型)ですが、タグは9個必要です。

スクロールできます
カテゴリタグ役割
主タグ(4個)A型 / B型 / C型 / D型シナリオ起動の引き金
緊急タグ(1個)D-緊急D型かつ6ヶ月生活不可の人を別シナリオに振り分け
嗜好タグ(4個)Q4-投資メイン / Q4-事業メイン / Q4-両方 / Q4-未定セグメント配信用(=後日「投資メインの人だけにメッセージ」が可能)

主タグだけだと「シナリオ起動」しかできません。

嗜好タグを別軸で持つことで、
後から「投資寄り」「事業寄り」のセグメント配信ができるようになります。

新判定ロジック:Q1×Q2×Q3 で4タイプ判定

当初は「時間(Q1) × お金(Q2)」の2軸で判定していました。

でも、運用設計を進めるうちに、ある違和感に気づきました。

200万円の貯金があっても、月の生活費が40万円なら5ヶ月で尽きる
これは「お金あり」じゃなくて「お金なし」状態のはず。

そこで、Q3(=6ヶ月収入なくても生活できるか?)を判定軸に追加しました。

新ロジック:お金あり = Q2≥B AND Q3≥B
絶対資金が50万以上あっても、Q3=A(=6ヶ月もたない)なら「お金なし」扱い。

これは事業の教科書「貯金÷月の生活費=残り月数」哲学そのものです。

絶対額じゃなく「残り月数」で判定する。これが診断の精度を一気に上げます。

タグ作成はAPIで(=管理画面UIなしでOK)

LINE Harnessにはタグ作成のAPIがあります。Claude Codeにこう頼むだけ:

curl -X POST "$API/api/tags" \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"A型(バランス)","color":"#10B981"}'

これを9回繰り返すだけ。

所要時間 15分
管理画面UIを使わずに、APIだけで完結します(=これがLINE Harnessの強み)。


Phase B:シナリオ設計(=5本・各4日間配信)

タグができたら、シナリオを設計します。
シナリオとは「あるタグが付いた友だちに、決めた間隔でメッセージを連続配信する仕組み」です。

5シナリオの全体像

スクロールできます
シナリオ起動タグDay 2(=翌日)Day 5(=最後)
A型A型タグ「事業or投資、まず1つに集中」事業の教科書【完全版】案内
B型B型タグ「初期投資ゼロの事業を1つ選ぶ」STEP1記事案内
C型C型タグ「NISAでインデックス投資から」投資の教科書【完全版】案内
D型D型タグ「6ヶ月分の防衛資金ゴールを決める」事業の教科書 STEP1案内
D-緊急(NEW)D-緊急タグ「固定費を月3万下げる」60分セッション案内

D-緊急の特殊扱い(=タグ排他)

D-緊急の人(=Q3=A の D型)は、D型タグを付けず D-緊急タグだけを付与します。

両方のタグを付けるとシナリオ2本が同時起動し、Day 2が2通同時に届くという事故が起きます。
排他で運用することで、配信の重複を防げます。

配信タイミング設計(=Day 2 を翌日に置く理由)

  • Day 2:1日後(=1440分)— 「次の一歩」を提示
  • Day 3:2日後(=2880分)— 60分体験セッション案内
  • Day 4:4日後(=5760分)— おすすめ書籍紹介
  • Day 5:7日後(=10080分)— 完全版誘導

Day 1がないのに気づきましたか?
Day 1相当の「診断結果メッセージ」は webhook 内で即時replyMessageで送るので、シナリオ側からは省略しています(=2重配信回避)。


\今ならAIプロンプト5選配布中!/

Phase C:webhook + replyMessage で「無料の対話」を実装する

ここがこの記事の本丸です。
5問対話を完全無料で動かす仕組みを、コードレベルで解説します。

LINE replyMessage の隠れた仕様

LINE Messaging APIの公式ドキュメントには明記されてないですが、実装で気づいた事実があります。

replyTokenの有効期限は60秒間。
その間なら0秒(即時)でも、1秒後でも、59秒後でも自由に遅延を入れられます
これがUX設計の自由度を一気に広げます。

つまり、Cloudflare Workersのctx.waitUntil + setTimeoutを組み合わせれば、「人間らしい間」を任意に設計できる

// 1秒の遅延を入れて返信(=人間らしい間)
c.executionCtx.waitUntil(
  new Promise((resolve) => setTimeout(resolve, 1000))
    .then(() => lineClient.replyMessage(replyToken, [message]))
);

follow event:友だち追加の瞬間にQ1配信

LINEには「friend_add」(=友だち追加)というイベントがあり、これがwebhookに飛んできます。

friend_addイベントのreplyTokenを使えば、「あいさつメッセージ + Q1」を無料で送れます(=LINE側の「あいさつメッセージ」機能を使わなくてOK)。

if (event.type === 'follow') {
  // 友だち追加 → 診断モード初期化
  await startDiagnosis(db, friend.id, friend.metadata);
  // Q1 + Quick Reply を replyMessage で送信(=無料)
  await lineClient.replyMessage(event.replyToken, [buildOpeningMessage()]);
}

message event:対話の状態を friend.metadata に保存

ユーザーが「A」「B」「C」「D」のいずれかを押すと、これは「テキストメッセージ」としてwebhookに飛んできます。

その時、LINE Harnessは「このユーザーは今Q3まで答えた」という状態を、friend.metadata(=JSON)に保存しています。

// metadataに保存される状態
{
  "diagnosis_state": {
    "currentQuestion": 3,
    "answers": { "q1": "B", "q2": "C" },
    "startedAt": "2026-05-01T14:30:00.000+09:00"
  }
}

次のメッセージを受信したら、現在のステップを見て次の質問 or 結果配信を返します。

// 診断対話中? → handleAnswer で次の質問 or 結果を1秒遅延で返信
const diagState = getDiagnosisState(friend.metadata);
if (diagState) {
  const result = await handleAnswer(db, friend.id, friend.metadata, diagState, incomingText);
  // 0.5秒(質問遷移) or 2秒(結果配信)で reply
  await delayedReply(lineClient, event.replyToken, result.message, result.suggestedDelayMs);
}
アラン

この「状態を friend.metadata に持たせる」のがミソなんだ。
DBにテーブル追加せずに、JSON1個で対話の進行管理ができる。
LINE Harnessが「friend.metadata」を提供してくれてるおかげで、ものすごくシンプルに組める。


Phase D:判定ロジック実装(=Q1×Q2×Q3 + D-緊急)

5問の答えから4タイプを振り分けるロジックを実装します。

判定マトリクス(=全パターン)

スクロールできます
Q3=A(無理)Q3=B(ギリギリ)Q3=C(できる)Q3=D(余裕)
Q1=A, Q2=AD型(緊急)D型D型D型
Q1=A, Q2=B+D型(緊急)C型C型C型
Q1=B+, Q2=AB型B型B型B型
Q1=B+, Q2=B+B型A型A型A型

太字部分が、Q3を判定軸に追加したことで挙動が変わったケースです。

コードでは1行のシンプルさ

function judgeType(q1: string, q2: string, q3: string): TypeKey {
  const timeRich = q1 !== 'A';
  const moneyRich = q2 !== 'A' && q3 !== 'A'; // Q3=A なら絶対資金あっても「お金なし」
  if (timeRich && moneyRich) return 'A';
  if (timeRich && !moneyRich) return 'B';
  if (!timeRich && moneyRich) return 'C';
  return 'D';
}

哲学(=「貯金÷月生活費=残り月数」)を、たった1行のq3 !== 'A'で表現しています。

ロイ

哲学が1行のコードに翻訳されている。
これがエンジニアリングの面白いところだ。

D-緊急タグの排他ロジック

// D-緊急なら D型タグつけず D-緊急タグだけ(=シナリオ重複起動を防ぐ)
if (isEmergency) {
  await addTagToFriend(db, friendId, TAG_IDS.D_EMERGENCY);
} else {
  await addTagToFriend(db, friendId, TAG_IDS[type]);
}

これでD-緊急の人は、専用シナリオ(=固定費圧縮 + 防衛資金最優先)が起動します。


ハマりポイント6選(=実際に詰まった全リスト)

診断ファネル実装で、僕は6回詰まりました。同じ罠を踏まないよう、全部公開します。

罠1:DBマイグレーション9個漏れ

症状:シナリオステップ追加で500エラー「duplicate column name」じゃなく謎のエラー。

原因:LINE Harnessの構築時、schema.sqlだけを実行して、その後のmigrations/*.sqlを流していなかった。

解決:

# 構築記事の Phase B Step 8 に追記すべきコマンド
for f in packages/db/migrations/*.sql; do
  npx wrangler d1 execute line-crm --remote --file=$f
done

これで全マイグレーションが適用される(=既に流れてるカラム追加は「duplicate」で失敗するが、未適用のものは反映される)。

罠2:Quick Replyは横スクロール仕様

症状:LINE Quick Replyのボタンを4個並べても、横スクロールになって縦に並ばない。

原因:Quick Replyは標準で「横並びスクロール」固定。縦並びは別仕様。

解決:Flex Message(=bubble + button)で組む。

{
  type: 'flex',
  contents: {
    type: 'bubble',
    body: {
      type: 'box', layout: 'vertical',
      contents: [
        { type: 'button', action: { type: 'message', label: 'A', text: 'A' } },
        { type: 'button', action: { type: 'message', label: 'B', text: 'B' } },
        // 縦に4個並ぶ
      ]
    }
  }
}

罠3:Pythonの urllib が Cloudflare WAF にブロック

症状:curlでは200 OKが返るのに、Pythonのurllib.requestで叩くと403 Forbidden。

原因:CloudflareのWAFがurllibのデフォルトUser-Agent(=「Python-urllib/3.x」)をブロックしてる。

解決:User-Agentを偽装。

headers={'User-Agent': 'curl/8.0'}

罠4:replyTokenは1リクエストで1回しか使えない

症状:「結果メッセージを2通連続で送りたい」と思って2回呼ぶと、2回目でInvalid replyTokenエラー。

解決:replyMessageは1リクエストで最大5メッセージまとめて送れる。配列で渡す:

await lineClient.replyMessage(replyToken, [message1, message2]); // OK

罠5:メタデータJSONのマージで既存値を壊す

症状:診断結果をfriend.metadataに保存したら、既存のpreferred_hourが消えた。

原因:JSON全部上書きしてた。

解決:既存JSONをparse → スプレッド演算子でマージ → stringify。

const existing = friend.metadata ? JSON.parse(friend.metadata) : {};
const merged = { ...existing, diagnosis: { ... } };
await db.prepare('UPDATE friends SET metadata = ? WHERE id = ?')
  .bind(JSON.stringify(merged), friend.id).run();

罠6:friend_addシナリオと診断モード初期化の競合

症状:友だち追加で診断スタートのつもりが、何も送られてこない。

原因:LINE Harness既存の「friend_addトリガーのシナリオ起動」ロジックがreplyTokenを先に消費していた(=競合)。

解決:friend_addトリガーのシナリオを作らない(=俺らはtag_addedトリガーで運用)。replyTokenが未消費のまま、診断初期化に使える。

ロイ

6つ全部踏んだ?

アラン

うん、全部踏んだ。
でもClaude Codeに「これエラー出た」って貼るだけで、毎回30秒で原因特定して直してくれる。
「ハマる→直す→学ぶ」のサイクルが圧倒的に早い。これがAI協業の本質だね。


まとめ:配信4通/友だち、月50友だちまで完全無料

僕がやったことを、もう一度整理します。

  • 9タグ作成(=主タグ4 + Q4×4 + D-緊急)
  • 5シナリオ × 4ステップ = 20通の文言投入
  • webhook + replyMessage で5問対話を完全無料化
  • 判定ロジックにQ3を追加(=「6ヶ月生活不可なら絶対資金あってもお金なし」)
  • D-緊急シナリオを別途用意(=固定費圧縮+防衛資金最優先)
  • 配信通数 = 4通/友だち(=月200通枠で50友だち完全無料)

2026年5月、LINE運用の「月3万円が当たり前」が「50友だちまで月0円」に書き換わった。
しかもClaude Codeさえあれば、コードを1行も書かずに自前で実装可能です。

次のステップ:友だち反応データを集める

今は「動く」状態。

次は「友だちの反応データ」を集めるフェーズです。

  • ブロック率(=配信内容に問題があれば上昇)
  • 各Day の開封率・既読率
  • セッション申込率
  • 診断完了率(=Q1〜Q5を全部答えた人の割合)

このデータを見て、装飾(=Flex化、ヒーロー画像、リッチメニュー)の優先順位を決めます。
売ってから作る」=リーンスタートアップの精神です。

アラン

装飾はいくらでも凝れる。
でも凝る前にデータを集めて、本当に必要な装飾だけに集中する。
これが「こだわりすぎず、データ駆動で進化させる」運用の核心です。


関連記事


無料の現在地診断(LINE登録)

あなたに向いてる事業/投資は?
5問・1分の現在地診断で、あなたのタイプが分かります。
診断後はアラン(本名:新夢シャド)から5日間、個別フォローが届きます。

自社・自店舗にも診断ファネルを導入したい方へ(無料資料請求)

「自社のLINE公式アカウントにも、この診断ファネルを実装したい」という事業オーナーの方へ。

まずは無料資料請求で、あなたの会社・店舗向けの実装プランを確認してみましょう。

このテーマをもっと深く学ぶ本

おすすめ書籍

シリコンバレー最重要思想家ナヴァル・ラヴィカント
→ 「自分のコードを資産化する」の章が、Claude Code時代に効きます

YouTubeでも解説中

同じテーマを動画で見たい人は、YouTubeチャンネルもどうぞ。
@nitiban-worldmoney


この記事は「事業の教科書」事業ツール編

事業を始めるための6つのSTEPを
体系的に学びたい方はこちら。

アラン
元ファミマSV✖️事業コンサル
投資と事業の「中級者」を増やすために働いています。
✅ファミマ本部SV10年、300店舗以上・年商20億の統括責任者
✅22歳から投資スタート、インデックス投資で+346%
✅バングラデシュに不動産保有(新興国を肌で知っている)
✅日本とバングラデシュ、両方の視点を持つ(3歳で初来日)
バングラデシュ出身、日本育ちです。
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次