概要

Google Analytics Data API v1 を使用すると、ファネル レポートを生成できます。 ファネル データ探索では、ユーザーがタスクを完了するまでのステップを視覚化し、各ステップでのユーザーの動向をすばやく確認できます。

コアレポートとの共有機能

ファネル レポート リクエストのセマンティクスは、多くの共有機能に対する Core レポート リクエストと同じです。たとえば、ファネル レポートでは、ページ分け、ディメンション フィルタ、ユーザー プロパティはコアレポートと同じように動作します。このガイドでは、ファネル レポート機能を中心に説明します。Data API v1 の Core Reporting 機能について詳しくは、レポートの基本ガイド高度なユースケースをご覧ください。

目標到達プロセスのレポート方法

Data API v1 は、runFunnelReport メソッドで目標到達プロセス レポート機能をサポートしています。このメソッドは、Google アナリティクスのイベントデータのカスタマイズされた目標到達プロセス レポートを返します。

報告エンティティの選択

Data API v1 のすべてのメソッドで、URL リクエストパス内に properties/GA4_PROPERTY_ID の形式で Google アナリティクス 4 プロパティ識別子を指定する必要があります。次に例を示します。

  POST  https://analyticsdata.googleapis.com/v1alpha/properties/GA4_PROPERTY_ID:runFunnelReport

レポートは、指定した Google アナリティクス 4 プロパティで収集された Google アナリティクス イベントデータに基づいて生成されます。

Data API クライアント ライブラリのいずれかを使用している場合は、リクエスト URL パスを手動で操作する必要はありません。ほとんどの API クライアントでは、文字列が properties/GA4_PROPERTY_ID の形式の property パラメータが提供されています。クライアント ライブラリの使用例については、クイック スタートガイドをご覧ください。

ファネル レポート リクエスト

ファネル レポートをリクエストするには、RunFunnelReportRequest オブジェクトを作成します。まずは以下のリクエスト パラメータから始めることをおすすめします。

  • dateRanges フィールドの有効なエントリ。

  • funnel フィールドに有効なファネルの仕様。

ファネルの仕様

RunFunnelReportRequest オブジェクトの funnel フィールドのファネルの仕様では、このファネルの steps を記述して、測定するユーザー ジャーニーを定義します。

ファネルのステップには、ファネルのステップに含まれる条件が 1 つ以上含まれています。各ステップに含める条件は、各ステップの filterExpression フィールドに記述できます。

各ファネル フィルタ式は、次の 2 種類のフィルタを組み合わせたものです。

  • funnelFieldFilter は、ディメンションまたは指標のフィルタを作成します。

  • funnelEventFilter は、単一のイベント名のイベントに一致するフィルタを作成します。オプションの funnelParameterFilterExpression フィールドが指定されている場合、単一のイベント名とパラメータ フィルタ式の両方に一致するイベントのサブセットのみが、このイベント フィルタに一致します。

フィルタは、ANDOR グループを使用して組み合わせることも、NOT 式を使用して否定することもできます。

目標到達プロセスの各ステップのレポート結果は、ディメンションに基づいて分類され、funnelBreakdown フィールドに指定されます。

ファネル レポートの例

Google アナリティクス管理画面の [ファネル データ探索] テンプレートで提供されるデフォルトのファネル レポートを、Google アナリティクス Data API v1 を使って再現してみましょう。

ファネル レポートの UI の例

目標到達プロセスのステップ

上記のファネル設定には、次のステップが含まれています。

# ステップの名前 条件
1 初回起動 / 初回訪問 イベント名は first_open または first_visit です。
2 オーガニック訪問者 firstUserMedium ディメンションには「オーガニック」という用語が含まれています。
3 セッションの開始 イベント名は session_start です。
4 スクリーン ビュー / ページビュー イベント名は screen_view または page_view です。
5 購入 イベント名は purchase または in_app_purchase です。

目標到達プロセスのステップ 1(初回起動/訪問)では、ウェブサイトまたはアプリで初めて操作を行ったすべてのユーザー(first_open イベントまたは first_visit イベントをトリガーしたユーザー)が含まれます。

