【Firebase×BigQuery】FirebaseのImport segmentsを使う

『特定のユーザーに向けて通知を配信する』
という事をやりたくて初めてImport segmentsというFirebaseの機能を使いました。

現在2021年9月18日時点で、まだβの機能。情報が少なくて困ったところもあったので、自分の備忘録のためにメモ。:writing_hand_tone1:

# Import segmentsとは
Firebaseの**Import segments**を活用すれば、Remote Config、 Cloud Messaging、In-App Messagingなどで、ユーザーのグループをターゲットにすることができるようになる。
ユーザー体験を、各ユーザーの特徴に合わせて、簡単にFirebaseコンソール上から調整することが可能になるということ:thumbsup:

# Segmentを利用してやってみたこと
Cloud MessagingでSegmentを条件に通知を配信する事をやってみた。流れとしては以下の通り。

1. BigQueryに存在するSegmentをFirebaseに取り込む（インポートする）
2. FCM(Firebase Cloud Messaging)で通知配信のターゲットの条件にセグメントを指定する
3. セグメントをターゲットの条件に指定して、特定のユーザーのみに通知を送る
![firebaseImportSegment.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266675/fbce9466-7102-6a9b-cdd9-35d560a08b07.png)

# 0.（前準備）FIrebase Cloud Messaging から通知が送れることの確認
Segmentの指定うんぬんの前にまずはCloud Messagingから手元の端末に通知を送ることができるか確認は済ませておきましょう。
既に送れることが確認済みの場合はここはスキップでよい。

1. Cloud Messagingを開き、『通知を作成する』を選択
2. ステップ１の通知のタイトルなどを任意で入れて、『テストメッセージを送信』を選択
![スクリーンショット 2021-07-28 11.23.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266675/b8bf8b8b-13ed-4db9-5043-13ce0c37f42b.png)
3. 『テストメッセージを送信』をタップすると、デバイスでのテストという画面が出るので、ここでテストしたい端末のトークンを追加して『テスト』をタップする
4. アプリに通知が届く。

※登録すると、最近使用したインスタンスIDとして残ってくれるのでトークンの追加は一度で大丈夫。

これでCloud Messagingから通知が送られることは確認ができた。

