> ## Documentation Index
> Fetch the complete documentation index at: https://lightdash-mintlify-e6012f7f.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Custom charts

> Chart types beyond the built-in set: reusable chart types you build for your project, and one-off charts written as a Vega-Lite spec.

**Custom** is a single entry in the chart type menu that covers two kinds of chart:

* **Project chart types** - reusable chart types built for your project. You describe the chart you want, Lightdash builds it, and anyone in the project can then use it like a built-in chart type.
* **Vega charts** - a one-off chart written as a [Vega-Lite](https://vega.github.io/vega-lite/examples) spec in a JSON editor. The spec belongs to that chart alone.

Pick **Custom** in the chart type menu, then choose between them in the **Custom chart type** picker.

## Project chart types

A project chart type is a chart type you build once and reuse. Describe the chart you want - a calendar heatmap, a hexbin map, a custom KPI layout - and Lightdash builds it, along with the inputs it needs (for example a "Category" dimension and a "Value" metric). Anyone in the project can then pick it as a chart type, map their own fields to its inputs, and save the result like any other chart.

The same chart type can power many saved charts, each with its own query and field mapping.

<Info>
  Project chart types are an enterprise feature, enabled by default on Lightdash Cloud. Self-hosted instances need the [data apps runtime configured](/guides/data-apps/self-hosting).
</Info>

### Browsing chart types

Every chart type in the project lives in the gallery. Go to **Browse** and pick **Chart types**.

Each card previews the chart type with sample data. Click a card to see its description, who built it, its inputs, and its current version, and to preview it in the Explorer, edit it, or delete it.

<Frame>
  <img alt="The chart type gallery, showing cards for each of the project's chart types" className="block dark:hidden" src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-chart-types-gallery-light.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=3f4b1bdefec9d0ab05a5a5223cff8411" width="1512" height="470" data-path="images/references/chart-types/custom-chart-types-gallery-light.png" />

  <img alt="The chart type gallery, showing cards for each of the project's chart types" className="hidden dark:block" src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-chart-types-gallery-dark.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=b5e438d56c36dc16936c230ebd4b1e0d" width="1512" height="470" data-path="images/references/chart-types/custom-chart-types-gallery-dark.png" />
</Frame>

### Building a chart type

Click **New chart type** in the gallery to open the builder, then describe the chart you want.

The builder previews the chart type with sample data as it's built. The **Configure** panel beside the preview holds the display options the chart type declares, along with a color palette to preview it against. Follow-up prompts create new versions, and **History** opens a panel where you can view an earlier version or restore it.

Name and describe the chart type in the header - that's what people see in the gallery and in the chart type picker. When it looks right, click **Preview in explorer** to try it against a real query.

<Frame>
  <img alt="The chart type builder, with the sample-data preview, the Configure panel, and the prompt bar" className="block dark:hidden" src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-chart-types-builder-light.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=1d5ea56e8336b2ee526fb0a260c40b04" width="1512" height="900" data-path="images/references/chart-types/custom-chart-types-builder-light.png" />

  <img alt="The chart type builder, with the sample-data preview, the Configure panel, and the prompt bar" className="hidden dark:block" src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-chart-types-builder-dark.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=882bf176ea0a71234537c9168f351cd5" width="1512" height="900" data-path="images/references/chart-types/custom-chart-types-builder-dark.png" />
</Frame>

You can also start one from any chart, without leaving the Explorer: pick **Custom** as the chart type and choose **Create new chart type** in the picker.

<Tip>
  Chart types can also be developed on your machine and uploaded with the CLI. See [Building data apps locally](/guides/data-apps/building-locally).
</Tip>

### Using a chart type in a chart

<Steps>
  <Step title="Run your query">
    Select the dimensions and metrics your chart needs and run the query. You have to run it before you can pick a custom chart type.
  </Step>

  <Step title="Pick the chart type">
    Open **Configure**, choose **Custom** in the chart type menu, then pick one from the **Project** group in the **Custom chart type** picker. Only chart types that finished building are listed.
  </Step>

  <Step title="Map your fields">
    Each of the chart type's inputs gets a field picker, the same as configuring axes on a bar or line chart. Required inputs can't be cleared.
  </Step>
</Steps>

<Frame>
  <img alt="The Custom chart type picker open in the Explorer, listing the built-in Vega editor and the project's own chart types" className="block dark:hidden" src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-chart-types-picker-light.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=b4302f593dafd45c4322dcba2b60f3d5" width="1512" height="900" data-path="images/references/chart-types/custom-chart-types-picker-light.png" />

  <img alt="The Custom chart type picker open in the Explorer, listing the built-in Vega editor and the project's own chart types" className="hidden dark:block" src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-chart-types-picker-dark.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=7306a3fa0cbd9e3c77f40dd353d1eaf3" width="1512" height="900" data-path="images/references/chart-types/custom-chart-types-picker-dark.png" />
</Frame>

The chart re-renders as you change the mapping or the underlying query.

<Frame>
  <img alt="A project chart type selected in the Explorer, with its inputs mapped to the query's fields and the chart rendering" className="block dark:hidden" src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-chart-types-mapping-light.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=7103ee79878eb7733aecdaf9d1afe901" width="1512" height="900" data-path="images/references/chart-types/custom-chart-types-mapping-light.png" />

  <img alt="A project chart type selected in the Explorer, with its inputs mapped to the query's fields and the chart rendering" className="hidden dark:block" src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-chart-types-mapping-dark.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=e1eaf386da0fb6b4b23dd33debf55c7e" width="1512" height="900" data-path="images/references/chart-types/custom-chart-types-mapping-dark.png" />
</Frame>

### Saving and dashboards

Save the chart like any other chart. The saved chart remembers which chart type it uses and how its inputs are mapped.

Saved charts render in chart view and as dashboard tiles, driven by each surface's own query - dashboard filters and [date zoom](/guides/date-zoom) apply like any other chart tile.

### Permissions

Chart types are available across the whole project. They don't live in spaces and can't be moved into one.

* Anyone who can view a chart can see the chart type it renders with.
* Editors and above can build new chart types.
* You can edit and delete the chart types you built. Project admins can edit and delete any of them.

## Vega charts

Vega charts are written as a [Vega-Lite](https://vega.github.io/vega-lite/examples) spec in a JSON editor, which unlocks an extended library of charts including heat maps, bubble plots, box plots and more. The spec is saved with the chart and isn't reusable elsewhere.

### Known limitations

These new Vega-lite powered charts offer enhanced flexibility and a broader range of visualizations, but there are important limitations to be aware of, particularly concerning interactivity and dashboard integration like:

* **Drill-Down Functionality**: The ability to drill into metrics by grouping them with dimensions (e.g., "Drill by") is not available in Vega charts.
* **View Underlying Data**: Users cannot click on data points within Vega charts to view the underlying records that compose those data points.
* **Cross-Filtering**: Interactive filtering across dashboard tiles by selecting elements within a chart (also known as cross-filtering) is not supported in Vega charts.

### Quickstart

The steps to create a Vega chart are as follows:

<Steps>
  <Step title="Gather your data">
    Return the data you need for your chart as normal using the Lightdash UI to select relevant dimensions and metrics.
  </Step>

  <Step title="Switch to Vega">
    Head to the chart configuration options and choose **Custom** in the chart type menu, then pick **Vega (JSON editor)** from the **Built in** group in the **Custom chart type** picker.

    <img src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-charts-drop-down.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=9b3d661da068b6be580197e5560aedbe" alt="" width="1512" height="900" data-path="images/references/chart-types/custom-charts-drop-down.png" />
  </Step>

  <Step title="Write your config">
    Select a template to load a sample configuration for the chart selected, or grab an example.
    <Tip> **Tip:** LLMs are great at updating Vega Lite configs </Tip>
  </Step>
</Steps>

Below are some example chart config templates that we got working in Lightdash, along with some tips on when to use each chart type.

## Vega templates

### Bar chart

You can already do this with presets in Lightdash, but it's a simple example you should be able to get working quickly. This chart works best with simple string or date dimensions and a numeric metric

<Accordion title="Here is an example config with tooltips and a pivot">
  ```json theme={null}
  {
    "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
    "mark": "bar",
    "encoding": {
      "x": {
        "field": "orders_order_date_week",
        "type": "temporal" // use quantitative if dimension if string or number
      },
      "y": {
        "field": "orders_total_order_amount",
        "type": "quantitative"
      },
      "color": { // Optional property to pivot the data
        "field": "orders_status",
        "type": "nominal"
      },
      "tooltip": [ // Optional property to show tooltips
        {"field": "orders_order_date_week", "type": "temporal", "title": "Order Date Week"},
        {"field": "orders_total_order_amount", "type": "quantitative", "title": "Total Order Amount"},
        {"field": "orders_status", "type": "nominal", "title": "Status"}
      ]
    }
  }
  ```
</Accordion>

#### Sankey-style bar chart

For true source-to-target flow diagrams, use the built-in [Sankey chart](/references/chart-types/sankey). The custom template below is an escape hatch for the stacked-bar variation that shows how segment proportions shift over time on a continuous x-axis — something the built-in Sankey doesn't do.

Use this chart when you want to show how parts of a whole change across categories or time and you want to visualize how individual segments flow from one stage to the next.

It's perfect for things like user cohorts, funnel stages, or survey responses over time. Any scenario where it's helpful to track how groups move or shift between steps.

[See a live demo of this chart](https://demo.lightdash.com/projects/d496d901-a76d-4916-9eae-b81bc7337013/saved/8db9bfd8-7e2d-41a0-8f7e-7a727660fb20) on our demo site.

The config below will output a sankey-style bar chart with the standard Vega-Lite settings, like this:

<img src="https://mintcdn.com/lightdash-mintlify-e6012f7f/MWRAgQ1AX3XMjudP/images/references/chart-types/sankey-style-bar-chart.png?fit=max&auto=format&n=MWRAgQ1AX3XMjudP&q=85&s=0f495e90569dd398547c24fe1f078b18" alt="" width="2334" height="1031" data-path="images/references/chart-types/sankey-style-bar-chart.png" />

<Accordion title="Example sankey-style 100% stacked bar chart config">
  ```json theme={null}
  {
    "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
    "config": {
      "axis": {
        "titleFontSize": 16,
        "labelFontSize": 14,
        "grid": false
      }
    },
    "layer": [
      {
        "mark": {
          "type": "area",
          "interpolate": "monotone"
        },
        "encoding": {
          "opacity": { "value": 0.4 },
          "x": {
            "field": "leads_created_at_month",
            "type": "temporal",
            "title": null,
            "axis": {
              "labelExpr": "timeFormat(datum.value, '%b %Y')",
              "grid": false
            }
          },
          "y": {
            "aggregate": "sum",
            "field": "_of_total",
            "type": "quantitative",
            "stack": "zero",
            "title": "% of Monthly Leads",
            "axis": {
              "labels": false,
              "grid": false,
              "format": ".0%"
            }
          },
          "color": {
            "field": "leads_lead_status",
            "type": "nominal",
            "title": "Lead status",
            "sort": {
              "op": "sum",
              "field": "_of_total",
              "order": "descending"
            },
            "scale": {
              "scheme": "dark2"
            }
          },
          "detail": {
            "field": "leads_lead_status",
            "type": "nominal"
          },
          "tooltip": [
            {
              "field": "leads_created_at_month",
              "type": "temporal",
              "title": "Month"
            },
            {
              "field": "leads_lead_status",
              "type": "nominal",
              "title": "Lead status"
            },
            {
              "aggregate": "sum",
              "field": "_of_total",
              "type": "quantitative",
              "title": "% of month",
              "format": "0%"
            }
          ],
          "order": {
            "aggregate": "sum",
            "field": "_of_total",
            "sort": "descending"
          }
        }
      },
      {
        "mark": {
          "type": "bar",
          "width": { "band": 1 }
        },
        "encoding": {
          "x": {
            "field": "leads_created_at_month",
            "type": "temporal",
            "axis": {
              "labelExpr": "timeFormat(datum.value, '%b %Y')",
              "grid": false
            }
          },
          "y": {
            "aggregate": "sum",
            "field": "_of_total",
            "type": "quantitative",
            "stack": "zero",
            "title": "% of Monthly Leads",
            "axis": {
              "grid": false,
              "format": ".0%"
            }
          },
          "color": {
            "field": "leads_lead_status",
            "type": "nominal",
            "title": "Lead status",
            "sort": {
              "op": "sum",
              "field": "_of_total",
              "order": "descending"
            },
            "legend": {
              "titleFontSize": 16,
              "labelFontSize": 14,
              "symbolSize": 300,
              "orient": "right",
              "direction": "vertical"
            },
            "scale": {
              "scheme": "dark2"
            }
          },
          "order": {
            "aggregate": "sum",
            "field": "_of_total",
            "sort": "descending"
          },
          "tooltip": [
            {
              "field": "leads_created_at_month",
              "type": "temporal",
              "title": "Month"
            },
            {
              "field": "leads_lead_status",
              "type": "nominal",
              "title": "Lead status"
            },
            {
              "aggregate": "sum",
              "field": "_of_total",
              "type": "quantitative",
              "title": "% of month",
              "format": ".1%"
            }
          ]
        }
      },
      {
        "mark": {
          "type": "text",
          "align": "center",
          "baseline": "line-top",
          "dx": 0,
          "fill": "black",
          "fontSize": 12
        },
        "encoding": {
          "x": {
            "field": "leads_created_at_month",
            "type": "temporal"
          },
          "y": {
            "aggregate": "sum",
            "field": "_of_total",
            "type": "quantitative",
            "stack": "center"
          },
          "detail": {
            "field": "leads_lead_status",
            "type": "nominal"
          },
          "text": {
            "aggregate": "sum",
            "field": "_of_total",
            "type": "quantitative",
            "format": ".1%"
          },
          "order": {
            "aggregate": "sum",
            "field": "_of_total",
            "sort": "descending"
          }
        }
      },
      {
        "mark": {
          "type": "text",
          "align": "center",
          "baseline": "middle"
        },
        "encoding": {
          "x": {
            "field": "leads_created_at_month",
            "type": "temporal"
          },
          "y": {
            "value": 1
          }
        }
      }
    ]
  }

  ```
</Accordion>

### Line chart with confidence interval

This chart works best with a date dimension on the x-axis and a numeric metric as the "Mean" with "Mean High" and "Mean Low" numeric values in your results.

[See a live demo of this chart](https://demo.lightdash.com/projects/2014e038-ff4b-4761-ae6f-fbf551e7b468/saved/f586131d-3ff2-4d86-95e9-eae6b14fbc42) on our demo site.

The config below will output a line chart with confidence interval bands that looks like this:

<img src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-chart-confidence-interval.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=2ab6a674f3d3f83420e7174062053e5e" alt="" width="2324" height="1020" data-path="images/references/chart-types/custom-chart-confidence-interval.png" />

<Accordion title="Example line chart with confidence interval config">
  ```json theme={null}
  {
    "layer": [
      {
        "mark": {
          "type": "errorband"
        },
        "encoding": {
          "y": {
            "type": "quantitative",
            "field": "profit_low"
          },
          "y2": {
            "type": "quantitative",
            "field": "profit_high"
          },
          "color": {
            "value": "#7c43bd"
          },
          "opacity": {
            "value": 0.25
          }
        }
      },
      {
        "mark": {
          "type": "line"
        },
        "encoding": {
          "y": {
            "axis": {
              "format": "$,.0f"
            },
            "type": "quantitative",
            "field": "dbt_orders_sum_of_profit",
            "title": "Profit"
          },
          "color": {
            "value": "#7c43bd"
          }
        }
      }
    ],
    "title": "Monthly profit with confidence intervals",
    "width": "container",
    "config": {
      "axis": {
        "grid": true
      },
      "view": {
        "stroke": null
      }
    },
    "height": 300,
    "$schema": "https://vega.github.io/schema/vega-lite/v6.json",
    "encoding": {
      "x": {
        "type": "temporal",
        "field": "dbt_orders_order_date_month",
        "title": "Month",
        "timeUnit": "yearmonth"
      },
      "tooltip": [
        {
          "type": "temporal",
          "field": "dbt_orders_order_date_month",
          "title": "Month",
          "timeUnit": "yearmonth"
        },
        {
          "type": "quantitative",
          "field": "dbt_orders_sum_of_profit",
          "title": "Profit (Mean)",
          "format": "$,.0f"
        },
        {
          "type": "quantitative",
          "field": "profit_low",
          "title": "Profit (Low)",
          "format": "$,.0f"
        },
        {
          "type": "quantitative",
          "field": "profit_high",
          "title": "Profit (High)",
          "format": "$,.0f"
        }
      ]
    }
  }
  ```
</Accordion>

### Heatmaps

Heatmaps are ideal for visualizing patterns across two categorical or temporal dimensions, making it easy to spot trends, hotspots, or anomalies at a glance. They're perfect for analyzing time-based patterns (like day of week vs. hour of day), comparing performance across categories, or identifying correlations in multi-dimensional data.

This chart works best with string or date dimensions and a numeric metric as color.

[See a live demo of this chart](https://demo.lightdash.com/projects/2014e038-ff4b-4761-ae6f-fbf551e7b468/saved/86a8e5d3-75e9-49ec-b65a-b3c6a4730217) on our demo site.

In this example, the heatmap uses orders data to show patterns across order weeks (x-axis) and days of the week (y-axis), with color intensity representing the number of orders. The config below will output a heatmap with the standard Vega-Lite settings that looks like this:

<img src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-charts-heatmap.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=4eef48c2ba0a64f3a3876c850eebc88e" alt="" width="2504" height="1036" data-path="images/references/chart-types/custom-charts-heatmap.png" />

<Accordion title="Example heatmap config">
  ```json theme={null}
  {
    "mark": "rect",
    "encoding": {
      "x": {
        "field": "dbt_orders_order_date_week",
        "type": "temporal",
        "title": "Week",
        "timeUnit": "yearweek"
      },
      "y": {
        "field": "dbt_orders_order_date_day_of_week_name",
        "type": "ordinal",
        "title": "Day of Week",
        "sort": [
          "Monday",
          "Tuesday",
          "Wednesday",
          "Thursday",
          "Friday",
          "Saturday",
          "Sunday"
        ]
      },
      "color": {
        "aggregate": "sum",
        "field": "dbt_orders_count_distinct_order_id",
        "type": "quantitative",
        "title": "Orders",
        "scale": {
          "scheme": "blues"
        }
      },
      "tooltip": [
        {
          "field": "dbt_orders_order_date_week",
          "type": "temporal",
          "title": "Week"
        },
        {
          "field": "dbt_orders_order_date_day_of_week_name",
          "type": "ordinal",
          "title": "Day of Week"
        },
        {
          "aggregate": "sum",
          "field": "dbt_orders_count_distinct_order_id",
          "type": "quantitative",
          "title": "Orders"
        }
      ]
    }
  }
  ```
</Accordion>

### Bubble Plots

Bubble plots build on top of standard scatter plot visualizations, by allowing you to adjust the size of a given point based on the output of a field. Here's one looking at some Healthcare data.

This chart works best with string or date dimensions and a numeric metric for the y-axis and another numeric metric for the size.

[See a live demo of this chart](https://demo.lightdash.com/projects/7992ac17-dbb3-4c8e-8658-fcbc96eea949/saved/ec504908-e693-4b89-98d2-c06085a2f815) on our demo site.

The config below will output a bubble plot with the standard Vega-Lite settings, like this:

<img src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-charts-bubble-plot.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=3df2f7af4b3179f48e40121b7eace78b" alt="" width="2498" height="1022" data-path="images/references/chart-types/custom-charts-bubble-plot.png" />

<Accordion title="Example Bubble blot config">
  ```json theme={null}
  {
    "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
    "layer": [
      {
        "mark": {
          "type": "point",
          "filled": true,
          "opacity": 0.7
        },
        "encoding": {
          "x": {
            "axis": {
              "title": "Total Discharges",
              "tickColor": "#6e7079",
              "labelColor": "#6e7079"
            },
            "type": "quantitative",
            "field": "inpatient_charges_sum_total_discharges"
          },
          "y": {
            "axis": {
              "title": "Total Charged ($)",
              "tickColor": "#6e7079",
              "labelColor": "#6e7079"
            },
            "type": "quantitative",
            "field": "inpatient_charges_sum_total_charged"
          },
          "size": {
            "type": "quantitative",
            "field": "inpatient_charges_avg_charged_per_discharge",
            "legend": {
              "title": "Avg Charged per Discharge"
            }
          },
          "color": {
            "value": "#7C6AED"
          },
          "tooltip": [
            {
              "type": "nominal",
              "field": "inpatient_charges_provider_state",
              "title": "State"
            },
            {
              "type": "quantitative",
              "field": "inpatient_charges_sum_total_discharges",
              "title": "Total Discharges"
            },
            {
              "type": "quantitative",
              "field": "inpatient_charges_sum_total_charged",
              "title": "Total Charged"
            },
            {
              "type": "quantitative",
              "field": "inpatient_charges_avg_charged_per_discharge",
              "title": "Avg Length of Stay"
            }
          ]
        }
      },
      {
        "mark": {
          "type": "line",
          "color": "#89bea4",
          "strokeWidth": 2
        },
        "encoding": {
          "x": {
            "type": "quantitative",
            "field": "inpatient_charges_sum_total_discharges"
          },
          "y": {
            "type": "quantitative",
            "field": "inpatient_charges_sum_total_charged"
          }
        },
        "transform": [
          {
            "on": "inpatient_charges_sum_total_discharges",
            "regression": "inpatient_charges_sum_total_charged"
          }
        ]
      }
    ]
  }
  ```
</Accordion>

### Funnel charts

For standard funnels, use the built-in [Funnel chart](/references/chart-types/funnel-chart) — it handles discrete stages with counts and stage-to-stage percentages out of the box. The custom template below is an escape hatch for styled variations the built-in chart doesn't support (e.g., custom trapezoid coloring, inline conversion-rate labels between stages).

Funnel charts are ideal for visualizing a flow or process where the quantity decreases step-by-step, such as sales pipelines, conversion rates, or order processes. Each stage is represented as a bar whose width reflects the corresponding value.

This chart works best with a categorical or string dimension (like status or step name) and a numeric metric (such as order amount or count) to measure at each step.

Funnel chart configurations are more complex than other charts. We recommend loading the template directly in Lightdash, which will automatically map your data fields.

[See a live demo of this chart](https://demo.lightdash.com/projects/d496d901-a76d-4916-9eae-b81bc7337013/saved/b19b6a9f-b7a7-4795-bbd7-48f39b425c69) on our demo site.

The config below will output a funnel chart with the standard Vega-Lite settings that looks like this:

<img src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-charts-funnel-chart.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=8b69c5756583eac25d8281a0d4e684e5" alt="Custom funnel chart" width="2336" height="972" data-path="images/references/chart-types/custom-charts-funnel-chart.png" />

<Accordion title="Example funnel chart config">
  ```json theme={null}
  {
    "$schema": "https://vega.github.io/schema/vega-lite/v5.json",

    "title": {
      "text": "Sales Funnel",
      "anchor": "middle",
      "fontSize": 18,
      "fontWeight": "bold"
    },

    "config": {
      "view": {
        "strokeWidth": 0
      }
    },

    "transform": [
      {
        "joinaggregate": [
          {
            "as": "max_count",
            "op": "max",
            "field": "leads_unique_lead_count"
          }
        ]
      },
      {
        "as": "x_start",
        "calculate": "(datum.max_count - datum.leads_unique_lead_count) / 2"
      },
      {
        "as": "x_end",
        "calculate": "datum.x_start + datum.leads_unique_lead_count"
      },
      {
        "as": "x_mid",
        "calculate": "datum.x_start + (datum.leads_unique_lead_count / 2)"
      },
      {
        "as": "label",
        "calculate": "datum.leads_unique_lead_count + ' ' + datum.leads_lead_status"
      },
      {
        "as": "change_label",
        "calculate": "isValid(datum.conversion_rate) ? '↓ ' + format(datum.conversion_rate * 100, '.1f') + '%' : ''"
      }
    ],

    "layer": [
      {
        "mark": {
          "type": "bar"
        },
        "encoding": {
          "x": {
            "axis": null,
            "type": "quantitative",
            "field": "x_start"
          },
          "x2": {
            "field": "x_end"
          },
          "y": {
            "axis": null,
            "sort": null,
            "type": "nominal",
            "field": "leads_lead_status",
            "scale": {
              "padding": 0.5,
              "reverse": true
            }
          },
          "color": {
            "type": "nominal",
            "field": "leads_lead_status",
            "scale": {
              "range": [
                "#FFE3CC",
                "#FFC199",
                "#FF9F66",
                "#FF7D33",
                "#E65C00",
                "#B34700"
              ]
            }
          }
        }
      },
      {
        "mark": {
          "type": "text",
          "align": "center",
          "color": "black",
          "baseline": "middle",
          "fontWeight": "bold"
        },
        "encoding": {
          "x": {
            "type": "quantitative",
            "field": "x_mid"
          },
          "y": {
            "axis": null,
            "sort": null,
            "type": "nominal",
            "field": "leads_lead_status",
            "scale": {
              "reverse": true
            }
          },
          "text": {
            "field": "label"
          },
          "yOffset": {
            "value": -8
          }
        }
      },
      {
        "mark": {
          "type": "text",
          "align": "center",
          "color": "black",
          "baseline": "middle",
          "fontSize": 12
        },
        "encoding": {
          "x": {
            "type": "quantitative",
            "field": "x_mid"
          },
          "y": {
            "axis": null,
            "sort": null,
            "type": "nominal",
            "field": "leads_lead_status",
            "scale": {
              "reverse": true
            }
          },
          "text": {
            "field": "change_label"
          },
          "yOffset": {
            "value": 10
          }
        }
      },
      {
        "mark": {
          "type": "point",
          "opacity": 0
        },
        "encoding": {
          "color": {
            "type": "nominal",
            "field": "leads_lead_status",
            "scale": {
              "range": [
                "#FFE3CC",
                "#FFC199",
                "#FF9F66",
                "#FF7D33",
                "#E65C00",
                "#B34700"
              ]
            },
            "legend": {
              "title": "Lead status",
              "orient": "right"
            }
          }
        }
      }
    ]
  }
  ```
</Accordion>

<Tip>
  If you add extra dimensions, the funnel chart will not render correctly.
</Tip>

### Waterfall charts

Waterfall charts show how an initial value is affected by a series of positive and negative changes, making it easy to see the cumulative effect of sequential increases and decreases. They're perfect for visualizing financial changes (revenue breakdown, budget analysis), customer lifecycle metrics, or any scenario where you need to track step-by-step contributions to a total.

This chart works best with a categorical or temporal dimension for the x-axis (like stages or time periods) and numeric metrics representing starting and ending values for each step.

[See a live demo of this chart](https://demo.lightdash.com/projects/d496d901-a76d-4916-9eae-b81bc7337013/saved/3706f242-e4c5-4bb7-9037-e750e18a06e4/) on our demo site.

The config below will output a waterfall chart with the standard Vega-Lite settings, like this:

<img src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-charts-waterfall.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=6ce598e8aa6b33e05aa03cb6babb95c0" alt="Custom Waterfall" width="2726" height="1018" data-path="images/references/chart-types/custom-charts-waterfall.png" />

<Accordion title="Example waterfall config">
  ```json theme={null}
  {
    "data": {
      "name": "table"
    },
    "layer": [
      {
        "mark": {
          "type": "bar",
          "opacity": 1
        },
        "encoding": {
          "y": {
            "type": "quantitative",
            "field": "base",
            "title": "Unique Active Users"
          },
          "y2": {
            "field": "end"
          },
          "color": {
            "type": "nominal",
            "field": "type",
            "scale": {
              "range": [
                "#BFAAF9",
                "#F28B82",
                "#E5E7EB"
              ],
              "domain": [
                "increase",
                "decrease",
                "no_change"
              ]
            },
            "legend": {
              "title": "Change Type"
            }
          },
          "tooltip": [
            {
              "field": "tracks_timestamp_day",
              "title": "Date",
              "timeUnit": "yearmonthdate"
            },
            {
              "field": "tracks_unique_user_count",
              "title": "Total Users"
            },
            {
              "field": "change",
              "title": "Change"
            }
          ]
        }
      },
      {
        "mark": {
          "dx": 50,
          "dy": 10,
          "type": "text",
          "align": "left",
          "color": "#333",
          "baseline": "middle",
          "fontWeight": "bold"
        },
        "encoding": {
          "x": {
            "type": "temporal",
            "field": "tracks_timestamp_day"
          },
          "y": {
            "type": "quantitative",
            "field": "end"
          },
          "text": {
            "type": "quantitative",
            "field": "change",
            "format": "+,d"
          }
        }
      }
    ],
    "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
    "encoding": {
      "x": {
        "axis": {
          "grid": false,
          "format": "%b %d",
          "tickCount": "day",
          "labelAngle": -45
        },
        "type": "temporal",
        "field": "tracks_timestamp_day",
        "title": "Date",
        "timeUnit": "yearmonthdate"
      }
    },
    "transform": [
      {
        "sort": [
          {
            "field": "tracks_timestamp_day"
          }
        ],
        "window": [
          {
            "as": "previous_value",
            "op": "lag",
            "field": "tracks_unique_user_count"
          }
        ]
      },
      {
        "as": "change",
        "calculate": "datum.tracks_unique_user_count - datum.previous_value"
      },
      {
        "as": "type",
        "calculate": "datum.change > 0 ? 'increase' : datum.change < 0 ? 'decrease' : 'no_change'"
      },
      {
        "as": "base",
        "calculate": "datum.previous_value || 0"
      },
      {
        "as": "end",
        "calculate": "datum.base + datum.change"
      }
    ],
    "description": "Waterfall chart showing changes in active unique users per day."
  }
  ```
</Accordion>

### Trellis area chart

Trellis area charts (also called small multiples or faceted area charts) are perfect for comparing trends across multiple categories over time, making it easy to spot patterns, outliers, and seasonality at a glance. They're ideal for analyzing product lines, user segments, marketing channels, or any scenario where you want to emphasize the shape of trends rather than exact values.

This chart works best with a temporal dimension for the x-axis, a categorical dimension for faceting, and a numeric metric for the y-axis.

[See a live demo of this chart](https://demo.lightdash.com/projects/2014e038-ff4b-4761-ae6f-fbf551e7b468/saved/8a80e49d-ef46-45fd-951f-62023a0df657) on our demo site.

The code below will give you a trellis area chart like this:

<img src="https://mintcdn.com/lightdash-mintlify-e6012f7f/MWRAgQ1AX3XMjudP/images/references/chart-types/trellis-area.png?fit=max&auto=format&n=MWRAgQ1AX3XMjudP&q=85&s=83f6e9dc859128bd248d919fa66d4fa1" alt="Custom trellis area chart" width="1522" height="762" data-path="images/references/chart-types/trellis-area.png" />

<Accordion title="Example trellis area chart config">
  ```
  {
    "$schema": "https://vega.github.io/schema/vega-lite/v6.json",
    "description": "Distinct order counts by browser and month.",
    "facet": {
      "row": {
        "field": "dbt_orders_browser",
        "type": "nominal",
        "title": "Browser"
      }
    },
    "spec": {
      "width": 600,
      "height": 60,
      "mark": "area",
      "encoding": {
        "x": {
          "field": "dbt_orders_order_date_week",
          "type": "temporal",
          "title": "Order Month",
          "axis": {
            "grid": true
          }
        },
        "y": {
          "field": "dbt_orders_count_distinct_order_id",
          "type": "quantitative",
          "title": "Distinct Orders",
          "axis": {
            "grid": false
          }
        },
        "color": {
          "field": "dbt_orders_browser",
          "type": "nominal",
          "legend": null
        },
        "tooltip": [
          {
            "field": "dbt_orders_browser",
            "type": "nominal",
            "title": "Browser"
          },
          {
            "field": "dbt_orders_order_date_week",
            "type": "temporal",
            "title": "Order Month"
          },
          {
            "field": "dbt_orders_count_distinct_order_id",
            "type": "quantitative",
            "title": "Distinct Orders"
          }
        ]
      }
    },
    "resolve": {
      "scale": {
        "y": "independent"
      }
    }
  }
  ```
</Accordion>

### Highlighted bar chart

Highlighted bar charts are perfect for comparing a metric across categories while drawing attention to a specific item of interest, making it easy to see how one bar stands out from the rest. They're ideal for emphasizing key accounts, top products, benchmark comparisons, or any scenario where you want to spotlight a particular category.

This chart works best with a categorical dimension and a numeric metric.

[See a live demo of this chart](https://demo.lightdash.com/projects/d496d901-a76d-4916-9eae-b81bc7337013/saved/0bd1c089-52ef-411a-9893-24a09d60e8e8) on our demo site.

The code below will give you a highlighted bar chart like this:

<img src="https://mintcdn.com/lightdash-mintlify-e6012f7f/0JEuqOUwh6wc7Fz5/images/references/chart-types/custom-charts-highlighted-bar.png?fit=max&auto=format&n=0JEuqOUwh6wc7Fz5&q=85&s=b972dc361c56913f5629ea9ec5e5c3b8" alt="" width="3014" height="1178" data-path="images/references/chart-types/custom-charts-highlighted-bar.png" />

<Accordion title="Example highlighted bar chart config">
  ```json theme={null}
  {
    "mark": {
      "type": "bar"
    },
    "encoding": {
      "x": {
        "axis": {
          "title": "Account Name",
          "labelAngle": -40
        },
        "sort": "-y",
        "type": "nominal",
        "field": "accounts_account_name"
      },
      "y": {
        "axis": {
          "format": "~s"
        },
        "type": "quantitative",
        "field": "accounts_total_estimated_annual_recurring_revenue",
        "title": "ARR $"
      },
      "color": {
        "value": "#b0b0b0",
        "legend": null,
        "condition": {
          "test": "datum.accounts_account_name === 'DMC Global Inc.'",
          "value": "#00B4D8"
        }
      },
      "tooltip": [
        {
          "type": "nominal",
          "field": "accounts_account_name",
          "title": "Account Name"
        },
        {
          "type": "quantitative",
          "field": "accounts_total_estimated_annual_recurring_revenue",
          "title": "Annual Recurring Revenue",
          "format": ","
        }
      ]
    }
  }
  ```
</Accordion>

### More examples

You can find more examples on the [Vega lite official website](https://vega.github.io/vega-lite/examples).
