// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

syntax = "proto3";

package google.analytics.data.v1alpha;

import "google/protobuf/duration.proto";

option go_package = "google.golang.org/genproto/googleapis/analytics/data/v1alpha;data";
option java_multiple_files = true;
option java_outer_classname = "ReportingApiProto";
option java_package = "com.google.analytics.data.v1alpha";

// A contiguous set of days: `startDate`, `startDate + 1`, ..., `endDate`.
// Requests are allowed up to 4 date ranges.
message DateRange {
  // The inclusive start date for the query in the format `YYYY-MM-DD`. Cannot
  // be after `end_date`. The format `NdaysAgo`, `yesterday`, or `today` is also
  // accepted, and in that case, the date is inferred based on the property's
  // reporting time zone.
  string start_date = 1;

  // The inclusive end date for the query in the format `YYYY-MM-DD`. Cannot
  // be before `start_date`. The format `NdaysAgo`, `yesterday`, or `today` is
  // also accepted, and in that case, the date is inferred based on the
  // property's reporting time zone.
  string end_date = 2;

  // Assigns a name to this date range. The dimension `dateRange` is valued to
  // this name in a report response. If set, cannot begin with `date_range_` or
  // `RESERVED_`. If not set, date ranges are named by their zero based index in
  // the request: `date_range_0`, `date_range_1`, etc.
  string name = 3;
}

// Dimensions are attributes of your data. For example, the dimension city
// indicates the city from which an event originates. Dimension values in report
// responses are strings; for example, the city could be "Paris" or "New York".
message Dimension {
  // The name of the dimension. See the [API
  // Dimensions](https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema#dimensions)
  // for the list of dimension names supported by core reporting methods such
  // as `runReport` and `batchRunReports`. See
  // [Realtime
  // Dimensions](https://developers.google.com/analytics/devguides/reporting/data/v1/realtime-api-schema#dimensions)
  // for the list of dimension names supported by the `runRealtimeReport`
  // method. See
  // [Funnel
  // Dimensions](https://developers.google.com/analytics/devguides/reporting/data/v1/exploration-api-schema#dimensions)
  // for the list of dimension names supported by the `runFunnelReport`
  // method.
  //
  // If `dimensionExpression` is specified, `name` can be any string that you
  // would like within the allowed character set. For example if a
  // `dimensionExpression` concatenates `country` and `city`, you could call
  // that dimension `countryAndCity`. Dimension names that you choose must match
  // the regular expression `^[a-zA-Z0-9_]$`.
  //
  // Dimensions are referenced by `name` in `dimensionFilter`, `orderBys`,
  // `dimensionExpression`, and `pivots`.
  string name = 1;

  // One dimension can be the result of an expression of multiple dimensions.
  // For example, dimension "country, city": concatenate(country, ", ", city).
  DimensionExpression dimension_expression = 2;
}

// Used to express a dimension which is the result of a formula of multiple
// dimensions. Example usages:
// 1) lower_case(dimension)
// 2) concatenate(dimension1, symbol, dimension2).
message DimensionExpression {
  // Used to convert a dimension value to a single case.
  message CaseExpression {
    // Name of a dimension. The name must refer back to a name in dimensions
    // field of the request.
    string dimension_name = 1;
  }

  // Used to combine dimension values to a single dimension.
  message ConcatenateExpression {
    // Names of dimensions. The names must refer back to names in the dimensions
    // field of the request.
    repeated string dimension_names = 1;

    // The delimiter placed between dimension names.
    //
    // Delimiters are often single characters such as "|" or "," but can be
    // longer strings. If a dimension value contains the delimiter, both will be
    // present in response with no distinction. For example if dimension 1 value
    // = "US,FR", dimension 2 value = "JP", and delimiter = ",", then the
    // response will contain "US,FR,JP".
    string delimiter = 2;
  }

  // Specify one type of dimension expression for `DimensionExpression`.
  oneof one_expression {
    // Used to convert a dimension value to lower case.
    CaseExpression lower_case = 4;

    // Used to convert a dimension value to upper case.
    CaseExpression upper_case = 5;

    // Used to combine dimension values to a single dimension.
    // For example, dimension "country, city": concatenate(country, ", ", city).
    ConcatenateExpression concatenate = 6;
  }
}

// The quantitative measurements of a report. For example, the metric
// `eventCount` is the total number of events. Requests are allowed up to 10
// metrics.
message Metric {
  // The name of the metric. See the [API
  // Metrics](https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema#metrics)
  // for the list of metric names supported by core reporting methods such
  // as `runReport` and `batchRunReports`. See
  // [Realtime
  // Metrics](https://developers.google.com/analytics/devguides/reporting/data/v1/realtime-api-schema#metrics)
  // for the list of metric names supported by the `runRealtimeReport`
  // method. See
  // [Funnel
  // Metrics](https://developers.google.com/analytics/devguides/reporting/data/v1/exploration-api-schema#metrics)
  // for the list of metric names supported by the `runFunnelReport`
  // method.
  //
  // If `expression` is specified, `name` can be any string that you would like
  // within the allowed character set. For example if `expression` is
  // `screenPageViews/sessions`, you could call that metric's name =
  // `viewsPerSession`. Metric names that you choose must match the regular
  // expression `^[a-zA-Z0-9_]$`.
  //
  // Metrics are referenced by `name` in `metricFilter`, `orderBys`, and metric
  // `expression`.
  string name = 1;

  // A mathematical expression for derived metrics. For example, the metric
  // Event count per user is `eventCount/totalUsers`.
  string expression = 2;

  // Indicates if a metric is invisible in the report response. If a metric is
  // invisible, the metric will not produce a column in the response, but can be
  // used in `metricFilter`, `orderBys`, or a metric `expression`.
  bool invisible = 3;
}

// To express dimension or metric filters. The fields in the same
// FilterExpression need to be either all dimensions or all metrics.
message FilterExpression {
  // Specify one type of filter expression for `FilterExpression`.
  oneof expr {
    // The FilterExpressions in and_group have an AND relationship.
    FilterExpressionList and_group = 1;

    // The FilterExpressions in or_group have an OR relationship.
    FilterExpressionList or_group = 2;

    // The FilterExpression is NOT of not_expression.
    FilterExpression not_expression = 3;

    // A primitive filter. In the same FilterExpression, all of the filter's
    // field names need to be either all dimensions or all metrics.
    Filter filter = 4;
  }
}

// A list of filter expressions.
message FilterExpressionList {
  // A list of filter expressions.
  repeated FilterExpression expressions = 1;
}

// An expression to filter dimension or metric values.
message Filter {
  // The dimension name or metric name. Must be a name defined in dimensions
  // or metrics.
  string field_name = 1;

  // Specify one type of filter for `Filter`.
  oneof one_filter {
    // Strings related filter.
    StringFilter string_filter = 2;

    // A filter for in list values.
    InListFilter in_list_filter = 3;

    // A filter for numeric or date values.
    NumericFilter numeric_filter = 4;

    // A filter for between two values.
    BetweenFilter between_filter = 5;
  }
}