※トークンの取得は、[Retrieve the current registration token](https://firebase.google.com/docs/cloud-messaging/android/first-message?authuser=0#retrieve-the-current-registration-token)を参考に。
以下のようなコードで簡単に取得できる。

```kotlin
FirebaseMessaging.getInstance().token.addOnCompleteListener(OnCompleteListener { task ->
    if (!task.isSuccessful) {
        Log.w(TAG, "Fetching FCM registration token failed", task.exception)
        return@OnCompleteListener
    }

    // Get new FCM registration token
    val token = task.result

    // Log and toast
    val msg = getString(R.string.msg_token_fmt, token)
    Log.d(TAG, msg)
    Toast.makeText(baseContext, msg, Toast.LENGTH_SHORT).show()
})
```

# 1. BigQueryとFirebaseの連携
FirebaseプロジェクトとそのアプリをBigQueryに連携させる手順は以下のとおり。
ここはすぐできます！:open_hands:

1. Firebaseのコンソールにログイン
2. 設定アイコン をクリックし、[プロジェクトの設定] を選択
3. [プロジェクトの設定] ページで [統合] タブをクリック
4. BigQuery カードで、[リンク] をクリック

↓
↓
↓
リンクが済むと、、、

* BigQuery側に`firebase_imported_segments`というデータセットが作成され、その中に`SegmentMemberships`と`SegmentMetadata`というテーブルが作成される。
* Firebaseは、このデータセットからデータをimportするために少なくとも12時間ごとにジョブを実行する(12時間よりも頻繁にインポートする場合もある)


# 2. BigQueryでSegmentを作成
今回はお試しで「test_label」というSegmentをBigQueryの`firebase_imported_segments`に作成するとする。
以下のように、各テーブルにinsertする。

### SegmentMemberships

```sql
insert into 
`hoge.firebase_imported_segments.SegmentMemberships`(instance_id, segment_labels, update_time) 
values ("xxxxxxxx", ["test_label"], CURRENT_TIMESTAMP())
```

| フィールド | 値 | 説明 |
|:-----------|------------|------------|
| instance_id      |xxxxxxxx| 特定のアプリインストールのFirebaseインストールID|
| segment_labels    | ["test_label"]| そのデバイス（"instance_id"）に含まれているセグメントラベルの配列|
| update_time       |CURRENT_TIMESTAMP()|現在時刻を適当に入れた。古いセグメントメンバーシップをBigQueryから削除するために使用する| 

instance IDの取得については、[クライアントIDを取得する](https://firebase.google.com/docs/projects/manage-installations#kotlin+ktx_1)を参考に。
update_timeには現在時刻を入れています。

### SegmentMetadata

```sql
insert into 
`hoge.firebase_imported_segments.SegmentMetadata`(segment_label, display_name) 
values ("test_label", "セグメントのテスト")
```
| フィールド | 値 | 説明 |
|:-----------|------------|------------|
| segment_label      |test_label| セグメントラベル|
| display_name     |セグメントのテスト| セグメントの人間が読める形式のUIに適した名前。Firebaseコンソールでインポートした際はここの名前が表示される|

:::note warn
SegmentMemberShipsの方に追加するsegment_labelがSegmentMedaDataテーブルに存在しないと、Firebase側でインポートしても反映されないので注意
:::

# 3. BigQueryからSegmentをFirebaseにインポートする（取り込む）
追加したSegmentをFirebaseにimportしたい。
Firebaseは、このデータセットから読み取るために少なくとも12時間ごとにジョブを実行するので放っておいても定期的にimportするが、手動で実行することもできる。

プロジェクトの設定→統合→BigQueryで、一番下に表示されている、**再度インポート**ボタンを押すだけ！！:innocent:
少々時間はかかるが、最大45分以内でimportが完了して、FireBase上で先ほど作成したSegmentを利用できるようになる。
![スクリーンショット 2021-09-17 16.16.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266675/af6de5c6-eb36-e143-c7a9-37b80abf49e6.png)

↓
↓
インポートが完了したら、FirebaseのコンソールでCloud Messagingを開く。通知の作成の中でターゲットを指定する際に、**インポートしたセグメント**を条件に作成した『test_label』のSegmentを指定して完了✨

イメージとしては、Googleアナリティクスのオーディエンスでターゲティングするのと似ている。

# インポートされなくて困った時は
BigQueryにSegment作ってインポートしたはずなのにFirebaseに反映されなくて悩んだ時間がありました。

そんなときは、私は以下の順で確認して最終的には再連携でうまくいきました。
参考までに。🙏

1. SegmentMemberShipのみに存在するラベルになっていないかを確認する。SegmentMetadataテーブルに存在しないラベルの場合、反映されない。
2. 端末のFirebase instance IDをもう一度確認して、テーブルに登録されているか確認する。 

確認する際は以下のようにリスナーを用意すればよい。

```kotlin
FirebaseInstallations.getInstance().id.addOnCompleteListener { task ->
    if (task.isSuccessful) {
        Log.d("Installations", "Installation ID: " + task.result)
    } else {
        Log.e("Installations", "Unable to get Installation ID")
    }
}
```
3.上記どちらも問題ない場合、FirebaseとBigQueryのリンクを一度切り、再連携を試みる（ ← 私はこれで解決しました。原因ははっきりとはよくわからないが、どうしてもインポートに失敗するな〜というときはお試しください。）

# おわり
FirebaseとBigQueryを連携して、独自のユーザーセグメントを簡単に作って、利用できるようになりました。
BigQuery側のデータを変更するだけでユーザーセグメントの作成ができて、アプリに実装を加える必要なくできるところが良い。🙆♥
RemoteConfigやFCMを利用すれば簡単にユーザーのグループ毎に最適なUI表示、通知、機能訴求などを遠隔で柔軟に調整できるので、これから色々活用してみよう。

# 参考文献
[セグメントのインポート](https://firebase.google.com/docs/projects/import-segments)
[Firebase プロジェクトを BigQuery にリンクする](https://support.google.com/firebase/answer/6318765?hl=ja#link&zippy=%2C%E3%81%93%E3%81%AE%E8%A8%98%E4%BA%8B%E3%81%AE%E5%86%85%E5%AE%B9)