Tổng quan

Google Analytics Data API phiên bản 1 cho phép bạn tạo báo cáo phễu. Kỹ thuật khám phá phễu cho phép bạn biểu diễn các bước mà người dùng cần thực hiện để hoàn tất một hành động bằng hình ảnh, và xem nhanh mức độ mà họ hoàn tất hoặc không hoàn tất ở mỗi bước.

Các tính năng được chia sẻ với báo cáo chính

Các yêu cầu báo cáo phễu có cùng ngữ nghĩa với các yêu cầu báo cáo chính cho nhiều tính năng được chia sẻ. Ví dụ: tính năng phân trang, Bộ lọc phương diện và Thuộc tính người dùng hoạt động giống như trong Báo cáo phễu như Báo cáo chính. Hướng dẫn này tập trung vào các tính năng báo cáo phễu. Để làm quen với chức năng Báo cáo chính của Data API phiên bản 1, hãy đọc hướng dẫn cơ bản về báo cáo cũng như hướng dẫn các trường hợp sử dụng nâng cao.

Phương pháp báo cáo phễu

Data API v1 hỗ trợ chức năng báo cáo phễu trong phương thức runFunnelReport. Phương thức này trả về một báo cáo phễu tuỳ chỉnh gồm dữ liệu sự kiện Google Analytics.

Chọn đối tượng báo cáo

Tất cả các phương thức của Data API phiên bản 1 đều yêu cầu phải chỉ định giá trị nhận dạng thuộc tính Google Analytics 4 bên trong đường dẫn yêu cầu URL ở dạng properties/GA4_PROPERTY_ID, chẳng hạn như:

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

Báo cáo thu được sẽ được tạo dựa trên dữ liệu sự kiện Google Analytics được thu thập trong tài sản Google Analytics 4 được chỉ định.

Nếu đang sử dụng một trong những thư viện ứng dụng Data API, bạn không cần phải thao tác trên đường dẫn URL yêu cầu theo cách thủ công. Hầu hết các ứng dụng API đều cung cấp tham số property dự kiến sẽ có một chuỗi ở dạng properties/GA4_PROPERTY_ID. Xem Hướng dẫn bắt đầu nhanh để biết các ví dụ về cách sử dụng thư viện ứng dụng.

Yêu cầu báo cáo phễu

Để yêu cầu một báo cáo phễu, bạn có thể tạo đối tượng RunFunnelReportRequest. Bạn nên bắt đầu với các tham số yêu cầu sau:

  • Mục nhập hợp lệ trong trường dateRanges.

  • Thông số kỹ thuật về phễu hợp lệ trong trường funnel.

Thông số kỹ thuật phễu

Thông số kỹ thuật về phễu trong trường funnel của đối tượng RunFunnelReportRequest xác định hành trình của người dùng mà bạn muốn đo lường bằng cách mô tả steps của phễu này.

Các bước phễu chứa một hoặc nhiều điều kiện mà người dùng phải đáp ứng để được đưa vào bước đó trong hành trình phễu. Bạn có thể mô tả các điều kiện để đưa vào từng bước trong trường filterExpression của từng bước.

Mỗi biểu thức bộ lọc phễu là sự kết hợp của hai loại bộ lọc:

  • funnelFieldFilter tạo bộ lọc cho một phương diện hoặc chỉ số.

  • funnelEventFilter tạo bộ lọc khớp với các sự kiện thuộc một tên sự kiện duy nhất. Nếu bạn chỉ định một trường funnelParameterFilterExpression (không bắt buộc), thì chỉ có một số sự kiện khớp với cả tên sự kiện đơn lẻ và biểu thức lọc thông số mới khớp với bộ lọc sự kiện này.

Bạn có thể kết hợp các bộ lọc bằng cách sử dụng các nhóm AND, OR, cũng như loại bỏ bằng biểu thức NOT.

Kết quả báo cáo cho từng bước phễu sẽ được phân tích dựa trên phương diện và được chỉ định trong trường funnelBreakdown.

Ví dụ về báo cáo phễu

Hãy sử dụng Google Analytics Data API phiên bản 1 để tái tạo báo cáo phễu mặc định được cung cấp trong mẫu Khám phá phễu của giao diện người dùng Google Analytics:

Giao diện người dùng mẫu báo cáo phễu

Bước kênh

Cấu hình phễu được hiển thị ở trên bao gồm các bước sau:

# Tên bước Điều kiện
1 Người dùng mở/truy cập lần đầu Tên sự kiện là first_open hoặc first_visit.
2 Khách truy cập không phải trả tiền Phương diện firstUserMedium chứa từ khoá "tự nhiên".
3 Bắt đầu phiên hoạt động Tên sự kiện là session_start.
4 Người dùng đã xem màn hình/trang Tên sự kiện là screen_view hoặc page_view.
5 Mua hàng Tên sự kiện là purchase hoặc in_app_purchase.

Bước 1 (Lượt mở/lượt truy cập đầu tiên) của phễu bao gồm tất cả người dùng sau lượt tương tác đầu tiên của họ với một trang web hoặc ứng dụng, tức là những người dùng đã kích hoạt sự kiện first_open hoặc first_visit.

