雑廉堂の雑記帳

GCP: Google Analytics API から情報を取得 (2)

今回は、Analytics Reporting API V4 を使ってみようと思います。

 

 

Google Analytics Rporting API V4

Image by Photo Mix from Pixabay

現在、Google アナリティクスからデータを取得する場合には、Analytics (アナリティクス) Reporting API V4 を使うようです。

前回記事の内容は、Google Analytics API は V3 になり、すでに旧バージョのようです。

チュートリアルの内容をざっと見てみましたが、ぶっちゃけ、アナリティクス API はおろか、Google API のことは何もわかってい私でも、V3 から V4 では、全く書き方が違っているのは素人の目にも明らかです。

 

アナリティクス ビューID の確認

前回の準備の他に、アナリティクス Reporting を使用する場合には、あらかじめビューIDを確認しておく必要があります。

アナリティクスのホーム画面から、「管理」、「ビュー」 → 「ビューの設定」 に 「ビューID」があるので控えておきます。

アナリティクス ビューIDの確認

 

アナリティクス Reporting のサンプルコード

Google Developers による 「はじめてのアナリティクス Reporting API v4: サービス アカウント向け Java クイックスタート 」の例です。

一応、Maven プロジェクトで作業しているので、次の Dependency を追加します。

<dependency>
    <groupId>com.google.apis</groupId>
    <artifactId>google-api-services-analyticsreporting</artifactId>
    <version>v4-rev9-1.22.0</version>
</dependency>

 

以下が、Java コードになります。Google Developer のコードとはインポート文が一部違います。

<JSON ファイルへのパス> と、<ビューID> はそれぞれ控えているものと置き換えてください。

import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.analyticsreporting.v4.AnalyticsReporting;
import com.google.api.services.analyticsreporting.v4.AnalyticsReportingScopes;
import com.google.api.services.analyticsreporting.v4.model.ColumnHeader;
import com.google.api.services.analyticsreporting.v4.model.DateRange;
import com.google.api.services.analyticsreporting.v4.model.DateRangeValues;
import com.google.api.services.analyticsreporting.v4.model.Dimension;
import com.google.api.services.analyticsreporting.v4.model.GetReportsRequest;
import com.google.api.services.analyticsreporting.v4.model.GetReportsResponse;
import com.google.api.services.analyticsreporting.v4.model.Metric;
import com.google.api.services.analyticsreporting.v4.model.MetricHeaderEntry;
import com.google.api.services.analyticsreporting.v4.model.Report;
import com.google.api.services.analyticsreporting.v4.model.ReportRequest;
import com.google.api.services.analyticsreporting.v4.model.ReportRow;

public class HelloAnalyticsReportingB {
    private static final String APPLICATION_NAME = "Hello Analytics Reporting";
    private static final JsonFactory JSON_FACTORY = new JacksonFactory();
    private static final String KEY_FILE_LOCATION = "<JSON ファイルへのパス>";
    private static final String VIEW_ID = "<ビューID>";

    public static void main(String[] args) {
        AnalyticsReporting service;
        try {
            service = initializeAnalyticsReporting();
            GetReportsResponse response = getReport(service);
            printResponse(response);
        } catch (GeneralSecurityException e) {
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        } catch (IOException e) {
            // TODO 自動生成された catch ブロック
            e.printStackTrace();
        }
    }

    /**
     * Analytics Reporting API V4 service オブジェクトの初期化
     *
     * @return 認証された Analytics Reporting API V4 Service オブジェクト
     * @throws GeneralSecurityException
     * @throws IOException
     * @since 0.0.1
     */
    @SuppressWarnings("resource")
    private static AnalyticsReporting initializeAnalyticsReporting() throws GeneralSecurityException, IOException {
        HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
        GoogleCredential credential = GoogleCredential
                .fromStream(new FileInputStream(KEY_FILE_LOCATION))
                .createScoped(AnalyticsReportingScopes.all());

        // Analytics Service オブジェクトを構築する
        return new AnalyticsReporting.Builder(httpTransport, JSON_FACTORY, credential).build();
    }