// The filter for string
message StringFilter {
  // The match type of a string filter
  enum MatchType {
    // Unspecified
    MATCH_TYPE_UNSPECIFIED = 0;

    // Exact match of the string value.
    EXACT = 1;

    // Begins with the string value.
    BEGINS_WITH = 2;

    // Ends with the string value.
    ENDS_WITH = 3;

    // Contains the string value.
    CONTAINS = 4;

    // Full match for the regular expression with the string value.
    FULL_REGEXP = 5;

    // Partial match for the regular expression with the string value.
    PARTIAL_REGEXP = 6;
  }

  // The match type for this filter.
  MatchType match_type = 1;

  // The string value used for the matching.
  string value = 2;

  // If true, the string value is case sensitive.
  bool case_sensitive = 3;
}

// The result needs to be in a list of string values.
message InListFilter {
  // The list of string values.
  // Must be non-empty.
  repeated string values = 1;

  // If true, the string value is case sensitive.
  bool case_sensitive = 2;
}

// Filters for numeric or date values.
message NumericFilter {
  // The operation applied to a numeric filter
  enum Operation {
    // Unspecified.
    OPERATION_UNSPECIFIED = 0;

    // Equal
    EQUAL = 1;

    // Less than
    LESS_THAN = 2;

    // Less than or equal
    LESS_THAN_OR_EQUAL = 3;

    // Greater than
    GREATER_THAN = 4;

    // Greater than or equal
    GREATER_THAN_OR_EQUAL = 5;
  }

  // The operation type for this filter.
  Operation operation = 1;

  // A numeric value or a date value.
  NumericValue value = 2;
}

// Order bys define how rows will be sorted in the response. For example,
// ordering rows by descending event count is one ordering, and ordering rows by
// the event name string is a different ordering.
message OrderBy {
  // Sorts by metric values.
  message MetricOrderBy {
    // A metric name in the request to order by.
    string metric_name = 1;
  }

  // Sorts by dimension values.
  message DimensionOrderBy {
    // Rule to order the string dimension values by.
    enum OrderType {
      // Unspecified.
      ORDER_TYPE_UNSPECIFIED = 0;

      // Alphanumeric sort by Unicode code point. For example, "2" < "A" < "X" <
      // "b" < "z".
      ALPHANUMERIC = 1;

      // Case insensitive alphanumeric sort by lower case Unicode code point.
      // For example, "2" < "A" < "b" < "X" < "z".
      CASE_INSENSITIVE_ALPHANUMERIC = 2;

      // Dimension values are converted to numbers before sorting. For example
      // in NUMERIC sort, "25" < "100", and in `ALPHANUMERIC` sort, "100" <
      // "25". Non-numeric dimension values all have equal ordering value below
      // all numeric values.
      NUMERIC = 3;
    }

    // A dimension name in the request to order by.
    string dimension_name = 1;

    // Controls the rule for dimension value ordering.
    OrderType order_type = 2;
  }

  // Specify one type of order by for `OrderBy`.
  oneof one_order_by {
    // Sorts results by a metric's values.
    MetricOrderBy metric = 1;

    // Sorts results by a dimension's values.
    DimensionOrderBy dimension = 2;
  }

  // If true, sorts by descending order.
  bool desc = 4;
}

// To express that the result needs to be between two numbers (inclusive).
message BetweenFilter {
  // Begins with this number.
  NumericValue from_value = 1;

  // Ends with this number.
  NumericValue to_value = 2;
}

// To represent a number.
message NumericValue {
  // One of a numeric value
  oneof one_value {
    // Integer value
    int64 int64_value = 1;

    // Double value
    double double_value = 2;
  }
}

// The specification of cohorts for a cohort report.
//
// Cohort reports create a time series of user retention for the cohort. For
// example, you could select the cohort of users that were acquired in the first
// week of September and follow that cohort for the next six weeks. Selecting
// the users acquired in the first week of September cohort is specified in the
// `cohort` object. Following that cohort for the next six weeks is specified in
// the `cohortsRange` object.
//
// For examples, see [Cohort Report
// Examples](https://developers.google.com/analytics/devguides/reporting/data/v1/advanced#cohort_report_examples).
//
// The report response could show a weekly time series where say your app has
// retained 60% of this cohort after three weeks and 25% of this cohort after
// six weeks. These two percentages can be calculated by the metric
// `cohortActiveUsers/cohortTotalUsers` and will be separate rows in the report.
message CohortSpec {
  // Defines the selection criteria to group users into cohorts.
  //
  // Most cohort reports define only a single cohort. If multiple cohorts are
  // specified, each cohort can be recognized in the report by their name.
  repeated Cohort cohorts = 1;

  // Cohort reports follow cohorts over an extended reporting date range. This
  // range specifies an offset duration to follow the cohorts over.
  CohortsRange cohorts_range = 2;

  // Optional settings for a cohort report.
  CohortReportSettings cohort_report_settings = 3;
}

// Defines a cohort selection criteria. A cohort is a group of users who share
// a common characteristic. For example, users with the same `firstSessionDate`
// belong to the same cohort.
message Cohort {
  // Assigns a name to this cohort. The dimension `cohort` is valued to this
  // name in a report response. If set, cannot begin with `cohort_` or
  // `RESERVED_`. If not set, cohorts are named by their zero based index
  // `cohort_0`, `cohort_1`, etc.
  string name = 1;

  // Dimension used by the cohort. Required and only supports
  // `firstSessionDate`.
  string dimension = 2;

  // The cohort selects users whose first touch date is between start date and
  // end date defined in the `dateRange`. This `dateRange` does not specify the
  // full date range of event data that is present in a cohort report. In a
  // cohort report, this `dateRange` is extended by the granularity and offset
  // present in the `cohortsRange`; event data for the extended reporting date
  // range is present in a cohort report.
  //
  // In a cohort request, this `dateRange` is required and the `dateRanges` in
  // the `RunReportRequest` or `RunPivotReportRequest` must be unspecified.
  //
  // This `dateRange` should generally be aligned with the cohort's granularity.
  // If `CohortsRange` uses daily granularity, this `dateRange` can be a single
  // day. If `CohortsRange` uses weekly granularity, this `dateRange` can be
  // aligned to a week boundary, starting at Sunday and ending Saturday. If
  // `CohortsRange` uses monthly granularity, this `dateRange` can be aligned to
  // a month, starting at the first and ending on the last day of the month.
  DateRange date_range = 3;
}