この動作を実装するために、以下のスニペットでは filterExpression フィールドを持つ FunnelStep オブジェクトを指定しています。フィルタ式のフィールドは、OR グループを使用して 2 つの FunnelEventFilter エンティティを組み合わせることで構築された FunnelFilterExpression オブジェクトです。

  {
    "name": "Purchase",
    "filterExpression": {
      "orGroup": {
        "expressions": [
          {
            "funnelEventFilter": {
              "eventName": "first_open"
            }
          },
          {
            "funnelEventFilter": {
              "eventName": "first_visit"
            }
          }
        ]
      }
    }
  }

ファネルのステップ 2(オーガニック ユーザー)には、最初のメディアに「organic」が含まれるユーザーが含まれます。以下のスニペットでは、FunnelFieldFilterfieldName フィールドが firstUserMedium ディメンションと一致するようにフィルタに指示します。stringFilter フィールドには、「organic」という語句を含むディメンションの値のみを含める条件が含まれます。

  {
    "name": "Organic visitors",
    "filterExpression": {
      "funnelFieldFilter": {
        "fieldName": "firstUserMedium",
        "stringFilter": {
          "matchType": "CONTAINS",
          "caseSensitive": false,
          "value": "organic"
        }
      }
    }
  }

ファネルの残りのステップも同様の方法で指定できます。

内訳ディメンション

オプションの内訳ディメンション(この例では deviceCategory)は、FunnelBreakdown オブジェクトを使用して指定できます。

  "funnelBreakdown": {
    "breakdownDimension": {
      "name": "deviceCategory"
    }
  }

デフォルトでは、内訳ディメンションの最初の 5 つの個別の値のみがレポートに含まれます。FunnelBreakdown オブジェクトの limit フィールドを使用すると、この動作をオーバーライドできます。

目標到達プロセス レポートのクエリ全体

上記のすべてのステップを使用してファネル レポートを生成する完全なクエリは次のとおりです。

HTTP

POST https://analyticsdata.googleapis.com/v1alpha/properties/GA4_PROPERTY_ID:runFunnelReport
{
  "dateRanges": [
    {
      "startDate": "30daysAgo",
      "endDate": "today"
    }
  ],
  "funnelBreakdown": {
    "breakdownDimension": {
      "name": "deviceCategory"
    }
  },
  "funnel": {
    "steps": [
      {
        "name": "First open/visit",
        "filterExpression": {
          "orGroup": {
            "expressions": [
              {
                "funnelEventFilter": {
                  "eventName": "first_open"
                }
              },
              {
                "funnelEventFilter": {
                  "eventName": "first_visit"
                }
              }
            ]
          }
        }
      },
      {
        "name": "Organic visitors",
        "filterExpression": {
          "funnelFieldFilter": {
            "fieldName": "firstUserMedium",
            "stringFilter": {
              "matchType": "CONTAINS",
              "caseSensitive": false,
              "value": "organic"
            }
          }
        }
      },
      {
        "name": "Session start",
        "filterExpression": {
          "funnelEventFilter": {
            "eventName": "session_start"
          }
        }
      },
      {
        "name": "Screen/Page view",
        "filterExpression": {
          "orGroup": {
            "expressions": [
              {
                "funnelEventFilter": {
                  "eventName": "screen_view"
                }
              },
              {
                "funnelEventFilter": {
                  "eventName": "page_view"
                }
              }
            ]
          }
        }
      },
      {
        "name": "Purchase",
        "filterExpression": {
          "orGroup": {
            "expressions": [
              {
                "funnelEventFilter": {
                  "eventName": "purchase"
                }
              },
              {
                "funnelEventFilter": {
                  "eventName": "in_app_purchase"
                }
              }
            ]
          }
        }
      }
    ]
  }
}

回答を報告

目標到達プロセス レポート API リクエストの目標到達プロセス レポート レスポンスは、FunnelSubReport オブジェクトとして返される 2 つの主要部分(目標到達プロセスの可視化と目標到達プロセス テーブル)で構成されます。

目標到達プロセス

