Skip to main content
Composite topics are currently in beta. Reach out to your Omni contact or Omni support to opt into the beta.
A few worked composite topics you can adapt. For the full reference of every parameter, see Composite topic parameters.

Complete example

A composite topic using the most common parameters:
Full composite topic example
topics: [orders_topic, marketing_topic]

label: "Orders & Marketing"
description: "Revenue and marketing performance, aligned by date and region"

shared_views: [date_spine, regions]

shared_dimensions:
  activity_date:
    label: "Activity date"
    description: "Date the order was placed or the campaign was active"
    ai_context: "Use this for any time-series comparison between orders and marketing."
    mappings:
      orders_topic:
        field: orders.created_at
      marketing_topic:
        field: campaigns.start_date

  region:
    label: "Region"
    mappings:
      orders_topic:
        field: regions.region_name
      marketing_topic:
        field: regions.region_name

shared_measures:
  revenue_per_dollar_spent:
    label: "Revenue per $ spent"
    sql: ${@orders_topic.orders.total_revenue} / NULLIF(${@marketing_topic.campaigns.total_spend}, 0)
    format: usdcurrency_2

  combined_event_count:
    label: "Total events"
    sql: ${@orders_topic.orders.count} + ${@marketing_topic.campaigns.count}
Shared measures take plain math over already-aggregated values — arithmetic, CASE, COALESCE, NULLIF, etc. See shared_measures for details.

Orders vs. shipments by week

A classic fan-out scenario: every order has one or more shipments. Joining directly inflates order revenue.
orders_and_shipments.composite_topic
topics: [orders_topic, shipments_topic]
label: "Orders & Shipments"

shared_dimensions:
  week:
    label: "Week"
    mappings:
      orders_topic:
        field: orders.created_at
      shipments_topic:
        field: shipments.shipped_at

shared_measures:
  fulfillment_rate:
    label: "Fulfillment rate"
    sql: ${@shipments_topic.shipments.count} / NULLIF(${@orders_topic.orders.count}, 0)
    format: percent_2
Pick Week, Orders → Total revenue, Shipments → Shipment count, and Fulfillment rate in a workbook — one row per week, all four columns correctly computed.

Marketing funnel across systems

Each funnel stage lives in its own topic (separate fact tables in different schemas). The composite topic stitches them together by cohort week.
acquisition_funnel.composite_topic
topics: [signups_topic, trials_topic, conversions_topic, churn_topic]
label: "Acquisition funnel"

shared_dimensions:
  cohort_week:
    label: "Cohort week"
    mappings:
      signups_topic:
        field: signups.signed_up_at
      trials_topic:
        field: trials.started_at
      conversions_topic:
        field: conversions.converted_at
      churn_topic:
        field: churn_events.churned_at

shared_measures:
  trial_to_paid_rate:
    label: "Trial → paid"
    sql: ${@conversions_topic.conversions.count} / NULLIF(${@trials_topic.trials.count}, 0)
    format: percent_2

  net_new_customers:
    label: "Net new customers"
    sql: ${@conversions_topic.conversions.count} - ${@churn_topic.churn_events.count}

Constellation schema with a date spine

When you want to chart multiple fact tables alongside a continuous date axis (no gaps for days with zero activity), use a date_spine shared view.
daily_kpis.composite_topic
topics: [orders_topic, support_topic, product_usage_topic]
label: "Daily KPIs"

shared_views: [date_spine]
Because date_spine is a shared view joined into every topic, every day appears in the result — even days with no orders, no tickets, or no usage events.