// Configures the extended reporting date range for a cohort report. Specifies
// an offset duration to follow the cohorts over.
message CohortsRange {
  // The granularity used to interpret the `startOffset` and `endOffset` for the
  // extended reporting date range for a cohort report.
  enum Granularity {
    // Should never be specified.
    GRANULARITY_UNSPECIFIED = 0;

    // Daily granularity. Commonly used if the cohort's `dateRange` is a single
    // day and the request contains `cohortNthDay`.
    DAILY = 1;

    // Weekly granularity. Commonly used if the cohort's `dateRange` is a week
    // in duration (starting on Sunday and ending on Saturday) and the request
    // contains `cohortNthWeek`.
    WEEKLY = 2;

    // Monthly granularity. Commonly used if the cohort's `dateRange` is a month
    // in duration and the request contains `cohortNthMonth`.
    MONTHLY = 3;
  }

  // Required. The granularity used to interpret the `startOffset` and
  // `endOffset` for the extended reporting date range for a cohort report.
  Granularity granularity = 1;

  // `startOffset` specifies the start date of the extended reporting date range
  // for a cohort report. `startOffset` is commonly set to 0 so that reports
  // contain data from the acquisition of the cohort forward.
  //
  // If `granularity` is `DAILY`, the `startDate` of the extended reporting date
  // range is `startDate` of the cohort plus `startOffset` days.
  //
  // If `granularity` is `WEEKLY`, the `startDate` of the extended reporting
  // date range is `startDate` of the cohort plus `startOffset * 7` days.
  //
  // If `granularity` is `MONTHLY`, the `startDate` of the extended reporting
  // date range is `startDate` of the cohort plus `startOffset * 30` days.
  int32 start_offset = 2;

  // Required. `endOffset` specifies the end date of the extended reporting date
  // range for a cohort report. `endOffset` can be any positive integer but is
  // commonly set to 5 to 10 so that reports contain data on the cohort for the
  // next several granularity time periods.
  //
  // If `granularity` is `DAILY`, the `endDate` of the extended reporting date
  // range is `endDate` of the cohort plus `endOffset` days.
  //
  // If `granularity` is `WEEKLY`, the `endDate` of the extended reporting date
  // range is `endDate` of the cohort plus `endOffset * 7` days.
  //
  // If `granularity` is `MONTHLY`, the `endDate` of the extended reporting date
  // range is `endDate` of the cohort plus `endOffset * 30` days.
  int32 end_offset = 3;
}

// Optional settings of a cohort report.
message CohortReportSettings {
  // If true, accumulates the result from first touch day to the end day. Not
  // supported in `RunReportRequest`.
  bool accumulate = 1;
}

// Response's metadata carrying additional information about the report content.
message ResponseMetaData {
  // The schema restrictions actively enforced in creating this report. To learn
  // more, see [Access and data-restriction
  // management](https://support.google.com/analytics/answer/10851388).
  message SchemaRestrictionResponse {
    // A metric actively restricted in creating the report.
    message ActiveMetricRestriction {
      // The name of the restricted metric.
      optional string metric_name = 1;

      // The reason for this metric's restriction.
      repeated RestrictedMetricType restricted_metric_types = 2;
    }

    // All restrictions actively enforced in creating the report. For example,
    // `purchaseRevenue` always has the restriction type `REVENUE_DATA`.
    // However, this active response restriction is only populated if the user's
    // custom role disallows access to `REVENUE_DATA`.
    repeated ActiveMetricRestriction active_metric_restrictions = 1;
  }

  // If true, indicates some buckets of dimension combinations are rolled into
  // "(other)" row. This can happen for high cardinality reports.
  //
  // The metadata parameter dataLossFromOtherRow is populated based on the
  // aggregated data table used in the report. The parameter will be accurately
  // populated regardless of the filters and limits in the report.
  //
  // For example, the (other) row could be dropped from the report because the
  // request contains a filter on sessionSource = google. This parameter will
  // still be populated if data loss from other row was present in the input
  // aggregate data used to generate this report.
  //
  // To learn more, see [About the (other) row and data
  // sampling](https://support.google.com/analytics/answer/13208658#reports).
  bool data_loss_from_other_row = 3;

  // Describes the schema restrictions actively enforced in creating this
  // report. To learn more, see [Access and data-restriction
  // management](https://support.google.com/analytics/answer/10851388).
  optional SchemaRestrictionResponse schema_restriction_response = 4;

  // The currency code used in this report. Intended to be used in formatting
  // currency metrics like `purchaseRevenue` for visualization. If currency_code
  // was specified in the request, this response parameter will echo the request
  // parameter; otherwise, this response parameter is the property's current
  // currency_code.
  //
  // Currency codes are string encodings of currency types from the ISO 4217
  // standard (https://en.wikipedia.org/wiki/ISO_4217); for example "USD",
  // "EUR", "JPY". To learn more, see
  // https://support.google.com/analytics/answer/9796179.
  optional string currency_code = 5;

  // The property's current timezone. Intended to be used to interpret
  // time-based dimensions like `hour` and `minute`. Formatted as strings from
  // the IANA Time Zone database (https://www.iana.org/time-zones); for example
  // "America/New_York" or "Asia/Tokyo".
  optional string time_zone = 6;

  // If empty reason is specified, the report is empty for this reason.
  optional string empty_reason = 7;

  // If `subjectToThresholding` is true, this report is subject to thresholding
  // and only returns data that meets the minimum aggregation thresholds. It is
  // possible for a request to be subject to thresholding thresholding and no
  // data is absent from the report, and this happens when all data is above the
  // thresholds. To learn more, see [Data
  // thresholds](https://support.google.com/analytics/answer/9383630) and [About
  // Demographics and
  // Interests](https://support.google.com/analytics/answer/2799357).
  optional bool subject_to_thresholding = 8;
}

// Describes a dimension column in the report. Dimensions requested in a report
// produce column entries within rows and DimensionHeaders. However, dimensions
// used exclusively within filters or expressions do not produce columns in a
// report; correspondingly, those dimensions do not produce headers.
message DimensionHeader {
  // The dimension's name.
  string name = 1;
}

// Describes a metric column in the report. Visible metrics requested in a
// report produce column entries within rows and MetricHeaders. However,
// metrics used exclusively within filters or expressions do not produce columns
// in a report; correspondingly, those metrics do not produce headers.
message MetricHeader {
  // The metric's name.
  string name = 1;

  // The metric's data type.
  MetricType type = 2;
}

// Report data for each row.
// For example if RunReportRequest contains:
//
// ```none
// "dimensions": [
//   {
//     "name": "eventName"
//   },
//   {
//     "name": "countryId"
//   }
// ],
// "metrics": [
//   {
//     "name": "eventCount"
//   }
// ]
// ```
//
// One row with 'in_app_purchase' as the eventName, 'JP' as the countryId, and
// 15 as the eventCount, would be:
//
// ```none
// "dimensionValues": [
//   {
//     "value": "in_app_purchase"
//   },
//   {
//     "value": "JP"
//   }
// ],
// "metricValues": [
//   {
//     "value": "15"
//   }
// ]
// ```
message Row {
  // List of requested dimension values. In a PivotReport, dimension_values
  // are only listed for dimensions included in a pivot.
  repeated DimensionValue dimension_values = 1;

  // List of requested visible metric values.
  repeated MetricValue metric_values = 2;
}

