Modules
A module represents a table in your database. A module includes dimensions, join paths, and metrics, making it the foundation for how data is modeled and explored in Steep.
File structure
Keep yaml files modular by defining one module per file.
YAML
module:
schema: "steep_demo_fintech"
table: "customers"
identifier: "customers"
description: "Records of customers, including IDs, name, sign-up date."
dimensions:
- column: "user_country"
type: "country"
joinPaths:
- from:
column: "id"
to:
table: "transactions"
column: "customer_id"
type: "one-to-many"
metrics:
- identifier: "registrations"
name: "Registrations"
description: "Total number of user sign-ups."
category: "Marketing"
type: "count"
time: "customers.created_at"
dimensions:
- "country"
Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
identifier | string | Unique name for the module within the workspace. | Required |
schema | string | Name of the database schema. | Required |
table | string | Name of the database table. | Required |
label | string | Display name for the module | Optional |
description | string | A short explanation of the table's contents. Helps teams understand what data the module represents. | Optional |
dimensions | array | Array of dimension definitions for this module | Optional |
metrics | array | Array of metric definitions for this module | Optional |
joinPaths | array | Array of join path definitions to other modules | Optional |
accessPolicies | array | Array of access policy definitions for this module. | Optional |
entities | array | Array of entity definitions for this module | Optional |
Access policy
An access policy controls which rows each workspace member can access. Access policies are defined on modules and filter data based on user attributes. Read more →
Access policies are defined as a list under accessPolicies within a module. Multiple policies on the same module are combined with AND.
YAML
accessPolicies:
- column: "account_id"
attribute: "user.account_id"
- schema: "steep_demo_fintech"
table: "transactions"
column: "country"
attribute: "user.market"
Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
schema | string | Name of the database schema. Optional if same schema as current module. | Optional |
table | string | Name of the database table. Optional if same table as current module. | Optional |
column | string | The column that contains the row-level information to filter on. | Required |
attribute | string | The user attribute that will determine how the policy filters data for each member, in user.<name> format. | Required |
Dimensions
A dimension represents a column in your database. Dimensions are used for breakdowns and filters. Examples of dimensions are country or segment.
YAML
dimensions:
- column: "country"
type: "country"
label: "Country"
description: "The country of the customer"
- column: "email"
type: "categorical"
label: "E-mail"
description: "The customer e-mail address"
Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
column | string | The name of the database column. The column name acts as the identifier of the dimension and is also used to match report filters. Dimensions can only be defined for string or boolean columns. | Required |
label | string | The display name of the dimension. If not defined, the column name will be used. | Optional |
description | string | A short explanation of what the dimension represents. Helps both data teams and business users understand its purpose. (currently not displayed for members) | Optional |
type | enum | The dimension type. Possible values: `categorical`, `city`, `country`, `h3-cell-index`, `time` | Required |
Join Paths
Join paths let you connect modules so that data from multiple modules can be combined into a single metric.
Define a join path in only one module. Once defined, the join can be used from both sides of the relationship.
Steep can automatically follow join paths up to two steps away.
YAML
This example joins the customers module to the transactions module using the id column on customers and customer_id on transactions.
joinPaths:
- from:
column: "id"
to:
table: "transactions"
column: "customer_id"
type: "one-to-many"
Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
from | object | A column in the from module (current module) that you want to join from. | Required |
to | object | The column in the module that you want to join to. | Required |
type | enum | Defines the relationship between the modules. Possible values: `one-to-one`, `one-to-many` | Required |
Metrics
A metric is an aggregation or calculation built on top of your modules. It represents key business indicators like order volume, active users, or conversion rate.
Metrics are defined in the module that represents the table that the metric is calculated on. Derived ratio metrics, which are not based on any table, can be defined in any module, but it is recommended to define them in the same module as the numerator metric.
Metric Parameters
| Parameter | Type | Description | Required | Applies to |
|---|---|---|---|---|
identifier | string | Unique metric identifier, used for referencing the metric. | Required | |
name | string | Display name of the metric. | Required | |
description | string | Explanation of what the metric measures. Helps data teams and business users understand its purpose. | Optional | |
dimensions | array | List of dimension columns available on the metric. Format: `schema.table.column`. schema and table are optional and can be omitted if same as current module. `this.*` can be used to get all dimensions from current module, while `schema.table.*` can be used to get all dimensions from a joined code module. | Optional | |
category | string | Metric category. You can add one category. | Optional | |
owner_emails | array | Email addresses of one or more metric owners. Must be workspace members. | Optional | |
is_private | boolean | Whether the metric is private. Defaults to false. | Optional | |
is_unlisted | boolean | Whether the metric is unlisted. Defaults to false. | Optional | |
time_grains | array | List of available time grains. Defaults to all time grains. | Optional | |
time_resampling | enum | Time resampling method. Defaults depends on the calculation type. Possible values: `sum/divide`, `average/repeat` | Optional | |
filters | array | One or more filters applied to the metric. | Optional | |
type | enum | Metric type. Possible values: `derived-ratio`, `sum`, `ratio`, `count`, `count-distinct`, `custom-value`, `custom-ratio` | Required | |
numerator | string | For ratio metrics, the column used for ratio calculations in the format: `table.column`. For derived ratio metrics, a reference to the numerator metric: a metric identifier, or an object with format `{ metric, slice? }`. | Required | derived-ratio, ratio |
denominator | string | For ratio metrics, the column used for ratio calculations in the format: `table.column`. For derived ratio metrics, a reference to the denominator metric: a metric identifier, or an object with format `{ metric, slice? }`. | Required | derived-ratio, ratio |
format | string | Format of a ratio metric. Defaults to 'percentage'. | Optional | derived-ratio, ratio, custom-ratio |
time | string | Column used to analyze the metric over time. Format: `table.column`. You can add only one time column. | Required | sum, ratio, count, count-distinct, custom-value, custom-ratio |
slices | array | One or more slices of the metric. | Optional | sum, ratio, count, count-distinct, custom-value, custom-ratio |
value | string | Column used for sum calculations. Format: `table.column`. | Required | sum |
distinct_on | string | Column to count distinct values on. Format: `table.column`. | Required | count-distinct |
sql_expression | string | SQL expression that returns the metric value. Columns mentioned in expression should be of format table.column. | Required | custom-value |
numerator_sql | string | SQL expression for the ratio numerator. Columns mentioned in expression should be of format table.column. | Required | custom-ratio |
denominator_sql | string | SQL expression for the ratio denominator. Columns mentioned in expression should be of format table.column. | Required | custom-ratio |
Slice Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
name | string | Name of the metric slice. | Required |
identifier | string | Unique identifier for the slice within the metric. Auto-generated from the name if omitted. | Optional |
filter | object | Filter applied to the metric slice. | Required |
Filter Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
schema | string | Name of the database schema. Optional if same schema as current module. | Optional |
table | string | Name of the database table. Optional if same table as current module. | Optional |
column | string | Name of the database column. | Required |
operator | enum | The operator to use for the filter. Possible values: `equals`, `not-equals`, `less-than`, `less-than-or-equal`, `greater-than`, `greater-than-or-equal`, `in`, `not-in`, `is`, `is-not`, `like`, `not-like` | Required |
expression | string | The expression to use for the filter. | Required |
Metric examples
Example yaml code for different metric types.
Sum
metrics:
- identifier: "order_vol"
name: "Order volume"
description: "Total sum of order value."
category: "Operations"
type: "sum"
time: "orders.created_at"
value: "orders.amount"
owner_emails:
- "vitor@company.com"
- "ebba@company.com"
is_private: true
is_unlisted: true
time_grains:
- "weekly"
- "monthly"
filters:
- column: "country"
operator: "not-equals"
expression: "test_country"
slices:
- name: "US"
identifier: "us"
filter:
column: "country"
operator: "equals"
expression: "US"
dimensions:
- "this.*"
Count
metrics:
- identifier: "orders"
name: "Orders"
description: "Number of orders."
category: "Operations"
type: "count"
time: "orders.created_at"
owner_emails:
- "vitor@company.com"
- "ebba@company.com"
filters:
- column: "country"
operator: "not-equals"
expression: "test_country"
dimensions:
- "this.*"
Ratio
metrics:
- identifier: "conversion_rate"
name: "Conversion rate"
description: "Conversion rate measures the percentage of users who sign-up."
type: "ratio"
time: "site.visit_at"
numerator: "site.conversions"
denominator: "site.visits"
format: "percentage"
dimensions:
- "this.*"
Unique count
metrics:
- identifier: "active_users"
name: "Active users"
description: "A user is considered active when they've made a transaction during the period"
type: "count-distinct"
time: "transactions.created_at"
distinct_on: "customers.customer_id"
dimensions:
- "this.*"
Custom Value
metrics:
- identifier: "partner_orders"
name: "Partner orders"
description: "Orders coming in through partner."
type: "custom-value"
time: "orders.created_at"
sql_expression: "SUM(CASE WHEN customers.type = 'partner' THEN orders.order_volume END)"
dimensions:
- "this.*"
Custom Ratio
metrics:
- identifier: "kyc_approved"
name: "KYC Approved %"
description: "Percentage of users approved through KYC processes. KYC stands for 'Know Your Customer': used to verify a customer's identity and assess risk, helping prevent fraud and financial crimes."
type: "custom-ratio"
time: "customers.created_at"
numerator_sql: "SUM(CASE WHEN customers.country != 'SE' THEN 1 END)"
denominator_sql: "COUNT(*)"
format: "percentage"
dimensions:
- "this.*"
Derived Ratio
A derived ratio divides one metric by another. The numerator and denominator each reference an operand metric in one of two ways:
- A metric identifier string, which uses the whole metric.
- An object of the form
{ metric, slice }, which references either the whole metric or a specific slice of that metric. The slice must be defined on the referenced metric. Omitsliceto use the whole metric.
Referencing a slice lets you build ratios such as "US orders per active customer" without defining a separate sliced metric. In the example below, the numerator uses the us slice of the orders metric while the denominator uses the full active_customers metric.
metrics:
- identifier: "orders_per_active_user"
name: "Orders per Active User"
description: "Number of orders per active customer"
category: "Commercial"
numerator:
metric: "orders"
slice: "us"
denominator: "active_customers"
type: "derived-ratio"
format: "number"
dimensions:
- "this.*"
Entities
An entity represents the row-level records of a module's table, such as customers or orders. Entities enable drill-downs from metrics into individual rows. Read more →
Define entities as a list under entities in the module that represents their table.
YAML
entities:
- identifier: "customer"
name: "Customer"
icon_name: "user"
primary_key: "id"
properties:
- column: "name"
name: "Name"
type: "string"
- column: "email"
name: "Email"
type: "string"
icon_name: "mail"
- column: "created_at"
name: "Signup date"
type: "date"
metrics:
- "registrations"
- "order_vol"
custom_links:
- name: "View in admin"
url_template: "https://admin.example.com/contacts/{id}"
Entity Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
identifier | string | Unique identifier for the entity within the workspace, used as the sync key. | Required |
name | string | Display name of the entity. | Required |
primary_key | string | Name of the primary key column on the entity's module table. | Required |
icon_name | string | Name of the icon displayed for this entity in the UI. Use a kebab-case icon name, e.g. `bar-chart`; unsupported names fall back to a default icon. | Optional |
properties | array | Per-instance attributes of the entity, shown as columns. At least one property is required; an entity with no properties is skipped during sync. | Optional |
metrics | array | Identifiers of metrics shown on the entity for drill-downs. Each metric must be on the entity's table or a table joined to it. | Optional |
custom_links | array | Deep-links to external tools, e.g. an admin URL for one of these entities. | Optional |
Property Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
column | string | Name of the column on the entity's module table. | Required |
name | string | Display name of the property. | Required |
type | enum | Value type of the property. Possible values: `number`, `time`, `date`, `string`, `boolean`, `uuid`, `geography` | Required |
icon_name | string | Name of the icon displayed alongside the property in the UI. Use a kebab-case icon name, e.g. `bar-chart`; unsupported names fall back to an icon based on the property's type. | Optional |
Custom Link Parameters
| Parameter | Type | Description | Required |
|---|---|---|---|
name | string | Display name of the custom link. | Required |
url_template | string | URL template with `{column}` placeholders filled in from the entity's row data, e.g. `https://example.com/{id}`. Each placeholder must name a column on the entity's module table. | Required |
Icon names
Set icon_name on an entity or property to one of the following names. Unrecognized names fall back to the default icon.
Show all 231 icon names
- airplane
- alarm-clock
- american-football
- anchor
- anonymous
- archive-box
- arrow-down
- arrow-left
- arrow-right
- arrow-up
- bag
- bank
- bar-chart
- basket-ball
- basketball-jersey
- battery
- bell
- bike
- boat
- bomb
- book
- bookmark
- bowl-of-food
- brain
- brick-wall
- briefcase
- bug
- bus
- cake
- calendar
- camera
- car
- celebration
- chart-block
- chat
- check-mark
- checkbox
- chef-hat
- clipboard
- clock
- clothes-hanger
- cloud
- cocktail-glass
- coffee-cup
- cohort-table
- command
- compact-disc
- comparison
- compass
- computer-chip
- cooking-put
- copy
- crane
- credit-card
- croissant
- crown
- cube
- dashboard-widgets
- database
- delivery-truck
- dial
- dice
- diving-goggles
- document
- emoji-happy
- emoji-sad
- exclamation-mark
- experiment-flask
- explosion
- eye
- eyes
- factory-building
- fast-forward
- filter
- fire
- first-aid-cross
- flag-straight
- flag-wavy
- flash
- floppy-disk
- flower
- folder
- football
- football-jersey
- function
- game-controller
- game-pad
- gasoline-pump
- ghost
- gift
- glass
- glasses-square
- globe
- globe-grid
- graduation-cap
- grid
- grocery-bag
- group
- hamburger
- headphones
- headset
- heart
- home
- identity-badge
- identity-card
- image
- information
- internet-browser
- journalist-hat
- key
- knife
- knife-and-fork
- laptop-computer
- leaf
- lifebuoy
- lightbulb
- line-chart
- link
- list
- lock
- looking-glass
- magic-wand
- magnet
- map
- map-pin
- medal
- megaphone
- melon
- microphone
- money-bag
- moon
- mountains
- movie-clapper-board
- mushroom
- musical-note
- newspaper
- office-building
- open-book
- palette
- paper-plane
- parcel
- parking-sign
- pen-tip
- pencil
- phone
- photo-album
- piano-keys
- pie-chart
- pie-chart-slice
- piggy-bank
- pill
- pizza-slice
- planet
- play
- poop
- portrait
- push-pin
- puzzle-piece
- question-mark
- quotation-mark
- rain-cloud
- rainbow
- rank-chart
- rays
- recycle
- reload
- resize-arrows
- ribbon
- robot
- rocket
- route
- ruler
- runner
- scale
- scissors
- scooter
- settings
- shopping-bag
- shovel
- sign
- skull
- small-battery
- snowflake
- sort
- sound-waves
- sparkles
- speaker
- speech-bubble
- speed-gague
- stack
- stack-horizontal
- stack-of-money
- stack-vertical
- stacked-bar-chart
- star
- sun
- sunglasses
- switch
- t-shirt
- table
- tag
- target
- target-with-arrow
- tennis-ball
- tennis-racket
- terminal
- text
- text-box
- thought-bubble
- thumbs-down
- thumbs-up
- ticket
- tool
- tools
- traffic-lights
- trashcan
- tree
- trophy
- tv
- umbrella
- user
- video
- warning-triangle
- water-drop
- wayfinder
- wind
- wind-spiral
- wine-glass
- wrist-watch
- yin-yang