LIFFでユーザー体験の向上を行う
※この記事は Wantedly から移行したものです。
社内プロダクトの1つに、ターゲット層のユーザーのほとんどがLINEを利用することを考慮し、LIFFと呼ばれる技術を採用しているものがあります。
LIFFを利用することで、容易にLINE上で動くアプリケーションを作成でき、またユーザーの体験も向上させることができます。
本記事では、LIFFの概要やメリット、具体的な利用例を紹介します。
LIFFとは
LIFFはLINE Front-end Frameworkの略で、LINE社が提供するウェブアプリのプラットフォームです。このプラットフォームで動作するウェブアプリを、LIFFアプリと呼びます。
アプリと聞くと身構える方もいるかもしれませんが、既存のウェブサイトのURLをLINE Developersコンソール画面で登録するだけでLIFFアプリになります。LINEでLIFFアプリのURLを開くことで、LIFFブラウザと呼ばれるWebViewを利用したブラウザでアプリケーションが開かれます。LIFFアプリはLIFF SDKが提供するAPIを利用でき、そのAPIを通じてLINEに登録したユーザーの情報やデバイスの情報の取得、LINEのアクション(投稿、カメラ起動、シェア等)を実行できます。
冒頭のプロダクトにてLIFFを利用する最大の目的は、シームレスな認証のためです。ユーザー登録やログインにおけるユーザーの離脱をなるべく避けるために、体験の良い認証を実現する必要がありました。LIFFを利用することで、ユーザーから見るとLINEログインすら必要がなくなり、アプリケーションを立ち上げると自動でログインしているように見えます。
LIFFは起動時にSDKがLINEログインを自動で行い、アクセストークンやIDトークンを取得します。冒頭のプロダクトではここで取得したIDトークンを利用し、API認証を行っています。LIFFのIDトークンは有効期限が1時間であり、有効期限が切れた際にはAPI認証が通らなくなります。そのため、アプリ上ではIDトークンの有効期限が切れたタイミングでアプリを一度閉じて、再度開いてもらうようにユーザーに促しています。アプリを1時間開きっぱなしというユースケースが想定されなかったため、上記の解決策でも問題ないと判断しました。
以下はLIFFアプリを開いてから実際にサーバーで認証するまでのシーケンス図で、このフローに沿って認証を行っています。
LIFFのAPIでできることの例として以下のようなものがあります。
ユーザー情報の取得
クライアント側で以下のような情報を取得できます。
- LINEユーザーID
- ユーザー名
- プロフィール画像URL
- メールアドレス
- IDトークンの有効期限
- ユーザーの認証時刻
- ユーザーが使用した認証方法
ログイン処理
LINEでLIFFアプリを開く場合は、LIFFの初期化時に自動でログイン処理が実行されますが、他の起動方法、例えばPCのブラウザから開く場合には別途ログイン処理を実装する必要があります。
login APIを利用すれば、処理実行時にLINEログインのダイアログが表示でき、PCのブラウザであっても容易にログイン処理を実装することができます。
ユーザーの友だちへのメッセージ送信
shareTargetPicker APIを利用することで、開発者が作成したメッセージを、ユーザーが選択したグループ・友だちに対して、ユーザーが送信したかのように投稿することができます。これにより、最小限のユーザーの手間で情報のシェア、拡散を促すことができます。
その他提供されているAPIは以下に記載されています。
利用例
以下では、フロントエンド側でどのようなLIFFの使い方をしているかを説明していきます。導入が非常に簡単であることがわかると思います。
まず、複数のコンポーネントからLIFFのAPIを呼べるようにProviderとHooksを作成します。
なお、今回IDトークンをAPI認証に利用していて、IDトークンの有効期限切れを把握したかったためisExpire関数を定義しています。
import React, { createContext, useContext, useEffect, useState } from 'react';
import type Liff from '@line/liff';
type UseLiff = {
idToken?: string;
initialized: boolean;
isInClient: boolean;
loggedIn: boolean;
closeWindow?: () => void;
isExpire: () => boolean;
login?: () => void;
logout?: () => void;
};
const LiffContext = createContext<typeof Liff>(undefined);
export const LiffProvider: React.FC = ({ children }) => {
const [liff, setLiff] = useState<typeof Liff>(undefined);
useEffect(() => {
(async () => {
const liff = (await import('@line/liff')).default;
await liff.init({ liffId: process.env.NEXT_PUBLIC_LIFF_ID });
setLiff(liff);
})();
}, []);
return <LiffContext.Provider value={liff}>{children}</LiffContext.Provider>;
};
export const useLiff = (): UseLiff => {
const liff = useContext(LiffContext);
if (!liff) {
return {
initialized: false,
isInClient: false,
loggedIn: false,
isExpire: () => false,
};
}
const isExpire = (): boolean => {
if (!liff.isLoggedIn()) {
return false;
}
const expirationTime = liff.getDecodedIDToken().exp;
return expirationTime < Date.now() / 1000;
};
return {
idToken: liff.getIDToken(),
initialized: true,
isInClient: liff.isInClient(),
loggedIn: liff.isLoggedIn(),
closeWindow: liff.closeWindow,
isExpire: isExpire,
login: liff.login,
logout: liff.logout,
};
};
これだけです。
あとは、LIFFのAPIを呼び出したいコンポーネントでuseLiff()を記述し、LIFFの情報を取得したりAPIを呼び出すことができます。
const { idToken, initialized, closeWindow, isExpire } = useLiff();
おわりに
LIFFの概要、できること、利用例を紹介させていただきました。LIFFはフレームワークと言いつつも、少ないコードの変更で部分的に導入できます。サービスがLINE上で利用されることを前提とするのであれば、ユーザーの体験を向上させる手段の一つとしてLIFFが有効だと感じました。
Discussion