🍄

GAS で Google Analytics Data API (GA4) を実行

2023/04/25に公開
1

やりたいこと

GA4 から Google Apps Script (GAS) で Google Analytics Data API を利用してデータを取得し、スプレッドシートに結果を保存します。
GA での分析はしたことがあり、設定値は理解している人で、データ取得処理を自動化したい人向けです。

準備

GA4 の ID を確認

管理>プロパティ設定>右上の ID をコピー

スプレッドシート& GAS を準備

新規にスプレッドシートを作成します。(ファイル名はなんでも OK)

GAS エディタを起動します。
拡張機能>Apps Script

GAS で Google Analytics Data API を利用できるようにします。
サービスの+>Google Analytics Data API を選択>追加

実装

共通メソッド

GA4 から取得した情報をスプシに書き込むのはどのようなデータを取得する場合も同じなので、メソッド化して呼び出せるようにしておきます。

コード.gs を writeReport.gs にリネームし、以下のコードをコピペします。
この時、「GA4のプロパティID」は準備の段階で確認した GA4 ID に書き換えます。

const GA4_PROPERTY_ID = "GA4のプロパティID";

// 指定されたシートにGAの結果を書き込む
function writeReport(sheet, report) {
  try {
    if (sheet.getLastRow() > 1 || sheet.getLastColumn() > 1) {
      sheet.getRange(1,1,sheet.getLastRow(),sheet.getLastColumn()).clear();
    }
    
    // Append the headers.
    const dimensionHeaders = report.dimensionHeaders.map(
        (dimensionHeader) => {
          return dimensionHeader.name;
        });

    const metricHeaders = report.metricHeaders.map(
        (metricHeader) => {
          return metricHeader.name;
        });
    const headers = [...dimensionHeaders, ...metricHeaders];

    sheet.appendRow(headers);

    // Append the results.
    const rows = report.rows.map((row) => {
      const dimensionValues = row.dimensionValues.map(
          (dimensionValue) => {
            return dimensionValue.value;
          });
      const metricValues = row.metricValues.map(
          (metricValues) => {
            return metricValues.value;
          });
      return [...dimensionValues, ...metricValues];
    });

    sheet.getRange(2, 1, report.rows.length, headers.length)
        .setValues(rows);

    Logger.log(`Report spreadsheet created: ${sheet.getSheetName()}`);
  } catch (e) {
    // TODO (Developer) - Handle exception
    Logger.log(`Failed to write report with error: ${e}`);
  }  
}

あとは、欲しいデータを取得してきて、このメソッドに投げてあげればスプシに結果が保存されます。

GAS はファイル順にコードがグローバル定義されていることになるので、共通メソッドのファイルはファイルリストの中で一番上に来るようにしておきます。

データ取得(大枠)

データを取得する処理は大まかに以下のようになります。
関数名、シート名は処理によって変更してください。
シートは事前に作成しておく必要があります。

function hoge() {
  // 取得したデータを書き込むシート
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("sheet_name");

  try {
    // メトリクス(値)、複数指定可能
    const metric1 = AnalyticsData.newMetric();
    metric1.name = "screenPageViews";

    // ディメンション(指標)、複数指定可能
    const dimension1 = AnalyticsData.newDimension();
    dimension1.name = "pagePath";

    // データの日付範囲
    const dateRange = AnalyticsData.newDateRange();
    dateRange.startDate = "2023-03-27";
    dateRange.endDate = "2023-04-10";

    // フィルター、複数指定可能
    const filter = AnalyticsData.newFilterExpression();
    // (設定複雑なので省略)

    // ソート
    const order = AnalyticsData.newOrderBy();
    // (省略)

    // 上で作った設定値をリクエストパラメータに設定
    const request = AnalyticsData.newRunReportRequest();
    request.dimensions = [dimension1];
    request.metrics = [metric1];
    request.dateRanges = dateRange;
    request.dimensionFilter = filter;
    request.orderBys = order;

    // API 実行(ここから下は基本書き換え不要)
    const report = AnalyticsData.Properties.runReport(request,
        'properties/' + GA4_PROPERTY_ID);
    if (!report.rows) {
      Logger.log('No rows returned.');
      return;
    }

    // 共通メソッドでスプシに書き込み
    writeReport(sheet, report);
  } catch (e) {
    // TODO (Developer) - Handle exception
    Logger.log(`Failed with error: ${e}`);
  }
}

