ハウテレビジョン技術ブログ

『外資就活ドットコム』『外資就活ネクスト』『mond』を開発している株式会社ハウテレビジョンの技術ブログです。

【開発Days vol.3】GA4のscreen_viewイベントにカスタムパラメータを追加してBigQueryで分析する実装ガイド

株式会社ハウテレビジョンのData And Analyticsチームにいるデータエンジニアです。

開発チームの新たな取り組み "開発Days"とはで紹介されたように、弊社では毎月連続した2日間、通常のプロダクト開発から一時的に離れ、技術的な課題に集中的に取り組む仕組みがあります。

今回は、その開発Days vol.3で実際に取り組んだプロジェクトの一つをご紹介します。

モバイルアプリの分析基盤強化をテーマに、GA4のscreen_viewイベントにカスタムパラメータを追加し、BigQueryでデータマートを構築するプロジェクトに取り組みました。この取り組みは、「未来への投資」カテゴリーに位置づけられ、ユーザー体験の理解を深めることで、今後のプロダクト改善やパーソナライゼーション機能の開発につなげることを目的としています。

開発Daysという集中できる環境があったからこそ、React Native側の実装からBigQueryでのデータ処理ロジックの構築まで、一気通貫で進めることができました。今回は、この実装の背景と具体的な方法、そして実装で得られた知見についてお話しできればと思っています。

なぜscreen_viewイベントにカスタムパラメータを追加したのか

背景

弊社では、就職活動をする学生向けのモバイルアプリを提供しており、ユーザーの利用動向を知ることが、サービス改善において重要です。

GA4ではscreen_viewイベントによって画面遷移を自動的にトラッキングできますが、標準のパラメータだけでは以下のような課題がありました:

  • どの求人ID(recruitment_id)を見ているのか分からない
  • どの企業の詳細ページを見ているのか紐付けられない

解決したかった課題

カスタムパラメータを追加することで、以下を実現したいと考えました:

  1. 詳細な利用動向分析: ユーザーがどのコンテンツに興味を持っているかを定量的に把握
  2. レコメンデーション精度向上: 閲覧ページを元にした推薦ロジックの改善
  3. ビジネス指標の可視化: 企業ごと、求人ごとの閲覧数を集計

screen_viewイベントの公式仕様

Firebase Analyticsにおける定義

Firebase Analytics公式ドキュメント「Measure screenviews」によると、screen_viewイベントは画面遷移を識別するために使用されるイベントです(出典)。

同ドキュメントでは、以下のように説明されています:

Google Analytics tracks screen transitions and attaches information about the current screen to events, enabling you to track metrics such as user engagement or user behavior per screen.

自動収集と手動送信

Analyticsはfirebase_screen_classなどの一部情報を自動的に計測しますが、同ドキュメントによれば、各画面で異なるUIViewController/Activity/Viewを使用しない場合(ゲームなど)は、手動でscreen_viewイベントを送信することが推奨されています。

React Nativeでの実装

基本的な実装方法

Firebase Analyticsの公式ドキュメントによれば、React Native(JavaScript)では以下のように実装できます(出典):

import { getAnalytics, logEvent } from "firebase/analytics";

const analytics = getAnalytics();
logEvent(analytics, 'screen_view', {
  firebase_screen: screenName,
  firebase_screen_class: screenClass
});

カスタムパラメータの追加実装

弊社では、ルーティング情報から必要なパラメータを抽出し、screen_viewイベントに追加する関数を実装しました:

function getScreenDetailsFromRoute(screenName, routeParams) {
  // ルーティング情報からカスタムパラメータを抽出
  if (routeParams) {
    const { recruitment_id, company_id } = routeParams;
    
    return {
      firebase_screen: screenName,
      firebase_screen_class: 'MainActivity',
      // カスタムパラメータを追加
      recruitment_id: recruitment_id,
      company_id: company_id
    };
  }
  
  return {
    firebase_screen: screenName,
    firebase_screen_class: 'MainActivity'
  };
}

// イベント送信
const analytics = getAnalytics();
const screenDetails = getScreenDetailsFromRoute(screenName, routeParams);
logEvent(analytics, 'screen_view', screenDetails);