ファネル レポートのレスポンスfunnelVisualization フィールドに返されるファネル ビジュアリゼーションには、ファネル レポートの概要が含まれます。名前が示すように、生成された目標到達プロセス レポートをすばやく視覚化するのに役立ちます。

目標到達プロセスの可視化の表の各行には、次のフィールドの一部またはすべてが含まれます。

  • 目標到達プロセスのステップ名(funnelStepName ディメンション)。

  • アクティブ ユーザー数(activeUsers 指標)。

  • セグメント(segment ディメンション)。ファネル クエリで Segment が指定されている場合にのみ存在します。

  • 日付(date ディメンション)。クエリで可視化タイプ TRENDED_FUNNEL が指定されている場合にのみ存在します。

  • 次のアクション ディメンション(funnelStepNextAction ディメンション)。ファネル クエリで FunnelNextAction が指定されている場合にのみ存在します。

上記のサンプル レポートの目標到達プロセスの表示セクションは、Google アナリティクスの管理画面に次のように表示されます。

目標到達プロセス レポートのヘッダー: サンプル

目標到達プロセスの表

目標到達プロセス レポート レスポンスfunnelTable フィールドに返される目標到達プロセス テーブルは、レポートの主要部分を表します。テーブルの各行には、次のフィールドの一部またはすべてが含まれています。

  • 目標到達プロセスのステップ名(funnelStepName ディメンション)。

  • 内訳ディメンション。

  • アクティブ ユーザー数(activeUsers 指標)。

  • ステップ完了率(funnelStepCompletionRate 指標)。

  • ステップの放棄数(funnelStepAbandonments 指標)。

  • ステップの放棄率(funnelStepAbandonmentRate 指標)。

  • セグメント名(segment ディメンション)。ファネル クエリで Segment が指定されている場合にのみ存在します。

コアレポート機能と同様に、合計値は、内訳ディメンション値として「RESERVED_TOTAL」を含む別個の行で返されます。

以下は、Google アナリティクスの UI に表示される目標到達プロセスの表の例です。 ファネル レポートの表: サンプル

未加工のレスポンス

次のスニペットは、runFunnelReport クエリに応答して返される元データの例を示しています。

上記のサンプル レポートでは、プロパティで収集されたデータに応じて、目標到達プロセスの各ステップに含まれるアクティブ ユーザーの数を示す次のレポートが返されます。

{
  "funnelTable": {
    "dimensionHeaders": [
      {
        "name": "funnelStepName"
      },
      {
        "name": "deviceCategory"
      }
    ],
    "metricHeaders": [
      {
        "name": "activeUsers",
        "type": "TYPE_INTEGER"
      },
      {
        "name": "funnelStepCompletionRate",
        "type": "TYPE_INTEGER"
      },
      {
        "name": "funnelStepAbandonments",
        "type": "TYPE_INTEGER"
      },
      {
        "name": "funnelStepAbandonmentRate",
        "type": "TYPE_INTEGER"
      }
    ],
    "rows": [
      {
        "dimensionValues": [
          {
            "value": "1. First open/visit"
          },
          {
            "value": "RESERVED_TOTAL"
          }
        ],
        "metricValues": [
          {
            "value": "4621565"
          },
          {
            "value": "0.27780178359495106"
          },
          {
            "value": "3337686"
          },
          {
            "value": "0.72219821640504889"
          }
        ]
      },
      {
        "dimensionValues": [
          {
            "value": "1. First open/visit"
          },
          {
            "value": "desktop"
          }
        ],
        "metricValues": [
          {
            "value": "4015959"
          },
          {
            "value": "0.27425279989163237"
          },
          {
            "value": "2914571"
          },
          {
            "value": "0.72574720010836768"
          }
        ]
      },
      {
        "dimensionValues": [
          {
            "value": "1. First open/visit"
          },
          {
            "value": "mobile"
          }
        ],
        "metricValues": [
          {
            "value": "595760"
          },
          {
            "value": "0.29156035987646034"
          },
          {
            "value": "422060"
          },
          {
            "value": "0.70843964012353966"
          }
        ]
      },
      {
        "dimensionValues": [
          {
            "value": "1. First open/visit"
          },
          {
            "value": "tablet"
          }
        ],
        "metricValues": [
          {
            "value": "33638"
          },
          {
            "value": "0.205571080325822"
          },
          {
            "value": "26723"
          },
          {
            "value": "0.79442891967417806"
          }
        ]
      },

...

    ],
    "metadata": {
      "samplingMetadatas": [
        {
          "samplesReadCount": "9917254",
          "samplingSpaceSize": "1162365416"
        }
      ]
    }
  },

  "funnelVisualization": {
    "dimensionHeaders": [
      {
        "name": "funnelStepName"
      }
    ],
    "metricHeaders": [
      {
        "name": "activeUsers",
        "type": "TYPE_INTEGER"
      }
    ],
    "rows": [
      {
        "dimensionValues": [
          {
            "value": "1. First open/visit"
          }
        ],
        "metricValues": [
          {
            "value": "4621565"
          }
        ]
      },

...

    ],
    "metadata": {
      "samplingMetadatas": [
        {
          "samplesReadCount": "9917254",
          "samplingSpaceSize": "1162365416"
        }
      ]
    }
  },
  "kind": "analyticsData#runFunnelReport"
}