// The value of a dimension.
message DimensionValue {
  // One kind of dimension value
  oneof one_value {
    // Value as a string if the dimension type is a string.
    string value = 1;
  }
}

// The value of a metric.
message MetricValue {
  // One of metric value
  oneof one_value {
    // Measurement value. See MetricHeader for type.
    string value = 4;
  }
}

// Current state of all quotas for this Analytics Property. If any quota for a
// property is exhausted, all requests to that property will return Resource
// Exhausted errors.
message PropertyQuota {
  // Standard Analytics Properties can use up to 200,000 tokens per day;
  // Analytics 360 Properties can use 2,000,000 tokens per day. Most requests
  // consume fewer than 10 tokens.
  QuotaStatus tokens_per_day = 1;

  // Standard Analytics Properties can use up to 40,000 tokens per hour;
  // Analytics 360 Properties can use 400,000 tokens per hour. An API request
  // consumes a single number of tokens, and that number is deducted from all of
  // the hourly, daily, and per project hourly quotas.
  QuotaStatus tokens_per_hour = 2;

  // Standard Analytics Properties can send up to 10 concurrent requests;
  // Analytics 360 Properties can use up to 50 concurrent requests.
  QuotaStatus concurrent_requests = 3;

  // Standard Analytics Properties and cloud project pairs can have up to 10
  // server errors per hour; Analytics 360 Properties and cloud project pairs
  // can have up to 50 server errors per hour.
  QuotaStatus server_errors_per_project_per_hour = 4;

  // Analytics Properties can send up to 120 requests with potentially
  // thresholded dimensions per hour. In a batch request, each report request
  // is individually counted for this quota if the request contains potentially
  // thresholded dimensions.
  QuotaStatus potentially_thresholded_requests_per_hour = 5;

  // Analytics Properties can use up to 35% of their tokens per project per
  // hour. This amounts to standard Analytics Properties can use up to 14,000
  // tokens per project per hour, and Analytics 360 Properties can use 140,000
  // tokens per project per hour. An API request consumes a single number of
  // tokens, and that number is deducted from all of the hourly, daily, and per
  // project hourly quotas.
  QuotaStatus tokens_per_project_per_hour = 6;
}

// Current state for a particular quota group.
message QuotaStatus {
  // Quota consumed by this request.
  int32 consumed = 1;

  // Quota remaining after this request.
  int32 remaining = 2;
}

// Breakdowns add a dimension to the funnel table sub report response.
message FunnelBreakdown {
  // The dimension column added to the funnel table sub report response. The
  // breakdown dimension breaks down each funnel step. A valid
  // `breakdownDimension` is required if `funnelBreakdown` is specified.
  Dimension breakdown_dimension = 1;

  // The maximum number of distinct values of the breakdown dimension to return
  // in the response. A `limit` of `5` is used if limit is not specified. Limit
  // must exceed zero and cannot exceed 15.
  optional int64 limit = 2;
}

// Next actions state the value for a dimension after the user has achieved
// a step but before the same user has achieved the next step. For example if
// the `nextActionDimension` is `eventName`, then `nextActionDimension` in the
// `i`th funnel step row will return first event after the event that qualified
// the user into the `i`th funnel step but before the user achieved the `i+1`th
// funnel step.
message FunnelNextAction {
  // The dimension column added to the funnel visualization sub report response.
  // The next action dimension returns the next dimension value of this
  // dimension after the user has attained the `i`th funnel step.
  //
  // `nextActionDimension` currently only supports `eventName` and most Page /
  // Screen dimensions like `pageTitle` and `pagePath`. `nextActionDimension`
  // cannot be a dimension expression.
  Dimension next_action_dimension = 1;

  // The maximum number of distinct values of the breakdown dimension to return
  // in the response. A `limit` of `5` is used if limit is not specified. Limit
  // must exceed zero and cannot exceed 5.
  optional int64 limit = 2;
}

// Configures the funnel in a funnel report request. A funnel reports on users
// as they pass through a sequence of steps.
//
// Funnel exploration lets you visualize the steps your users take to complete a
// task and quickly see how well they are succeeding or failing at each step.
// For example, how do prospects become shoppers and then become buyers? How do
// one time buyers become repeat buyers? With this information, you can improve
// inefficient or abandoned customer journeys.
message Funnel {
  // In an open funnel, users can enter the funnel in any step, and in a closed
  // funnel, users must enter the funnel in the first step. Optional. If
  // unspecified, a closed funnel is used.
  bool is_open_funnel = 1;

  // The sequential steps of this funnel.
  repeated FunnelStep steps = 2;
}

// Steps define the user journey you want to measure. Steps contain one or
// more conditions that your users must meet to be included in that step of
// the funnel journey.
message FunnelStep {
  // The distinctive name for this step. If unspecified, steps will be named
  // by a 1 based indexed name (for example "0. ", "1. ", etc.). This name
  // defines string value returned by the `funnelStepName` dimension. For
  // example, specifying `name = Purchase` in the request's third funnel step
  // will produce `3. Purchase` in the funnel report response.
  string name = 1;

  // If true, this step must directly follow the previous step. If false,
  // there can be events between the previous step and this step. If
  // unspecified, `isDirectlyFollowedBy` is treated as false.
  bool is_directly_followed_by = 2;

  // If specified, this step must complete within this duration of the
  // completion of the prior step. `withinDurationFromPriorStep` is inclusive
  // of the endpoint at the microsecond granularity. For example a duration of
  // 5 seconds can be completed at 4.9 or 5.0 seconds, but not 5 seconds and 1
  // microsecond.
  //
  // `withinDurationFromPriorStep` is optional, and if unspecified, steps may
  // be separated by any time duration.
  optional google.protobuf.Duration within_duration_from_prior_step = 3;

  // The condition that your users must meet to be included in this step of
  // the funnel journey.
  FunnelFilterExpression filter_expression = 4;
}

// Funnel sub reports contain the dimension and metric data values. For example,
// 12 users reached the second step of the funnel.
message FunnelSubReport {
  // Describes dimension columns. Funnel reports always include the funnel step
  // dimension in sub report responses. Additional dimensions like breakdowns,
  // dates, and next actions may be present in the response if requested.
  repeated DimensionHeader dimension_headers = 1;

  // Describes metric columns. Funnel reports always include active users in sub
  // report responses. The funnel table includes additional metrics like
  // completion rate, abandonments, and abandonments rate.
  repeated MetricHeader metric_headers = 2;

  // Rows of dimension value combinations and metric values in the report.
  repeated Row rows = 3;

  // Metadata for the funnel report.
  FunnelResponseMetadata metadata = 4;
}

// User segments are subsets of users who engaged with your site or app. For
// example, users who have previously purchased; users who added items to their
// shopping carts, but didn’t complete a purchase.
message UserSegment {
  // Defines which users are included in this segment. Optional.
  UserSegmentCriteria user_inclusion_criteria = 1;

  // Defines which users are excluded in this segment. Optional.
  UserSegmentExclusion exclusion = 2;
}

