asken テックブログ

askenエンジニアが日々どんなことに取り組み、どんな「学び」を得ているか、よもやま話も織り交ぜつつ綴っていきます。 皆さまにも一緒に学びを楽しんでいただけたら幸いです!

モバイルのカスタマーレビュー通知システムを作ってみた

はじめに

こんにちは。モバイルのテックリードの大澤です。 普段はあすけんのAndroid/iOSアプリを開発しています。

モバイルアプリをよくするためにユーザーの声を聞き、改善に繋げる必要があります。

その中でも、App StoreやGoogle Playに投稿されるカスタマーレビューは貴重なデータとなります。

本記事では、モバイルアプリのカスタマーレビューを通知するシステムをなぜ作ったか、どのように実装するのかについて解説します。

なぜ、システムが必要なのか?

カスタマーレビューを手動で確認する方法としては以下のものがあります。

  • App StoreやGoogle Playで確認する。
  • App StoreやGoogle Playの管理画面で確認する。

手動での確認には色々と問題があります。

  1. リアルタイム性
    1. 不具合が発生した時に迅速に対応したい。
    2. リリースした機能の反応を見るのに即時で確認したい。
  2. 確認作業の手間
    1. ストアアプリや管理画面でチェックするのは実際の画面まで行くにはステップが多く、毎日実施するのは大変。
  3. 属人化
    1. ストアアプリや管理画面のチェックを仮に実施する場合は特定の人に偏ってしまい、特定の人がやらなくなると廃れてしまう。

システム実装イメージ

手動では上記の問題があるので

自動化をしてカスタマーレビューの情報収集し定期的にSlack通知する仕組みを作ります。

社員誰でも見れる状態にしたいのでSlackに通知します。

実装方法

Google Playの場合

システム概要

Google Apps ScriptでGoogle Play Developer APIを使用し、Google Playのカスタマーレビューを取得し、取得情報をSlackに通知し、スプレッドシートに書き込む。

  • 一覧で見れるようにスプレッドシートに書き込んでいます。

Google Play Developer API

APIを使うために認証処理が必要です。

必要な設定は下記の記事に詳しく載っているので割愛します。

https://qiita.com/Nekoq0o0p/items/71d962ed9a93b95df5bf

環境変数はGCSで設定した値を使います

PRIVATE_KEY_GCS

CLIENT_EMAIL_GCS

SCOPEは今回はandroidpublisherのAPIを使いたいので

https://www.googleapis.com/auth/androidpublisher を設定します

https://developers.google.com/identity/protocols/oauth2/scopes?hl=ja

認証には下記のライブラリを使います。

https://github.com/googleworkspace/apps-script-oauth2

return OAuth2.createService('GCS')
      .setTokenUrl('https://oauth2.googleapis.com/token')
      .setPrivateKey(PRIVATE_KEY_GCS)
      .setIssuer(CLIENT_EMAIL_GCS)
      .setPropertyStore(PropertiesService.getScriptProperties())
      .setScope(SCOPE);

認証後に下記のAPIをリクエストするとカスタマーレビューが取得できます。

GET /androidpublisher/v3/applications/{packageName}/reviews

https://developers.google.com/android-publisher/api-ref/rest#rest-resource:-v3.reviews

取得後はSlackやスプレッドシート用にデータを加工します

App Storeの場合

システム概要

Github ActionsでApp Store Connect APIを実行し、AppStoreからカスタマーレビューを取得し、情報をSlackに通知する。

App Store Connect APIの利用方法

APIを使用するには、認証が必要です。

そのため、まずApp Store ConnectでAPIキーを作成します。

作成したキーからAPIリクエストを行う際には、以下の情報が必要になります。

  • Issuer ID(App Store Connectで確認可能)
  • Key ID(作成したAPIキーの識別子)
  • p8ファイルの秘密鍵(ダウンロードした.p8ファイル)

弊社の環境ではすでにApp Store Connect APIを使用していたので、API リクエストに必要なものはGithub Actionsに設定してありました。

Github Actionsのスケジュールに組み込んで実行するようにします。

全体の処理の流れとしてはAPI リクエストに必要な変数を読み込みJWTを生成し、

カスタマーレビュー取得のAPIをリクエストしています。

リクエストした結果を加工しSlackに通知しています。

https://developer.apple.com/documentation/appstoreconnectapi/customer-reviews

require 'net/http'
require 'jwt'
require 'json'
require 'uri'
require 'time'

# 必要な情報
ISSUER_ID = "your_issuer_id"
KEY_ID = "your_key_id"
PRIVATE_KEY_PATH = "path/to/AuthKey_XXXXXXXXXX.p8"
APP_ID = "your_app_id"

# ペイロード
payload = {
  iss: ISSUER_ID,
  iat: Time.now.to_i,         # 発行時間
  exp: Time.now.to_i + (60 * 15), # 15分後に期限切れ
  aud: "appstoreconnect-v1"
}

# ヘッダー
headers = {
  kid: KEY_ID,
  alg: 'ES256'
}

# 秘密鍵を読み込む
private_key = OpenSSL::PKey::EC.new(File.read(PRIVATE_KEY_PATH))

# JWTを生成
token = JWT.encode(payload, private_key, 'ES256', headers)

uri = URI("https://api.appstoreconnect.apple.com/v1/apps/#{APP_ID}/customerReviews")
    params = {
      'fields[customerReviews]' => 'xxx', # 必要な情報に絞る
      'sort' => '-createdDate',            # 最新順
      'limit' => 50                        # 取得件数
    }
    uri.query = URI.encode_www_form(params)
    http = Net::HTTP.new(uri.host, uri.port)
    http.use_ssl = true
    request = Net::HTTP::Get.new(uri)
    request['Authorization'] = "Bearer #{token}"

    response = http.request(request)
    
puts response

成果

不具合対応のきっかけになる

  • レビューに書き込みがあることで不具合調査のきっかけになりました。

機能改善のアイディアに活用

  • Slackで見れるようになったことでレビューコメントから機能改善のアイディアに活用する事例が増えました。

モチベーションになる

  • 評価の良いレビューを見ると開発のモチベーションになります。

今後の展望

集計したデータを活用するためにAIなどで分析できるように仕組みも取り入れたいと思いました。

askenでは一緒に働いてくれる仲間を募集しています。

hrmos.co

参考記事

https://qiita.com/Nekoq0o0p/items/71d962ed9a93b95df5bf