> ## Documentation Index
> Fetch the complete documentation index at: https://unif.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Metrics reference

> Every metric, what it counts, and what it excludes.

A metric name means one thing across all six entities. This page is the definition of record — if
a number surprises you, the answer is usually here.

## Reading the conventions

<CardGroup cols={3}>
  <Card title="Money" icon="dollar-sign">
    Converted to your requested `currency`. Always period-scoped.
  </Card>

  <Card title="Rates and shares" icon="percent">
    Ratios, never percentages. `0.25` is 25%.
  </Card>

  <Card title="Null vs zero" icon="circle-minus">
    `null` means not available or not computable. `0` means genuinely zero.
  </Card>
</CardGroup>

## Money and volume

<ResponseField name="revenue" type="number">
  Gross merchandise value of orders **placed** within the period, before returns, cancellations
  and platform fees. This is a demand measure, not a settlement measure — it will not match a
  seller's payout statement, and it is not meant to.
</ResponseField>

<ResponseField name="units_sold" type="integer">
  Item quantity across orders placed in the period. An order of three units counts as three.
</ResponseField>

<ResponseField name="avg_unit_price" type="number">
  `revenue / units_sold` for shops and categories. Shifts with mix, not only with pricing — a
  shop that starts selling a cheaper line moves this number without changing any price.
</ResponseField>

<ResponseField name="avg_sale_price" type="number">
  The product-level equivalent: revenue divided by units sold for one listing. Compare it against
  `price.current` to detect discount-driven volume.
</ResponseField>

<ResponseField name="revenue_growth_rate" type="number">
  Change in `revenue` against the immediately preceding window of equal length, as a ratio.
  `null` when the preceding window has no data — see [Periods](/docs/concepts/periods#growth-rates).
</ResponseField>

<ResponseField name="revenue_by_source" type="object">
  Revenue split across selling surfaces as ratios summing to 1: `video`, `live`, `mall`, `search`.
  Where a channel cannot attribute a surface, its key is absent rather than zero.
</ResponseField>

<Warning>
  `revenue` counts orders placed. Refunds, chargebacks and cancellations are **not** deducted, and
  neither are platform fees or creator commissions. For categories with high return rates, treat
  it as an upper bound on realized sales.
</Warning>

## Content performance

<ResponseField name="views" type="integer">
  Lifetime views of a video, not views within the requested period. Video metrics accumulate; the
  period on a video search filters by publish date instead.
</ResponseField>

<ResponseField name="engagement_rate" type="number">
  `(likes + comments + shares) / views`, as a ratio. Computed over the same lifetime window as
  `views`.
</ResponseField>

<ResponseField name="gpm" type="number">
  Gross revenue per **thousand** views — `revenue / views × 1000` — in your requested currency.
  The single most useful efficiency metric for comparing creators, because it is neutral to
  audience size.
</ResponseField>

<ResponseField name="avg_views_per_video" type="number">
  Mean views across the creator's videos published in the period. Heavily skewed by outliers;
  read it alongside `gpm` rather than alone.
</ResponseField>

<ResponseField name="follower_growth" type="integer">
  Net followers gained over the period. Can be negative.
</ResponseField>

## Livestream metrics

<ResponseField name="viewers" type="integer">
  Unique viewers across the session.
</ResponseField>

<ResponseField name="peak_concurrent_viewers" type="integer">
  The maximum watching simultaneously — the number that tells you whether a promotion landed.
</ResponseField>

<ResponseField name="avg_watch_seconds" type="number">
  Mean watch duration per viewer, in seconds.
</ResponseField>

## Counts

<ResponseField name="creators_count" type="integer">
  Distinct creators who drove attributed sales in the period. On a product, this is the affiliate
  breadth behind it — a product with 200 creators is in a different competitive position than one
  with 3, at the same revenue.
</ResponseField>

<ResponseField name="products_sold_count" type="integer">
  Distinct products with at least one sale, which is usually far smaller than `products_count` —
  the size of the catalogue.
</ResponseField>

<ResponseField name="videos_count / livestreams_count" type="integer">
  Content published in the period that carried at least one product.
</ResponseField>

## Which metrics exist on which entity

| Metric                | Shop | Product | Creator | Video | Livestream | Category |
| --------------------- | :--: | :-----: | :-----: | :---: | :--------: | :------: |
| `revenue`             |   ✓  |    ✓    |    ✓    |   ✓   |      ✓     |     ✓    |
| `units_sold`          |   ✓  |    ✓    |    ✓    |   ✓   |      ✓     |     ✓    |
| `revenue_growth_rate` |   ✓  |    ✓    |    —    |   —   |      —     |     ✓    |
| `revenue_by_source`   |   ✓  |    ✓    |    —    |   —   |      —     |     —    |
| `avg_unit_price`      |   ✓  |    —    |    —    |   —   |      —     |     ✓    |
| `avg_sale_price`      |   —  |    ✓    |    —    |   —   |      —     |     —    |
| `gpm`                 |   —  |    ✓    |    ✓    |   ✓   |      ✓     |     —    |
| `engagement_rate`     |   —  |    —    |    ✓    |   ✓   |      —     |     —    |
| `creators_count`      |   ✓  |    ✓    |    —    |   —   |      —     |     ✓    |
| `viewers`             |   —  |    —    |    —    |   —   |      ✓     |     —    |

<Note>
  A dash means the metric is not defined for that entity and will not appear. A metric that *is*
  defined but unavailable for your channel and market comes back `null` and is listed in
  `meta.missing_fields` — see [Coverage](/docs/concepts/coverage).
</Note>

## Filtering and sorting

Any metric in the table above can be filtered with a [range](/docs/workflows/search#range-filters)
and used as a `sort` key, subject to coverage. Check
[`GET /coverage`](/docs/concepts/coverage) for the `filterable` and `sortable` flags on a specific
channel and market before shipping a query that depends on one.

```json theme={null}
{
  "filters": { "gpm": { "gte": 40 }, "revenue": { "gte": 25000 } },
  "sort": [{ "field": "gpm", "direction": "desc" }]
}
```
