بررسی اجمالی

Google Analytics Data API v1 به شما امکان می دهد گزارش های قیف تولید کنید. کاوش قیف به شما این امکان را می‌دهد تا مراحلی را که کاربران برای تکمیل یک کار برمی‌دارند تجسم کنید و به سرعت ببینید که در هر مرحله چقدر موفق یا شکست می‌خورند.

ویژگی های مشترک با گزارش های اصلی

درخواست‌های گزارش‌دهی قیفی همان معنایی را با درخواست‌های گزارش اصلی برای بسیاری از ویژگی‌های مشترک دارند. برای مثال صفحه‌بندی، فیلترهای ابعاد و ویژگی‌های کاربر در گزارش‌های قیف مانند گزارش‌های اصلی رفتار می‌کنند. این راهنما بر ویژگی های گزارش قیف تمرکز دارد. برای آشنایی با عملکرد اصلی گزارش‌دهی Data API v1، راهنمای اصول گزارش‌دهی و همچنین راهنمای موارد استفاده پیشرفته را بخوانید.

روش گزارش قیفی

Data API v1 از عملکرد گزارش قیف در روش runFunnelReport پشتیبانی می کند. این روش یک گزارش قیف سفارشی از داده‌های رویداد Google Analytics شما را برمی‌گرداند.

انتخاب یک نهاد گزارشگر

همه روش‌های Data API v1 نیاز دارند که شناسه ویژگی Google Analytics 4 در یک مسیر درخواست URL به شکل properties/GA4_PROPERTY_ID مشخص شود، مانند:

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

گزارش حاصل بر اساس داده‌های رویداد Google Analytics جمع‌آوری‌شده در ویژگی Google Analytics 4 ایجاد می‌شود.

اگر از یکی از کتابخانه های سرویس گیرنده Data API استفاده می کنید، نیازی به دستکاری مسیر URL درخواست به صورت دستی نیست. اکثر سرویس گیرندگان API یک پارامتر property را ارائه می دهند که انتظار رشته ای به شکل properties/GA4_PROPERTY_ID را دارد. برای مثال هایی از استفاده از کتابخانه های سرویس گیرنده ، راهنمای شروع سریع را ببینید.

درخواست گزارش قیف

برای درخواست گزارش قیف، می توانید یک شی RunFunnelReportRequest بسازید. توصیه می کنیم با این پارامترهای درخواست شروع کنید:

  • یک ورودی معتبر در قسمت dateRanges .

  • یک مشخصات قیف معتبر در قسمت funnel .

مشخصات قیف

یک مشخصات قیف در فیلد funnel یک شی RunFunnelReportRequest ، سفر کاربر را که می‌خواهید با توصیف steps این قیف اندازه‌گیری کنید، تعریف می‌کند.

مراحل قیف شامل یک یا چند شرط است که کاربران شما باید آنها را داشته باشند تا در آن مرحله از سفر قیف قرار گیرند. شرایط گنجاندن در هر مرحله را می توان در قسمت filterExpression هر مرحله توضیح داد.

هر عبارت فیلتر قیفی ترکیبی از دو نوع فیلتر است:

  • funnelFieldFilter یک فیلتر برای یک بعد یا متریک ایجاد می کند.

  • funnelEventFilter فیلتری ایجاد می کند که رویدادهای یک نام رویداد را منطبق می کند. اگر یک فیلد اختیاری funnelParameterFilterExpression مشخص شده باشد، فقط زیرمجموعه رویدادهایی که با نام رویداد واحد و عبارات فیلتر پارامتر مطابقت دارند با این فیلتر رویداد مطابقت دارند.

فیلترها را می توان با استفاده از گروه های AND ، OR و همچنین با استفاده از عبارت NOT نفی کرد.

نتایج گزارش برای هر مرحله قیف بر اساس بعد و مشخص شده در قسمت funnelBreakdown تجزیه می شود.

نمونه گزارش قیف

بیایید از Google Analytics Data API v1 برای بازتولید گزارش قیف پیش‌فرض ارائه شده در قالب کاوش قیف رابط کاربری Google Analytics استفاده کنیم:

نمونه رابط کاربری گزارش قیف

مراحل قیف

پیکربندی قیف نشان داده شده در بالا شامل مراحل زیر است:

# نام مرحله وضعیت
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 راه اندازی کرده اند.