// A user matches a criteria if the user's events meet the conditions in the
// criteria.
message UserSegmentCriteria {
  // A user matches this criteria if the user matches each of these
  // `andConditionGroups` and each of the `andSequenceGroups`.
  // `andConditionGroups` may be empty if `andSequenceGroups` are specified.
  repeated UserSegmentConditionGroup and_condition_groups = 1;

  // A user matches this criteria if the user matches each of these
  // `andSequenceGroups` and each of the `andConditionGroups`.
  // `andSequenceGroups` may be empty if `andConditionGroups` are specified.
  repeated UserSegmentSequenceGroup and_sequence_groups = 2;
}

// Scoping specifies which events are considered when evaluating if a user
// meets a criteria.
enum UserCriteriaScoping {
  // Unspecified criteria scoping. Do not specify.
  USER_CRITERIA_SCOPING_UNSPECIFIED = 0;

  // If the criteria is satisfied within one event, the user matches the
  // criteria.
  USER_CRITERIA_WITHIN_SAME_EVENT = 1;

  // If the criteria is satisfied within one session, the user matches the
  // criteria.
  USER_CRITERIA_WITHIN_SAME_SESSION = 2;

  // If the criteria is satisfied by any events for the user, the user
  // matches the criteria.
  USER_CRITERIA_ACROSS_ALL_SESSIONS = 3;
}

// Conditions tell Analytics what data to include in or exclude from the
// segment.
message UserSegmentConditionGroup {
  // Data is included or excluded from the segment based on if it matches
  // the condition group. This scoping defines how many events the
  // `segmentFilterExpression` is evaluated on before the condition group
  // is determined to be matched or not. For example if `conditionScoping =
  // USER_CRITERIA_WITHIN_SAME_SESSION`, the expression is evaluated on all
  // events in a session, and then, the condition group is determined to be
  // matched or not for this user. For example if `conditionScoping =
  // USER_CRITERIA_WITHIN_SAME_EVENT`, the expression is evaluated on a single
  // event, and then, the condition group is determined to be matched or not for
  // this user.
  //
  // Optional. If unspecified, `conditionScoping = ACROSS_ALL_SESSIONS` is
  // used.
  UserCriteriaScoping condition_scoping = 1;

  // Data is included or excluded from the segment based on if it matches
  // this expression. Expressions express criteria on dimension, metrics,
  // and/or parameters.
  SegmentFilterExpression segment_filter_expression = 2;
}

// Define conditions that must occur in a specific order for the user to be
// a member of the segment.
message UserSegmentSequenceGroup {
  // All sequence steps must be satisfied in the scoping for the user to
  // match the sequence. For example if `sequenceScoping =
  // USER_CRITERIA_WITHIN_SAME_SESSION`, all sequence steps must complete within
  // one session for the user to match the sequence. `sequenceScoping =
  // USER_CRITERIA_WITHIN_SAME_EVENT` is not supported.
  //
  // Optional. If unspecified, `conditionScoping = ACROSS_ALL_SESSIONS` is
  // used.
  UserCriteriaScoping sequence_scoping = 1;

  // Defines the time period in which the whole sequence must occur; for
  // example, 30 Minutes. `sequenceMaximumDuration` is inclusive
  // of the endpoint at the microsecond granularity. For example a sequence
  // with a maximum duration of 5 seconds can be completed at 4.9 or 5.0
  // seconds, but not 5 seconds and 1 microsecond.
  //
  // `sequenceMaximumDuration` is optional, and if unspecified, sequences can
  // be completed in any time duration.
  google.protobuf.Duration sequence_maximum_duration = 2;

  // An ordered sequence of condition steps. A user's events must complete
  // each step in order for the user to match the
  // `UserSegmentSequenceGroup`.
  repeated UserSequenceStep user_sequence_steps = 3;
}

// A condition that must occur in the specified step order for this user
// to match the sequence.
message UserSequenceStep {
  // If true, the event satisfying this step must be the very next event
  // after the event satifying the last step. If false, this step indirectly
  // follows the prior step; for example, there may be events between the
  // prior step and this step. `isDirectlyFollowedBy` must be false for
  // the first step.
  bool is_directly_followed_by = 1;

  // This sequence step must be satisfied in the scoping for the user to
  // match the sequence. For example if `sequenceScoping =
  // WITHIN_SAME_SESSION`, this sequence steps must complete within one
  // session for the user to match the sequence. `stepScoping =
  // ACROSS_ALL_SESSIONS` is only allowed if the `sequenceScoping =
  // ACROSS_ALL_SESSIONS`.
  //
  // Optional. If unspecified, `stepScoping` uses the same
  // `UserCriteriaScoping` as the `sequenceScoping`.
  UserCriteriaScoping step_scoping = 2;

  // A user matches this sequence step if their events match this
  // expression. Expressions express criteria on dimension, metrics,
  // and/or parameters.
  SegmentFilterExpression segment_filter_expression = 3;
}

// Specifies which users are excluded in this segment.
message UserSegmentExclusion {
  // Specifies how long an exclusion will last if a user matches the
  // `userExclusionCriteria`.
  //
  // Optional. If unspecified, `userExclusionDuration` of
  // `USER_EXCLUSION_TEMPORARY` is used.
  UserExclusionDuration user_exclusion_duration = 1;

  // If a user meets this condition, the user is excluded from membership in
  // the segment for the `userExclusionDuration`.
  UserSegmentCriteria user_exclusion_criteria = 2;
}

// Enumerates options for how long an exclusion will last if a user matches
// the `userExclusionCriteria`.
enum UserExclusionDuration {
  // Unspecified exclusion duration. Do not specify.
  USER_EXCLUSION_DURATION_UNSPECIFIED = 0;

  // Temporarily exclude users from the segment during periods when the
  // user meets the `userExclusionCriteria` condition.
  USER_EXCLUSION_TEMPORARY = 1;

  // Permanently exclude users from the segment if the user ever meets the
  // `userExclusionCriteria` condition.
  USER_EXCLUSION_PERMANENT = 2;
}

// Session segments are subsets of the sessions that occurred on your site or
// app: for example, all the sessions that originated from a particular
// advertising campaign.
message SessionSegment {
  // Defines which sessions are included in this segment. Optional.
  SessionSegmentCriteria session_inclusion_criteria = 1;

  // Defines which sessions are excluded in this segment. Optional.
  SessionSegmentExclusion exclusion = 2;
}

// A session matches a criteria if the session's events meet the conditions in
// the criteria.
message SessionSegmentCriteria {
  // A session matches this criteria if the session matches each of these
  // `andConditionGroups`.
  repeated SessionSegmentConditionGroup and_condition_groups = 1;
}

// Scoping specifies which events are considered when evaluating if a
// session meets a criteria.
enum SessionCriteriaScoping {
  // Unspecified criteria scoping. Do not specify.
  SESSION_CRITERIA_SCOPING_UNSPECIFIED = 0;