Để triển khai hành vi này, đoạn mã dưới đây chỉ định một đối tượng FunnelStep có trường filterExpression. Trường biểu thức lọc là một đối tượng FunnelFilterExpression được tạo bằng cách kết hợp 2 thực thể FunnelEventFilter thông qua nhóm OR.

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

Bước 2 (Khách truy cập tự nhiên) của phễu bao gồm những người dùng có phương tiện đầu tiên chứa từ "không phải trả tiền". Trong đoạn mã dưới đây, trường fieldName của FunnelFieldFilter hướng dẫn bộ lọc khớp với phương diện firstUserMedium. Trường stringFilter chứa một điều kiện để chỉ bao gồm các giá trị của kích thước có chứa từ "không phải trả tiền".

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

Bạn có thể chỉ định các bước trong phễu còn lại theo cách tương tự.

Phương diện phân tích

Bạn có thể chỉ định một phương diện phân tích không bắt buộc (trong ví dụ này là deviceCategory) bằng cách sử dụng đối tượng FunnelBreakdown:

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

Theo mặc định, chỉ có 5 giá trị riêng biệt đầu tiên của phương diện phân tích được đưa vào báo cáo. Bạn có thể dùng trường limit của đối tượng FunnelBreakdown để ghi đè hành vi này.

Truy vấn báo cáo phễu hoàn tất

Dưới đây là một truy vấn hoàn chỉnh tạo báo cáo phễu bằng cách sử dụng tất cả các bước được mô tả ở trên:

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"
                }
              }
            ]
          }
        }
      }
    ]
  }
}

Phản hồi báo cáo

Phản hồi báo cáo phễu của yêu cầu API báo cáo phễu bao gồm hai phần chính, cả hai phần đều được trả về dưới dạng một đối tượng FunnelSubReport: Hình ảnh hóa kênhBảng phễu.

Hình ảnh hóa kênh

Hình ảnh phễu được trả về trong trường funnelVisualization của Phản hồi báo cáo phễu chứa thông tin tổng quan về báo cáo phễu. Điều này rất hữu ích, đúng như tên gọi ngụ ý, giúp bạn xem nhanh báo cáo phễu đã tạo.

Mỗi hàng của bảng Hình ảnh hoá phễu chứa một số hoặc tất cả các trường sau:

  • Tên bước phễu (phương diện funnelStepName).

  • Số người dùng đang hoạt động (activeUsers chỉ số).

  • Phân đoạn (segment phương diện). Chỉ hiển thị nếu Segment được chỉ định trong truy vấn phễu.

  • Ngày (date phương diện). Chỉ hiển thị nếu kiểu hình ảnh TRENDED_FUNNEL được chỉ định trong truy vấn.

  • Phương diện hành động tiếp theo (funnelStepNextAction phương diện). Chỉ hiển thị nếu FunnelNextAction được chỉ định trong truy vấn phễu.

Đây là cách giao diện người dùng Google Analytics sẽ hiển thị phần Hình ảnh hóa kênh của báo cáo ví dụ được thảo luận ở trên:

Tiêu đề báo cáo phễu: mẫu

Bảng phễu

Bảng phễu, được trả về trong trường funnelTable của Phản hồi báo cáo phễu, đại diện cho phần chính của báo cáo. Mỗi hàng của bảng chứa một số hoặc tất cả các trường sau:

  • Tên bước phễu (phương diện funnelStepName).

  • Phương diện phân tích.

  • Số người dùng đang hoạt động (activeUsers chỉ số).

  • Tỷ lệ hoàn thành bước (chỉ số funnelStepCompletionRate).

  • Số lượt bỏ ngang bước (chỉ số funnelStepAbandonments).

  • Tỷ lệ bỏ ngang bước (chỉ số funnelStepAbandonmentRate).

  • Tên phân đoạn (segment phương diện). Chỉ hiển thị nếu Segment được chỉ định trong truy vấn phễu.

Tương tự như chức năng Báo cáo chính, tổng giá trị được trả về trong một hàng riêng biệt có RESERVED_TOTAL là giá trị phương diện phân tích.

Dưới đây là ví dụ về Bảng phễu hiển thị trong giao diện người dùng Google Analytics: Bảng báo cáo phễu: mẫu

Câu trả lời thô

Đoạn mã dưới đây minh hoạ một ví dụ về dữ liệu thô được trả về để phản hồi truy vấn runFunnelReport.

Tuỳ thuộc vào dữ liệu mà tài sản của bạn thu thập, báo cáo mẫu ở trên sẽ trả về báo cáo sau đây cho biết số lượng người dùng đang hoạt động có trong từng bước phễu.

{
  "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"
}

Thư viện ứng dụng

Hãy xem Hướng dẫn bắt đầu nhanh để được giải thích về cách cài đặt và định cấu hình thư viện ứng dụng.

Dưới đây là các ví dụ về cách sử dụng thư viện ứng dụng chạy một truy vấn phễu và in phản hồi.

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)