LINE MINI App ตอนที่ 2: การทำ Custom Action

Sitthi Thiammekha
LINE Developers Thailand
6 min readMar 28, 2024

ในบทความที่แล้ว ผมได้เกริ่นถึง LINE MINI App ไปบ้างแล้ว ใครยังไม่ได้อ่าน หรืออยากทบทวนความทรงจำ กลับไปอ่าน ตอนที่ 1 ได้ที่นี่ก่อนครับ

วันนี้เรามาต่อตอนที่ 2 กัน ว่าด้วยเรื่องของ Feature สำคัญอันหนึ่งของ LINE MINI App นั่นก็คือ การแชร์ข้อความนั่นเอง โดยในเอกสารของ LINE เรียกฟีเจอร์นี้ว่า การทำ Custom Action

ก่อนจะไปทำความรู้จักกับ Custom Action อยากเล่าสั้นๆเกี่ยวกับองค์ประกอบของ LINE MINI App กันนิดนึงก่อนครับ

ส่วนประกอบ (Components) ของ LINE MINI App

หน้าจอของ MINI App แบ่งเป็น 2 ส่วน ได้แก่

A) Header : เป็นส่วนที่ประกอบไปด้วยชื่อ App, ปุ่ม Action (Share / Refresh) และปุ่มปิด

B) Body : เป็นส่วนการแสดงผลของ App ที่สามารถออกแบบได้ตามต้องการ

จะเห็นว่าใน Section A) ซึ่งเป็นส่วนของ Header นั้น จะมีปุ่ม action ที่ใช้สำหรับ Share ได้อยู่แล้ว ซึ่งจะเป็นการแชร์ Link ของ MINI App นี้ออกไปตรงๆ

แต่การทำ Custom Action จะอยู่ใน Section B) ที่เป็น Body ของ Web App ของเราโดยเราสามารถออกแบบให้มีปุ่ม action บางอย่าง ที่ทำหน้าที่ Share Content ออกไปหาเพื่อนๆใน LINE โดยใช้ฟังก์ชัน ShareTargetPicker ของ LIFF ต่างกันที่เนื้อหาที่แชร์ออกไป เราสามารถกำหนดรูปแบบเองได้ เป็นรูปแบบ Flex Message เพียงแต่ต้องออกแบบ Flex Message ให้ตรงตามข้อกำหนดที่ LINE ตั้งขึ้นด้วยเท่านั้นเอง

การทำ Custom action button

หากใครเคยทำ LIFF มาก่อน จะทราบดีว่า LIFF มีฟังก์ชัน ShareTargetPicker ที่ใช้แชร์ content ไปให้เพื่อนๆใน LINE ได้

จากรูปด้านบน ก็คือการทำ Custom Action ที่ปุ่ม “Share with friends” นั่นเอง

Custom action button นี้ จริงๆก็คือการใช้งานฟังก์ชัน ShareTargetPicker เพียงแต่มีการกำหนดรูปแบบของ content หรือข้อความที่จะส่งออกไป ว่าจะต้องเป็นรูปแบบที่กำหนดเท่านั้น เพื่อให้คงความน่าเชื่อถือ และไม่เป็นการสแปมผู้ใช้นั่นเอง

โดยรูปแบบที่อนุญาตให้ใช้ได้ตอนนี้มี 2 รูปแบบ เรียกว่า standard type (ซ้าย) และ image list type (ขวา)

แต่ในกรณีที่ Business Requirement ไม่สามารถใช้รูปแบบนี้ได้จริงๆ ก็สามารถลองส่ง request ไปที่ mini_request@linecorp.com ได้

โดยทั้ง 2 รูปแบบ ประกอบไปด้วย 7 section ดังนี้

A : รูปภาพ cover (optional)

  • แนะนำเป็นรูปภาพ ขนาดไม่ใหญ่เกินไป เพื่อให้แสดงผลได้พอดีกับขนาดของ Bubble

B : Title (Required) => หัวข้อของสิ่งที่ต้องการแชร์

C : Subtitle = > Subtitle ของสิ่งที่แชร์

D : Detail => รายการ/รายละเอียด

  • ถ้าเป็น standard type ใส่ได้สูงสุด 10 items
  • ถ้าเป็น image list type ใส่ได้สูงสุด 5 items