メトリクス、ディメンション

欲しい指標の名称を name に入れれば良いです。
name は https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema で探します。
日本語で見ると API Name が和名になってしまうので、English のまま探すか、日本語であたりをつけて API Name を引き当てます。

複数指定したい場合は、リクエストパラメータに設定する際に配列内に追加すれば良いです。

    // メトリクス(値)、複数指定可能
    const metric1 = AnalyticsData.newMetric();
    metric1.name = "screenPageViews";

    const metric2 = AnalyticsData.newMetric();
    metric2.name = "screenPageViewsPerUser";

    // 上で作った設定値をリクエストパラメータに設定
    const request = AnalyticsData.newRunReportRequest();
    request.metrics = [metric1, metric2];

フィルター

公式ドキュメントを参照しながら組み立てます。

条件が1つの場合

newFilterExpression() で FilterExpression インスタンスを作成し、FilterExpression.filter に指標と値を指定した Filter をセットします。

例として、リファラ(指標)が Zenn の TOP ページ(値)だった場合でフィルタを作成します。

// 前のページがTOPに絞り込み
    const dimensionFilter = AnalyticsData.newFilterExpression();
    const referrerFilter = AnalyticsData.newFilter();
    referrerFilter.fieldName = "pageReferrer";    // フィルタする指標
    const referrerStringFilter = AnalyticsData.newStringFilter();    // フィルタの種類、文字列フィルタ
    referrerStringFilter.matchType = "EXACT";    // 完全一致
    referrerStringFilter.value = "https://zenn.dev/";    // フィルタする値
    referrerFilter.stringFilter = referrerStringFilter;
    dimensionFilter.filter = referrerFilter;

StringFilter では完全一致の他、含む、指定した値で始まる、正規表現、など GA で使えるものは一通り指定できます。

条件が複数の場合

andGroup、orGroup により、それぞれ And 条件、 Or 条件を指定できます。

    // 除外ページを設定
    const dimensionFilter1 = AnalyticsData.newFilterExpression();
    const notExpression = AnalyticsData.newFilterExpression();
    const notPagePathFilter = AnalyticsData.newFilter();
    notPagePathFilter.fieldName = "pagePath";
    const notPagePathStringFilter = AnalyticsData.newStringFilter();
    notPagePathStringFilter.matchType = "FULL_REGEXP";
    notPagePathStringFilter.value = "^(\/ignore|\/except).*";
    notPagePathFilter.stringFilter = notPagePathStringFilter;
    notExpression.filter = notPagePathFilter;
    dimensionFilter1.notExpression = notExpression;

    // 端末種類でフィルタ
    const dimensionFilter2 = AnalyticsData.newFilterExpression();
    const deviceFilter = AnalyticsData.newFilter();
    deviceFilter.fieldName = "deviceCategory";
    const deviceStringFilter = AnalyticsData.newStringFilter();
    deviceStringFilter.matchType = "EXACT";
    deviceStringFilter.value = "Desktop";
    deviceFilter.stringFilter = deviceStringFilter;
    dimensionFilter2.filter = deviceFilter;

    // 複数フィルタを And で指定
    const dimensionFilters = AnalyticsData.newFilterExpressionList();
    dimensionFilters.expressions = [dimensionFilter1, dimensionFilter2]
    const dimensionFilter = AnalyticsData.newFilterExpression();
    dimensionFilter.andGroup = dimensionFilters;

フィルター部分のコードが長くなりがち・・・。
とりあえず取得してからスプシで処理した方が楽かもしれません。
API では一度に10000データまでしか取得できないので、溢れる時に使うと良さそうです。

定期実行

左メニューのトリガー > トリガーを追加
時間手動型、日付ベースのタイマーをセットすると、毎日同じ時間に実行します。

Discussion