diff --git a/docs/stats-api.md b/docs/stats-api.md index d4141089..227dcc38 100644 --- a/docs/stats-api.md +++ b/docs/stats-api.md @@ -5,7 +5,7 @@ toc_max_heading_level: 4 import { ApiV2Example, ExamplesTip } from '../src/js/apiv2-example.tsx'; import { Required, Optional } from '../src/js/api-helpers.tsx'; -import { getExampleCode } from '../src/js/examples.tsx'; +import { getExampleCode, EXAMPLE_RESPONSE_META } from '../src/js/examples.tsx'; import CodeBlock from '@theme/CodeBlock'; import { SiteContextProvider } from '../src/js/sites.tsx'; @@ -75,18 +75,49 @@ Metrics represent values to be calculated with the query. Valid metrics are: -| Metric name | Description | -| --- | --- | -| `visitors` | The number of unique visitors | -| `visits` | The number of visits/sessions | -| `pageviews` | The number of pageview events | -| `views_per_visit` | The number of pageviews divided by the number of visits. Returns a floating point number. | -| `bounce_rate` | Bounce rate percentage | -| `visit_duration` | Visit duration in seconds | -| `events` | The number of events (pageviews + custom events). When filtering by a goal, this metric corresponds to "Total Conversions" in the dashboard. | -| `percentage` | The percentage of visitors of total who fall into this category: Requires: dimension list | -| `conversion_rate` | The percentage of visitors who completed the goal. Requires: dimension list passed, an event:goal filter or event:goal dimension | -| `group_conversion_rate` | The percentage of visitors who completed the goal with the same dimension. Requires: dimension list passed, an event:goal filter or event:goal dimension | +| Metric name | Type | Description | Requirements | +| --- | --- | --- | --- | +| `visitors` | `int` | The number of unique visitors | | +| `visits` | `int` | The number of visits/sessions | | +| `pageviews` | `int` | The number of pageview events | | +| `views_per_visit` | `float` | The number of pageviews divided by the number of visits. | | +| `bounce_rate` | `float` | Bounce rate percentage | | +| `visit_duration` | `int` | Visit duration in seconds | | +| `events` | `int` | The number of events (pageviews + custom events). When filtering by a goal, this metric corresponds to "Total Conversions" in the dashboard. | | +| `percentage` | `float` | The percentage of visitors of total who fall into this category: Requires: dimension list | Requires non-empty `dimensions` | +| `conversion_rate` | `float` | The percentage of visitors who completed the goal. | Requires non-empty `dimensions`, `event:goal` filter or dimension being set | +| `group_conversion_rate` | `float` | The percentage of visitors who completed the goal with the same dimension. Requires: dimension list passed, an event:goal filter or event:goal dimension | Requires non-empty `dimensions`, event:goal filter or dimension being set | +| `average_revenue` | `Revenue` or null | Average revenue per revenue goal conversion | Requires [revenue goals](docs/ecommerce-revenue-tracking.md), `event:goal` filter or dimension for a relevant revenue goal. | +| `total_revenue` | `Revenue` or null | Total revenue from revenue goal conversions | Requires [revenue goals](docs/ecommerce-revenue-tracking.md), `event:goal` filter or dimension for a relevant revenue goal. | + + +
+ Read more about revenue metrics + + To use revenue metrics, users should configure [revenue goals](docs/ecommerce-revenue-tracking.md). + + Revenue metric response type has the following structure: + + ```js + { + value: float, + currency: string, // e.g. "USD" or "EUR" + short: string, // e.g. "€500.2M" + long: string, // e.g. "€500,200,700.25" + } + ``` + + `long` and `short` options are human-friendly formatted results. + + There are scenarios where revenue metrics can't be calculated. For example: + 1. When no revenue goals are configured + 2. No `event:goal` filter or dimension + 3. No revenue goal matches `event:goal` filter + 4. No `event:goal` dimension and filtered revenue goals have different currencies. + + In these cases, revenue is returned as `null`s and `response.meta.metric_warning` value will have a warning for why the metric could not + be calculated. See [response.meta structure](#meta) and [example](#example-revenue-warning) +
### dimensions {#dimensions} @@ -313,10 +344,11 @@ Each result row contains: - `dimensions` - values for each `dimension` listed in query. In the same order as query `dimensions`, empty if no dimensions requested. - `metrics` - List of metric values, in the same order as query `metrics` - ### meta -Meta information about this query. Related: [include.imports](#include.imports) and [include.time_labels](#include.time_labels). +Meta information about this query, including warnings and auxiliary data. Related: [include](#include). + +{EXAMPLE_RESPONSE_META} ### query @@ -382,4 +414,15 @@ In this example, imported data could not be included due to dimension and filter + +### Revenue metrics {#example-revenue-metrics} + + + +### Revenue metrics could not be calculated {#example-revenue-warning} + +In this example, revenue metrics could not be calculated due to different currency filters. [More information](#metrics) + + + diff --git a/src/js/apiv2-examples/response-meta.json b/src/js/apiv2-examples/response-meta.json new file mode 100644 index 00000000..e79c04a3 --- /dev/null +++ b/src/js/apiv2-examples/response-meta.json @@ -0,0 +1,32 @@ +{ + // Whether imported data was included + // Only set if include.imports was set + "imports_included": false, + + // Information about why including imported data failed + "imports_skip_reason": "unsupported_interval", + "imports_warning": "Imported stats are not included because the time dimension (i.e. the interval) is too short.", + + // Warnings about specific metrics + // Currently only set if a revenue metric was used and was unable to be calculated + "metric_warnings": { + "total_revenue": { + "code": "no_revenue_goals_matching", + "warning": "Revenue metrics are null as there are no matching revenue goals." + } + }, + + // Only set if include.time_labels was set + "time_labels": [ + "2024-09-10 00:00:00", + "2024-09-10 01:00:00", + "2024-09-10 02:00:00", + "2024-09-10 03:00:00", + "2024-09-10 04:00:00", + "2024-09-10 05:00:00", + "2024-09-10 06:00:00" + ], + + // Only set if include.total_rows was set + "total_rows": 342 +} diff --git a/src/js/apiv2-examples/revenue-metrics-query.json b/src/js/apiv2-examples/revenue-metrics-query.json new file mode 100644 index 00000000..98ea02ea --- /dev/null +++ b/src/js/apiv2-examples/revenue-metrics-query.json @@ -0,0 +1,6 @@ +{ + "site_id": "dummy.site", + "metrics": ["total_revenue"], + "date_range": "all", + "dimensions": ["event:goal"] +} diff --git a/src/js/apiv2-examples/revenue-metrics-response.json b/src/js/apiv2-examples/revenue-metrics-response.json new file mode 100644 index 00000000..94b09a56 --- /dev/null +++ b/src/js/apiv2-examples/revenue-metrics-response.json @@ -0,0 +1,30 @@ +{ + "results": [ + { + "dimensions": ["North America Purchases"], + "metrics": [ + { + "short": "$96.3M", + "value": 96336315, + "long": "$96,336,315.00", + "currency": "USD" + } + ] + }, + { + "dimensions": ["Visit /"], + "metrics": [null] + } + ], + "meta": {}, + "query": { + "site_id": "dummy.site", + "metrics": ["total_revenue"], + "date_range": ["2021-12-14T00:00:00+00:00", "2024-12-11T23:59:59+00:00"], + "filters": [], + "dimensions": ["event:goal"], + "order_by": [["total_revenue", "desc"]], + "include": {}, + "pagination": {"offset": 0, "limit": 10000} + } +} diff --git a/src/js/apiv2-examples/revenue-warning-query.json b/src/js/apiv2-examples/revenue-warning-query.json new file mode 100644 index 00000000..37698939 --- /dev/null +++ b/src/js/apiv2-examples/revenue-warning-query.json @@ -0,0 +1,8 @@ +{ + "site_id": "dummy.site", + "metrics": ["total_revenue"], + "date_range": "all", + "filters": [ + ["is", "event:goal", ["PurchaseUSD", "PurchaseEUR"]] + ] +} diff --git a/src/js/apiv2-examples/revenue-warning-response.json b/src/js/apiv2-examples/revenue-warning-response.json new file mode 100644 index 00000000..5e0cb5ea --- /dev/null +++ b/src/js/apiv2-examples/revenue-warning-response.json @@ -0,0 +1,23 @@ +{ + "results": [ + {"metrics": [null], "dimensions": ["Visit /"]} + ], + "meta": { + "metric_warnings": { + "total_revenue": { + "code": "no_single_revenue_currency", + "warning": "Revenue metrics are null as there are multiple currencies for the selected event:goals." + } + } + }, + "query": { + "site_id": "dummy.site", + "metrics": ["total_revenue"], + "date_range": ["2021-12-14T00:00:00+00:00", "2024-12-11T23:59:59+00:00"], + "filters": [["is", "event:goal", ["PurchaseUSD", "PurchaseEUR"]]], + "dimensions": [], + "order_by": [["total_revenue", "desc"]], + "include": {}, + "pagination": {"offset": 0, "limit": 10000} + } +} diff --git a/src/js/examples.tsx b/src/js/examples.tsx index 1781cc78..49e271e9 100644 --- a/src/js/examples.tsx +++ b/src/js/examples.tsx @@ -2,6 +2,8 @@ function read(path: string): string { return require(`!!raw-loader?esModule=false!./${path}`) } +export const EXAMPLE_RESPONSE_META = read("apiv2-examples/response-meta.json") + const EXAMPLES = [ { id: "example-aggregate", @@ -74,6 +76,18 @@ const EXAMPLES = [ title: "Including imported data failed", query: read("apiv2-examples/imports-bad-filter-query.json"), exampleResponse: read("apiv2-examples/imports-bad-filter-response.json"), + }, + { + id: "example-revenue-metrics", + title: "Revenue metrics", + query: read("apiv2-examples/revenue-metrics-query.json"), + exampleResponse: read("apiv2-examples/revenue-metrics-response.json"), + }, + { + id: "example-revenue-warning", + title: "Revenue metrics could not be calculated", + query: read("apiv2-examples/revenue-warning-query.json"), + exampleResponse: read("apiv2-examples/revenue-warning-response.json"), } ]