經過前幾天的學習,我們已經成功掌握了 LINE Bot 六大基礎訊息類型的發送技巧,為訊息互動奠定了穩固的基礎。今天,我們將踏入更具挑戰性的進階應用領域!
在實際的 LINE Bot 開發場景中,除了六大基礎訊息類型外,LINE 官方還提供了三種進階訊息格式:Template Message
、Imagemap Message
及 Flex Message
。
今天,我們將深入探索第一種進階訊息格式 Template Message
,學習如何運用預設的模板佈局,快速打造出視覺統一且互動豐富的訊息回覆。
本日程式碼的範例連結
Day 13提到的訊息共通參數
Sender
及Quick Reply
同樣適用於所有進階訊息格式(Template Message、ImageMapMessage、FlexMessage)。
Template Message
可以理解為 LINE 官方預先設計的訊息模板佈局系統。開發者只需將所需參數代入模板中,即可快速產生具有統一視覺風格的互動式訊息。這種設計大幅提升了開發效率,但相對地在客製化程度上會有一定的限制。
模板訊息總共有四種:
四種模板訊息的共通屬性
所有 Template Message
都必須包含 altText
屬性,作為 LINE 通知顯示的替代文字。當使用者收到推播通知時,會顯示此文字內容。
Message
型別是LINE SDK
提供的所有訊息回覆類型的聯合型別
在先前的實作中,我們採用「輸入什麼型別,就回覆什麼型別」的對應模式。舉例來說:使用者輸入文字訊息,LINE Bot 就回應文字訊息。這種設計主要是為了方便展示六大基礎訊息類型的對照效果。
然而在實際開發場景中,我們不應該被這種限制束縛。當收到文字訊息時,我們應該能夠靈活回覆各種訊息類型,只要符合 LINE Bot
支援的回覆格式即可。因此,我們將型別調整為更通用的 Message
類型,讓訊息回覆更加靈活。
line-webhook/line-webhook.types.ts
export type MessageEventHandlerMap = {
[K in EventMessage['type']]: (
event: Extract<EventMessage, { type: K }>,
) => Message; // 主要調整這個部分,讓回傳型別不被限制
};
支援可選標題及縮圖配置,並提供 1-4 個按鈕的互動選項。
核心參數:
可選參數:
rectangle(長寬比:1.51:1)
顯示。line-message/types/template-button-message.ts
import { Action } from '@line/bot-sdk';
type HttpsURL = `https://${string}`;
export type TemplateButtonMessageReq = {
altText: string;
text: string;
action: Action[];
title?: string;
thumbnailImageUrl?: HttpsURL;
};
這裡透過 createButtonTemplateMessage
函式來封裝複雜的模板訊息結構,讓開發者只需專注在必要參數的配置上,簡化訊息建立流程。
line-message/line-message.service.ts
createButtonTemplateMessage(
templateButtonMessageReq: TemplateButtonMessageReq,
): TemplateMessage {
const { altText, text, actions, thumbnailImageUrl, title } =
templateButtonMessageReq;
const buttonTemplateMessage: TemplateMessage = {
type: MessageType.Template,
altText,
template: {
type: MessageType.TemplateButton,
text,
actions,
title,
...(thumbnailImageUrl && { thumbnailImageUrl }), // 可選參數的處理
},
};
return buttonTemplateMessage;
}
Button Template Message Action 最多只能四個!!
在 Action 類型的選擇上,常用的有三種::message(訊息回傳)、postback(資料回傳)及 uri(開啟連結),本範例先以 message 類型進行示範。
當使用者傳送 button 文字時,我們會回覆事先準備好的 Button Template
訊息。
line-webhook/line-webhook.service
private async handleMessageEvent(event: MessageEvent): Promise<void> {
const messageEventHandlerMap = {
text: (message) {
const { text } = message;
// text 是使用者傳送的文字內容
if (text === 'button') {
return this.lineMessageService.createButtonTemplateMessage({
altText: '按鈕小精靈通知',
thumbnailImageUrl: 'https://res.cloudinary.com/dseg0uwc9/image/upload/v1753953684/2025%20IT%20%E9%90%B5%E4%BA%BA%E8%B3%BD/dog_icon_grxcsl.jpg',
title: '標題',
text: '按鈕小精靈出來吧',
actions: [
{
type: 'message',
label: '我是按鈕 1',
text: '我是按鈕 1 號',
},
{
type: 'message',
label: '我是按鈕 2',
text: '我是按鈕 2 號',
},
{
type: 'message',
label: '我是按鈕 3',
text: '我是按鈕 3 號',
},
{
type: 'message',
label: '我是按鈕~',
text: '我是按鈕 4 號',
},
],
});
}
},
} satisfies Partial<MessageEventHandlerMap>;
}
專為決策判斷場景設計的模板訊息,必須且只能擁有兩個按鈕
Confirm Template
是最簡潔的模板格式,適用於需要使用者做出「是/否」、「確認/取消」等二選一決策的情境。與 Button Template
不同,Confirm Template
沒有標題
和縮圖
功能
透過 Tuple 型別明確定義需要兩個
Action
,編譯時期避免參數數量錯誤的情況發生
line-message/types/template-confirm-message
import { QuickReplyItem, Sender } from '@line/bot-sdk';
export type TemplateConfirmMessageReq = {
altText: string;
text: string;
actions: [Action, Action];
sender?: Sender;
quickReplyItems?: Omit<QuickReplyItem, 'type'>[];
};
line-message/line-message.service.ts
createConfirmTemplateMessage(
templateConfirmMessageReq: TemplateConfirmMessageReq,
): TemplateMessage {
const { altText, text, actions } =
templateConfirmMessageReq;
const templateConfirmMessage: TemplateMessage = {
type: MessageType.Template,
altText,
template: {
type: MessageType.TemplateConfirm,
text,
actions,
},
};
return templateConfirmMessage;
}
常被使用的模板訊息 ⭐⭐⭐
支援最多 10 張卡片,每張卡片最多 3 個按鈕,且所有卡片的按鈕數量必須相同。
建議可以限制一下 action 數量,避免 action 數量不一致的行為
這裡透過泛型約束的方式,讓原先的函數能夠在編譯時期驗證每張卡片的按鈕數量是否一致,確保所有卡片的 action
數量都符合 Carousel Template
的規範要求。
line-message/types/template-carousel-message.ts
import { QuickReplyItem, Sender, TemplateColumn } from '@line/bot-sdk';
type FixedArray<T, N extends number> = T[] & { length: N };
type LimitedActionColumn<N extends number> = Omit<
TemplateColumn,
'defaultAction' | 'imageBackgroundColor' | 'actions'
> & {
actions: FixedArray<TemplateColumn['actions'][number], N>;
};
export type TemplateCarouselMessageReq<N extends number = number> = {
altText: string;
cards: LimitedActionColumn<N>[];
sender?: Sender;
quickReplyItems?: Omit<QuickReplyItem, 'type'>[];
};
Carousel Template
與 Button Template
的主要差異在於 cards
參數,每張卡片支援以下配置:
核心參數:
可選參數:
卡片的參數配置與 Button Template
基本相同,但透過陣列形式支援多張卡片的輪播展示。
line-message.service/line-message.service.ts
createTemplateCarouselMessage<N extends number>(
templateCarouselMessageReq: TemplateCarouselMessageReq<N>,
): TemplateMessage {
const { altText, cards, sender, quickReplyItems } =
templateCarouselMessageReq;
const templateCarouselMessage: TemplateMessage = {
type: MessageType.Template,
altText,
template: {
type: MessageType.TemplateCarousel,
columns: [...cards],
},
};
return templateCarouselMessage;
}
透過泛型參數指定每張卡片的按鈕數量,實現編譯時期的靜態檢查:
line-webhook.service/line-webhook.service.ts
// 指定每張卡片只能有 1 個按鈕
this.lineMessageService.createTemplateCarouselMessage<1>({
altText: '最新活動消息!!',
cards: [
{
text: '新生代狗狗寵物展',
thumbnailImageUrl:
'https://res.cloudinary.com/dseg0uwc9/image/upload/v1753953684/2025%20IT%20%E9%90%B5%E4%BA%BA%E8%B3%BD/dog_icon_grxcsl.jpg',
actions: [
{
type: 'message',
label: '搶先第一手資訊',
text: '可愛狗狗展',
},
],
},
{
text: '可愛貓貓展',
thumbnailImageUrl:
'https://res.cloudinary.com/dseg0uwc9/image/upload/v1753953684/2025%20IT%20%E9%90%B5%E4%BA%BA%E8%B3%BD/dog_icon_grxcsl.jpg',
actions: [
{
type: 'message',
label: '搶先第一手資訊',
text: '可愛貓貓展',
},
],
},
],
實務開發中的熱門選擇 ⭐⭐⭐
以圖片為主軸的輪播卡片模板,版型固定,只能調整圖片及按鈕。
每張卡片均必須填寫以下配置:
定義上會跟 Carousel Template 蠻類似的,但是這邊因為只能設定一個按鈕,所以會相對單純。
import { QuickReplyItem, Sender, TemplateImageColumn } from '@line/bot-sdk';
export type TemplateImageCarouselMessageReq = {
altText: string;
cards: TemplateImageColumn[]; // 這邊的型別跟 Carousel Template 不同喔!!!
sender?: Sender;
quickReplyItems?: Omit<QuickReplyItem, 'type'>[];
};
使用上與 Carousel Template
相似,但 ImageCarousel Template
的每張卡片都必須設置圖片和按鈕。
createTemplateImageCarouselMessage(
templateImageCarouselMessageReq: TemplateImageCarouselMessageReq,
): TemplateMessage {
const { altText, cards, sender, quickReplyItems } =
templateImageCarouselMessageReq;
const templateImageCarouselMessage: TemplateMessage = {
type: MessageType.Template,
altText,
template: {
type: MessageType.TemplateImageCarousel,
columns: [...cards],
},
...this.buildCommonMessageProps(sender, quickReplyItems),
};
return templateImageCarouselMessage;
}
今天我們完成了第一種進階回覆訊息 Template Message 的實作。這類模板的使用方式相當直觀,只需準備好必要參數,就能快速產生對應的模板訊息。
然而,正如開頭提到的,Template Message 的客製化程度有限。例如想為商品模板加上「特價標籤」或其他個性化元素,Template Message 無法直接實現。這種標準化的限制,讓模板訊息比較難凸顯獨特的設計特色。