重要なポイントは、既存の標準パラメータ(firebase_screenfirebase_screen_class)に加えて、任意のカスタムパラメータを追加できることです。

BigQueryでのデータ処理

BigQueryエクスポートのスキーマ構造

GA4のデータは以下の構造でBigQueryにエクスポートされます(出典):

  • データセット名: analytics_<property_id>
  • テーブル名: events_YYYYMMDD(日次)、events_intraday_YYYYMMDD(ストリーミング)

Google Analytics公式ヘルプ「BigQuery Export schema」ドキュメントによると:

Each column in the events_YYYYMMDD table represents an event-specific parameter.

つまり、各イベントのパラメータはevent_paramsという配列型のカラムに格納されます。

event_paramsの構造

event_paramsはREPEATED型のRECORDフィールドで、以下の構造を持ちます:

  • key: パラメータ名(STRING)
  • value: パラメータ値(RECORD型)
    • string_value: 文字列型の値
    • int_value: 整数型の値
    • float_value: 浮動小数点型の値
    • double_value: 倍精度浮動小数点型の値

カスタムパラメータの抽出クエリ

弊社では、以下のようなSQLクエリを使用してカスタムパラメータを抽出し、データマートを構築しました:

-- 企業詳細画面のスクリーンビュー集計
SELECT
  date,
  "company" AS category,
  SAFE_CAST(
    SELECT value.string_value 
    FROM UNNEST(logs.event_params) 
    WHERE key="company_id"
  AS INT64) AS target_id,
  COUNT(*) AS score
FROM ga4_logs AS logs
WHERE event_name LIKE "screen_view"
  AND (SELECT value.string_value FROM UNNEST(logs.event_params) WHERE key="screenName") = const.COMPANY_DETAIL_SCREEN
GROUP BY 1, 2, 3

このクエリでは:

  1. UNNEST(event_params)で配列を展開
  2. params.keyでパラメータ名を特定
  3. params.value.string_valueで文字列値を取得
  4. REGEXP_EXTRACTでURLパターンから企業IDを抽出(代替方法)
  5. COUNT(*)で閲覧数を集計

実装フローと段階的リリース

なぜ段階的なリリースが必要なのか

モバイルアプリの特性上、以下の制約があります:

  1. アプリストアの審査: リリースまでに数日かかる
  2. ユーザーの更新: 全ユーザーが最新版を使うまでに時間がかかる
  3. 一定のデータ量: 分析に十分なデータ量が必要

そのため、以下の順序で実装を進めました。

実装の流れ

1. React Native側の改修とリリース完了

まず、アプリ側でカスタムパラメータを送信するコードを実装し、アプリストアにリリースしました。

// リリース前: 標準パラメータのみ
logEvent(analytics, 'screen_view', {
  firebase_screen: screenName,
  firebase_screen_class: screenClass
});

// リリース後: カスタムパラメータを追加
logEvent(analytics, 'screen_view', {
  firebase_screen: screenName,
  firebase_screen_class: screenClass,
  recruitment_id: recruitment_id  // 追加
});

2. データマート修正のPR作成済み

アプリのリリースと並行して、BigQueryでのデータ処理ロジックをPRとして作成しました。ただし、この時点ではまだマージしません。

3. データ収集 + 事業部相談後にマージ予定

  • カスタムパラメータを含むイベントが十分に蓄積されるのを待つ
  • 実際のデータを使ってクエリの動作を検証
  • 事業部とデータの妥当性を確認
  • 問題がなければデータマートのPRをマージ

データ遅延の考慮

Google Analytics公式ヘルプによれば、イベント発生日から最大3日間はデータが更新される可能性があります(出典):

Analytics will update the daily tables (events_YYYYMMDD) with events for those dates for up to three days after the dates of the events.

そのため、データマートのマージは、十分な期間を置いてから行う必要があります。

実装で得られた知見

デフォルトの"screen_view"では不完全

React Nativeアプリで標準的に収集されるscreen_viewイベントには、以下のようなパラメータが含まれます:

  • firebase_screen: 画面名(例: "RecruitmentDetailScreen")
  • firebase_screen_class: 画面のクラス名(例: "MainActivity")

