> For the complete documentation index, see [llms.txt](https://v2.dataos.info/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://v2.dataos.info/build/stage-2-productize/define-models-and-logic/semantic-models/business-metrics.md).

# Business Metrics

Business metrics are time-series analytical definitions that sit on top of semantic models. A metric takes a measure, a time column, and optional grouping dimensions, and turns them into a single queryable unit that dashboards, APIs, and consumers can use.

Define one metric per file in `models/metrics/`:

```
models/metrics/
├── daily_sales_performance.yml
├── weekly_revenue_trends.yml
├── customer_lifetime_value.yml
├── rfm_value_by_segment.yml
└── fulfillment_conversion.yml
```

***

## File structure

```yaml
kind: metric
name: <metric_name>
measure: <semantic_name>.<measure_name>
ts: <semantic_name>.<time_column>
granularity: <day|week|month|quarter|year>

dimensions:
  - <semantic_name>.<column_name>

segments:
  - <semantic_name>.<segment_name>

description: <what this metric measures>
owner: <team or person>
tags: [tag1, tag2]
```

**Required fields:**

* `kind: metric`
* `name`: unique identifier for the metric across the project.
* `measure`: the measure to calculate, in `<semantic_name>.<measure_name>` format.
* `ts`: the time column for time-series aggregation, in `<semantic_name>.<column_name>` format.
* `granularity`: the default time bucket (`second`, `minute`, `hour`, `day`, `week`, `month`, `quarter`, `year`).

***

## Example 1: daily\_sales\_performance

`models/metrics/daily_sales_performance.yml` from `orders-analytics` tracks daily revenue by region and category. It uses the `total_daily_revenue` measure from the `daily_sales` semantic model, with `order_date` as the time axis and `day` as the default granularity:

```yaml
kind: metric
name: daily_sales_performance
measure: daily_sales.total_daily_revenue
ts: daily_sales.order_date
granularity: day
dimensions:
  - name: region
    ref: daily_sales.region_name
  - name: category
    ref: daily_sales.category
segments:
  - daily_sales.high_revenue_days
description: Daily revenue trends by region and category.
tags:
  - sales
  - revenue
  - daily
terms:
  - sales.daily_performance
  - metric.daily_revenue
```

What this metric exposes:

* A consumer can query daily revenue totals by any combination of region and category.
* The `high_revenue_days` segment (days with revenue >= 500) is pre-defined and can be applied to filter the query.
* The `tags` and `terms` fields make the metric discoverable in the Data Product Hub.

***

## Example 2: customer\_lifetime\_value (cross-model metric)

`models/metrics/customer_lifetime_value.yml` uses the average CLV measure from the `customer_profile` semantic model. It groups by `region_name` and `customer_segment`, both from `customer_profile`. The time axis is `first_order_date` at monthly granularity:

```yaml
kind: metric
name: customer_lifetime_value
measure: customer_profile.avg_customer_lifetime_value
ts: customer_profile.first_order_date
granularity: month
dimensions:
  - name: region
    ref: customer_profile.region_name
  - name: customer_segment
    ref: customer_profile.customer_segment
segments:
  - customer_profile.high_value_customers
description: Average customer lifetime value by customer segment and region.
tags:
  - customer
  - ltv
  - revenue
terms:
  - customer.ltv_analysis
  - metric.customer_value
```

This metric shows average lifetime value per acquisition cohort (by first order date) and lets consumers slice by region or customer segment to understand which groups generate the most value over time.

***

## Minimal example

The smallest valid metric is just the four required fields:

```yaml
kind: metric
name: daily_sales_performance
measure: daily_sales.total_daily_revenue
ts: daily_sales.order_date
granularity: day
```

***

## Full example with segments, tags, terms

```yaml
kind: metric
name: daily_sales_performance
measure: daily_sales.total_daily_revenue
ts: daily_sales.order_date
granularity: day

dimensions:
  - name: region
    ref: daily_sales.region_name
  - name: category
    ref: daily_sales.category

segments:
  - daily_sales.high_revenue_days

description: Daily revenue trends by region and category.
tags:
  - sales
  - revenue
  - daily
terms:
  - sales.daily_performance
```

***

## Cross-model metrics

A metric can draw its measure, time column, and dimensions from different semantic models. Vulcan resolves the join paths automatically, provided the relevant semantic models declare joins between each other. The `customer_lifetime_value` metric above is an example: its measure and time column come from `customer_profile`, and its dimensions also come from `customer_profile`, which already has the required joins to the underlying silver models.

For the full cross-model metric reference including join path resolution and multi-model dimension slicing, see [Business Metrics](/concepts/resources/vulcan/components/semantics/business_metrics.md) in the Vulcan under Concepts.

***

## Dimensions: bare references and named slices

**Bare reference**: auto-derives the name from the field after the dot:

```yaml
dimensions:
  - subscriptions.plan_type      # becomes dimension name: plan_type
  - users.signup_channel         # becomes dimension name: signup_channel
```

**Named slice**: use when you want a different display name, or when two columns from different models would derive the same name:

```yaml
dimensions:
  - name: user_country
    ref: users.country

  - name: shipping_country
    ref: shipping.country
```

Named slices can also override metadata (description, tags, terms) for this metric specifically, without changing the underlying semantic model.

***

## Segments

Segments apply predefined filters from semantic models as string references:

```yaml
segments:
  - subscriptions.active_subscriptions
  - subscriptions.high_value_accounts
```

The `active_subscriptions` and `high_value_accounts` segments must be defined in the `subscriptions` semantic model.

**Segments on metrics cannot carry per-entry metadata**: description, tags, and terms for segments must be set on the semantic model, not here.

***

## Granularity

The `granularity` field sets the default time bucket for aggregation:

| Value     | Bucket     |
| --------- | ---------- |
| `second`  | Per-second |
| `minute`  | Per-minute |
| `hour`    | Hourly     |
| `day`     | Daily      |
| `week`    | Weekly     |
| `month`   | Monthly    |
| `quarter` | Quarterly  |
| `year`    | Yearly     |

Consumers can always override the granularity at query time. You do not need separate metric definitions for daily, weekly, and monthly views of the same data.

***

## Validation

Vulcan validates metric definitions automatically at `vulcan plan`. It checks that:

* `measure` references a valid measure on a semantic model.
* `ts` references a valid time or date column.
* `granularity` is a recognized value.
* All dimension and segment references are valid.
* For cross-model references, join paths exist between the involved models.
* Dimension names are unique across `dimensions` and `segments` in the metric.
* `measure` and `ts` do not point to the same reference.
* Forbidden legacy keys (`time`, `slices`) are not present.

***

## Legacy keys to avoid

Two older keys are explicitly rejected and cause validation to fail:

| Legacy key | Use instead  |
| ---------- | ------------ |
| `time`     | `ts`         |
| `slices`   | `dimensions` |


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://v2.dataos.info/build/stage-2-productize/define-models-and-logic/semantic-models/business-metrics.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