    /**
     * Analytics Reporting API V4 クエリを実行する
     *
     * @param service 認証された Analytics Reporting API V4 サービスオブジェクト
     * @return GetReportResponse Analytics Reporting API V4 レスポンス
     * @throws IOException
     * @since 0.0.1
     */
    private static GetReportsResponse getReport(AnalyticsReporting service) throws IOException {
        // DateRange オブジェクトの生成
        DateRange dateRange = new DateRange();
        dateRange.setStartDate("7DaysAgo");
        dateRange.setEndDate("today");

        // Metric オブジェクトを作成
        Metric sessions = new Metric()
                .setExpression("ga:sessions")
                .setAlias("session");

        Dimension pageTitle = new Dimension().setName("ga:pageTitle");

        // ReportRequest オブジェクトを作成
        ReportRequest request = new ReportRequest().setViewId(VIEW_ID)
                .setDateRanges(Arrays.asList(dateRange))
                .setMetrics(Arrays.asList(sessions))
                .setDimensions(Arrays.asList(pageTitle));

        ArrayList<ReportRequest> requests = new ArrayList<>();
        requests.add(request);

        // GetReportRequest オブジェクトを生成
        GetReportsRequest getReport = new GetReportsRequest()
                .setReportRequests(requests);

        // batchGetメソッドを呼び出す
        GetReportsResponse response = service.reports().batchGet(getReport).execute();

        // レスポンスを返す
        return response;
    }

    /**
     * Analytics Reporting API V4 レスポンスを解析して表示
     *
     * @param response Analytics Reporting API V4 レスポンス
     * @since 0.0.1
     */
    private static void printResponse(GetReportsResponse response) {
        for (Report report : response.getReports()) {
            ColumnHeader header = report .getColumnHeader();
            List<String> dimensionHeaders = header.getDimensions();
            List<MetricHeaderEntry> metricHeaders = header.getMetricHeader().getMetricHeaderEntries();
            List<ReportRow> rows = report.getData().getRows();

            if (rows == null ) {
                System.out.println("No data found for " + VIEW_ID);
                return;
            }

            for (ReportRow row : rows) {
                List<String> dimensions = row.getDimensions();
                List<DateRangeValues> metrics = row.getMetrics();

                for (int i = 0; i < dimensionHeaders.size() && i < dimensions.size(); i++) {
                    System.out.println(dimensionHeaders.get(i) + ": " + dimensions.get(i));
                }

                for (int j = 0; j < metrics.size(); j++) {
                    System.out.println("Date Range (" + j + "): ");
                    DateRangeValues values = metrics.get(j);
                    for (int k = 0; k < values.getValues().size() && k < metricHeaders.size(); k++) {
                        System.out.println(metricHeaders.get(k).getName() + ": " + values.getValues().get(k));
                    }
                }
            }
        }
    }
}

 

Dimension ? Metric ??

このソース中、getReport メソッドで実際のレコードを検索していることがわかります。

DateRange は検索するレコードの日付範囲ということはわかるとして、DimensionMetric がよくわかりません。

Dimension は直訳すると「次元」??

Metric は 「メートル法の」???

また、Google Developers では、Metric は「指標」と訳されており、なおさらよくわかりませんね。

なんだかよくわからないので英語の意味を考えるのはここで止めておきましょう。そんなことは他の頭のいい人たちがやってくれます。

ソースを見ながらいろいろ考えてみたところ、SQL で GROUP BY で集計するクエリを想像してみるとよいのかもと想像してみました。要するに、

Dimension
GROUP BY でグループ化したいフィールド。
Metric
集計関数で集計したいフィールド。

今回のソースの場合、

SELECT pagetitle, SUM(session)
FROM Analytics
WHERE view_id = xxx
    AND date_range BETWEEN @today AND @7DaysAgo
GROUP BY pagetitle

と考えればしっくりとくると思います。

なるほど、この Dimension や Metrics っていうのは O/Rマッパーの役割を果たしているのか。。。

・・では、ここで、ページビューのランキングデータを得たい場合どうすればよいのか。

まず、SQL で考えてみると、

SELECT pagetitle, SUM(pageview) As pvsum
FROM Analytics
WHERE view_id = xxx
    AND date_range BETWEEN @today AND @7DaysAgo
GROUP BY pagetitle
ORDER BY pvsum DESC

となります。

先程の考え方でいくと、

となりそうです。

ただ、ORDER BY はどのようにすればよいのかわかりませんね。

 

Dimensions & Metrics Explorer を使ってみる

Dimensions & Metrics Explorer にアクセスすると、Dimension と Metric を調べることが出来ます。

この中にある、Page Tracking という項目の中に、

の項目があるのがわかりますね。さらに、