しかし、これだけでは以下の情報が不足していました:

1. コンテンツIDの欠如

画面名だけでは「求人詳細画面を見た」ことは分かりますが、「どの求人を見たか」は分かりません。例えば: - RecruitmentDetailScreenという画面名は取得できる - しかしrecruitment_id=26881という情報は含まれていない

つまり、以下のような分析ができませんでした:

  • 「この求人は何回閲覧されたか」
  • 「このユーザーはどの企業に興味を持っているか」
  • 「求人Aと求人Bのどちらが人気か」

2. 画面遷移だけでは不十分

標準のscreen_viewでは、以下のような情報しか得られません:

RecruitmentDetailScreen → 100回
CompanyDetailScreen → 80回

しかし、ビジネス上本当に知りたいのは:

求人ID=26881 → 50回
求人ID=15234 → 30回
求人ID=98765 → 20回

このような「コンテンツ単位」での集計です。

3. 解決策: カスタムパラメータの追加

そこで、画面遷移時に以下のような明示的なカスタムパラメータを追加することにしました:

logEvent(analytics, 'screen_view', {
  firebase_screen: 'RecruitmentDetailScreen',
  firebase_screen_class: 'MainActivity',
  recruitment_id: '26881',  // カスタムパラメータ: 求人ID
  company_id: '12345'       // カスタムパラメータ: 企業ID
});

これにより: - コンテンツ単位での閲覧数を正確に把握できる - ユーザーの興味関心を定量的に把握できる - レコメンデーションロジックに活用できる - BigQuery上でのデータ分析が容易になる

event_paramsの扱いで学んだこと

BigQueryでのevent_paramsの扱いには、以下のポイントがあります:

1. REPEATED型の展開は必須

-- NG: そのまま参照できない
SELECT event_params.key
FROM table

-- OK: UNNESTで展開
SELECT params.key
FROM table, UNNEST(event_params) AS params

2. valueフィールドは複数の型を持つRECORD型

-- 文字列の場合
params.value.string_value

-- 整数の場合
params.value.int_value

-- 浮動小数点の場合
params.value.float_value

3. サブクエリでの抽出も有効

SELECT
  (SELECT value.string_value 
   FROM UNNEST(event_params) 
   WHERE key="recruitment_id") AS recruitment_id
FROM table

パフォーマンスの考慮

UNNESTを使用するクエリは、データ量が多い場合にパフォーマンスに影響を与える可能性があります。弊社では以下の対策を行いました:

  1. パーティション分割の活用: WHERE date >= '2025-01-01'のように日付で絞り込み
  2. 事前集計: よく使う集計結果をマテリアライズドビューとして保存
  3. インデックスの活用: BigQueryの自動最適化を活用

まとめ

GA4のscreen_viewイベントにカスタムパラメータを追加することで、より詳細なユーザー利用動向を知ることが可能になりました。

実装のポイントをまとめると:

React Native側 - Firebase AnalyticsのlogEventでカスタムパラメータを送信 - ルーティング情報から必要なパラメータを抽出 - 標準パラメータと併用することで互換性を保つ

BigQuery側 - UNNEST関数でevent_paramsを展開 - カスタムパラメータの抽出には型に注意 - URLパターンからの抽出も代替手段として有効

リリース戦略 - アプリのリリースサイクルを考慮した段階的実装 - PRを先に作成し、一定のデータが集まり次第マージ - データ遅延(最大3日)を考慮した検証期間

今後も、ユーザー体験の理解を深めるために、カスタムパラメータの追加や、データ基盤の改善を継続的に行っていきます。


最後に、今回ご紹介した開発チームの取り組みに共感いただけるエンジニアの方がいらっしゃいましたら、ぜひ私たちのチームにジョインしませんか?弊社では、一緒に技術的な課題に取り組んでくれるエンジニアを募集中です!

現在募集中の採用情報の詳細は下記をご覧ください。

https://herp.careers/v1/howtv/requisition-groups/dfc2cc4a-edcc-49c0-9d83-b5870b734c04