จะต้องประกอบด้วย section C หรือ D อย่างน้อย 1 อย่าง หรือมีทั้ง C และ D ก็ได้

E : Button (Required)

  • กำหนดปุ่ม Action ได้ 1–3 buttons
  • ต้องมีอย่างน้อย 1 button ที่มี link (URI Action) ไปหน้าดู detail เพื่อดูรายละเอียดของสิ่งที่แชร์

F : Footer (Required)

  • Fix รูปแบบ ดังนี้ LINE MINI App icon ตามด้วย App name ตามด้วยรูป >
  • กำหนด URI Action เพื่อไปหน้า App top page เมื่อผู้ใช้กดที่รูปนี้ (https://miniapp.line.me/{your-liffId})

ซึ่งในแต่ละ Section มีการกำหนดมาตรฐานของ Element ต่างๆเอาไว้ค่อนข้างละเอียด ดูได้ที่นี่ ซึ่งนักพัฒนาต้องทำตามรูปแบบนี้เท่านั้น และมีข้อกำหนดเพิ่มเติมว่า

  • ต้องให้ Flex Container เป็นแบบ Bubble เท่านั้น ห้ามใช้ Carousel
  • ห้ามเปลี่ยนแปลง Property ของ Element ต่างๆที่กำหนดไว้
  • สามารถระบุ Action ได้แค่ภายใน Section E และ F ได้เท่านั้น

สามารถดูตัวอย่าง JSON แบบเต็มๆได้ที่

เมื่อได้รูปแบบข้อความที่จะแชร์แล้ว ก็ใช้ฟังก์ชั่น liff.shareTargetPicker() ส่งออกไปได้เลย

เดี๋ยวเรามาลองทำไปพร้อมๆกันครับ แต่ก่อนจะไปลงมือกัน ใครยังไม่ได้สร้าง MINI App Channel ขอให้เริ่มสร้าง ตามบทความนี้ ก่อนนะครับ

เราไปเริ่ม code กันครับ

จากบทความครั้งที่แล้ว เราทำไปจนถึงแบบนี้แล้ว

จะทำต่อจากของเดิม หรือเริ่มต้นใหม่ เพื่อทบทวนก็ไม่ติดนะครับ

เดี๋ยวผมจะปรับเป็นแอพดูรูปแมวละกัน เป็นตัวอย่างของการนำ Custom Action ไปใช้งาน

กลับไปที่ stackblitz แล้วแก้ไข index.js เอาง่ายๆ มีแค่รูปภาพ กับปุ่ม Share ประมาณนี้

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0,viewport-fit=cover"
/>
<title>LINE MINI Cat</title>
<script src="https://static.line-scdn.net/liff/edge/2/sdk.js"></script>
</head>
<body id="body">
<section id="profile">
<img id="pictureUrl" src="https://cataas.com/cat" />
</section>
<section id="button">
<button id="btnShare">Share</button>
</section>
</body>
</html>

Credit : รูปภาพ ผมยืมมาจาก https://cataas.com/ ซึ่งเป็นเว็บ API ที่มีภาพแมวให้ใช้ครับ ลองไปเล่นกันดูได้

จากนั้น แก้ไขไฟล์ index.js นิดหน่อย ตามนี้ครับ

import './style.css';
import msgForShare from './flex-share.json';

const btnShare = document.getElementById('btnShare');

async function main() {
await liff.init({ liffId: '9999999999-xxxxxxxx' });
btnShare.style.display = 'block';
}
main();

async function shareMsg() {
await liff.shareTargetPicker([msgForShare]);
}

btnShare.onclick = () => {
shareMsg();
};

สิ่งที่เพิ่มเติมมาคือการ import msgForShare เพื่อนำมาใช้ส่งข้อความนั่นเอง

อย่าลืมแก้ไข liffId เป็นของตัวเองด้วยนะครับ

จากนั้นให้เราสร้างไฟล์ flex-share.json ขึ้นมา เดี๋ยวเราจะเอาข้อความที่จะแชร์มาบันทึกไว้ตรงนี้

ออกแบบข้อความสำหรับแชร์

ลองเอาตัวอย่าง JSON ของข้อความแบบ standard type มาดูครับ ตัว JSON จะมีหน้าตาแบบนี้

{
"type": "bubble",
"hero": {
"type": "image",
"url": "https://example.com/hero-image.png", // Specify the appropriate image URL
"size": "full",
"aspectRatio": "20:13",
"aspectMode": "cover"
},
"body": {
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "text",
"text": "Main title",
"size": "lg",
"color": "#000000",
"weight": "bold",
"wrap": true
}
],
"spacing": "none"
},
{
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "text",
"text": "Sub-title",
"size": "sm",
"color": "#999999",
"wrap": true
}
],
"spacing": "none"
},
{
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "Label 1",
"size": "sm",
"color": "#555555",
"wrap": false,
"flex": 20
},
{
"type": "text",
"text": "Description 1",
"size": "sm",
"color": "#111111",
"wrap": false,
"flex": 55
}
],
"flex": 1,
"spacing": "sm"
},
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "text",
"text": "Label 2",
"size": "sm",
"color": "#555555",
"wrap": false,
"flex": 20
},
{
"type": "text",
"text": "Description 2",
"size": "sm",
"color": "#111111",
"wrap": false,
"flex": 55
}
],
"flex": 1,
"spacing": "sm"
}
],
"spacing": "sm",
"margin": "lg",
"flex": 1
},
{
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "button",
"action": {
"type": "uri",
"label": "View details",
"uri": "https://miniapp.line.me/123456-abcedfg" // Specify the LINE MINI App page.
},
"style": "primary",
"height": "md",
"color": "#17c950"
},
{
"type": "button",
"action": {
"type": "uri",
"label": "Share",
"uri": "https://miniapp.line.me/123456-abcedfg/share" // Specify the LINE MINI App page.
},
"style": "link",
"height": "md",
"color": "#469fd6"
}
],
"spacing": "xs",
"margin": "lg"
}
],
"spacing": "md"
},
"footer": {
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "separator",
"color": "#f0f0f0"
},
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "image",
"url": "https://example.com/line-mini-app-icon.png", // Specify the LINE MINI App icon.
"flex": 1,
"gravity": "center"
},
{
"type": "text",
"text": "Service name",
"flex": 19,
"size": "xs",
"color": "#999999",
"weight": "bold",
"gravity": "center",
"wrap": false
},
{
"type": "image",
"url": "https://vos.line-scdn.net/service-notifier/footer_go_btn.png",
"flex": 1,
"gravity": "center",
"size": "xxs",
"action": {
"type": "uri",
"label": "action",
"uri": "https://miniapp.line.me/123456-abcedfg" // Specify the top page of the LINE MINI App.
}
}
],
"flex": 1,
"spacing": "md",
"margin": "md"
}
]
}
}

