マーケティング部門の責任者から「購入履歴や会員ランクに合わせて、リッチメニューを自動で切り替えたい。さらに、メニュー内のタブを押したら表示内容も切り替えたい」と依頼され、何から手をつければよいか迷っていませんか?
LINE Official Account Manager(管理画面)でもリッチメニューは作れます。ただし、すべての友だちに同じメニューを出す設定が中心です。会員ランクや購入履歴に合わせて表示を変えるには、Messaging APIを使ってリッチメニューを作成し、ユーザー単位でリンクする設計が必要になります。そもそもMessaging APIの初期設定がまだ不安な場合は、先にMessaging API設定の基本手順を確認しておくと、この後の実装がスムーズです。
リッチメニューの実装で大切なのは、画像・座標・API順序・表示優先順位を分けて理解することです。画像サイズやboundsの指定を先に固め、作成、画像アップロード、ユーザーリンクの順番でAPIを実行すれば、ユーザー別の出し分けシステムを安全に構築できます。
この記事の書き手:設楽 徹(したら とおる)
LINE Messaging API 実装スペシャリスト / シニア・ソリューションアーキテクト
大手ECプラットフォームや顧客管理システム(CRM)において、会員データベースと連動した「動的リッチメニュー制御システム」の構築・統括を10年以上手掛ける。
「リファレンスの海で独りコードを書き、仕様の罠や深夜の手戻りと戦うインハウスエンジニアの胃の痛みに寄り添い、今夜確実に動く正攻法をお届けします」
1ピクセルのズレを防ぐ!実装前にエンジニアが固めるべき「画像スペック」と「座標」のルール
開発フェーズにおいて、エンジニアを苦しめやすいのが画像アップロード時の 400 Bad Request です。LINEのリッチメニューでは、画像サイズ、ファイル形式、ファイル容量、タップ領域の座標を、JSON定義と矛盾なく合わせる必要があります。
「デザイナーがスマホで見やすいように綺麗に作ってくれた画像」が中途半端なサイズで、実装時に弾かれるケースは珍しくありません。手戻りを防ぐため、エンジニア側であらかじめ以下のガードレールを共有してください。
リッチメニュー画像を準備するときは、以下の項目を先に確認しておくと、画像アップロード時のエラーや座標ズレを減らせます。
| 項目 | Messaging APIでの確認ポイント | 実務上の推奨 | 注意点 |
|---|---|---|---|
| 大きいリッチメニュー (標準的な2段表示) |
2500 × 1686 px が公式サンプルでよく使われる |
2500 × 1686 px |
デザインテンプレートとboundsを同じ基準で作る |
| 小さいリッチメニュー (コンパクト表示) |
2500 × 843 px が公式サンプルでよく使われる |
2500 × 843 px |
高さが半分になるため、文字量を詰め込みすぎない |
| 画像形式・容量 | png / jpeg、Messaging APIでは画像容量に上限あり |
PNGまたはJPEGで軽量化 | 容量だけでなく、実際の画像形式も確認する |
| タップ領域 | areas は複数指定でき、Messaging APIでは最大20領域 |
まずは3〜6領域に抑える | 細かく分けすぎると誤タップが増えやすい |
画像サイズを確定させたら、次に潜む罠がボタンのタップ領域を感知させる「バウンディングボックス(bounds)」の座標計算です。リッチメニューのJSON構造を定義する際、各ボタン領域は x 座標、y 座標、width(幅)、height(高さ)の4つのパラメータで指定します。
たとえば 2500 × 1686 px の画像を4分割するなら、左上の領域は "x": 0, "y": 0, "width": 1250, "height": 843 のように定義できます。ここで x + width が全体幅を超えたり、y + height が全体高さを超えたりすると、作成時や検証時にエラーになる可能性があります。