クライアント ライブラリ

クライアント ライブラリをインストールして構成する方法については、クイック スタートガイドをご覧ください。

以下に、ファネル クエリを実行してレスポンスを出力するクライアント ライブラリの使用例を示します。

Java

import com.google.analytics.data.v1alpha.AlphaAnalyticsDataClient;
import com.google.analytics.data.v1alpha.DateRange;
import com.google.analytics.data.v1alpha.Dimension;
import com.google.analytics.data.v1alpha.DimensionHeader;
import com.google.analytics.data.v1alpha.FunnelBreakdown;
import com.google.analytics.data.v1alpha.FunnelEventFilter;
import com.google.analytics.data.v1alpha.FunnelFieldFilter;
import com.google.analytics.data.v1alpha.FunnelFilterExpression;
import com.google.analytics.data.v1alpha.FunnelFilterExpressionList;
import com.google.analytics.data.v1alpha.FunnelStep;
import com.google.analytics.data.v1alpha.FunnelSubReport;
import com.google.analytics.data.v1alpha.MetricHeader;
import com.google.analytics.data.v1alpha.Row;
import com.google.analytics.data.v1alpha.RunFunnelReportRequest;
import com.google.analytics.data.v1alpha.RunFunnelReportResponse;
import com.google.analytics.data.v1alpha.SamplingMetadata;
import com.google.analytics.data.v1alpha.StringFilter;
import com.google.analytics.data.v1alpha.StringFilter.MatchType;

/**
 * Google Analytics Data API sample application demonstrating the creation of a funnel report.
 *
 * <p>See
 * https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1alpha/properties/runFunnelReport
 * for more information.
 *
 * <p>Before you start the application, please review the comments starting with "TODO(developer)"
 * and update the code to use correct values.
 *
 * <p>To run this sample using Maven:
 *
 * <pre>{@code
 * cd google-analytics-data
 * mvn compile exec:java -Dexec.mainClass="com.google.analytics.data.samples.RunFunnelReportSample"
 * }</pre>
 */
public class RunFunnelReportSample {

  public static void main(String... args) throws Exception {
    /**
     * TODO(developer): Replace this variable with your Google Analytics 4 property ID before
     * running the sample.
     */
    String propertyId = "YOUR-GA4-PROPERTY-ID";
    sampleRunFunnelReport(propertyId);
  }