เปิด Flex Simulator https://developers.line.biz/flex-simulator จะเจอหน้าจอแบบนี้

กดปุ่ม View as JSON ตรงมุมบนขวา แล้ววาง JSON ลงไป แล้วกด Apply เลยครับ

ใครเจอ Error แบบนี้ไม่ต้องตกใจครับ เนื่องจากใน JSON แอบมี comment อยู่ คุณต้องลบ comment ที่อยู่ใน JSON ทั้งหมดออกก่อน (แบบ standard มี 5 จุด, แบบ image list มี 9 จุด)

ใครขี้เกียจลบเอง ผมทำไว้ให้แล้ว เอาไปใช้ต่อได้เลย https://gist.github.com/kamnan43/a75d6d14290bc045a69729e3f8293f08
จากนั้นกด Apply จะได้หน้าตาแบบนี้ครับ

ให้เราปรับแต่ง Message โดยการเปลี่ยนข้อความหรือเปลี่ยนรูปตามต้องการครับ แต่ต้องยังคงรูปแบบ A-F ตามด้านบนอยู่นะครับ ถ้าปรับแล้วรูปแบบผิดเพี้ยนไป ตอนส่ง Submit App ของเราจะไม่ผ่านนะครับ

ผมลองปรับเป็นข้อความออกมาหน้าตาแบบนี้ครับ