  // If the criteria is satisfied within one event, the session matches the
  // criteria.
  SESSION_CRITERIA_WITHIN_SAME_EVENT = 1;

  // If the criteria is satisfied within one session, the session matches
  // the criteria.
  SESSION_CRITERIA_WITHIN_SAME_SESSION = 2;
}

// Conditions tell Analytics what data to include in or exclude from the
// segment.
message SessionSegmentConditionGroup {
  // Data is included or excluded from the segment based on if it matches
  // the condition group. This scoping defines how many events the
  // `segmentFilterExpression` is evaluated on before the condition group
  // is determined to be matched or not. For example if `conditionScoping =
  // SESSION_CRITERIA_WITHIN_SAME_SESSION`, the expression is evaluated on all
  // events in a session, and then, the condition group is determined to be
  // matched or not for this session. For example if `conditionScoping =
  // SESSION_CRITERIA_WITHIN_SAME_EVENT`, the expression is evaluated on a
  // single event, and then, the condition group is determined to be matched or
  // not for this session.
  //
  // Optional. If unspecified, a `conditionScoping` of `WITHIN_SAME_SESSION`
  // is used.
  SessionCriteriaScoping condition_scoping = 1;

  // Data is included or excluded from the segment based on if it matches
  // this expression. Expressions express criteria on dimension, metrics,
  // and/or parameters.
  SegmentFilterExpression segment_filter_expression = 2;
}

// Specifies which sessions are excluded in this segment.
message SessionSegmentExclusion {
  // Specifies how long an exclusion will last if a session matches the
  // `sessionExclusionCriteria`.
  //
  // Optional. If unspecified, a `sessionExclusionDuration` of
  // `SESSION_EXCLUSION_TEMPORARY` is used.
  SessionExclusionDuration session_exclusion_duration = 1;

  // If a session meets this condition, the session is excluded from
  // membership in the segment for the `sessionExclusionDuration`.
  SessionSegmentCriteria session_exclusion_criteria = 2;
}

// Enumerates options for how long an exclusion will last if a session
// matches the `sessionExclusionCriteria`.
enum SessionExclusionDuration {
  // Unspecified exclusion duration. Do not specify.
  SESSION_EXCLUSION_DURATION_UNSPECIFIED = 0;

  // Temporarily exclude sessions from the segment during periods when the
  // session meets the `sessionExclusionCriteria` condition.
  SESSION_EXCLUSION_TEMPORARY = 1;

  // Permanently exclude sessions from the segment if the session ever meets
  // the `sessionExclusionCriteria` condition.
  SESSION_EXCLUSION_PERMANENT = 2;
}

// Event segments are subsets of events that were triggered on your site or app.
// for example, all purchase events made in a particular location; app_exception
// events that occurred on a specific operating system.
message EventSegment {
  // Defines which events are included in this segment. Optional.
  EventSegmentCriteria event_inclusion_criteria = 1;

  // Defines which events are excluded in this segment. Optional.
  EventSegmentExclusion exclusion = 2;
}

// An event matches a criteria if the event meet the conditions in the
// criteria.
message EventSegmentCriteria {
  // An event matches this criteria if the event matches each of these
  // `andConditionGroups`.
  repeated EventSegmentConditionGroup and_condition_groups = 1;
}

// Scoping specifies which events are considered when evaluating if an event
// meets a criteria.
enum EventCriteriaScoping {
  // Unspecified criteria scoping. Do not specify.
  EVENT_CRITERIA_SCOPING_UNSPECIFIED = 0;

  // If the criteria is satisfied within one event, the event matches the
  // criteria.
  EVENT_CRITERIA_WITHIN_SAME_EVENT = 1;
}

// Conditions tell Analytics what data to include in or exclude from the
// segment.
message EventSegmentConditionGroup {
  // `conditionScoping` should always be `EVENT_CRITERIA_WITHIN_SAME_EVENT`.
  //
  // Optional. If unspecified, a `conditionScoping` of
  // `EVENT_CRITERIA_WITHIN_SAME_EVENT` is used.
  EventCriteriaScoping condition_scoping = 1;

  // Data is included or excluded from the segment based on if it matches
  // this expression. Expressions express criteria on dimension, metrics,
  // and/or parameters.
  SegmentFilterExpression segment_filter_expression = 2;
}

// Specifies which events are excluded in this segment.
message EventSegmentExclusion {
  // `eventExclusionDuration` should always be `PERMANENTLY_EXCLUDE`.
  //
  // Optional. If unspecified, an `eventExclusionDuration` of
  // `EVENT_EXCLUSION_PERMANENT` is used.
  EventExclusionDuration event_exclusion_duration = 1;

  // If an event meets this condition, the event is excluded from membership
  // in the segment for the `eventExclusionDuration`.
  EventSegmentCriteria event_exclusion_criteria = 2;
}

// Enumerates options for how long an exclusion will last if an event
// matches the `eventExclusionCriteria`.
enum EventExclusionDuration {
  // Unspecified exclusion duration. Do not specify.
  EVENT_EXCLUSION_DURATION_UNSPECIFIED = 0;

  // Permanently exclude events from the segment if the event ever meets
  // the `eventExclusionCriteria` condition.
  EVENT_EXCLUSION_PERMANENT = 1;
}

// A segment is a subset of your Analytics data. For example, of your entire set
// of users, one segment might be users from a particular country or city.
// Another segment might be users who purchase a particular line of products or
// who visit a specific part of your site or trigger certain events in your app.
//
// To learn more, see [GA4 Segment
// Builder](https://support.google.com/analytics/answer/9304353).
message Segment {
  // The name for this segment. If unspecified, segments are named "Segment".
  // This name defines string value returned by the `segment` dimension. The
  // `segment` dimension prefixes segment names by the 1-based index number of
  // the segment in the request (for example "1. Segment", "2. Segment", etc.).
  string name = 1;

  // A segment is specified in one scope.
  oneof one_segment_scope {
    // User segments are subsets of users who engaged with your site or app.
    UserSegment user_segment = 2;

    // Session segments are subsets of the sessions that occurred on your site
    // or app.
    SessionSegment session_segment = 3;

    // Event segments are subsets of events that were triggered on your site or
    // app.
    EventSegment event_segment = 4;
  }
}

// Expresses combinations of segment filters.
message SegmentFilterExpression {
  // Specify one type of filter for `SegmentFilterExpression`.
  oneof expr {
    // The SegmentFilterExpression in `andGroup` have an AND relationship.
    SegmentFilterExpressionList and_group = 1;

    // The SegmentFilterExpression in `orGroup` have an OR relationship.
    SegmentFilterExpressionList or_group = 2;

    // The SegmentFilterExpression is NOT of `notExpression`.
    SegmentFilterExpression not_expression = 3;

    // A primitive segment filter.
    SegmentFilter segment_filter = 4;

    // Creates a filter that matches events of a single event name. If a
    // parameter filter expression is specified, only the subset of events that
    // match both the single event name and the parameter filter expressions
    // match this event filter.
    SegmentEventFilter segment_event_filter = 5;
  }
}

