弊社で作っている feather for Twitter(以下 feather) には最近サポータープランという課金機能を追加しました。
課金されたときに Slack に通知が来たら楽しいなと思い実装してみました。
課金されると以下のような形で Slack に投稿されます。
構成と処理の流れ
feather には Google Analytics が組み込んでありますので課金アイテムが購入されたときには in_app_purchase
のイベントが発生するのでそれをトリガにして firebase functions を実行します。
Slack に通知されるまでの処理の流れは以下のとおりです。
- feather (iOS App) で購入が行われる
- Google Analytics に
in_app_purchase
イベントが記録される- 特に何も実装しなくても自動的に記録されます(便利)
- firebase functions で
in_app_purchase
をトリガにしているコードが実行される- コードは後述
- Slack に通知される
firebase functions のコード
functions.analytics.event("in_app_purchase").onLog()
を使用すると Analytics の購入イベントをトリガにした functions を作れます。
export const inAppPurchase = functions.analytics .event("in_app_purchase") .onLog(async (event) => { const { WebClient } = await import("@slack/web-api") const client = new WebClient(slackToken) // Slack に通知する処理 return onInAppPurchase(event, client.chat) })
参考: https://firebase.google.com/docs/analytics/extend-with-functions
event の中身
onLog
ので得られる event
の中身はかなりざっくりとした型定義しか無いので実際に何が入ってくるかはよくわかりません。
実際に来たイベントを log してみると以下のようなものが得られます。
- 例
event.valueInUSD
は USD ですがevent.params["price"]
を使うとローカライズされた金額(currencyが JPY なら円)が入ってきます。event.params["product_name"]
にはローカライズされた商品名が入ってきます
全体(値は適当に伏せています):
onInAppPurchase.event AnalyticsEvent = { params: { currency: 'JPY', engaged_session_event: 1, firebase_conversion: 1, firebase_event_origin: '', firebase_screen_class: '', firebase_screen_id: number, ga_dedupe_id: number, ga_session_id: number, ga_session_number: number, price: number, product_id: 'product_id', product_name: '商品名', quantity: number, session_duration: number, subscription: number, validated: number, value: number }, name: 'in_app_purchase', valueInUSD: number, reportingDate: '20211129', logTime: '2021-11-29T01:33:00', user: UserDimensions { deviceInfo: { deviceCategory: 'mobile', deviceId: 'string', deviceModel: 'iPhone13,2', deviceTimeZoneOffsetSeconds: 0, limitedAdTracking: true, mobileBrandName: 'Apple', mobileMarketingName: 'iPhone', mobileModelName: 'iPhone', platformVersion: '15.1.1', userDefaultLanguage: 'ja-jp' }, geoInfo: { city: 'HogeHoge City', continent: '000', country: 'Japan', region: 'Tokyo' }, appInfo: { appId: 'appId', appInstanceId: '', appPlatform: 'IOS', appStore: 'iTunes', appVersion: '4.0.0' }, firstOpenTime: 'date', userProperties: { // アプリで指定した userProperties // https://firebase.google.com/docs/analytics/user-properties?platform=ios }, bundleInfo: ExportBundleInfo { bundleSequenceId: number, serverTimestampOffset: number } } }
"in_app_purchase" の注意点
in_app_purchase
は本番環境のアプリ(AppStoreからのもの)の場合にのみイベントが発火します。 TestFlight などの SandBox 環境から課金された場合にはイベントは発生しません。
firebase analytics 的にはイベントが発生しているため Dashboard に値が反映されるのですが、 functions は発火しないので注意しましょう。
このため、先に述べた event
の中身にどういったものが入っているのかはアプリをリリースして課金が発生するまでわかりませんでした。
Slack に投稿している内容
以下のような内容で Slack に post しています。 feather のサポータープランには高額のマハラジャという概念があるのでマハラジャの人が購入した際には見分けやすいように色を変えています。
const options: ChatPostMessageArguments = { channel: featherNotifySlackChannel, as_user: true, text: isMaharaja ? "マハラジャが購入しました" : "購入されました👏", attachments: [ { color: isMaharaja ? "good" : undefined, fields: [ { title: "商品", value: product }, { title: "価格", value: `${price} [${currency}]` }, { title: "言語", value: userDefaultLanguage, }, { title: "OS", value: osVer, short: true }, { title: "App Ver", value: featherVer, short: true }, ], }, ], } await client.postMessage(options)
まとめ
iOS アプリでアプリ内課金が発生した際に Google Analytics と firebase functions を使ってSlack に投稿する方法について紹介しました。
この通知は大量に購入される商品に対して行うと Slack への投稿が大量になり大変なことになってしまうと思うので、適用できる範囲は限られると思いますが、それほど頻度が高くない場合にはテンションを上げる効果があると思うのでおすすめです。