ブライダル

ブライダルのLINE公式アカウント:来館前・来館後・成約後でリッチメニューを切り替える設計

結婚式場やフォトスタジオのLINE公式アカウントで、来館前・来館後・成約後・挙式後とリッチメニューを替えていく設計を、作る側の目線で整理します。2人で1組の扱い、ブロック中の人、タブとの両立、APIの使い分けまで書きました。

この記事の結論:結婚式場のLINE公式アカウントは、来館の予約から挙式の後まで、同じお二人と長く付き合う入口です。リッチメニューを関係の段階に合わせて替えるなら、まず「状態」を5つ前後に絞り、メニューは状態の数だけ作ります。切り替えは、顧客の記録の状態から「この人に出すべきメニュー」を計算して合わせる処理を1つ用意し、状態が変わったとき・友だち追加やブロック解除のとき・毎晩の見直しの3回、同じ処理を呼びます。お二人で1組であること、ブロック中の人には結びつけられないこと、タブで切り替えたメニューを元に戻してしまわないこと。この3つを最初から設計に入れておくと、運用で崩れません。

ブライダルの業態で、トーク画面の下のメニューを「来館前」「来館後」「成約後」と替えていく仕組みを、実装する立場から書いていきます。前提にしたのはLINEの公式の仕様(確認日 2026-10-02)で、特定の式場の事例は出てきません(扱うのは仕組みの側の話だけ)。

株式会社bundlyzeでは、顧客管理の側とLINE公式アカウントを結ぶ連携を、自社で開発してきました。この記事の判断は、そうした連携を作るときに考えてきたことが元になっています。

式場とお二人の関係は、来館から挙式後まで続く

フィットネスや飲食のように「何度も来てもらう」業態と違い、式場とお二人の関係は一方向に進みます。フェアに来る前は会場を比べている段階、来館した後は見積もりを持ち帰って検討する段階、成約した後は打ち合わせを重ねて当日に向かう段階。段階ごとに、LINEを開いたときに知りたいことがはっきり変わります。

そのため、全員に同じメニューを出し続けると、成約したお二人にはフェアの案内ばかりが並び、検討中のお二人には打ち合わせの入口が並ぶ、というずれが起きます。業種を問わないメニューの置き方は、会社のコラムLINEリッチメニューの設計にまとめているので、ここでは式場ならではの切り替えの作り方に絞ります。

状態を絞り、きっかけと記録する人を決める

最初に、お二人の状態と、状態が変わるきっかけ、それを誰がシステムに記録するかを表にします。

状態 変わるきっかけ 記録するのは メニューの主役
来館前 友だち追加 自動(何もしない) フェアの日程、来館の予約、アクセス
来館の予約あり 予約の確定 予約の仕組み 当日の集合場所、駐車場、予約の変更
来館後・検討中 来館の受付 受付のスタッフ 見積もりの相談、再来館の予約、質問
成約後 契約の記録 担当のスタッフ 打ち合わせの予約、準備の一覧、担当への連絡
挙式後 挙式日を過ぎた 自動(毎晩の処理) 写真や記念日の案内

決めておきたいのは次の点です。

  • 「来館前」はユーザー単位のメニューを使わない。 友だち追加した直後の人には、デフォルトのメニューを出せば足ります。ユーザー単位で結びつけるのは、状態が進んだ人だけにします
  • 見送りになったお二人は、デフォルトに戻す。 結びつけを解除すると、デフォルトのメニューが代わりに表示されます
  • メニューは人ごとではなく、状態ごとに作る。 1つのチャネルで作れるリッチメニューは最大1000件です。お二人ごとに名前入りの画像を作るような設計は、上限にも運用にも合いません

2人で1組:ユーザーIDを組にひも付ける

式場の顧客は、多くの場合「お二人」で1件です。LINEは1人ずつ友だち追加するので、顧客の記録の側で、1つの組に複数のLINEのユーザーIDを持てるようにしておきます。

組と、組に属するLINEのユーザーsql
create table couples (
  id           text primary key,
  stage        text not null,   -- before_visit / visit_booked / visited / contracted / after_wedding / closed
  wedding_date date
);

create table couple_line_users (
  couple_id    text not null references couples(id),
  line_user_id text not null unique,  -- Webhook の source.userId
  added_at     timestamp not null,
  primary key (couple_id, line_user_id)
);

2人目をどう組に入れるかも、先に決めておきます。来館の受付で見せるQRコードから LIFF の画面を開いてもらい、IDトークンをサーバーで検証してから組に加える、という形にすると、他人が勝手に組へ入る心配がありません。画面の側が渡すユーザーIDをそのまま使わないのは、LINEの資料が示しているとおりです。

切り替えは「計算して合わせる」処理を1つだけ持つ

状態が変わるたびに個別にメニューを付け替えるコードを書くと、どこかで付け替え漏れが起きます。そこで、「組の状態から、出すべきメニューを計算し、今のメニューと違えば結びつけ直す」処理を1つだけ作り、いろいろな場面から同じものを呼びます。

組の状態に合わせて、メニューを結びつけ直すts
const MENU_BY_STAGE: Record<string, string[] | null> = {
  before_visit:  null,                            // デフォルトのメニューに任せる
  visit_booked:  ['richmenu-visit-booked'],
  visited:       ['richmenu-visited'],
  contracted:    ['richmenu-prep', 'richmenu-contact'], // タブで切り替える2枚
  after_wedding: ['richmenu-after'],
  closed:        null,
};

