試した動機

クライアントサイドはAPIのアクセスログやらを直接触る機会がないと思いますが、ふとユーザーの垂れ流しになっているイベントログを使ってあそんでみたいなと思ったのがきっかけです。

なので色々探したところ、FirebaseAnalyticsでイベント計測をしてCloud Functionsで出力をする方法が見つかったので、そちらの手段を紹介します。

Analyticsにイベントを送信する方法はiOSで書きますが、イベント送信処理以降はAndroidも同じようにできるので、参考にしていただければと思います。

軽くFirebaseなどの紹介

Googleのサービスはとにかくドキュメントを読み込むことをおすすめします。

Firebase Analytics

紹介すら不要なAnalyticsです。

Webでよく使われるGoogle Analyticsとは別サービスな印象です。

Firebase Cloud Functions

このサービスが今回肝になります。

現在Beta版ではありますが、全く問題なく使えました。

このサービスを使って、Firebase Analyticsからイベントログを受け取って好き勝手するという目標が叶えられました。

環境構築の前に、勉強になったらサンプル集を紹介したいと思います。

Firebase Cloud Functionsのサンプル紹介

これがものすごく勉強になりました。

特に参考になったものをピックアップします。

課金イベントが発生したらpush通知でクーポンを送信する

Firebase Analyticsin_app_purchaseイベントが送信されたら、課金した金額に応じてクーポンをPush通知で送信するサンプルです。

これをみて、Firebase Analyticsのイベントからの受け取り方を知りました。

GithubのWebhookをHTTPsで受け取ってSlackに送信する

HTTPSのエンドポイントをFirebase Cloud Functionsで作るサンプルです。

Storageに画像が保存されたらCloud Vision APIでチェックして必要であればモザイクかける

タイトルのまんまですが、Storageに画像が保存されたらCloud Vision APIでチェックしてアダルト or グロ判定だった場合、保存された画像にモザイク処理を施すという処理のサンプルです。

上記の他にもたくさんサンプル置いてあるので、1度全部見に行くと楽しい気持ちになれると思います。

それでは早速環境構築から進めて行きたいと思います。

Firebase Cloud Functionsのコードを書く

Firebaseのアカウントとプロジェクトはできている前提で話を進めます。

まだの方は以下のFirebaseのドキュメントを参考に作成してください。

iOS用

Android用

それでは進めて行きます。

環境構築

以下の環境で進めて行きます。

Cloud Functions

node.js: 8.1.4
npm: 5.4.0

ディレクトリ作ります。

$ mkdir SampleCloudFunctions
$ cd SampleCloudFunctions

まずはFirebaseを作成したアカウントでログインしてください。

$ firebase login
? Allow Firebase to collect anonymous CLI usage information? Yes

Visit this URL on any device to log in: ${認証URL}

Waiting for authentication...

✔  Success! Logged in as ryo.kosuge@gmail.com

アカウントミスった場合は

$ firebase logout
✔  Logged out from ryo.kosuge@gmail.com

と実行すればログアウトできるので、違うアカウントで認証してください。

ではFunctionsの環境構築して行きます。

ScreenShot1

firebase initを実行します。

$ firebase init

     🔥🔥🔥🔥🔥🔥🔥🔥 🔥🔥🔥🔥 🔥🔥🔥🔥🔥🔥🔥🔥  🔥🔥🔥🔥🔥🔥🔥🔥 🔥🔥🔥🔥🔥🔥🔥🔥     🔥🔥🔥     🔥🔥🔥🔥🔥🔥  🔥🔥🔥🔥🔥🔥🔥🔥
     🔥🔥        🔥🔥  🔥🔥     🔥🔥 🔥🔥       🔥🔥     🔥🔥  🔥🔥   🔥🔥  🔥🔥       🔥🔥
     🔥🔥🔥🔥🔥🔥    🔥🔥  🔥🔥🔥🔥🔥🔥🔥🔥  🔥🔥🔥🔥🔥🔥   🔥🔥🔥🔥🔥🔥🔥🔥  🔥🔥🔥🔥🔥🔥🔥🔥🔥  🔥🔥🔥🔥🔥🔥  🔥🔥🔥🔥🔥🔥
     🔥🔥        🔥🔥  🔥🔥    🔥🔥  🔥🔥       🔥🔥     🔥🔥 🔥🔥     🔥🔥       🔥🔥 🔥🔥
     🔥🔥       🔥🔥🔥🔥 🔥🔥     🔥🔥 🔥🔥🔥🔥🔥🔥🔥🔥 🔥🔥🔥🔥🔥🔥🔥🔥  🔥🔥     🔥🔥  🔥🔥🔥🔥🔥🔥  🔥🔥🔥🔥🔥🔥🔥🔥