  /**
   * Runs a funnel query to build a report with 5 funnel steps.
   *
   * <ol>
   *   <li>First open/visit (event name is `first_open` or `first_visit`).
   *   <li>Organic visitors (`firstUserMedium` dimension contains the term "organic").
   *   <li>Session start (event name is `session_start`).
   *   <li>Screen/Page view (event name is `screen_view` or `page_view`).
   *   <li>Purchase (event name is `purchase` or `in_app_purchase`).
   * </ol>
   *
   * The report configuration reproduces the default funnel report provided in the Funnel
   * Exploration template of the Google Analytics UI. See more at
   * https://support.google.com/analytics/answer/9327974
   */
  static void sampleRunFunnelReport(String propertyId) throws Exception {

    // Using a default constructor instructs the client to use the credentials
    // specified in GOOGLE_APPLICATION_CREDENTIALS environment variable.
    try (AlphaAnalyticsDataClient analyticsData = AlphaAnalyticsDataClient.create()) {
      RunFunnelReportRequest.Builder requestBuilder =
          RunFunnelReportRequest.newBuilder()
              .setProperty("properties/" + propertyId)
              .addDateRanges(DateRange.newBuilder().setStartDate("30daysAgo").setEndDate("today"))
              .setFunnelBreakdown(
                  FunnelBreakdown.newBuilder()
                      .setBreakdownDimension(Dimension.newBuilder().setName("deviceCategory")));

      // Adds each step of the funnel.
      requestBuilder
          .getFunnelBuilder()
          .addSteps(
              FunnelStep.newBuilder()
                  .setName("First open/visit")
                  .setFilterExpression(
                      FunnelFilterExpression.newBuilder()
                          .setOrGroup(
                              FunnelFilterExpressionList.newBuilder()
                                  .addExpressions(
                                      FunnelFilterExpression.newBuilder()
                                          .setFunnelEventFilter(
                                              FunnelEventFilter.newBuilder()
                                                  .setEventName("first_open")))
                                  .addExpressions(
                                      FunnelFilterExpression.newBuilder()
                                          .setFunnelEventFilter(
                                              FunnelEventFilter.newBuilder()
                                                  .setEventName("first_visit"))))));
      requestBuilder
          .getFunnelBuilder()
          .addSteps(
              FunnelStep.newBuilder()
                  .setName("Organic visitors")
                  .setFilterExpression(
                      FunnelFilterExpression.newBuilder()
                          .setFunnelFieldFilter(
                              FunnelFieldFilter.newBuilder()
                                  .setFieldName("firstUserMedium")
                                  .setStringFilter(
                                      StringFilter.newBuilder()
                                          .setMatchType(MatchType.CONTAINS)
                                          .setCaseSensitive(false)
                                          .setValue("organic")))));
      requestBuilder
          .getFunnelBuilder()
          .addSteps(
              FunnelStep.newBuilder()
                  .setName("Session start")
                  .setFilterExpression(
                      FunnelFilterExpression.newBuilder()
                          .setFunnelEventFilter(
                              FunnelEventFilter.newBuilder().setEventName("session_start"))));

      requestBuilder
          .getFunnelBuilder()
          .addSteps(
              FunnelStep.newBuilder()
                  .setName("Screen/Page view")
                  .setFilterExpression(
                      FunnelFilterExpression.newBuilder()
                          .setOrGroup(
                              FunnelFilterExpressionList.newBuilder()
                                  .addExpressions(
                                      FunnelFilterExpression.newBuilder()
                                          .setFunnelEventFilter(
                                              FunnelEventFilter.newBuilder()
                                                  .setEventName("screen_view")))
                                  .addExpressions(
                                      FunnelFilterExpression.newBuilder()
                                          .setFunnelEventFilter(
                                              FunnelEventFilter.newBuilder()
                                                  .setEventName("page_view"))))));
      requestBuilder
          .getFunnelBuilder()
          .addSteps(
              FunnelStep.newBuilder()
                  .setName("Purchase")
                  .setFilterExpression(
                      FunnelFilterExpression.newBuilder()
                          .setOrGroup(
                              FunnelFilterExpressionList.newBuilder()
                                  .addExpressions(
                                      FunnelFilterExpression.newBuilder()
                                          .setFunnelEventFilter(
                                              FunnelEventFilter.newBuilder()
                                                  .setEventName("purchase")))
                                  .addExpressions(
                                      FunnelFilterExpression.newBuilder()
                                          .setFunnelEventFilter(
                                              FunnelEventFilter.newBuilder()
                                                  .setEventName("in_app_purchase"))))));

      // Make the request.
      RunFunnelReportResponse response = analyticsData.runFunnelReport(requestBuilder.build());
      printRunFunnelReportResponse(response);
    }
  }