// A list of segment filter expressions.
message SegmentFilterExpressionList {
  // The list of segment filter expressions
  repeated SegmentFilterExpression expressions = 1;
}

// An expression to filter dimension or metric values.
message SegmentFilter {
  // The dimension name or metric name.
  string field_name = 1;

  // Specify one type of filter for `Filter`.
  oneof one_filter {
    // Strings related filter.
    StringFilter string_filter = 4;

    // A filter for in list values.
    InListFilter in_list_filter = 5;

    // A filter for numeric or date values.
    NumericFilter numeric_filter = 6;

    // A filter for between two values.
    BetweenFilter between_filter = 7;
  }

  // Specifies the scope for the filter.
  SegmentFilterScoping filter_scoping = 8;
}

// Scopings specify how the dimensions & metrics of multiple events
// should be considered when evaluating a segment filter.
message SegmentFilterScoping {
  // If `atAnyPointInTime` is true, this filter evaluates to true for all
  // events if it evaluates to true for any event in the date range of the
  // request.
  //
  // This `atAnyPointInTime` parameter does not extend the date range of
  // events in the report. If `atAnyPointInTime` is true, only events within
  // the report's date range are considered when evaluating this filter.
  //
  // This `atAnyPointInTime` is only able to be specified if the criteria
  // scoping is `ACROSS_ALL_SESSIONS` and is not able to be specified in
  // sequences.
  //
  // If the criteria scoping is `ACROSS_ALL_SESSIONS`, `atAnyPointInTime` =
  // false is used if unspecified.
  optional bool at_any_point_in_time = 1;
}

// Creates a filter that matches events of a single event name. If a parameter
// filter expression is specified, only the subset of events that match both the
// single event name and the parameter filter expressions match this event
// filter.
message SegmentEventFilter {
  // This filter matches events of this single event name. Event name is
  // required.
  optional string event_name = 1;

  // If specified, this filter matches events that match both the single event
  // name and the parameter filter expressions.
  //
  // Inside the parameter filter expression, only parameter filters are
  // available.
  optional SegmentParameterFilterExpression
      segment_parameter_filter_expression = 2;
}

// Expresses combinations of segment filter on parameters.
message SegmentParameterFilterExpression {
  // Specify one type of filter for `SegmentParameterFilterExpression`.
  oneof expr {
    // The SegmentParameterFilterExpression in `andGroup` have an AND
    // relationship.
    SegmentParameterFilterExpressionList and_group = 1;

    // The SegmentParameterFilterExpression in `orGroup` have an OR
    // relationship.
    SegmentParameterFilterExpressionList or_group = 2;

    // The SegmentParameterFilterExpression is NOT of `notExpression`.
    SegmentParameterFilterExpression not_expression = 3;

    // A primitive segment parameter filter.
    SegmentParameterFilter segment_parameter_filter = 4;
  }
}

// A list of segment parameter filter expressions.
message SegmentParameterFilterExpressionList {
  // The list of segment parameter filter expressions.
  repeated SegmentParameterFilterExpression expressions = 1;
}

// An expression to filter parameter values in a segment.
message SegmentParameterFilter {
  // The field that is being filtered.
  oneof one_parameter {
    // This filter will be evaluated on the specified event parameter. Event
    // parameters are logged as parameters of the event. Event parameters
    // include fields like "firebase_screen" & "currency".
    //
    // Event parameters can only be used in segments & funnels and can only be
    // used in a descendent filter from an EventFilter. In a descendent filter
    // from an EventFilter either event or item parameters should be used.
    string event_parameter_name = 1;

    // This filter will be evaluated on the specified item parameter. Item
    // parameters are logged as parameters in the item array. Item parameters
    // include fields like "item_name" & "item_category".
    //
    // Item parameters can only be used in segments & funnels and can only be
    // used in a descendent filter from an EventFilter. In a descendent filter
    // from an EventFilter either event or item parameters should be used.
    //
    // Item parameters are only available in ecommerce events. To learn more
    // about ecommerce events, see the [Measure ecommerce]
    // (https://developers.google.com/analytics/devguides/collection/ga4/ecommerce)
    // guide.
    string item_parameter_name = 2;
  }

  // Specify one type of filter.
  oneof one_filter {
    // Strings related filter.
    StringFilter string_filter = 4;

    // A filter for in list values.
    InListFilter in_list_filter = 5;

    // A filter for numeric or date values.
    NumericFilter numeric_filter = 6;

    // A filter for between two values.
    BetweenFilter between_filter = 7;
  }

  // Specifies the scope for the filter.
  SegmentParameterFilterScoping filter_scoping = 8;
}

// Scopings specify how multiple events should be considered when evaluating a
// segment parameter filter.
message SegmentParameterFilterScoping {
  // Accumulates the parameter over the specified period of days before
  // applying the filter. Only supported if criteria scoping is
  // `ACROSS_ALL_SESSIONS` or `WITHIN_SAME_SESSION`. Only supported if the
  // parameter is `event_count`.
  //
  // For example if `inAnyNDayPeriod` is 3, the event_name is "purchase",
  // the event parameter is "event_count", and the Filter's criteria is
  // greater than 5, this filter will accumulate the event count of purchase
  // events over every 3 consecutive day period in the report's date range; a
  // user will pass this Filter's criteria to be included in this segment if
  // their count of purchase events exceeds 5 in any 3 consecutive day period.
  // For example, the periods 2021-11-01 to 2021-11-03, 2021-11-02 to
  // 2021-11-04, 2021-11-03 to 2021-11-05, and etc. will be considered.
  //
  // The date range is not extended for the purpose of having a full N day
  // window near the start of the date range. For example if a report is for
  // 2021-11-01 to 2021-11-10 and `inAnyNDayPeriod` = 3, the first two day
  // period will be effectively shortened because no event data outside the
  // report's date range will be read. For example, the first four periods
  // will effectively be: 2021-11-01 to 2021-11-01, 2021-11-01 to 2021-11-02,
  // 2021-11-01 to 2021-11-03, and 2021-11-02 to 2021-11-04.
  //
  // `inAnyNDayPeriod` is optional. If not specified, the
  // `segmentParameterFilter` is applied to each event individually.
  optional int64 in_any_n_day_period = 1;
}

// Expresses combinations of funnel filters.
message FunnelFilterExpression {
  // Specify one type of filter for `FunnelFilterExpression`.
  oneof expr {
    // The FunnelFilterExpression in `andGroup` have an AND relationship.
    FunnelFilterExpressionList and_group = 1;

    // The FunnelFilterExpression in `orGroup` have an OR relationship.
    FunnelFilterExpressionList or_group = 2;

    // The FunnelFilterExpression is NOT of `notExpression`.
    FunnelFilterExpression not_expression = 3;

    // A funnel filter for a dimension or metric.
    FunnelFieldFilter funnel_field_filter = 4;

    // Creates a filter that matches events of a single event name. If a
    // parameter filter expression is specified, only the subset of events that
    // match both the single event name and the parameter filter expressions
    // match this event filter.
    FunnelEventFilter funnel_event_filter = 5;
  }
}

