Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.omni.co/llms.txt

Use this file to discover all available pages before exploring further.

Level of Detail (LoD) fields control the granularity at which an aggregation is computed. When used as a measure, an LoD produces an aggregation of an aggregation, such as an average of averages or a percent of total.

How it works

The easiest way to understand an LoD measure is to read it as SQL. For example, this avg_customer_lifetime_spend LoD first sums each customer’s order amounts, then averages those per-customer totals at whatever grain the query is run. In this example, that’s by country:
avg_customer_lifetime_spend:  
  sql: ${orders.amount}  
  aggregate_type: average  
  level_of_detail:  
    aggregate_type: sum  
    fixed: [customers.id]
The level_of_detail block defines the inner query: fixed: [customers.id] with aggregate_type: sum produces one summed row per customer — that’s the first aggregation. The measure’s aggregate_type: average then takes those per-customer totals and averages them at the query’s grain. That’s the “aggregation of an aggregation” shape: a per-customer SUM feeding into a per-country AVG. Note that the outer GROUP BY customers.country clause comes from the dimensions selected in the query, not the LoD definition itself.

Syntax

<measure_name>:
  aggregate_type: <aggregation>
  level_of_detail:
    aggregate_type: <aggregation>
    <grouping_strategy>: [<field_name>]
    custom_primary_key_sql: <field_reference>
    cancel_query_filters: <true_false>
    filters:
      <field>:
        <filter_operator>: <value>
        cancel_query_filter: <true_false>

Properties

measure_name
object
The name of the measure. Measure names must:
  • Be unique within the view
  • Start with a letter
  • Contain only alphanumeric characters and underscores

Examples

Customer lifetime revenue
measures:
  customer_lifetime_revenue:
    aggregate_type: sum
    sql: ${order_items.sale_price}
    level_of_detail:
      aggregate_type: sum
      always_include: [users.user_id]
      cancel_query_filters: true
Fixed level of detail
measures:
  category_total_revenue:
    aggregate_type: sum
    sql: ${order_items.revenue}
    level_of_detail:
      aggregate_type: sum
      fixed: [products.category]
Exclude dimensions from grouping
measures:
  overall_average_score:
    aggregate_type: average
    sql: ${reviews.score}
    level_of_detail:
      aggregate_type: average
      always_exclude: [stores.region]
Sum distinct on with custom primary key
measures:
  total_by_order:
    aggregate_type: sum
    sql: ${order_items.amount}
    level_of_detail:
      aggregate_type: sum_distinct_on
      custom_primary_key_sql: ${order_items.order_id}
      fixed: []
Selectively ignore a specific global filter
measures:
  arr_balance:
    aggregate_type: sum
    sql: ${accounts.arr_cumulative}
    level_of_detail:
      aggregate_type: max
      fixed: [accounts.logo, orders.date]
      filters:
        orders.date:
          cancel_query_filter: true  # Ignores global date filter for this level of detail only
Replace a cancelled filter with a different value
measures:
  california_revenue:
    aggregate_type: sum
    sql: ${order_items.revenue}
    level_of_detail:
      aggregate_type: sum
      fixed: [stores.state]
      filters:
        stores.state:
          is: California  # Replaces any global state filter with California
          cancel_query_filter: true
Compare with cancel_query_filters (all-or-nothing)
measures:
  total_lifetime_value:
    aggregate_type: sum
    sql: ${order_items.sale_price}
    level_of_detail:
      aggregate_type: sum
      always_include: [users.user_id]
      cancel_query_filters: true  # Ignores all global filters