Überblick

Mit der Google Analytics Data API Version 1 können Sie Trichterberichte erstellen. Mit der explorativen Trichteranalyse können Sie die Schritte visualisieren, die Nutzer zum Abschließen einer Aufgabe durchlaufen. So sehen Sie auf einen Blick, wie erfolgreich die einzelnen Schritte abgeschlossen werden.

Gemeinsame Funktionen mit Kernberichten

Anfragen zu Trichterberichten haben für viele gemeinsam genutzte Funktionen dieselbe Semantik wie Anfragen für grundlegende Berichte. Beispielsweise verhalten sich die Dimensionsfilter und Nutzereigenschaften in Trichterberichten genauso wie grundlegende Berichte. Dieser Leitfaden befasst sich mit den Funktionen für Trichterberichte. Wenn Sie sich mit den Core Reporting-Funktionen der Data API Version 1 vertraut machen möchten, lesen Sie den Leitfaden Grundlagen der Berichterstellung und Erweiterte Anwendungsfälle.

Methode für Trichterberichte

Die Data API Version 1 unterstützt Trichterberichte in der Methode runFunnelReport. Mit dieser Methode wird ein benutzerdefinierter Trichterbericht mit Ihren Google Analytics-Ereignisdaten zurückgegeben.

Eine meldende Entität auswählen

Bei allen Methoden der Data API Version 1 muss die Google Analytics 4-Property-ID in einem URL-Anfragepfad im Format properties/GA4_PROPERTY_ID angegeben werden. Beispiel:

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

Der Bericht wird anhand der Google Analytics-Ereignisdaten generiert, die in der angegebenen Google Analytics 4-Property erfasst wurden.

Wenn Sie eine der Data API-Clientbibliotheken verwenden, müssen Sie den URL-Pfad der Anfrage nicht manuell bearbeiten. Die meisten API-Clients bieten einen property-Parameter, der einen String in Form von properties/GA4_PROPERTY_ID erwartet. Beispiele zur Verwendung der Clientbibliotheken finden Sie in der Kurzanleitung.

Trichterberichtsanfrage

Wenn Sie einen Trichterbericht anfordern möchten, können Sie ein RunFunnelReportRequest-Objekt erstellen. Wir empfehlen, mit diesen Anfrageparametern zu beginnen:

  • Ein gültiger Eintrag im Feld dateRanges.

  • Eine gültige Trichterspezifikation im Feld funnel.

Trichterspezifikation

Eine Trichterspezifikation im Feld funnel eines RunFunnelReportRequest-Objekts definiert den Kaufprozess, den Sie messen möchten, indem steps dieses Trichters beschrieben wird.

Trichterschritte enthalten eine oder mehrere Bedingungen, die Ihre Nutzer erfüllen müssen, um in diesen Schritt des Trichters einbezogen zu werden. Die Bedingungen für die Aufnahme in die einzelnen Schritte können im Feld filterExpression des jeweiligen Schritts beschrieben werden.

Jeder Trichterfilterausdruck ist eine Kombination aus zwei Arten von Filtern:

  • Mit funnelFieldFilter wird ein Filter für eine Dimension oder einen Messwert erstellt.

  • funnelEventFilter erstellt einen Filter, der den Ereignissen eines einzelnen Ereignisnamens entspricht. Wenn ein optionales Feld funnelParameterFilterExpression angegeben ist, entspricht nur die Teilmenge der Ereignisse, die sowohl dem einzelnen Ereignisnamen als auch den Parameterfilterausdrücken entsprechen, diesem Ereignisfilter.

Filter können mit AND- und OR-Gruppen kombiniert oder mit einem NOT-Ausdruck negiert werden.

Die Berichtsergebnisse für jeden Trichterschritt werden anhand der Dimension aufgeschlüsselt und im Feld funnelBreakdown angegeben.

Beispiel für einen Trichterbericht

Wir verwenden die Google Analytics Data API Version 1, um den Standardtrichterbericht zu reproduzieren, der in der Vorlage Explorative Trichteranalyse der Google Analytics-Benutzeroberfläche enthalten ist:

Beispiel für die Benutzeroberfläche eines Trichterberichts

Trichterschritte

Die oben gezeigte Trichterkonfiguration umfasst die folgenden Schritte:

# Schrittname Bedingung
1 Erst. Öffnen/Besuch Ereignisname ist „first_open“ oder „first_visit“.
2 Organische (d. h. mit unbezahlter Suche herbeigeführte) Besuche Die Dimension firstUserMedium enthält den Begriff „organisch“.
3 Sitzungsstart Ereignisname lautet „session_start“.
4 Bildschirm-/Seitenaufruf Ereignisname ist „screen_view“ oder „page_view“.
5 Kaufen Ereignisname ist „purchase“ oder „in_app_purchase“.

Schritt 1 (Erstes Öffnen/Besuch) des Trichters umfasst alle Nutzer nach ihrer ersten Interaktion mit einer Website oder Anwendung, also Nutzer, die first_open- oder first_visit-Ereignisse ausgelöst haben.