リッチメニュー「作成・画像反映・ユーザーリンク」の3ステップAPI実装手順
Messaging APIを利用してプログラムから特定のメニューを有効化するには、独立した3つのリクエストを正しい順番で実行します。ここでは、リッチメニューを作成し、画像をアップロードし、特定ユーザーへリンクする流れを整理します。
TypeScriptやNode.jsでBot全体を実装する場合は、先にLINE BotのTypeScript実装を確認しておくと、Webhook処理や環境変数の扱いも理解しやすくなります。
STEP 1: リッチメニューのオブジェクト構造定義(Create)
まず、メニューの物理サイズ、チャットバーのテキスト、バウンディングボックス(タップ領域)の座標、タップ時の挙動(アクション)を結びつけたJSONファイルを、LINEのサーバーへPOSTします。
- Requestエンドポイント:
POST https://api.line.me/v2/bot/richmenu - Headers:
Authorization: Bearer {YOUR_CHANNEL_ACCESS_TOKEN}Content-Type: application/json
{
"size": {
"width": 2500,
"height": 1686
},
"selected": true,
"name": "Premium_Member_Menu",
"chatBarText": "限定メニューを見る",
"areas": [
{
"bounds": {
"x": 0,
"y": 0,
"width": 1250,
"height": 843
},
"action": {
"type": "uri",
"label": "限定クーポン",
"uri": "https://example.com/premium-coupon"
}
},
{
"bounds": {
"x": 1250,
"y": 0,
"width": 1250,
"height": 843
},
"action": {
"type": "postback",
"label": "通常メニューへ切り替え",
"data": "action=switch_to_regular"
}
}
]
}
このリクエストに成功すると、LINE側から固有のオブジェクト識別キーである richMenuId (例: richmenu-1234567890abcdef...)が返却されます。この richMenuId が、以降の画像アップロードやユーザーリンクで使う主キーになります。
STEP 2: デザイン画像のアップロード(Upload)
STEP 1で生成された richMenuId をURLパスのパラメータに埋め込み、用意したデザイン画像のバイナリデータをPOSTで送ります。ここで重要なのは、画像アップロード系のドメインが api-data.line.me である点です。
- Requestエンドポイント:
POST https://api-data.line.me/v2/bot/richmenu/{richMenuId}/content - Headers:
Authorization: Bearer {YOUR_CHANNEL_ACCESS_TOKEN}Content-Type: image/png(またはimage/jpeg)- Binary Data: 仕様に合わせた画像バイナリ
成功した場合は、ステータスコード 200 OK が返ります。画像が反映されない場合は、URLのドメイン、Content-Type、画像形式、ファイル容量、画像サイズを順番に確認してください。
STEP 3: 対象ユーザーへの個別リンク処理(Link)
最後に、準備が整ったリッチメニューを特定のユーザーに適用します。自社ECサイト上のユーザーIDと紐付いたLINEの固有識別子 userId をURLに含め、リクエストを送信します。
- Requestエンドポイント:
POST https://api.line.me/v2/bot/user/{userId}/richmenu/{richMenuId} - Headers:
Authorization: Bearer {YOUR_CHANNEL_ACCESS_TOKEN}
リクエストが成功すると、通常はステータスコード 200 OK が返ります。対象ユーザーが友だち追加していない、ブロックしている、または userId が誤っている場合は、期待通りに表示されない可能性があります。
なお、Messaging APIを介して1つのLINE公式アカウントに登録・保持できるリッチメニュー数には上限があります。ユーザーIDごとに無制限に動的生成するのではなく、会員ランクや用途ごとに定義した固定の richMenuId を使い回す設計にしてください。
✍️ 専門家の経験からの一言アドバイス
【結論】: LINE Official Account Managerで設定したデフォルトメニューと、Messaging API経由でユーザー個別にリンクしたメニューが競合した場合、通常はユーザー単位のリッチメニューが優先されます。
なぜなら、デフォルトのリッチメニューは「ユーザー単位のリッチメニューがリンクされていないユーザー」に表示される位置づけだからです。管理画面の設定を消す前に、対象ユーザーに個別リンクが残っていないかを確認してください。この優先順位を理解しておくと、テスト環境での動作検証がスムーズになります。
自社DBとWebhookで連動する「属性別出し分け」&「タブ切り替え」の構築ロジック
企業のビジネス要件で求められやすい「購入履歴(会員ランク)に応じた動的出し分け」と、画面上でメニューを切り替える「タブ機能」は、同じリッチメニューでも設計が異なります。
会員ランク(属性情報)による動的出し分け
プレミアム会員と無料会員で異なるリッチメニューを表示させる場合、あらかじめサーバー起動時または管理バッチで、プレミアム用リッチメニュー(richMenuId_A)と無料会員用リッチメニュー(richMenuId_B)の2種類をLINE側に作成・登録しておきます。
自社ECサイト側のデータベース(DB)で購入完了フラグやランク昇格ログが書き換わったタイミングで、バックエンドのシステムコードから対象ユーザーの userId を指定し、STEP 3の個別リンクAPI(POST /user/{userId}/richmenu/{richMenuId})を実行します。これにより、自社DBの会員ステータスと、ユーザーの実機スマホ画面に表示されるリッチメニューを同期できます。
ユーザーの操作で切り替わる「タブ切り替え」
1つのメニュー画面に収まらない情報をタブで表現する場合、現在は richmenuswitch アクションとリッチメニューエイリアスを使う構成が基本です。以前のように、すべてを postback とWebhookの個別リンク更新で処理する設計も可能ですが、単純なタブ切り替えだけならエイリアス方式の方が分かりやすく、バックエンド処理も軽くなります。
- デザインの準備: 画像内に「タブ1(現在地)」「タブ2」というボタン領域をあらかじめデザインしたメニューAと、逆に「タブ1」「タブ2(現在地)」としたメニューBの2つのオブジェクトを用意します。
- エイリアスの作成: メニューAに
richmenu-alias-a、メニューBにrichmenu-alias-bのようなリッチメニューエイリアスを紐付けます。 - 切替アクションの設定: メニューAの「タブ2」領域には
type: "richmenuswitch"とrichMenuAliasId: "richmenu-alias-b"を指定します。メニューB側にも、メニューAへ戻る切替アクションを設定します。
Webhookサーバーでポストバックイベントを扱う処理も併用する場合は、Messaging APIのWebhook設定を先に確認してください。WebhookサーバーをCloudflare Workersなどで公開する場合は、HonoでLINE Botを構築する手順も参考になります。