という項目があり、どうやらページのパスが取得できそうです。

 

ORDER BY はどうやって実装する?

ReportRequest | アナリティクス Reporting API v4 | Google Developers 」 を見てみると、ReportRequest には Metric や Dimension のリストだけでなく、orderBys プロパティに対して、OrderBy オブジェクトのリストを渡す事ができそうです。

OrderBy オブジェクトの定義は次のようになっており、fieldNamesortOrder を指定すると良さそうです。

{
    "fieldName": string,
    "orderType": enum(OrderType),
    "sortOrder": enum(SortOrder)
}

sortOrder には、ASCENDING (昇順) と、DESCENDING (降順) を指定できます。

 

ページビューの順番で出力させてみる

ここまでを踏まえて、ページビューの順番(降順)で各ページのページビュー数とセッション数を表示できるように、getReport メソッドの内容を書き換えました。

/**
 * Analytics Reporting API V4 クエリを実行する
 *
 * @param service 認証された Analytics Reporting API V4 サービスオブジェクト
 * @return GetReportResponse Analytics Reporting API V4 レスポンス
 * @throws IOException
 * @since 0.0.1
 */
private static GetReportsResponse getReport(AnalyticsReporting service) throws IOException {
    // DateRange オブジェクトの生成
    DateRange dateRange = new DateRange();
    dateRange.setStartDate("7DaysAgo");
    dateRange.setEndDate("today");

    // Metric オブジェクトを作成
    Metric sessions = new Metric()
            .setExpression("ga:sessions")
            .setAlias("session");
    Metric pageviews = new Metric()
            .setExpression("ga:pageviews")
            .setAlias("pageview");

    // Dimension オブジェクトを作成
    Dimension pageTitle = new Dimension().setName("ga:pageTitle");
    Dimension pagePath = new Dimension().setName("ga:pagePath");

    // OrderBy オブジェクトを作成
    OrderBy orderBy = new OrderBy().setFieldName("ga:pageviews").setSortOrder("DESCENDING");

    // ReportRequest オブジェクトを作成
    ReportRequest request = new ReportRequest().setViewId(VIEW_ID)
            .setDateRanges(Arrays.asList(dateRange))
            .setMetrics(Arrays.asList(pageviews, sessions))
            .setDimensions(Arrays.asList(pagePath, pageTitle))
            .setOrderBys(Arrays.asList(orderBy));

    ArrayList<ReportRequest> requests = new ArrayList<>();
    requests.add(request);

    // GetReportRequest オブジェクトを生成
    GetReportsRequest getReport = new GetReportsRequest()
            .setReportRequests(requests);

    // batchGetメソッドを呼び出す
    GetReportsResponse response = service.reports().batchGet(getReport).execute();

    // レスポンスを返す
    return response;
}

これで、全ページの情報を取得することに成功しました。

 

全ページではなくて、トップ10ページを出力させるには

全ページ表示されると、IDE のコンソールが改ページしてしまって、上位の情報がわからないよ、という状態になる場合もあると思うので、ここは出力する行数を制御してしまいたいものです。

これも、さっきのページ に書かれていました。

pageSize
返される最大行数を設定。

まさにこれですね。本来ページング用とのことですが、これも MySQL などの、LIMIT .. OFFSET も同じような用途なので、これを使って行数を制限してみたいと思います。

 

ちなみに、デフォルトでは、1回のクエリで最大1000行 返されます。また、指定した値に関係なく、Reporting API から返される最大行数は、リクエストにつき100,000行です。

 

変更点は、以下の部分だけです。

// ReportRequest オブジェクトを作成
ReportRequest request = new ReportRequest().setViewId(VIEW_ID)
        .setDateRanges(Arrays.asList(dateRange))
        .setMetrics(Arrays.asList(pageviews, sessions))
        .setDimensions(Arrays.asList(pagePath, pageTitle))
        .setOrderBys(Arrays.asList(orderBy))
        .setPageSize(10);  // 10ページ分取得

これで実行してみた結果、ページビューの多い順 (降順) に10ページ分の情報が表示されました。

 

まとめ

これで、Simple GA Ranking で表示されなくなったとしても自前でランキングを取得できそうですね。

あ、でもそうだとすると、Java ではなくて PHP で API を勉強しておけばよかったのかな・・

・・というわけで、また課題が一つ増えたみたいですねぇ。

モバイルバージョンを終了