برای پیاده سازی این رفتار، قطعه زیر یک شی FunnelStep را با یک فیلد filterExpression مشخص می کند. فیلد بیان فیلتر یک شی FunnelFilterExpression است که با ترکیب دو موجودیت FunnelEventFilter با استفاده از یک گروه OR ساخته شده است.

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

مرحله 2 (بازدیدکنندگان ارگانیک) قیف شامل کاربرانی است که اولین رسانه آنها عبارت "ارگانیک" را شامل می شود. در قطعه زیر، فیلد fieldName از FunnelFieldFilter به فیلتر دستور می دهد تا با بعد firstUserMedium مطابقت داشته باشد. فیلد stringFilter شامل شرایطی است که فقط مقادیر بعد را شامل می شود که عبارت "ارگانیک" را در بر می گیرد.

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

مراحل باقی مانده قیف را می توان به روشی مشابه مشخص کرد.

بعد شکست

یک بعد تفکیک اختیاری ( deviceCategory در این مثال) را می توان با استفاده از یک شی FunnelBreakdown مشخص کرد:

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

به طور پیش فرض، تنها 5 مقدار متمایز اول بعد تفکیک در گزارش گنجانده شده است. می توانید از فیلد limit شی FunnelBreakdown برای لغو این رفتار استفاده کنید.

درخواست گزارش قیف را کامل کنید

در اینجا یک پرس و جو کامل است که با استفاده از تمام مراحل توضیح داده شده در بالا، یک گزارش قیف تولید می کند:

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 برگردانده می‌شوند: تجسم قیف و جدول قیف .

تجسم قیف

تجسم قیف، که در قسمت funnelVisualization در Funnel Report Response بازگردانده شده است، حاوی نمای کلی سطح بالایی از گزارش قیف است. همانطور که از نام آن پیداست، برای تجسم سریع گزارش قیف تولید شده مفید است.

هر ردیف از جدول تجسم قیف حاوی برخی یا همه فیلدهای زیر است:

  • نام مرحله قیف (بعد funnelStepName ).

  • تعداد کاربران فعال (متریک activeUsers ).

  • بخش (بعد segment ). تنها در صورتی ارائه شود که Segment در جستار قیف مشخص شده باشد.

  • تاریخ (بعد date ). تنها در صورتی ارائه شود که نوع تجسم TRENDED_FUNNEL در جستار مشخص شده باشد.

  • بعد اقدام بعدی (بعد funnelStepNextAction ). تنها در صورتی ارائه شود که FunnelNextAction در کوئری قیف مشخص شده باشد.

به این صورت است که رابط کاربری Google Analytics بخش تجسم قیف را در گزارش مثال مورد بحث در بالا نمایش می دهد:

سربرگ گزارش قیف: نمونه

میز قیفی

جدول قیف، که در قسمت funnelTable پاسخ گزارش قیف برگردانده شده است، بخش اصلی گزارش را نشان می دهد. هر ردیف از جدول شامل برخی یا همه فیلدهای زیر است:

  • نام مرحله قیف (بعد funnelStepName ).

  • بعد شکست.

  • تعداد کاربران فعال (متریک activeUsers ).

  • نرخ تکمیل مرحله (متریک funnelStepCompletionRate ).

  • تعداد دفعات رها شدن گام (متریک funnelStepAbandonments ).

  • نرخ رها شدن گام (متریک funnelStepAbandonmentRate ).

  • نام بخش (بعد segment ). تنها در صورتی ارائه شود که Segment در جستار قیف مشخص شده باشد.

مشابه عملکرد Core Reporting، مقادیر کل در یک ردیف جداگانه با RESERVED_TOTAL به عنوان مقدار بعد تفکیک بازگردانده می‌شوند.

در زیر نمونه ای از جدول قیف نمایش داده شده در رابط کاربری گوگل آنالیتیکس آورده شده است: جدول گزارش قیف: نمونه

پاسخ خام

قطعه زیر نمونه ای از داده های خام را نشان می دهد که در پاسخ به query 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"
}

کتابخانه های مشتری

برای توضیح نحوه نصب و پیکربندی کتابخانه های سرویس گیرنده، به راهنمای شروع سریع مراجعه کنید.

در زیر نمونه‌هایی با استفاده از کتابخانه‌های سرویس گیرنده وجود دارد که یک پرس و جوی قیف را اجرا می‌کنند و پاسخ را چاپ می‌کنند.

جاوا

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());
    }
  }
}

پایتون

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)