📸

【Roblox】ユーザーの行動ログを集計してKPIを確認する

2025/03/07に公開

はじめに

前回はExperience内で管理しているゲームデータを定期的に取得するシステムを紹介しました。
まだ読まれていない場合は、こちらを先にご覧ください。

今回はユーザーの行動ログを取得、集計してKPIの進捗を確認するためのシステムを構築しましたので、その概要を紹介させて頂きます。
※行動ログとはユーザーが起こしたアイテムの取得や消費などのアクションを記録したログを指します。

Robloxバージョン:0.658.0.6580461

使用サービス

本システムは以下のサービスを使用しています。

  • Roblox
    • Open Cloud API
      • universe-datastores.objects:list
      • universe-datastores.objects:read
      • universe-datastores.objects:delete
    • DataStore
  • Google Workspace
    • Google Apps Script (GAS)
    • Spreadsheet

システム設計

本システムは行動ログの取得→集計→削除の順で処理を行います。

まず初めに行動ログを取得します。

  1. Experienceはユーザーの行動ログをDataStoreに保存する
  2. スケジュール管理用Spreadsheetから、ログ取得済み日時を確認する
  3. Open Cloud APIを実行して、DataStore内の行動ログを取得する
  4. 取得した行動ログをログ保存用Spreadsheetに保存する
  5. スケジュール管理用Spreadsheetに、ログ取得済みを記録する

次に行動ログを集計します。

  1. スケジュール管理用Spreadsheetから、ログ集計済み日時を確認する
  2. ログ保存用Spreadsheetから集計対象日の行動ログを読み込む
  3. 集計したデータを保存用Spreadsheetに保存する
  4. スケジュール管理用Spreadsheetに、ログ集計済みを記録する

最後に行動ログを削除します。

  1. スケジュール管理用Spreadsheetから、ログ削除対象日を確認する
  2. ログ保存用Spreadsheetからログ削除対象日のKeyリストを読み込む
  3. Open Cloud APIを実行して、DataStore内の行動ログを削除する
  4. スケジュール管理用Spreadsheetに、ログ削除済みを記録する

設計詳細

システム設計の各フローの詳細について説明します。
GASは5分おきに起動するようトリガー設定をしておきます。また実行時間を5分以内に制限する事で、重複せず5分ごとにGASが起動するようにしています。

行動ログ取得

1.Experienceはユーザーの行動ログをDataStoreに記録する

行動ログをDataStoreに保存するEntryのフォーマットは、以下のように定義しました。

"value": {
    /* -- 基本情報 ----------------------------------------- */
    "action_id": 1,                     // ログ識別ID
    "action_at": "2025-01-02 03:04:05", // ログ作成日時 (UTC)
    /* -- ユーザー情報 -------------------------------------- */
    "user_id": 000000000001,            // ユーザーID
    "user_name": "Taro Kamata",         // ユーザー名
    "user_local": "ja-jp",              // 国識別
    /* -- 行動ログ情報 ----------------------------------------- */
    "log_version": "1",                 // 行動ログフォーマットバージョン
    "log_parameter": {                  // 行動ログの内容
        ...
    },
    /* --------------------------------------------------- */
}

「行動ログの内容」は「行動ログID」と共にフォーマットを決定します。
例えば、ユーザーがUGCステージを作成した場合のログは以下のように定義しました。

  • 行動ログID: 1
  • 行動ログの内容:
    "log_parameter": {
        "ugc_stage_id": 10001,
        "ugc_object_ids": [101, 103, 105],
    }
    

また、Keyは「YYYYMMDDhhmmss_UserId」と定義しました。

2.スケジュール管理用Spreadsheetから、ログ取得済み日時を確認する

何時までの行動ログを取得したかを記録しておき、次回取得する行動ログを特定するのに使用します。

3.Open Cloud APIを実行して、DataStore内の行動ログを取得する

まず、List Data Store EntriesのAPIを使用してKeyのリストを取得します。[1]
その際Query Parameterのfilterに「id.startsWith("YYYYMMDDhhm")」と指定する事で、YYYY/MM/DD hh:m0:00 〜 YYYY/MM/DD hh:m9:59までの10分間に作られた行動ログのKeyを取得するようにしました。
次に、得られたKeyを用いてGet Data Store EntryのAPIを実行する事で、10分間に作られた行動ログを取得します。
なお、Open Cloud APIは複数同時に実行できますので、GASで非同期通信できるUrlFetchApp.fetchAll() 関数を使用します。ただし、Open Cloud APIの1分間の通信回数制限を超えないようにUtilities.sleep()で時間調整する必要がありました。

行動ログ取得のGASは5分間隔で起動しますが、行動ログは10分間に作られた分をまとめて取得します。よって、GASの起動の2回に1回はスケジュール管理用Spreadsheetの確認だけ行い、なにもしないように実装しました。

この余白時間は、行動ログを取得しきれなかった場合に続きを行う予備作業の時間となります。

また、通信障害等でログの取得に遅延が発生した場合に、復旧のための作業時間としても使います。

4.取得した行動ログをログ保存用Spreadsheetに保存する