Um dieses Verhalten zu implementieren, wird im folgenden Snippet ein FunnelStep-Objekt mit einem filterExpression-Feld angegeben. Das Filterausdruckfeld ist ein FunnelFilterExpression-Objekt, das durch Kombination von zwei FunnelEventFilter-Entitäten mithilfe einer OR-Gruppe erstellt wird.

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

Schritt 2 (organische Besucher) des Trichters umfasst Nutzer, deren erstes Medium den Begriff „organisch“ enthält. Im folgenden Snippet wird der Filter im Feld fieldName von FunnelFieldFilter angewiesen, der Dimension firstUserMedium zu entsprechen. Das Feld stringFilter enthält eine Bedingung, mit der nur die Werte der Dimension einbezogen werden, die den Begriff „organic“ enthalten.

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

Die restlichen Schritte im Trichter können auf ähnliche Weise angegeben werden.

Aufschlüsselungsdimension

Eine optionale Aufschlüsselungsdimension (in diesem Beispiel deviceCategory) kann mit einem FunnelBreakdown-Objekt angegeben werden:

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

Standardmäßig werden nur die ersten fünf Werte der Aufschlüsselungsdimension in den Bericht aufgenommen. Mit dem Feld limit des FunnelBreakdown-Objekts können Sie dieses Verhalten überschreiben.

Anfrage zum Vollständigen Trichterbericht

Hier ist eine vollständige Abfrage, mit der mit allen oben beschriebenen Schritten ein Trichterbericht erstellt wird:

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

Antwort melden

Die Trichterberichtantwort einer API-Anfrage für Trichterberichte besteht aus zwei Hauptteilen, die beide als FunnelSubReport-Objekt zurückgegeben werden: Trichtervisualisierung und Trichtertabelle.

Trichter-Visualisierung

Die Trichter-Visualisierung wird im Feld funnelVisualization der Antwort auf Trichterbericht zurückgegeben und enthält eine allgemeine Übersicht des Trichterberichts. Wie der Name schon sagt, ist dies nützlich, um den generierten Trichterbericht schnell darzustellen.

Jede Zeile der Tabelle zur Trichtervisualisierung enthält einige oder alle der folgenden Felder:

  • Name des Schritts im Trichter (funnelStepName Dimension).

  • Anzahl der aktiven Nutzer (activeUsers Messwert).

  • Segment (segment Dimension). Ist nur vorhanden, wenn in der Trichterabfrage Segment angegeben ist.

  • Datum (date Dimension). Ist nur vorhanden, wenn der Visualisierungstyp TRENDED_FUNNEL in der Abfrage angegeben wurde.

  • Nächste Aktionsdimension (funnelStepNextAction Dimension). Ist nur vorhanden, wenn FunnelNextAction in der Trichterabfrage angegeben ist.

So würde der Abschnitt „Trichtervisualisierung“ des oben erläuterten Beispielberichts in der Google Analytics-Benutzeroberfläche angezeigt werden:

Überschriften des Trichterberichts: Beispiel

Trichtertabelle

Die Trichtertabelle wird im Feld funnelTable der Antwort auf Trichterbericht zurückgegeben und stellt den Hauptteil des Berichts dar. Jede Zeile der Tabelle enthält einige oder alle der folgenden Felder:

  • Name des Schritts im Trichter (funnelStepName Dimension).

  • Aufschlüsselungsdimension.

  • Anzahl der aktiven Nutzer (activeUsers Messwert).

  • Schrittabschlussrate (Messwert: funnelStepCompletionRate).

  • Anzahl der Ausstiege in einem Schritt (Messwert: funnelStepAbandonments).

  • Ausstiegsrate für diesen Schritt (Messwert: funnelStepAbandonmentRate).

  • Segmentname (segment Dimension). Ist nur vorhanden, wenn in der Trichterabfrage Segment angegeben ist.

Ähnlich wie bei den grundlegenden Funktionen zur Berichterstellung werden Gesamtwerte in einer separaten Zeile zurückgegeben, die RESERVED_TOTAL als Aufschlüsselungsdimensionswert hat.

Unten sehen Sie ein Beispiel für die Trichtertabelle, die in der Google Analytics-Benutzeroberfläche angezeigt wird: Berichtstabelle „Trichter“: Stichprobe

Rohantwort

Das folgende Snippet zeigt ein Beispiel für Rohdaten, die als Antwort auf die runFunnelReport-Abfrage zurückgegeben werden.

Abhängig von den von Ihrer Property erfassten Daten würde der Beispielbericht oben den folgenden Bericht mit der Anzahl der aktiven Nutzer in jedem Trichterschritt anzeigen.

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

Clientbibliotheken

In der Kurzanleitung wird beschrieben, wie Sie Clientbibliotheken installieren und konfigurieren.

Im Folgenden finden Sie Beispiele für die Verwendung von Clientbibliotheken, die eine Trichterabfrage ausführen und die Antwort ausgeben.

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)