How to Implement a LINE MINI App Custom Action Button
A LINE MINI App custom action button is a button in the app body that opens LINE’s share target picker. After the user chooses friends, groups, or chats, liff.shareTargetPicker() sends a developer-created share message on the user’s behalf. Use LINE’s prescribed Flex Message layout, point detail buttons to permanent MINI App links, and treat cancellation separately from success or failure.
Key takeaways
- The built-in header action button shares the current page automatically; a custom action button lets the app control the share-message content.
- Both unverified and verified LINE MINI Apps can use a custom action button. It is not a production service-message permission.
- The user must be logged in, and share target picker must be enabled in LINE Developers Console.
- LINE’s custom format uses one Flex Message
bubble, not acarousel, with a required title, button area, and branded footer. - A resolved Promise without a result means the user cancelled; only
{ status: "success" }confirms that the share completed.
What a LINE MINI App custom action button actually does
LINE’s official custom action button guide distinguishes two share controls. The built-in action button lives in the header, is displayed by LINE, and shares the page currently open. Its behavior and share content cannot be customized. A custom action button lives in your MINI App body and launches the target picker with content your application assembles.
This is a user-initiated share flow, not a server notification:
| Feature | Custom action button | Service message | Messaging API message |
|---|---|---|---|
| Initiator | User taps a button and selects recipients | Server follows up on an eligible MINI App action | Official Account bot replies or sends to eligible recipients |
| Main API | liff.shareTargetPicker() in the MINI App | Service Message API on the server | Messaging API on the server |
| Sender shown to recipient | The sharing user | Regional LINE MINI App notice chat | LINE Official Account |
| Content control | Prescribed custom Flex Message format | Reviewed service-message template | Supported Messaging API message objects |
| Verification gate | Available to unverified and verified MINI Apps | Verified MINI App required for production | Messaging API channel and Official Account rules apply |
If verification or notifications are the real question, use the verified-versus-unverified MINI App guide and the service message vs Messaging API comparison. The custom button does not grant either messaging capability.
LINE MINI App custom action button implementation checklist
1. Enable and test the share target picker
Initialize LIFF normally, confirm the user is logged in, and enable share target picker in LINE Developers Console. LINE’s LIFF API reference states that both conditions are required.
Before enabling the button, check liff.isApiAvailable("shareTargetPicker"). In a smartphone external browser, the picker also requires an SSO login session; auto login alone may lead to the email login screen instead of the picker. Test inside the LIFF browser and in the external-browser path your users actually follow.
2. Build the prescribed Flex Message, not an arbitrary card
LINE requires a Flex Message bubble for this custom share format and explicitly excludes a carousel. The card must have a concise title, either a subtitle or detail list, a button area, and a branded footer. Depending on the chosen standard or image-list layout, follow the documented component properties rather than treating the example as a general Flex Message canvas.
The button area can contain up to three buttons. At least one must open a detail page for the shared content. The footer identifies the LINE MINI App and links back to its top page.
3. Use permanent links for every non-top destination
Do not put the ordinary web endpoint URL into a button that should reopen a specific MINI App screen. LINE documents the formula as:
LIFF URL + (LINE MINI App page URL - endpoint URL) = permanent link
For example, if the LIFF URL is https://miniapp.line.me/123456-abcdefg, the endpoint is https://example.com, and the page is https://example.com/orders/42?from=share, the permanent link is:
https://miniapp.line.me/123456-abcdefg/orders/42?from=share
LINE’s permanent-link guide allows paths, query strings, and fragments. Test the exact link in LINE, including authentication, expired records, and deleted content. The header’s built-in action button generates its own permanent link; custom message buttons do not.
4. Call the picker from an explicit user action
Keep the message small and derive its text and links from a server-authorized record, not untrusted query parameters. A minimal control flow looks like this:
async function shareOrder(order) {
if (!liff.isApiAvailable("shareTargetPicker")) {
return { outcome: "unavailable" };
}
try {
const result = await liff.shareTargetPicker([
{
type: "flex",
altText: `Order ${order.reference}`,
contents: buildApprovedBubble(order),
},
]);
return result?.status === "success"
? { outcome: "shared" }
: { outcome: "cancelled" };
} catch (error) {
return { outcome: "failed", error };
}
}
The helper above is an implementation pattern, not a complete LINE layout. buildApprovedBubble() must return the prescribed Bubble structure from the current LINE guide.
5. Separate success, cancellation, and pre-display errors
The LIFF Promise has three important outcomes:
| Outcome | API behavior | Application behavior |
|---|---|---|
| Sent | Resolves with { status: "success" } | Show a restrained success state; do not claim a recipient opened the link |
| Cancelled | Resolves without a result object | Return to the page without an error alert |
| Failed before picker display | Rejects with LiffError | Log a safe error code and offer retry or the built-in header share path |
LINE does not provide the number of people who received a target-picker share. Do not manufacture recipient counts, delivery analytics, or conversion events from the resolved Promise.
6. Run a device-level acceptance matrix
At minimum, test logged-in and logged-out states, LIFF browser and smartphone external browser, picker enabled and disabled, single and multiple recipients, cancellation, a valid deep link, an expired deep link, and long localized content. Also verify that OpenChat is not presented as a supported target; the API reference lists groups, friends, and chats, excluding OpenChat.
Where UnifyPort fits
UnifyPort does not implement liff.shareTargetPicker(), create the LINE target picker, validate the custom Flex Message layout, or provide share-recipient analytics. Those belong to the official LINE MINI App and LIFF flow.
UnifyPort fits after a different user action: an ordinary customer sends a message to a connected LINE account. Supported messages can arrive as normalized message.received events. When a webhook endpoint has a signing_secret, deliveries include X-Device-Timestamp and X-Device-Signature for HMAC-SHA256 verification.
That boundary is useful when a shared MINI App page leads to a later support conversation. Keep the share event, order or campaign ID, and inbound conversation as separate records that your application correlates. Review the LINE authorization guide and provider message-support matrix before relying on an inbound or reply capability.
Limitations and trade-offs
- Use the built-in header action button when sharing the current page is enough; it is simpler and automatically produces the page’s permanent link.
- Use the custom button only when the share message needs a guided, LINE-compliant card. It adds layout, link, login, and device-testing work.
- A custom action button cannot send silently, choose recipients automatically, prove delivery, or expose the recipient count.
- It does not replace service messages, Messaging API push messages, an Official Account, or customer-support intake.
FAQ
Can an unverified LINE MINI App use a custom action button?
Yes. LINE’s current custom-features matrix lists custom action buttons for both unverified and verified MINI Apps. Production service messages remain a separate verified-only feature.
What is the difference between the built-in and custom action buttons?
The built-in header button shares the page currently open and its content cannot be customized. A custom body button calls liff.shareTargetPicker() with a developer-created, guideline-compliant share message.
Does liff.shareTargetPicker() tell me how many people received the message?
No. LINE says it neither collects nor provides the recipient count for target-picker shares. A success result confirms the share action, not views or conversions.
Why did the Promise resolve without status: "success"?
If the user closes the picker before sending, the Promise resolves without a result object. Treat that as cancellation, not as an API error.
Should a detail button use the endpoint URL or a permanent link?
Use a permanent LINE MINI App link for any page other than the top page. It preserves the MINI App context and can include a path, query string, or fragment.
Next step
Implement and validate the card against LINE’s official custom action button guide. If the separate requirement is receiving ordinary LINE customer messages, start with the UnifyPort LINE authorization guide.
Sources
Official LINE sources checked on August 8, 2026: