LIFF x LINEログイン アンケートフォーム作成

# 前段！
以下のイベントの前段の記事です。LIFFでアンケートフォームを作成し、送信結果をスプレッドシートに蓄積します。

https://linedevelopercommunity.connpass.com/event/292986

###### 動画はこちら！チャンネル登録もポチとお願いします

https://www.youtube.com/watch?v=U2SCbF-djNA

#### 完成イメージ

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/769453b9-6003-636c-0111-37784e0b7d48.png"/>

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/00cd8c34-2f8f-f9ea-f0dd-1afe7a23b1b4.png"/>

公式アカウントだけでは収集できない属性を取得可能となるため、マーケティング等に役立つのではないでしょうか！
アンケートは当該LINEユーザーのUID（識別子）を取得できているため、UIDを指定して属性ごとにメッセージ配信なども可能となります。

:::note info
この前段を実施しない場合は、以下を友達登録していただけるとLINE（LIFF）側のアンケートフォームをお試し頂けます。
＊イベント終了後は削除するかもしれません。

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/ce9533ff-af3f-f9a9-f239-85dce0893d27.png"/>

:::

#### 準備

当ハンズオン内では、 LINE Developers と Replit を使用します。
イベント内ではアカウント作成は致しませんので、必要に応じてご準備ください。

それでは Let's キノコ🍄

# LINE Developersコンソールにログイン

[こちら](https://developers.line.biz/ja/docs/line-developers-console/)

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/c2cc49d7-f006-59ea-7171-9741094bbb2a.png"/>

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/221c0f6d-909b-22ab-8534-bca3814b461c.png"/>


# プロバイダー作成

プロバイダーを作成します。

:::note info
プロバイダー = LINEアカウントを管理するエンティティや組織を指し、個人や企業、団体などが該当する
:::

<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/efa4c46b-77b6-e93c-e82c-a3da2240e97b.png"/>


# LINEログインチャネル作成

続いてチャネルを作成します。

:::note info
チャネル = LINEのサービスと外部サービスやアプリケーションを結びつけるための通信路を指し、LINE Messaging APIを使用するためには、チャネルを作成する必要がある
:::

<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/ef7ac028-24e0-f7b8-0fdf-b7e9a4d4f922.png"/>


以下の設定をし作成

| 項目 | 設定値 | 備考 |
|:-:|:-:|:-:|
| チャネルの種類  | (LINEログイン)  | デフォルト値  |
| プロバイダー  | (作成・選択したプロバイダー)  | デフォルト値 |
| 会社・事業者の所在国・地域   | 日本  |   |
| チャネル名   | まっしゅるセミナーアンケート  |  |
| チャネル説明   | まっしゅるセミナーアンケート  |  |
| アプリタイプ   | ウェブアプリ  |  |

#### LINEログインチャネルの設定
| タブ | 項目 | 設定 |
|:-:|:-:|:-:|
|LINEログイン設定| コールバックURL  | GASデプロイ時に発行されるウェブアプリURL |
| LIFF  | 追加 | あとで追加 |

#### 公開 

「開発中」をクリックし公開

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/5139d9fa-56f9-1acd-d3b2-30e540e6aa82.png"/>

<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/725de465-b473-d0a1-560e-3815b677e938.png"/>



# Messaging APIチャネルを作成

<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/f544c486-38c4-607e-bcf0-925fa30380f5.png"/>

以下を設定し、作成

| 項目 | 設定値 | 備考 |
|:-:|:-:|:-:|
| チャネルの種類  | (Messaging API)  | デフォルト値  |
| プロバイダー  | (作成・選択したプロバイダー)  | デフォルト値 |
| 会社・事業者の所在国・地域   | 日本  |   |
| チャネル名   | まっしゅるセミナーアンケート  |  |
| チャネル説明   | まっしゅるセミナーアンケート  |  |
| 大業種   | 個人  |  |
| 小業種   |　個人（その他）  |   |


#### Messaging APIの設定

Messaging API設定タブよりチャネルアクセストークンを発行する

<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/ce0ae14a-86b8-1c8b-d333-e9e9cc42affc.png"/>

# GASの準備

## スプレッドシートを自身のGoogleドライブにコピー

[こちら](https://docs.google.com/spreadsheets/d/1Y8XlwPMIm1Qtg7hgXKriIDhm5FkEu_SM0tZWuznuuqQ/edit?usp=sharing)

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/37f00996-c482-e6dc-2ac9-c7f5f4bde1e0.png"/>

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/c00268a3-d444-0d86-7c37-e1ee7659605b.png"/>

#### 拡張機能より AppsScriptを起動

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/5f3a3112-7cdb-aac2-ebbc-cb464ef0cbdc.png"/>
<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/7c6df1fa-5365-24b3-c05c-44ab939f2084.png"/>


## GAS

#### スクリプトプロパティを追加

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/34aba2c4-d0c6-6e27-5522-a0f7b300ed58.png"/>

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/d378ddff-5ff5-aa53-8380-9286e6fde562.png"/>

| プロパティ名 | 設定値 | 備考 |
|:-:|:-:|:-:|
| LINE_ACCESS_TOKEN  | Messaging APIで発行したチャネルアクセストークン  |  |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/24941ccf-ff18-7521-1ac0-9d49b824a629.png)


### デプロイ

デプロイを管理よりデプロイ

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/5afb7304-8578-2789-746d-7b00a59316e0.png"/>

デプロイメントの作成（ウェブアプリとしてデプロイ）

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/6f41ce34-6085-7b2c-8f28-b65f61691fbb.png"/>

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/27cc23b4-cd55-ebf0-70e6-5c3eec266fb3.png"/>


| 項目 | 設定値 | 備考 |
|:-:|:-:|:-:|
| 次のユーザーとして実行  | 自分  |  |
| アクセスできるユーザー  | 全員  |  |

#### デプロイ押下後、アクセス承認

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/2853836c-b84e-1233-c4f6-fa1d9a7b65ca.png"/>

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/6cae509b-443e-f8e9-d297-5c659cbdd8ac.png"/>

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/ebae6102-81ae-3335-4b94-c133e510847b.png"/>

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/d14c7165-6f4a-bcbe-1f57-d1f991ce03f6.png"/>

上記 `ウェブアプリURL` は、 Replit の設定、および LINEログイン設定のコールバックURL　に使用

:::note info
再度デプロイする場合は！

「デプロイを管理」から「新バージョン」を選択してデプロイします。「新しいデプロイ」をすると、デプロイ後のウェブURLが変わってしまうので、その際は該当箇所を合わせて修正してください。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/f3b3ed3d-0f8d-0a0a-bfed-e13e06e5a4ab.png"/>

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/59d6d4c4-0c60-1ad7-2f35-ce7da0a679a5.png"/>
:::

#### デプロイURLをコールバックURLに設定

LINEログイン設定にてコールバックURLに設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/6eba6046-ea69-85e8-ca1c-165d2ef805b3.png)


# LIFFアプリの追加

LINEログインに戻り

[参考](https://developers.line.biz/ja/docs/liff/registering-liff-apps/#registering-liff-app)

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/b13058e9-4a9f-c21e-a77a-7a9d74b2cd5c.png"/>

| 項目 | 設定値 | 備考 |
|:-:|:-:|:-:|
| LIFFアプリ名  | まっしゅるセミナーアンケート  |  |
| サイズ  | Tall  |  |
| エンドポイントURL   | Replit デプロイURL  |仮で https://example.com を指定（後ほど更新） |
| Scope   | profile  |  |
| ボットリンク機能   | Off  |  |


LIFFアプリが追加される

<img width="800" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/19db8134-f1d8-8294-4da5-d614a4325cbf.png"/>

# Replit

[Replit ログイン](https://replit.com/)

新規作成にて、 React Javascript を選択し作成

:::note info
Replit を準備していない方は以下のURLを指定を頂くと、アンケート送信までをお試し頂けます。
＊実際の送信データはこちら側のスプレッドシートに蓄積されます。
https://ancke.happy2mylife.repl.co
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/fedac937-b23e-9335-bc53-b81dc972de4c.png)

#### 作成直後

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/b5c4937e-f839-d61d-32bb-228b2e768e30.png)


以下を参考に、 index.html, App.jsx, App.css の３ファイルを修正します。


#### liff sdk 追加

```index.html
<script src="https://static.line-scdn.net/liff/edge/versions/2.12.0/sdk.js"></script>
```

<details><summary>コピペ用</summary>

```
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>まっしゅるアンケート</title>
    <script src="https://static.line-scdn.net/liff/edge/versions/2.12.0/sdk.js"></script>

  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/index.jsx"></script>
		
    <!--
    This script places a badge on your repl's full-browser view back to your repl's cover
    page. Try various colors for the theme: dark, light, red, orange, yellow, lime, green,
    teal, blue, blurple, magenta, pink!
    -->
    <script src="https://replit.com/public/js/replit-badge-v2.js" theme="dark" position="bottom-right"></script>
  </body>
</html>

```

</details>

#### App.jsx 修正

コピペ後、それぞれ設定してください。

```
const LIFF_ID = 【LIFF ID】;
const GAS_URL = 【GASデプロイURL】;
```

<details><summary>コピペ用</summary>

```
import React, { useEffect, useState } from 'react';
import './App.css'

export default function App() {
  const LIFF_ID = 【LIFF ID】;
  const GAS_URL = 【GASデプロイURL】;

  const ageOptions = ['10代', '20代', '30代', '40代', '50代', '60代以上'];
  const genderOptions = ['男性', '女性', 'その他'];
  const courseOptions = ['Aコース(500円)', 'Bコース(1,000円)', 'Cコース(1,500円)'];

  const [name, setName] = useState('');
  const [userId, setUserId] = useState('');
  const [age, setAge] = useState(ageOptions[0]);
  const [date, setDate] = useState('');
  const [gender, setGender] = useState(genderOptions[0]);
  const [course, setCourse] = useState(courseOptions[0]);
  const [otherText, setOtherText] = useState('');

  useEffect(() => {
    liff.init({ liffId: LIFF_ID }).then(() => {
      if (liff.isLoggedIn()) {
        liff.getProfile().then((profile) => {
          setName(profile.displayName);
          setUserId(profile.userId);
        });
      } else {
        liff.login();
      }
    });
  }, []);

  const handleAgeChange = (e) => setAge(e.target.value);
  const handleDateChange = (e) => setDate(e.target.value);
  const handleGenderChange = (e) => setGender(e.target.value);
  const handleCourseChange = (e) => setCourse(e.target.value);
  const handleOtherTextChange = (e) => setOtherText(e.target.value);

  const handleSubmit = (e) => {
    e.preventDefault();

    if (date.length === 0) {
      alert('参加希望日を選択してください。');
      return;
    }
    fetch(GAS_URL, {
      method: 'POST',
      body: JSON.stringify({ userId, name, age, date, gender, course, otherText }),
    })
      .then((response) => {
        if (response.ok) {
          alert('送信しました。');
          liff.closeWindow();
          return response.json();
        } else {
          alert('送信に失敗しました。もう一度お試しください。');
        }
      })
      .then((json) => {
        console.log(json);
      })
      .catch((error) => {
        console.error('Error:', error);
      });
  };

  return (
    <>
      <h1>まっしゅるブラザーズセミナー</h1>
      <div id="profile">お名前： {name}</div>
      <div id="form-container">
        <form id="survey-form" onSubmit={handleSubmit}>
          <label htmlFor="date">参加希望日: </label>
          <input type="date" id="date" name="date" value={date} onChange={handleDateChange} /><br />
          <label htmlFor="age">年代: </label>
          <select id="age" name="age" value={age} onChange={handleAgeChange}>
            {ageOptions.map((ageOption, index) =>
              <option value={ageOption} key={index}>{ageOption}</option>
            )}
          </select><br />
          <label>性別: </label>
          {genderOptions.map((option, index) => (
            <React.Fragment key={index}>
              <input type="radio" id={option} name="gender" value={option} checked={gender === option} onChange={handleGenderChange} />
              <label htmlFor={option} className="gender-label">{option}</label>
            </React.Fragment>
          ))}
          <label htmlFor="course">コース選択: </label>
          <select id="course" name="course" value={course} onChange={handleCourseChange}>
            {courseOptions.map((couseOption, index) =>
              <option value={couseOption} key={index}>{couseOption}</option>
            )}
          </select><br />
          <label htmlFor="text">その他: </label>
          <input type="text" id="text" name="text" value={otherText} onChange={handleOtherTextChange} /><br />
          <button id="submit" type="submit">送信</button>
        </form>
      </div></>
  );
}
```

</details>

#### App.css 修正


<details><summary>コピペ用</summary>

```
.App {
  font-size: xx-large;
  font-family: Arial, sans-serif;
  color: #333;
  height: 100%;
  width: 100%;
  margin: 0;
  padding: 20px;
  background-color: #f4f4f4;
}

h1 {
  color: #555;
  text-align: center;
}

#profile {
  text-align: center;
}

#form-container {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
}

#survey-form {
  width: 60%;
  background: #ffffff;
  padding: 20px;
  border-radius: 5px;
  box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}

button[type="submit"] {
  font-size: 1.5em;
  padding: 10px;
  width: 100%;
  background-color: #4caf50;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  margin-top: 20px;
  transition: background-color 0.3s;
}

button[type="submit"]:hover {
  background-color: #45a049;
}

label,
input,
select {
  margin: 10px 0;
  display: block;
}

input[type="radio"] {
  display: inline-block;
}

.gender-label {
  display: inline-block;
  margin-left: 5px;
  margin-right: 15px;
}
```

</details>


#### 実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/9aa94fb9-21eb-a73b-8c44-c7e81c2d3763.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/fc2e4005-7d3c-1cf5-bff2-cdf21d88ce46.png)

#### LIFF エンドポイントURLに設定

上記 Replit のデプロイURLをエンドポイントURLに設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/140e3406-285a-4d15-ae70-dd4a93e98de3.png)



# リッチメニュー作成

[LINE Official Account Manager](https://manager.line.biz/)

#### メニュー - トークルーム管理 からリッチメニューを選択

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/4b0a3ac4-a4dd-8a73-a508-9f44a40c6ffc.png"/>

#### タイトルやメニュー表示期間を設定

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/fae55187-1565-104b-8d1a-1b2da99f7ee8.png"/>

#### テンプレートと画像の設定

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/7d434589-9137-4e24-89be-3162f0d92a65.png"/>

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/a0667119-7c64-a05f-defd-96d6a71dacae.png"/>

画像をアップロードすることも可能ですが、ここでは直接画像を作成します。

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/a0d02aa4-02b3-1ea2-85fd-256c29331f25.png"/>

#### アクションの設定

| 項目 | 設定 |
|:-:|:-:|
| タイプ  | リンク  |
| URL  | LIFF URL  |
| アクションラベル  | アンケート  |

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/0e469c4d-4da6-27ed-b3cb-03fe01d56adc.png"/>

設定したら保存

# ボット友達追加

Messaging APIの設定より

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/a6f76110-7834-aaa3-edfa-adcdcfe08bb6.png"/>

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/6929e8bc-952a-44e6-6821-8091a03d2f30.png"/>

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/9335f58b-fdbf-4dc7-8e38-e7ad014a139b.png"/>

- LINEログインにて自動的にログイン

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/399259a2-1112-5459-e631-2325442a8b22.png"/>


<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/cb04599e-97ad-af03-f22e-2e9fe462854f.png"/>

- 許可設定

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/fedef412-03b6-6cde-5c66-8613296fc0df.png"/>

- アンケートフォーム
    - `お名前` にユーザーの名前が表示されていることが分かる
    
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/769453b9-6003-636c-0111-37784e0b7d48.png"/>


- 送信完了＆LINEに申し込み内容が通知される

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/c1e26eb6-4b64-a4f5-6572-a9d4e026a2ea.png"/>

<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/a818437f-8ea6-3f23-b6dd-584c492a11cc.png"/>

- スプレッドシートに記録されていく

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/00cd8c34-2f8f-f9ea-f0dd-1afe7a23b1b4.png"/>


# ということで

続いて、Google Looker StudioにてLet's集計！！

https://qiita.com/specialman9999/private/ebb8ef728570ada85e4a