  /** Prints results of a runFunnelReport call. */
  static void printRunFunnelReportResponse(RunFunnelReportResponse response) {
    System.out.println("Report result:");
    System.out.println("=== FUNNEL VISUALIZATION ===");
    printFunnelSubReport(response.getFunnelVisualization());

    System.out.println("=== FUNNEL TABLE ===");
    printFunnelSubReport(response.getFunnelTable());
  }

  /** Prints the contents of a FunnelSubReport object. */
  private static void printFunnelSubReport(FunnelSubReport funnelSubReport) {
    System.out.println("Dimension headers:");
    for (DimensionHeader dimensionHeader : funnelSubReport.getDimensionHeadersList()) {
      System.out.println(dimensionHeader.getName());
    }
    System.out.println();

    System.out.println("Metric headers:");
    for (MetricHeader metricHeader : funnelSubReport.getMetricHeadersList()) {
      System.out.println(metricHeader.getName());
    }
    System.out.println();

    System.out.println("Dimension and metric values for each row in the report:");
    for (int rowIndex = 0; rowIndex < funnelSubReport.getRowsCount(); rowIndex++) {
      Row row = funnelSubReport.getRows(rowIndex);
      for (int fieldIndex = 0; fieldIndex < row.getDimensionValuesCount(); fieldIndex++) {
        System.out.printf(
            "%s: '%s'%n",
            funnelSubReport.getDimensionHeaders(fieldIndex).getName(),
            row.getDimensionValues(fieldIndex).getValue());
      }
      for (int fieldIndex = 0; fieldIndex < row.getMetricValuesCount(); fieldIndex++) {
        System.out.printf(
            "%s: '%s'%n",
            funnelSubReport.getMetricHeaders(fieldIndex).getName(),
            row.getMetricValues(fieldIndex).getValue());
      }
    }
    System.out.println();

    System.out.println("Sampling metadata for each date range:");
    for (int metadataIndex = 0;
        metadataIndex < funnelSubReport.getMetadata().getSamplingMetadatasCount();
        metadataIndex++) {
      SamplingMetadata samplingMetadata =
          funnelSubReport.getMetadata().getSamplingMetadatas(metadataIndex);
      System.out.printf(
          "Sampling metadata for date range #%d: samplesReadCount=%d, samplingSpaceSize=%d%n",
          metadataIndex,
          samplingMetadata.getSamplesReadCount(),
          samplingMetadata.getSamplingSpaceSize());
    }
  }
}

Python

from google.analytics.data_v1alpha import AlphaAnalyticsDataClient
from google.analytics.data_v1alpha.types import (
    DateRange,
    Dimension,
    Funnel,
    FunnelBreakdown,
    FunnelEventFilter,
    FunnelFieldFilter,
    FunnelFilterExpression,
    FunnelFilterExpressionList,
    FunnelStep,
    RunFunnelReportRequest,
    StringFilter,
)


def run_sample():
    """Runs the sample."""
    # TODO(developer): Replace this variable with your Google Analytics 4
    #  property ID before running the sample.
    property_id = "YOUR-GA4-PROPERTY-ID"
    run_funnel_report(property_id)