เมื่อปรับแต่งข้อความจนพอใจแล้ว ก็ copy JSON มาใช้ครับ โดยการกดปุ่ม View as JSON จะมีปุ่ม Copy อยู่ด้านล่างครับ

สังเกตว่า JSON ที่ได้มา มี type เป็น bubble นะครับ

ซึ่งก่อนที่จะนำไปใช้ได้ เราต้องแปลงให้อยู่ในรูปแบบ Flex Message แบบนี้ก่อนครับ

ถ้าใครขี้เกียจแปลงเอง ผมขอแนะนำตัวช่วยครับ EX10 Flex Formatter

แค่เอา JSON จาก Flex Simulator ไปวางด้านซ้าย ระบบจะแปลงออกมาให้ทางด้านขวา แล้ว Copy จากด้านขวาเอาไปใช้งานได้เลยครับ

โดย Copy ไปวางที่ไฟล์ flex-share.json แล้วบันทึกได้เลย

ตอนนี้ระบบพร้อมสำหรับการทดสอบละ ตรวจสอบให้แน่ใจว่าคุณเปิดใช้งาน ShareTargetPicker เรียบร้อยแล้ว โดยสามารถเปิดได้ที่ tab LIFF ของ MINI App Channel

จากนั้นก็ลองทดสอบได้เลยครับ โดยการเปิด link ของ MINI App ตรง LIFF URL : Developing ไปวางบน Browser ได้เลย

สิ่งแรกที่จะเปลี่ยนไปจากการทำ LIFF ปกติก็คือ link ของ MINI App จะไม่สามารถเปิดได้บน External Browser นะครับ ถ้าเปิดขึ้นมาจะเป็นแบบนี้

ให้ลองทดสอบโดยการเปิด link MINI App อีกครั้งในมือถือดูแทนนะครับ จะได้หน้าตาแบบนี้

เมื่อกดปุ่ม Share จะแสดงหน้าจอของ LINE ให้เลือกเพื่อน แล้วกดแชร์ข้อความออกไป เพื่อนของเราก็จะได้รับข้อความหน้าตาแบบนี้เลย

เมื่อเพื่อนของเรากดปุ่ม View Details ก็สามารถเข้าถึง Web App แบบเดียวกับเราได้เลย

มีจุดสังเกตนิดนึงตรง Footer ที่เป็นเครื่องหมาย > ตรงนี้ LINE กำหนดว่าให้ใส่ URL Action เป็น Top Page ของ MINI App นั่นหมายความว่า ผู้ใช้ก็สามารถเข้าถึง MINI App จากปุ่มนี้ได้เช่นเดียวกัน

เท่านี้ก็เรียบร้อย เป็นอันว่าเราสามารถสร้าง Custom Action บน LINE MINI App ได้แล้ว

ส่วนคนที่ยังสงสัยว่า เอ ทำได้แล้วจะเอาไปประยุกต์ใช้ยังไง ผมมีตัวอย่างมาให้ดูอันหนึ่ง

งานนี้เป็นโปรเจคที่เราพัฒนามาจากผลงานที่ได้รางวัล LINE HACK 2023
ของทีม Ma Run Gun ซึ่งเป็น (MINI) App สำหรับคนรักงานวิ่ง สามารถดูข้อมูลงานวิ่ง สมัครงานวิ่ง และแชร์งานวิ่งให้เพื่อนได้ด้วย

ตรงข้างๆปุ่ม สมัคร ก็จะมีปุ่มแชร์ ให้เราสามารถส่งข้อความไปเชิญชวนเพื่อนมาวิ่งกับเราได้เลย หน้าตาของข้อความที่เพื่อนได้รับก็จะเป็นแบบนี้

หวังว่าจะพอเป็นไอเดียในการเอาไปสร้างเป็น MINI App กันนะครับ
ใครมีไอเดียอื่นเจ๋งๆ ลองมาแบ่งปันกันนะครับ

เดี๋ยวตอนต่อไป ตอนที่ 3 ผมจะมาแชร์ต่อในเรื่องการส่ง Service Message เป็นการส่งข้อความหาผู้ใช้แบบฟรีๆ ไม่ต้องง้อ Push Message แล้ว จะเป็นยังไง รอติดตามกันนะครับ

--

--