// A list of funnel filter expressions.
message FunnelFilterExpressionList {
  // The list of funnel filter expressions.
  repeated FunnelFilterExpression expressions = 1;
}

// An expression to filter dimension or metric values.
message FunnelFieldFilter {
  // The dimension name or metric name.
  string field_name = 1;

  // Specify one type of filter.
  oneof one_filter {
    // Strings related filter.
    StringFilter string_filter = 4;

    // A filter for in list values.
    InListFilter in_list_filter = 5;

    // A filter for numeric or date values.
    NumericFilter numeric_filter = 6;

    // A filter for between two values.
    BetweenFilter between_filter = 7;
  }
}

// Creates a filter that matches events of a single event name. If a parameter
// filter expression is specified, only the subset of events that match both the
// single event name and the parameter filter expressions match this event
// filter.
message FunnelEventFilter {
  // This filter matches events of this single event name. Event name is
  // required.
  optional string event_name = 1;

  // If specified, this filter matches events that match both the single event
  // name and the parameter filter expressions.
  //
  // Inside the parameter filter expression, only parameter filters are
  // available.
  optional FunnelParameterFilterExpression funnel_parameter_filter_expression =
      2;
}

// Expresses combinations of funnel filters on parameters.
message FunnelParameterFilterExpression {
  // Specify one type of filter for `FunnelParameterFilterExpression`.
  oneof expr {
    // The FunnelParameterFilterExpression in `andGroup` have an AND
    // relationship.
    FunnelParameterFilterExpressionList and_group = 1;

    // The FunnelParameterFilterExpression in `orGroup` have an OR
    // relationship.
    FunnelParameterFilterExpressionList or_group = 2;

    // The FunnelParameterFilterExpression is NOT of `notExpression`.
    FunnelParameterFilterExpression not_expression = 3;

    // A primitive funnel parameter filter.
    FunnelParameterFilter funnel_parameter_filter = 4;
  }
}

// A list of funnel parameter filter expressions.
message FunnelParameterFilterExpressionList {
  // The list of funnel parameter filter expressions.
  repeated FunnelParameterFilterExpression expressions = 1;
}

// An expression to filter parameter values in a funnel.
message FunnelParameterFilter {
  // The field that is being filtered.
  oneof one_parameter {
    // This filter will be evaluated on the specified event parameter. Event
    // parameters are logged as parameters of the event. Event parameters
    // include fields like "firebase_screen" & "currency".
    //
    // Event parameters can only be used in segments & funnels and can only be
    // used in a descendent filter from an EventFilter. In a descendent filter
    // from an EventFilter either event or item parameters should be used.
    string event_parameter_name = 1;

    // This filter will be evaluated on the specified item parameter. Item
    // parameters are logged as parameters in the item array. Item parameters
    // include fields like "item_name" & "item_category".
    //
    // Item parameters can only be used in segments & funnels and can only be
    // used in a descendent filter from an EventFilter. In a descendent filter
    // from an EventFilter either event or item parameters should be used.
    //
    // Item parameters are only available in ecommerce events. To learn more
    // about ecommerce events, see the [Measure ecommerce]
    // (https://developers.google.com/analytics/devguides/collection/ga4/ecommerce)
    // guide.
    string item_parameter_name = 2;
  }

  // Specify one type of filter.
  oneof one_filter {
    // Strings related filter.
    StringFilter string_filter = 4;

    // A filter for in list values.
    InListFilter in_list_filter = 5;

    // A filter for numeric or date values.
    NumericFilter numeric_filter = 6;

    // A filter for between two values.
    BetweenFilter between_filter = 7;
  }
}

// The funnel report's response metadata carries additional information about
// the funnel report.
message FunnelResponseMetadata {
  // If funnel report results are
  // [sampled](https://support.google.com/analytics/answer/13331292), this
  // describes what percentage of events were used in this funnel report. One
  // `samplingMetadatas` is populated for each date range. Each
  // `samplingMetadatas` corresponds to a date range in order that date ranges
  // were specified in the request.
  //
  // However if the results are not sampled, this field will not be defined.
  repeated SamplingMetadata sampling_metadatas = 1;
}

// If funnel report results are
// [sampled](https://support.google.com/analytics/answer/13331292), this
// metadata describes what percentage of events were used in this funnel
// report for a date range. Sampling is the practice of analyzing a subset of
// all data in order to uncover the meaningful information in the larger data
// set.
message SamplingMetadata {
  // The total number of events read in this sampled report for a date range.
  // This is the size of the subset this property's data that was analyzed in
  // this funnel report.
  int64 samples_read_count = 1;

  // The total number of events present in this property's data that could
  // have been analyzed in this funnel report for a date range. Sampling
  // uncovers the meaningful information about the larger data set, and this
  // is the size of the larger data set.
  //
  // To calculate the percentage of available data that was used in this
  // funnel report, compute `samplesReadCount/samplingSpaceSize`.
  int64 sampling_space_size = 2;
}

// Represents aggregation of metrics.
enum MetricAggregation {
  // Unspecified operator.
  METRIC_AGGREGATION_UNSPECIFIED = 0;

  // SUM operator.
  TOTAL = 1;

  // Minimum operator.
  MINIMUM = 5;

  // Maximum operator.
  MAXIMUM = 6;

  // Count operator.
  COUNT = 4;
}

// A metric's value type.
enum MetricType {
  // Unspecified type.
  METRIC_TYPE_UNSPECIFIED = 0;

  // Integer type.
  TYPE_INTEGER = 1;

  // Floating point type.
  TYPE_FLOAT = 2;

  // A duration of seconds; a special floating point type.
  TYPE_SECONDS = 4;

  // A duration in milliseconds; a special floating point type.
  TYPE_MILLISECONDS = 5;

  // A duration in minutes; a special floating point type.
  TYPE_MINUTES = 6;

  // A duration in hours; a special floating point type.
  TYPE_HOURS = 7;

  // A custom metric of standard type; a special floating point type.
  TYPE_STANDARD = 8;

  // An amount of money; a special floating point type.
  TYPE_CURRENCY = 9;

  // A length in feet; a special floating point type.
  TYPE_FEET = 10;

  // A length in miles; a special floating point type.
  TYPE_MILES = 11;

  // A length in meters; a special floating point type.
  TYPE_METERS = 12;

  // A length in kilometers; a special floating point type.
  TYPE_KILOMETERS = 13;
}

// Categories of data that you may be restricted from viewing on certain GA4
// properties.
enum RestrictedMetricType {
  // Unspecified type.
  RESTRICTED_METRIC_TYPE_UNSPECIFIED = 0;

  // Cost metrics such as `adCost`.
  COST_DATA = 1;

  // Revenue metrics such as `purchaseRevenue`.
  REVENUE_DATA = 2;
}
