ReactNative with Expo にFirebase Analyticsを導入して、BigQueryに連携して、DataPortalでダッシュボードを作った話

タイトル通りなのですが、ReactNative with Expo で開発をしているiOS, AndroidアプリにFirebase Analyticsを導入しました。さらに、BigQueryに連携して、DataPortalでダッシュボードを作りましたので、その一連の流れをまとめておきたいと思います。

## 成果物
対象は[ヒンディー音読](https://takuya0206.hateblo.jp/entry/developed_Hindi_readaloud_app)という、ヒンディー語の音読 / リピーティング / シャドーイング が簡単に練習できるアプリケーションです。以下のように、画面ごとに「どのボタンがどのぐらいタップされているか？」「どのコンテンツがどのぐらい学習されているか？」を見えるようにしました。
※スクリーンショットの数値はデバッグ時に私が踏んだものです

![プレイ画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147086/2b0e89f0-8a82-dc15-aa73-01e867f29e42.png)
![設定画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147086/25e29b9b-11ee-41d4-5a6c-f1fd7d27be2e.png)

画面のスクリーンショットに紐づけてタップ数を表示しているため、直感的にわかりやすく、またダッシュボード上で表示期間や比較期間を選べるようにしているので、改善の為の定量的分析が非常にやりやすいです。

## 構成
- [Firebase Analytics](https://firebase.google.com/products/analytics)
- [Google Analytics](https://analytics.google.com/analytics/web/)
- [BigQuery](https://cloud.google.com/bigquery)
- [DataPortal](http://datastudio.google.com/?utm_source=hc&utm_medium=button&utm_campaign=about-datastudio&utm_content=access-ds-now#/navigation/reporting)

Firebaseを起点に各アプリケーション・サービスを連携させていきます。個人開発では無料枠の範囲に収まると思うので、費用の負担はなく構築が可能です。
![ダッシュボード構成.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147086/434eac77-b75c-d1e1-ee4f-45e5352b5d7d.jpeg)

## 導入手順
### 1. Expo に FirebaseAnalytics を導入する
基本的には[公式ドキュメント](https://docs.expo.io/guides/setup-native-firebase/)通りに進めるだけです。ただし、開発時にローカルでExpoを通じてアプリを起動させるときは、Webアプリケーションとして設定されていないと収集できないようになっています。そのため、ローカルで動作確認などを行いたい場合のapp.jsonは次のようになります。

```app.json
    "ios": {
      "bundleIdentifier": "<あなたのbundleId>",
      "googleServicesFile": "./GoogleService-Info.plist"
    },
    "android": {
      "package": "<あなたのpackage>",
      "googleServicesFile": "./google-services.json",
      "versionCode": 1
    },
    "web": {
      "config": {
        "firebase": {
          "appId": "<あなたのappId>",
          "apiKey": "<あなたのapiKey>",
          "measurementId": "<あなたのmeasurementId>"
        }
      }
    }
```

### 2. UserIdを記録する
ユーザーIDが付与されるアプリケーションであれば、それをそのまま記録すれば良いでしょう。一方で、ログインなしで使用できるアプリケーションもあるかと思います。私のアプリがそうで、その場合は端末固有のIDを記録しておきたいところなのですが、`Constants.installationId`には以下のように記載があり、別の手段を使う必要があります。

>[Constants.installationId](https://docs.expo.io/versions/v42.0.0/sdk/constants/#constantsinstallationid)
>This property is deprecated and will be removed in SDK 44. Please implement it on your own using expo-application's androidId on Android and a storage API such as expo-secure-store on iOS and localStorage on Web.

調べてみると、[Application](https://docs.expo.io/versions/latest/sdk/application/)に使えそうなAPIがありました。Androidの場合は`Application.androidId`、iOSの場合は`Application.getIosIdForVendorAsync()`でユニークなIDが取得できそうです。ただし、永続的にユニークというわけではないので注意が必要です。[GitHubのIssue](https://github.com/expo/expo/issues/6398)でこれらのAPIに対しての質疑がありました。ともあれ、コードは以下のようになりました。


```analyzeLog.ts
import * as Device from 'expo-device'
import { androidId, getIosIdForVendorAsync } from 'expo-application'
 
export const logUserId = async (): Promise<void> => {
  if(Device.osName === 'iOS' || Device.osName === 'iPadOS') {
    const iosId = await getIosIdForVendorAsync()
    await Analytics.setUserId(iosId)
  } else if (Device.osName === 'Android') {
    await Analytics.setUserId(androidId)
  } else {
    await Analytics.setUserId('null')
  }
}
```

あわせて`UserProperty`を記録すると良いですが、私のアプリでは該当の情報が存在しないため割愛します。

### 3. スクリーンの遷移を記録する
これまでGoogle AnalyticsでWebのログ解析をしていた人にとっては驚くところではないでしょうか。FirebaseAnalyticsでは各ページごとに遷移の記録を実装しなければいけません。[React Navigation](https://docs.expo.io/versions/latest/sdk/firebase-analytics/#react-navigation)を使っている人は、それぞれのページに仕込まなくても良いそうです。が、私は残念ながらこれに気づかず普通に各スクリーンごとに書いてしまいました。とほほ。

```analyzeLog.ts
export const logCurrentScreen = async (name: screenNameType): Promise<void> => {
  await Analytics.setCurrentScreen(name)
}
```
```Setting.ts
useEffect(() => {
  // ログ用
  logCurrentScreen('Setting')
}, [])
```

### 4. イベントを記録する
追跡したいイベント（=ユーザーの行動）に対して、ログ取得のコードを書いていきましょう。どのようにログを取得するべきかはアプリの内容や分析したい箇所によって異なると思いますが、Firebase Analyticsで推奨されているイベントがいくつか用意されていまして、利用できるところは推奨のものを利用すると良さそうです。 → [[GA4] 推奨イベント](https://support.google.com/analytics/answer/9267735)
私は言語学習のアプリだったので、一般的なボタンタップのイベントに合わせて、具体的な学習内容を記録するようにしました。

```analyzeLog.ts
export const logLearningEvent = async (unitId: string, practice: practiceListProperty ):Promise<void> => {
  await Analytics.logEvent('learningEvent', {
    unitId,
    practiceTitle: practice.practiceTitle,
    speaker: practice.Ja_speaker
  })
}
```

### 5. FirebaseとBigQueryを連携する
ここまで来ると、FirebaseまたはGoogle Analytics上で取得したログを見ることができるようになっています。レポートをカスタマイズすることもできるので、ユーザーの属性などの情報を簡単に得ることができます。一方で、ダッシュボードとしては使いづらいところがあります。また、取得したイベントのログを全て閲覧することはできません。そこで、FirebaseとBigQueryを連携させることで、より詳細なデータ分析ができるようになります。連携自体はそこまで難しいものではなく、[公式ドキュメント](https://support.google.com/firebase/answer/6318765?hl=ja#)を読みながらクリックしていくだけで出来るはずです。

![スクリーンショット 2021-07-24 21.51.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147086/b35401f9-7919-03f8-e6cb-7eefe10a0757.png)

### 6. BigQueryでクエリを書く
実施したいデータ分析の内容に応じてクエリを書いていきましょう。...と言いつつ、私はここの工程は特に何もしませんでした。私が成果物のところに貼ったダッシュボード程度であれば、rawデータをそのままDataPortalに接続しても作成することが可能です。より詳細な分析をしたい方のみ対応ください。この記事が参考になりそうでした。 → [Firebaseで取得したログをBigQueryに連携してユーザー操作をトラッキングする](https://future-architect.github.io/articles/20210316/#3-BigQuery%E3%81%A7%E3%82%AF%E3%82%A8%E3%83%AA%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B)

### 7. BigQueryとDataPortalを連携する
![スクリーンショット 2021-07-24 21.59.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147086/dce73017-219a-c428-ae93-58be44b86077.png)
「データを追加」をクリックすると上記のような選択肢がせり上がってきます。ここにBigQueryが含まれているので、後は順番にクリックしていくだけです。連携自体は非常に簡単にできるのですが、DataPortalそのものは使用に癖があるので慣れるまで大変かもしれません。
BigQueryのrawデータをそのままDataPortalに接続した場合、以下のようなフィールドの構成になっていて、ネストされているパラメーターをそのままディメンションに使用することが出来ません。

- Event Name
- Event Param Name
- Event Param Value
- Event Param Value (String)

実は私もDataPortalのベストプラクティスがよくわかっていないのですが、私のアプリはイベント設計がとてもシンプルになっているので、フィルタを活用することで必要なデータを表示しています。例えば、Setting画面のページビューを表示するのであれば、`Event Param Name`が `firebase_screen`になっているイベントの`Event Param Value (String)`が`Setting`になっているSUMを表示すれば良いです。なので、以下のように`Event Param Value (String)`でフィルタをかけることによって、該当の数字以外を除外してスコアカードの中に表示するようにしています。

![スクリーンショット 2021-07-24 22.07.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147086/3c2d1931-b5ac-b108-2e5a-076280c49dd3.png)

## 終わりに
というわけで、私がReactNative with Expo で開発したアプリに、Firebase Analyticsを導入して、BigQueryに連携して、DataPortalでダッシュボードを作った話でした。おそらく他にもっと良いやり方はあると思うのですが、私の使用用途に対してはこれで十分必要なデータが見れているので、これで良しとします。ではでは。

![プレイ画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147086/2b0e89f0-8a82-dc15-aa73-01e867f29e42.png)
![設定画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147086/25e29b9b-11ee-41d4-5a6c-f1fd7d27be2e.png)