Spreadsheetは後で確認しやすいように行動ログの種類、月ごとに分ける事にしました。
そしてログの作成日のシート「YYYY/MM/DD」を作成し、行動ログをテーブル形式(1行目にカラム、2行目以降に行動ログ)で保存しました。

entry_key log
20240102030405_000000000001 {"action_id": 1, "action_at": "2024-01-02 03:04:05", "user_id": 000000000001, "user_name": "Taro Kamata", "user_local": "ja-jp", "log_version": "1", "log_parameter": {"ugc_stage_id": 10001, "ugc_object_ids": [101, 103, 105]}}
20240102030959_000000000002 {"action_id": 1, "action_at": "2024-01-02T03:09:59Z", "user_id": 000000000002, "user_name": "Taro Yamada", "user_local": "ja-jp", "log_version": "1", "log_parameter": {"ugc_stage_id": 10002, "ugc_object_ids": [101, 103, 106]}}

5.スケジュール管理用Spreadsheetに、ログ取得済みを記録する

行動ログの取得と保存が完了したら、スケジュール管理用Spreadsheetに何時までの行動ログを取得したかを書き込みます。処理のどこかでエラーが発生した場合は、次回のGASが行動ログの取得からやり直します。

行動ログ集計

1.スケジュール管理用Spreadsheetから、ログ集計済み日時を確認する

何時までの行動ログを集計したかを記録しておき、次回集計する行動ログを特定するのに使用します。

2.ログ保存用Spreadsheetから集計対象日の行動ログを読み込む

ログ保存用Spreadsheetの集計対象日のシートから行動ログを読み込みます。[1:1]

3.集計したデータを保存用Spreadsheetに保存する

Spreadsheetは後で確認しやすいように集計データの種類、月ごとに分けました。
そして集計日のシート「YYYY/MM/DD」を作成し、データをテーブル形式(1行目にカラム、2行目以降に集計データ)で保存しました。

ugc_object_id ugc_object_name used_count
101 Aaaaaaaaaa 2
103 Cccccccccc 2
105 Eeeeeeeeee 1
106 Ffffffffff 1

ugc_object_nameは集計時にマスターデータ管理用Spreadsheetから取得しています。

4.スケジュール管理用Spreadsheetに、ログ集計済みを記録する

行動ログの集計と保存が完了したら、スケジュール管理用Spreadsheetに集計対象日の日付を書き込みます。処理のどこかでエラーが発生した場合は、次回のGASが行動ログの読み込みからやり直します。

行動ログ削除

1.スケジュール管理用Spreadsheetから、ログ削除済み日時を確認する

何時までの行動ログのEntryをDataStoreから削除したかを記録しておき、次回削除する行動ログを特定するのに使用します。

2.ログ保存用Spreadsheetからログ削除対象日のKeyリストを読み込む

ログ保存用Spreadsheetの削除対象日のシートからEntryのKeyリストを読み込みます。

3.Open Cloud APIを実行して、DataStore内の行動ログを削除する

Delete Data Store EntryのAPIを使用してEntryを削除します。[1:2]

4.スケジュール管理用Spreadsheetに、ログ削除済み日時を記録する

行動ログの削除が完了したら、スケジュール管理用Spreadsheetに削除対象日の日付を書き込みます。処理のどこかでエラーが発生した場合は、次回のGASがEntryのKeyリストの読み込みからやり直します。

システムの統合

複数のGASがそれぞれOpen Cloud APIを実行すると、意図せずに1分間のリクエスト回数制限を超えてしまう可能性があります。今回は行動ログの取得、集計、削除処理を1つのGASにまとめてAPIの実行を管理するようにしました。
また、Experience内で管理しているゲームデータを定期的に取得するシステムも統合しました。

統合後は以下のフローチャートのように、処理を順番に実行するように実装しました。
GASの実行時間が残っているならば次の処理を行い、時間切れならばGASを終了します。

  1. ゲームデータの取得
    毎日なるべく同じ時間にゲームデータを取得し、24時間ごとの推移を確認したいので優先順位は一番高くしました。
  2. 行動ログを集計
    いつ行っても結果は変わりませんが、KPIを確認する担当者を待たせないために早めに集計を終わらせました。
  3. 行動ログを取得
    ゲームデータの取得や行動ログの集計の邪魔にならないように、優先順位を低くしました。
  4. 行動ログを削除
    ログの削除は遅延してもどこにも影響がないため、優先順位は一番低くしました。

以下は、それぞれの処理が理想的な挙動をした場合の図となります。

エラー対応・サービスの制限

エラー対応及びサービスの制限は前回の記事をご確認ください。

まとめ

ユーザーの行動ログを取得、集計してKPIの進捗を定期的に取得するシステムの概要を紹介しました。
ゲームデータの取得と同様にOpen Cloud APIを使用する事で、行動ログを取得する事ができます。
Spreadsheetに保存しておけば、グラフを作成してデータの推移を確認する事も、月の合計値や平均値を出して分析する事も、KPIを確認する事も容易に行えるでしょう。

お読みいただきありがとうございました。

参考

脚注
  1. GASの実行時間以内に対応し切れない場合は、次回のGASで続きから処理します。 ↩︎ ↩︎ ↩︎

ランド・ホー Roblox開発チーム

Discussion