You're about to initialize a Firebase project in this directory:

  /Users/nagisa-kosuge/Workspaces/Blog/Node/SampleCloudFunctions

? Which Firebase CLI features do you want to setup for this folder? Press Space to select features, then Enter to confirm your choices. (Press <space> to select)
❯◯ Database: Deploy Firebase Realtime Database Rules
 ◯ Functions: Configure and deploy Cloud Functions
 ◯ Hosting: Configure and deploy Firebase Hosting sites

と表示されるのでカーソルキーでFunctionsを選択してください。

選択すると以下のようにプロジェクトを選ぶように迫られます。

=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add,
but for now we'll just set up a default project.

? Select a default Firebase project for this directory:
  [don't setup a default project]
❯ SampleCloudFunctions (samplecloudfunctions)
  [create a new project]

作っていない場合はここで[create a new project]しても大丈夫です。

今回はSampleCloudFunctionsを選択します。

$ firebase init functions

     🔥🔥🔥🔥🔥🔥🔥🔥 🔥🔥🔥🔥 🔥🔥🔥🔥🔥🔥🔥🔥  🔥🔥🔥🔥🔥🔥🔥🔥 🔥🔥🔥🔥🔥🔥🔥🔥     🔥🔥🔥     🔥🔥🔥🔥🔥🔥  🔥🔥🔥🔥🔥🔥🔥🔥
     🔥🔥        🔥🔥  🔥🔥     🔥🔥 🔥🔥       🔥🔥     🔥🔥  🔥🔥   🔥🔥  🔥🔥       🔥🔥
     🔥🔥🔥🔥🔥🔥    🔥🔥  🔥🔥🔥🔥🔥🔥🔥🔥  🔥🔥🔥🔥🔥🔥   🔥🔥🔥🔥🔥🔥🔥🔥  🔥🔥🔥🔥🔥🔥🔥🔥🔥  🔥🔥🔥🔥🔥🔥  🔥🔥🔥🔥🔥🔥
     🔥🔥        🔥🔥  🔥🔥    🔥🔥  🔥🔥       🔥🔥     🔥🔥 🔥🔥     🔥🔥       🔥🔥 🔥🔥
     🔥🔥       🔥🔥🔥🔥 🔥🔥     🔥🔥 🔥🔥🔥🔥🔥🔥🔥🔥 🔥🔥🔥🔥🔥🔥🔥🔥  🔥🔥     🔥🔥  🔥🔥🔥🔥🔥🔥  🔥🔥🔥🔥🔥🔥🔥🔥

You're about to initialize a Firebase project in this directory:

  /${ディレクトリ名}/SampleCloudFunctions


=== Project Setup

First, let's associate this project directory with a Firebase project.
You can create multiple project aliases by running firebase use --add,
but for now we'll just set up a default project.

i  .firebaserc already has a default project, skipping

=== Functions Setup

A functions directory will be created in your project with a Node.js
package pre-configured. Functions can be deployed with firebase deploy.

✔  Wrote functions/package.json
✔  Wrote functions/index.js
? Do you want to install dependencies with npm now? Yes
npm notice created a lockfile as package-lock.json. You should commit this file.
added 201 packages in 6.342s

i  Writing configuration info to firebase.json...
i  Writing project information to .firebaserc...

✔  Firebase initialization complete!

という風に初期設定が完了しました。

以下のようにファイルが生成されていると思います。

$ tree -L 2
.
├── firebase.json
└── functions
    ├── index.js
    ├── node_modules
    ├── package-lock.json
    └── package.json

2 directories, 4 files

もしできていない場合はプロジェクトのプランが無料になっているのが原因だと思います。

のでプロジェクトのコンソールの左下にプラン表示をSparkからBlazeに変更してください。

ScreenShot2

クレジットカード登録等ありますが、今回のFunctionsは200万リクエストまで無料なので、超えることはないと思います。

また他のFirebaseのサービスを使う際にもクレジットカード必須のものもあるので、しておいた方が無難かと思います。

ではFirebase Analyticsからカスタムイベントを受け取ってログを出力するソースコードを書いて行きます。

Firebase Analyticsのカスタムイベントを受け取るソースコード

以下のように作りました。

const functions = require('firebase-functions');

// // Create and Deploy Your First Cloud Functions
// // https://firebase.google.com/docs/functions/write-firebase-functions
//
// exports.helloWorld = functions.https.onRequest((request, response) => {
//  response.send("Hello from Firebase!");
// });

const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

// [START all]
// [START trigger]
exports.outputEventLog = functions.analytics.event('button_tap').onLog( event => {
// [END trigger]
    console.log(event);
})
// [END all]

button_tapというイベントが発生したらconsole.log(event)するという簡単な処理です。

このeventという値に色々なパラメーターが付いています。

後で紹介するので、今はこのままにしておいてください。

補足

以下の2行は他のFirebaseのサービスを使う際に必要な処理になります。

const admin = require('firebase-admin');
admin.initializeApp(functions.config().firebase);

ので、今回はいらない(必要ない)ですが、例えばカスタムイベントを受け取ってPush通知を送りたいなど他のサービスを使用する際は必須となりますのでお気をつけください。

Firebase Cloud Functionsにデプロイする

以下のコマンドでデプロイします。

$ firebase deploy

=== Deploying to 'samplecloudfunctions'...

i  deploying functions
i  functions: ensuring necessary APIs are enabled...
i  runtimeconfig: ensuring necessary APIs are enabled...
✔  runtimeconfig: all necessary APIs are enabled
✔  functions: all necessary APIs are enabled
i  functions: preparing functions directory for uploading...
i  functions: packaged functions (14.49 KB) for uploading
✔  functions: functions folder uploaded successfully
i  starting release process (may take several minutes)...
i  functions: creating function outputEventLog...

✔  functions[outputEventLog]: Successful create operation.
✔  functions: all functions deployed successfully!

✔  Deploy complete!

Project Console: https://console.firebase.google.com/project/samplecloudfunctions/overview

deployが完了したら、管理画面をリロードしてみてください。

以下のようになっていたら成功です。

ScreenShot3

ではイベントを送信するアプリを作ってみようと思います。

Firebase Analyticsに値を送る

初期設定はドキュメントをみてやってください。

環境は以下になります。

iOS

Xcode: 8.3.3
iOS SDK: Latest iOS (iOS 10.3)
iOS Deployment Target: iOS 8.0

サンプルプロジェクトは以下のレポジトリに置いておきました。

実装を進めて行きます。

UIButton配置してイベントを送る

以下のようなUIViewControllerを継承したクラスを作りました。

import UIKit
import FirebaseAnalytics

class ViewController: UIViewController {

    @IBOutlet weak var button: UIButton?

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    @IBAction func tappedButton(_ button: UIButton) {
        Analytics.logEvent("button_tap", parameters: nil)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

ほぼ初期状態です。

画面の中央にボタンを配置しました。

@IBAction func tappedButton(_ : UIButton)が呼ばれたらCloud Functionsで指定したイベントを送信するだけのものになります。

DebugViewレポートの設定方法

Analyticsのイベントログが管理画面に反映されるようになるまで最大で24時間ほどかかるらしいです。

なので、しっかり送れているかの確認が後手に回ってしまいます。

しかし、DebugViewレポートを使えばリアルタイムに送信されているかどうかがわかるようになりますので、それの設定方法を紹介します。

まずは以下のようにEdit Scheme…を開きます。

ScreenShot4

以下の様にArguments Passed On Launch-FIRDebugEnabledを入れてください。

ScreenShot5

この状態で再度ラン(Cmd + R)すると、ログがいっぱい出力されます。

その状態で**DebugViewレポートの管理画面に行くとログが出力されると思います。

ScreenShot6

蛇足でしたが、便利な機能の紹介でした。

Cloud Functionsで値を受け取るためにイベントをコンバージョンとして設定する

イベントが反映されるのが、最大1日なのですぐにはできないですが、反映されたあとの必要な設定を説明します。

私自身これに気がつくのに小一時間あれじゃない、これじゃないと格闘しました。

詳しくはドキュメントに書いてありますので、そちらをご覧ください。

このまま設定方法をスクショと一緒に紹介して行きます。

コンバージョンマークをつける

ScreenShot7

イベントの左にswitcherがあるので、それをOnにします。

ScreenShot8

これで準備完了です。

実際にログを確認する

あとは用意した端末でCloud Functionsで受け取る任意のログイベントを送信して管理画面で計測が上がっていれば成功です。

ScreenShot9

少しラグがありますが、以下のように表示されているかと思います。

ScreenShot10

反映が遅い場合はデバッグモードのせいもあるので、上記で書いたDebugViewレポートで設定した-FIRDebugEnabledのチェックを外して、再インストールするなりすると値が反映されるかと思います。

Firebase Analyticsで設定しているユーザープロパティや、イベントのパラメーターなどの参照方法は以下を参考にしてください。

最後に

リアルタイムでAnalyticsのイベントを取得できるとクライアントサイドでもできることの夢が広がるかと思います。

サーバーのログを扱いたいけど簡単に扱えない人はまずAnalyticsCloud Functionsでイベントログを集計してみるというのも1つの手段になるかと思います。

私はこちらのログからユーザーレコメンドのサンプルを作って社内LT大会で発表しました。

そこらへんも別途記事に書けたらなと思います。

以上になります。