Skip to content

Commit

Permalink
Merge pull request #571 from plausible/revenue-metrics-apiv2
Browse files Browse the repository at this point in the history
Revenue metrics in APIv2
  • Loading branch information
macobo authored Jan 7, 2025
2 parents 36a9839 + aa477bb commit 96b583c
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 15 deletions.
73 changes: 58 additions & 15 deletions docs/stats-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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. |


<details>
<summary>Read more about revenue metrics</summary>

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)
</details>

### dimensions <Optional /> {#dimensions}

Expand Down Expand Up @@ -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).

<CodeBlock language="javascript">{EXAMPLE_RESPONSE_META}</CodeBlock>

### query

Expand Down Expand Up @@ -382,4 +414,15 @@ In this example, imported data could not be included due to dimension and filter

<ApiV2Example id="example-imports-warning" />


### Revenue metrics {#example-revenue-metrics}

<ApiV2Example id="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)

<ApiV2Example id="example-revenue-warning" />

</SiteContextProvider>
32 changes: 32 additions & 0 deletions src/js/apiv2-examples/response-meta.json
Original file line number Diff line number Diff line change
@@ -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
}
6 changes: 6 additions & 0 deletions src/js/apiv2-examples/revenue-metrics-query.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"site_id": "dummy.site",
"metrics": ["total_revenue"],
"date_range": "all",
"dimensions": ["event:goal"]
}
30 changes: 30 additions & 0 deletions src/js/apiv2-examples/revenue-metrics-response.json
Original file line number Diff line number Diff line change
@@ -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}
}
}
8 changes: 8 additions & 0 deletions src/js/apiv2-examples/revenue-warning-query.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"site_id": "dummy.site",
"metrics": ["total_revenue"],
"date_range": "all",
"filters": [
["is", "event:goal", ["PurchaseUSD", "PurchaseEUR"]]
]
}
23 changes: 23 additions & 0 deletions src/js/apiv2-examples/revenue-warning-response.json
Original file line number Diff line number Diff line change
@@ -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}
}
}
14 changes: 14 additions & 0 deletions src/js/examples.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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"),
}
]

Expand Down

0 comments on commit 96b583c

Please sign in to comment.