Reports: Funnels
Relevant source files
The following files were used as context for generating this wiki page:
The Funnels report is a powerful analytics tool within Umami designed to track and visualize user progression through a specific sequence of actions on a website. Its primary purpose is to "understand the conversion and drop-off rate of users" as they navigate a predefined path, such as a registration flow, checkout process, or marketing campaign journey.
By defining a series of steps, which can be either page views (path) or custom tracked events (event), users can measure how many visitors complete each step, where they drop off, and the overall conversion rate of the entire sequence. This provides critical insights for optimizing user experience and improving conversion goals. Funnels are a specific type of the generic Report entity in the system.
Sources: src/components/messages.ts:211-214, src/lib/schema.ts:101-118, prisma/schema.prisma:243-258
Data Model & Storage
Funnel configurations are stored in the Report table in the database. The type column is set to 'funnel', and the specific configuration for the funnel is stored as a JSON object in the parameters column.
Sources: prisma/schema.prisma:247, src/app/(main)/websites/[websiteId]/(reports)/funnels/FunnelEditForm.tsx:28-32
Prisma Schema
The diagram below shows the Report model and its relationships with the User and Website models.
This ER diagram illustrates how a Funnel Report is associated with a User and a Website.
Sources: prisma/schema.prisma:243-258
Report Table Fields
| Field | Type | Description |
|---|---|---|
id | String | Unique identifier for the report (UUID). |
userId | String | Foreign key linking to the User who created the report. |
websiteId | String | Foreign key linking to the Website the report belongs to. |
type | String | The type of report. For funnels, this is always 'funnel'. |
name | String | The user-defined name of the funnel report. |
description | String | An optional description for the report. |
parameters | Json | A JSON object containing the funnel's configuration, such as window and steps. |
Sources: prisma/schema.prisma:243-258
Funnel Configuration and Validation
A funnel report is defined by a set of parameters that are validated against a predefined schema before being saved. The primary configuration is done through the FunnelEditForm component.
Sources: src/app/(main)/websites/[websiteId]/(reports)/funnels/FunnelEditForm.tsx, src/lib/schema.ts:101-118
Funnel Parameters
The following parameters define a funnel's behavior and are stored in the parameters field of the Report model.
| Parameter | Type | Description | Default Value |
|---|---|---|---|
name | string | The name of the funnel. | '' |
window | number | The maximum time in minutes a user has to complete the next step after the previous one. | 60 |
steps | array | An array of objects defining the sequence of the funnel. Must contain 2 to 8 steps. | [{ type: 'path', value: '' }] |
Sources: src/app/(main)/websites/[websiteId]/(reports)/funnels/FunnelEditForm.tsx:43-45, src/lib/schema.ts:101-118
Validation Schema
The system uses Zod to validate the funnel report payload on the server side. The funnelReportSchema ensures that all required parameters are present and correctly formatted.
// src/lib/schema.ts
export const funnelReportSchema = z.object({
type: z.literal('funnel'),
parameters: z.object({
startDate: z.coerce.date(),
endDate: z.coerce.date(),
window: z.coerce.number().positive(),
steps: z
.array(
z.object({
type: z.enum(['path', 'event']),
value: z.string(),
}),
)
.min(2)
.max(8),
}),
});
Sources: src/lib/schema.ts:101-118
A funnel must have a minimum of 2 and a maximum of 8 steps. Each step is defined by its type (path for a URL path or event for a custom event name) and its value.
Sources: src/lib/schema.ts:115, src/app/(main)/websites/[websiteId]/(reports)/funnels/FunnelEditForm.tsx:16
Frontend Architecture
The user interface for Funnels is composed of several React components that work together to fetch, display, and manage funnel reports.
Sources: src/app/(main)/websites/[websiteId]/(reports)/funnels/FunnelsPage.tsx, src/app/(main)/websites/[websiteId]/(reports)/funnels/Funnel.tsx, src/app/(main)/websites/[websiteId]/(reports)/funnels/FunnelEditForm.tsx
Component Diagram
This diagram shows the relationship between the main components of the Funnels feature.
This graph illustrates the component hierarchy and data flow hooks used in the Funnels UI.
FunnelsPage.tsx: The main page that lists all available funnel reports for a given website. It uses theuseReportsQueryhook to fetch the list of reports oftype: 'funnel'.Funnel.tsx: Renders a single funnel report. It takes the report configuration as props and uses theuseResultQueryhook to fetch the calculated funnel data (visitor counts, drop-off rates, etc.).FunnelEditForm.tsx: A form, typically shown in a dialog, for creating a new funnel or editing an existing one. It uses theuseUpdateQueryhook to persist changes to the backend.
Sources: src/app/(main)/websites/[websiteId]/(reports)/funnels/FunnelsPage.tsx:11, src/app/(main)/websites/[websiteId]/(reports)/funnels/Funnel.tsx:21, src/app/(main)/websites/[websiteId]/(reports)/funnels/FunnelEditForm.tsx:25
Data Fetching Flow
The following sequence diagram shows how a funnel report's data is requested and rendered.
This diagram shows the end-to-end flow from the UI to the database to retrieve and display funnel metrics.
Sources: src/app/(main)/websites/[websiteId]/(reports)/funnels/Funnel.tsx:21, src/queries/sql/reports/getFunnel.ts:16
Backend Data Retrieval
The core logic for calculating funnel metrics resides in the getFunnel function, which supports both PostgreSQL and ClickHouse databases. It dynamically constructs an SQL query based on the funnel's configured steps and time window.
Sources: [src/queries/sql/reports/getFunnel.ts]
Query Logic Flow
The function builds a query using Common Table Expressions (CTEs), where each CTE represents a step in the funnel.
This flowchart outlines the logic for building the multi-step funnel query in getFunnel.ts.
Sources: src/queries/sql/reports/getFunnel.ts:35-98
Relational (PostgreSQL) Query
For PostgreSQL, the query identifies sessions that complete step 1, then joins those results to find sessions that also complete step 2 within the specified window (in minutes), and so on for each step.
A key part of the query is chaining the steps together within the time window:
-- src/queries/sql/reports/getFunnel.ts
, level${levelNumber} AS (
select distinct we.session_id, we.created_at
from level${i} l
join website_event we
on l.session_id = we.session_id
where we.website_id = {{websiteId::uuid}}
and we.created_at between l.created_at and ${getAddIntervalQuery(
`l.created_at `,
`${window} minute`,
)}
and we.${column} ${operator} {{${i}}}
and we.created_at <= {{endDate}}
)
Sources: src/queries/sql/reports/getFunnel.ts:71-84
Result Formatting
After the database returns the raw visitor counts for each level, the formatResults function processes this data to calculate additional metrics like dropped, dropoff, and remaining percentages, which are then displayed in the UI.
Sources: src/queries/sql/reports/getFunnel.ts:200-216
Summary
The Funnels report feature is a core component of Umami's analytical capabilities. It provides a flexible and powerful way to define, measure, and visualize user conversion paths. By leveraging a generic Report data model, a robust Zod validation schema, and a dynamic SQL generation engine, it can efficiently calculate multi-step conversion funnels across large datasets, providing actionable insights into user behavior and website performance.