def run_funnel_report(property_id="YOUR-GA4-PROPERTY-ID"):
    """Runs a funnel query to build a report with 5 funnel steps.
      Step 1: First open/visit (event name is `first_open` or `first_visit`).
      Step 2: Organic visitors (`firstUserMedium` dimension contains the term
      "organic").
      Step 3: Session start (event name is `session_start`).
      Step 4: Screen/Page view (event name is `screen_view` or `page_view`).
      Step 5: Purchase (event name is `purchase` or `in_app_purchase`).

    The report configuration reproduces the default funnel report provided in
    the Funnel Exploration template of the Google Analytics UI.
    See more at https://support.google.com/analytics/answer/9327974
    """
    client = AlphaAnalyticsDataClient()

    request = RunFunnelReportRequest(
        property=f"properties/{property_id}",
        date_ranges=[DateRange(start_date="30daysAgo", end_date="today")],
        funnel_breakdown=FunnelBreakdown(
            breakdown_dimension=Dimension(name="deviceCategory")
        ),
        funnel=Funnel(
            steps=[
                FunnelStep(
                    name="First open/visit",
                    filter_expression=FunnelFilterExpression(
                        or_group=FunnelFilterExpressionList(
                            expressions=[
                                FunnelFilterExpression(
                                    funnel_event_filter=FunnelEventFilter(
                                        event_name="first_open"
                                    )
                                ),
                                FunnelFilterExpression(
                                    funnel_event_filter=FunnelEventFilter(
                                        event_name="first_visit"
                                    )
                                ),
                            ]
                        )
                    ),
                ),
                FunnelStep(
                    name="Organic visitors",
                    filter_expression=FunnelFilterExpression(
                        funnel_field_filter=FunnelFieldFilter(
                            field_name="firstUserMedium",
                            string_filter=StringFilter(
                                match_type=StringFilter.MatchType.CONTAINS,
                                case_sensitive=False,
                                value="organic",
                            ),
                        )
                    ),
                ),
                FunnelStep(
                    name="Session start",
                    filter_expression=FunnelFilterExpression(
                        funnel_event_filter=FunnelEventFilter(
                            event_name="session_start"
                        )
                    ),
                ),
                FunnelStep(
                    name="Screen/Page view",
                    filter_expression=FunnelFilterExpression(
                        or_group=FunnelFilterExpressionList(
                            expressions=[
                                FunnelFilterExpression(
                                    funnel_event_filter=FunnelEventFilter(
                                        event_name="screen_view"
                                    )
                                ),
                                FunnelFilterExpression(
                                    funnel_event_filter=FunnelEventFilter(
                                        event_name="page_view"
                                    )
                                ),
                            ]
                        )
                    ),
                ),
                FunnelStep(
                    name="Purchase",
                    filter_expression=FunnelFilterExpression(
                        or_group=FunnelFilterExpressionList(
                            expressions=[
                                FunnelFilterExpression(
                                    funnel_event_filter=FunnelEventFilter(
                                        event_name="purchase"
                                    )
                                ),
                                FunnelFilterExpression(
                                    funnel_event_filter=FunnelEventFilter(
                                        event_name="in_app_purchase"
                                    )
                                ),
                            ]
                        )
                    ),
                ),
            ]
        ),
    )
    response = client.run_funnel_report(request)
    print_run_funnel_report_response(response)


def print_funnel_sub_report(funnel_sub_report):
    """Prints the contents of a FunnelSubReport object."""
    print("Dimension headers:")
    for dimension_header in funnel_sub_report.dimension_headers:
        print(dimension_header.name)

    print("\nMetric headers:")
    for metric_header in funnel_sub_report.metric_headers:
        print(metric_header.name)

    print("\nDimensions and metric values for each row in the report:")
    for row_idx, row in enumerate(funnel_sub_report.rows):
        print("\nRow #{}".format(row_idx))
        for field_idx, dimension_value in enumerate(row.dimension_values):
            dimension_name = funnel_sub_report.dimension_headers[field_idx].name
            print("{}: '{}'".format(dimension_name, dimension_value.value))

        for field_idx, metric_value in enumerate(row.metric_values):
            metric_name = funnel_sub_report.metric_headers[field_idx].name
            print("{}: '{}'".format(metric_name, metric_value.value))

    print("\nSampling metadata for each date range:")
    for metadata_idx, metadata in enumerate(
        funnel_sub_report.metadata.sampling_metadatas
    ):
        print(
            "Sampling metadata for date range #{}: samplesReadCount={}, "
            "samplingSpaceSize={}".format(
                metadata_idx, metadata.samples_read_count, metadata.sampling_space_size
            )
        )


def print_run_funnel_report_response(response):
    """Prints results of a runFunnelReport call."""
    print("Report result:")
    print("=== FUNNEL VISUALIZATION ===")
    print_funnel_sub_report(response.funnel_visualization)

    print("=== FUNNEL TABLE ===")
    print_funnel_sub_report(response.funnel_table)