✍️ 専門家の経験からの一言アドバイス
【結論】: 単純なタブ切り替えはrichmenuswitchとリッチメニューエイリアスで実装し、会員ランク変更やDB連動が必要な場面だけ個別リンクAPIを使い分けてください。
すべてをWebhook経由のpostbackで処理すると、実装自由度は高くなります。一方で、サーバー処理、重複イベント対策、ログ管理、エラー時の復旧設計が必要です。ユーザーの連打やWebhook再送を考慮する場合は、イベントIDや処理キーを使った重複排除を入れておくと、本番運用時の不安を減らせます。
開発現場のトラブルシューティング:400エラー・座標ズレ・管理画面との競合対策
テスト環境やステージング環境へのデプロイ直前に意図しない挙動に遭遇した場合は、原因を切り分ける順番が重要です。デプロイや公開URLの準備で詰まっている場合は、先にLINE開発のデプロイ手順も確認してください。
ケース1:画像アップロード時に 400 Bad Request が返る
- 【原因と確認ポイント】
まず、アップロード先がhttps://api-data.line.me/v2/bot/richmenu/{richMenuId}/contentになっているか確認してください。次に、画像サイズ、ファイル容量、Content-Type、実際の画像形式を見直します。拡張子だけを.pngに変えても、内部バイナリが正しいPNG/JPEG形式でなければエラーになる可能性があります。
ケース2:エリア定義JSONのPOST時に400エラーになる
- 【原因と確認ポイント】
areas配列内のバウンディングボックス(bounds)の座標計算を見直してください。各エリアの"x" + "width"の値が、全体サイズで定義した"width": 2500を超えていないか、または"y" + "height"の値が"height": 1686(あるいは843)を超過していないかを確認します。作成前にPOST /v2/bot/richmenu/validateを使って検証する方法も有効です。
ケース3:リンクAPI成功後も実機のメニューが変わらない
- 【原因と確認ポイント】
リクエスト時に送信したuserIdと、テストしている実機アカウントのIDが一致しているか、DBのレコードを確認してください。API側で指定したuserIdまたはrichMenuIdの文字列にタイポ、余分な空白、改行コードが混入していないかも確認します。実機側では、一度トークルームから戻り、再度トークルームを開き直して描画更新を促してください。
ケース4:個別リンクを解除してデフォルトメニューに戻したい
- 【原因と確認ポイント】
個別リンクAPIで紐付けたリッチメニューは、明示的に解除しない限りユーザーに残る場合があります。元のデフォルト状態に戻すには、ユーザーのuserIdをパスに指定してDELETE https://api.line.me/v2/bot/user/{userId}/richmenuを実行してください。これにより個別設定が解除され、デフォルトのリッチメニューが表示対象になります。
まとめ
Messaging APIを使った高度なリッチメニューのプログラム制御は、画像・座標・API順序・表示優先順位を分けて設計すれば、実務でも安定させやすいマーケティング基盤になります。
- 画像解像度の事前合意: デザイナーに丸投げせず、
2500x1686pxなどの推奨サイズ、容量、画像形式、タップ領域を先に共有する。 - 3ステップシーケンスの遵守: 作成(ID発行) → 画像バイナリ転送 → 個別ユーザーリンク の順番で実装し、ログとエラーハンドリングを残す。
- 用途別の切り分け: 会員ランク別の出し分けは個別リンクAPI、タブ切り替えは
richmenuswitchとリッチメニューエイリアスを基本にする。
仕様の罠を理解できれば、リッチメニューは単なる固定メニューではなく、ユーザー属性に合わせて体験を変えられる強力なUIになります。まずは小さな検証環境で、作成・画像反映・ユーザーリンク・解除までを一通り試し、本番実装へ進めてください。
参考文献・公式情報リスト
本仕様設計は、2026年5月時点で確認できるLINE公式デベロッパー向け一次情報をもとに記述しています。仕様は変更される可能性があるため、実装前には必ず公式ドキュメントも確認してください。
参考文献リスト
LINE Bot リッチメニューに関するよくある質問 (FAQ)
LINE Botのリッチメニュー実装でつまずきやすいポイントを、Q&A形式でまとめました。
LINE Bot リッチメニューは管理画面だけで作れますか?
一律表示なら管理画面でも作成できます。
ただし、会員ランク別の出し分けやシステム連動を行う場合は、Messaging APIでリッチメニューを作成し、ユーザー単位でリンクする設計が必要になります。
リッチメニュー画像のアップロードで400エラーが出る原因は何ですか?
画像サイズ、形式、容量、アップロード先URLを確認してください。
特に画像アップロード先は api-data.line.me です。api.line.me に送っている、Content-Typeが違う、PNG/JPEGとして正しく書き出せていない、といった原因でも失敗する可能性があります。
リッチメニューのタブ切り替えはpostbackで作るべきですか?
単純なタブ切り替えなら、richmenuswitchとリッチメニューエイリアスが基本です。
postbackとWebhookを使う方法もありますが、サーバー処理や重複イベント対策が必要になります。タブ表示だけなら、まず公式の切替アクションを使う設計から検討してください。
個別リンクしたリッチメニューを元に戻すにはどうすればいいですか?
ユーザーとのリンク解除APIを実行します。
DELETE /v2/bot/user/{userId}/richmenu を実行すると、ユーザー単位のリッチメニューリンクを解除できます。解除後は、設定状況に応じてデフォルトのリッチメニューが表示されます。



コメント