async function syncRichMenu(coupleId: string) {
  const couple = await db.getCouple(coupleId);
  const wanted = MENU_BY_STAGE[couple.stage];
  for (const userId of await db.lineUsersOf(coupleId)) {
    const current = await line.getUserRichMenuId(userId); // GET /v2/bot/user/{userId}/richmenu
    if (wanted === null) {
      if (current) await line.unlinkRichMenu(userId);     // DELETE /v2/bot/user/{userId}/richmenu
      continue;
    }
    // 同じ状態のタブのどれかが出ていれば、合っているとみなす
    if (current && wanted.map(menuIdOf).includes(current)) continue;
    await line.linkRichMenu(userId, menuIdOf(wanted[0])); // POST /v2/bot/user/{userId}/richmenu/{richMenuId}
  }
}

この処理を呼ぶのは、次の3つの場面です。

  1. 状態が変わったとき:予約の確定、来館の受付、契約の記録の直後
  2. フォローイベントが届いたとき:友だち追加と、ブロック解除の両方
  3. 毎晩:挙式日を過ぎた組を「挙式後」に進めたうえで、全組を見直す

ユーザー単位で結びつけたメニューは、その場で表示に反映されます。一方、デフォルト側の変更は、トーク画面に入り直すまで反映されないので、状態ごとのメニューはユーザー単位で結びつけるほうが、切り替わりを確かめやすくなります。

ブロック中の人と、タブの扱いでつまずかない

運用に入ってから崩れやすいのが、次の2つです。

ブロックしている人には、結びつけが効かない。 LINEのリファレンスには、ブロック中や友だちでない人に対して解除を呼ぶと、ステータス200が返っても実際には解除されないと書かれています。複数人に結びつける一括の呼び出しでも、202が返ったうえで、その人たちは対象から外れます。成約の記録を付けたときにお二人の片方がブロックしていた、ということは起こりえます。だからこそ、フォローイベント(follow.isUnblocked が付いて届くブロック解除を含む)で、同じ同期の処理を呼び直します。

タブで切り替えたメニューを、同期で戻してしまう。 成約後のメニューを「準備」と「連絡」の2枚に分け、リッチメニューエイリアスと切り替えのアクションでタブにする場合、タブを押すたびに、その人に結びついたメニューが別のものに替わります。同期の処理が「準備のメニューでなければ結びつけ直す」と書かれていると、連絡のタブを開いた直後に、毎晩の処理が準備のタブへ戻してしまいます。上のコードのように、同じ状態に属するメニューのどれかが出ていれば「合っている」とみなすようにしておきます。

まとめて替える場面では、APIを使い分ける

1組ずつ替える場面と、まとめて替える場面では、使うエンドポイントと注意点が違います。

場面 使うもの 注意すること
1組の状態が変わった POST /v2/bot/user/{userId}/richmenu/{richMenuId} すぐに反映される。お二人分、2回呼ぶ
毎晩、挙式日を過ぎた組をまとめて進める POST /v2/bot/richmenu/bulk/link 1回で最大500人。処理は非同期で、202が返っても結びついていない場合があるので、後で1人分ずつ取得して確かめる
季節に合わせて、成約後のメニューの画像を差し替える POST /v2/bot/richmenu/batch(type: link で古いメニューから新しいメニューへ) 1時間に3回まで。resumeRequestKey を付けておくと、途中で失敗しても残りだけをやり直せる(有効期間は14日)

季節の差し替えは、新しいメニューを作り、画像を付けて、テスト用のアカウントに結びつけて見た目を確かめてから、一括操作で置き換えます。置き換えた後、古いメニューを消すのは、一括操作の進み具合を取得して完了を見てからにします。

メニューの画像には、お二人の情報を入れない

状態ごとのメニューは、同じ状態の全員に同じ画像が出ます。挙式日までの日数や、お二人の名前を画像に入れたくなりますが、それは状態ごとのメニューでは作れませんし、作るべきでもありません。

個別の情報は、メニューのボタンから開く LIFF の画面に出します。画面を開いたときにIDトークンをサーバーで検証し、その人が属する組の情報だけを返します。打ち合わせの日時や見積もりのように、お二人以外に見えてはいけない情報は、この形でしか出さない設計にします。

出典(LINEの公式資料)

記載はすべて 2026-10-02 時点で確かめたものです。

よくある質問

お二人のうち片方しか友だち追加していない場合、メニューはどうなりますか?

友だち追加していない人には、ユーザー単位のメニューを結びつけられません。組の記録に1人分のLINEのユーザーIDだけを持たせておき、もう1人が後から友だち追加したときのフォローイベントで組に加え、その時点の状態のメニューを結びつけます。

来館したかどうかは、どうやってシステムに伝えればいいですか?

受付のスタッフが顧客の記録で「来館済み」にする操作を、切り替えのきっかけにするのが確実です。来館の予約が入っていたことと、実際に来たことは別なので、予約の日時が過ぎたことだけで自動に切り替えると、来なかった人にも来館後のメニューが出てしまいます。

メニューの画像を季節ごとに替えたいときは、全員を結びつけ直す必要がありますか?

ありません。Messaging API の一括操作を使うと、古いメニューが結びついている全員を、新しいメニューへまとめて置き換えられます。ただし1時間に3回までしか呼べないので、新しいメニューを作って中身を確かめてから、1回で置き換えます。