Cloud Functions for Firebaseを使ってアプリ内課金の発生を検知してSlack通知する
FirebaseのCloud Functionsは、Firebase内のイベントとお手軽に連携することができます。
今回は、Analyticsイベントの発火を検知して、Cloud FunctionsからSlack通知してみましょう。
セットアップ
- Nodeが必要なので、インストール。
- Firebase Cloud FunctionsはNode8とNode10が動きます
- でも、Node8のサポートは2020/03で終了したので、Node10を利用しましょう
- ただし、 Node10でCloud Functions for Firebaseを利用するには、プランをBlazeにする必要があるので注意
- Firebase Cloud Functionの 公式ドキュメント から、Firebase CLIをインストールしましょう
$ npm install -g firebase-tools
- FirebaseCLIでFirebaseにログイン
$ firebase login
- ログインできていることを確認
$ firebase projects:list
- ディレクトリに移動してfunctionsを初期化
$ firebase init functions
-
Create a new project
を選択するとProjectから生成してくれる。手順に従って進む。 - ProjectIDとNameを登録し、TypeScriptかJavaScriptを選択。TSLintを利用するかどうかも聞かれる
- npmの依存をインストールするかどうかを聞かれる。yarnを利用したい場合は、No
- 初期設定できたら、
firebase.json
.firebaserc
を確認- [ ポイント] もし複数環境を切り替えたい場合、"dev": "sandbox-dev-hoge" のようにdefaultの横に足してあげると良い
- functionsディレクトリが生成されていて、そこにfunctions関数のソースコードがある。開発はこの中で行う
- デプロイは
firebase deploy --only functions
- 管理画面にも今作ったfirebaseプロジェクトができているはず
アプリ内課金イベントを検知する
アプリ内課金のAnalyticsイベントは、デフォルトで設定されており、Firebase Analyticsが自動で検知して収集してくれます。
複数の課金商品がある場合などは、独自に設定しましょう。
Analyticsイベントとの連携方法
- 公式SampleCode https://github.com/firebase/functions-samples/blob/master/coupon-on-purchase/functions/index.js
Firebase Analytics のイベント連携 ドキュメント より以下を引用
Cloud Functions では、Google アナリティクスの AnalyticsEvent がサポートされています。このイベントは、ユーザー アクティビティでコンバージョン イベントが生成されるたびにトリガーされます。たとえば、in_app_purchase イベントが生成されるとトリガーされる関数を作成して、アプリ内購入が行われたことを示すことができます。functions.analytics.event() メソッドを使用して関数をトリガーするアナリティクス イベントを指定し、onLog() イベント ハンドラ内でイベントを処理する必要があります。
つまり、 functions.analytics.event('in_app_purchase').onLog((event) => { ... }
と書くことで、イベント連携ができます。
実装する
- SlackのIncoming Webhook URLを生成して取得
- add package
$ npm install request @types/request
- firebase functions:config:set slack.url="URLを入れる"
- これはコード内でfunctions.config().slack.urlとして参照できる
- 以下を実装
- .region("asia-northeast1") とつけて東京リージョンを指定
- 引数のeventのなかに情報が入っている
- .analytics.event("in_app_purchase_coins") には、監視したいイベントを指定する
import * as functions from "firebase-functions";
import * as request from "request";
exports.sendSlackMessageOnPurchaseCoin = functions
.region("asia-northeast1")
.analytics.event("in_app_purchase_coins")
.onLog((event) => sentMessageToSlack(event, "コインが購入されました"));
exports.sendSlackMessageOnPurchaseSubscription = functions
.region("asia-northeast1")
.analytics.event("in_app_purchase_subscription")
.onLog((event) => sentMessageToSlack(event, "サブスクが購入されました"));
const sentMessageToSlack = (
event: functions.analytics.AnalyticsEvent,
message: string
): request.Request => {
const url = functions.config().slack.url;
const user = event.user;
const purchaseValue = event.valueInUSD; // Amount of the purchase in USD.
const userLanguage = user?.deviceInfo.userDefaultLanguage; // The user language in language-country format.
const screenName = event.params["firebase_screen_class"];
return request.post(url, {
json: {
text:
`${message}💰 $${purchaseValue} \n` +
"```\n" +
`at time: ${event.logTime} \n` +
`lang: ${userLanguage} \n` +
`country: ${event.user?.geoInfo.country} \n` +
`model: ${event.user?.deviceInfo?.mobileModelName} \n` +
`appId: ${event.user?.appInfo?.appId} \n` +
`appVersion: ${event.user?.appInfo?.appVersion} \n` +
`screen: ${screenName} \n` +
"```\n",
},
});
};