Data Flow
Relevant source files
The following files were used as context for generating this wiki page:
- README.md
- src/tracker/index.js
- src/app/(main)/console/[websiteId]/TestConsolePage.tsx
- scripts/seed/generators/events.ts
- src/lib/constants.ts
- src/app/(main)/websites/[websiteId]/(reports)/breakdown/Breakdown.tsx
- cypress/e2e/website.cy.ts
- scripts/seed-data.ts
- src/app/(main)/websites/[websiteId]/(reports)/utm/UTM.tsx
- src/app/(main)/websites/[websiteId]/(reports)/goals/Goal.tsx
Introduction
Umami is a simple, fast, privacy-focused alternative to Google Analytics. The data flow within Umami is designed to be lightweight and efficient, capturing user interactions on a client's website and processing them for insightful analytics reports. The process begins with a client-side JavaScript tracker that sends data to a collection endpoint. The backend then processes and stores this data in a PostgreSQL database. Finally, the Umami dashboard queries this data to populate various reports and visualizations.
This document outlines the end-to-end flow of data, from its collection via the tracking script to its eventual display in the analytics dashboard. It covers the structure of the data, the endpoints involved, and the components responsible for processing and visualization.
Client-Side Data Collection
Data collection is initiated by the Umami tracking script (script.js), which is embedded on a user's website. This script is responsible for capturing page views, custom events, and user interactions, and sending them to the Umami backend.
Sources: src/tracker/index.js, src/app/(main)/console/[websiteId]/TestConsolePage.tsx
The Tracking Script
The tracking script is loaded asynchronously on the page and configured using data-* attributes on the <script> tag.
Sources: src/app/(main)/console/[websiteId]/TestConsolePage.tsx:112-117, cypress/e2e/website.cy.ts:50-52
The following diagram illustrates the initialization and event capturing process of the client-side tracker.
Sources: src/tracker/index.js:1-218
Configuration
The script's behavior is controlled by several data-* attributes:
| Attribute | Description |
|---|---|
data-website-id | Required. The unique ID for the website being tracked. |
data-host-url | The base URL of the Umami instance. |
data-auto-track | If set to false, disables automatic page view and event tracking. Defaults to true. |
data-do-not-track | If set to true, respects the browser's Do Not Track setting. |
data-cache | Enables caching of the session ID. |
data-domains | A comma-separated list of domains to track. If specified, tracking will only occur on these domains. |
data-tag | A tag to associate with all events collected by the script. |
Sources: src/tracker/index.js:23-33
Automatic Event Tracking
When data-auto-track is enabled (the default), the script automatically tracks:
- Page Views: An initial page view is tracked on load. Subsequent page views are tracked by hooking into
history.pushStateandhistory.replaceStateto detect client-side route changes. - Click Events: The script listens for clicks on elements with a
data-umami-eventattribute. It captures the event name and any additionaldata-umami-event-*attributes.
Sources: src/tracker/index.js:90-141
Manual Event Tracking (window.umami object)
The script exposes a global window.umami object with methods for manual tracking.
umami.track(name, data): Tracks a page view or a custom event.- If called with no arguments, it tracks a standard page view.
- If called with a
name(string), it tracks a custom event with that name. - If
data(object) is provided, it is sent as the event's data.
umami.identify(id, data): Associates subsequent events with a user identity. Theidcan be a string or an object containing user properties.
Sources: src/tracker/index.js:183-206, src/app/(main)/console/[websiteId]/TestConsolePage.tsx:16-103
Example of tracking a custom event with data:
window.umami.track('track-event-with-data', {
test: 'test-data',
boolean: true,
number: 1,
});
Sources: src/app/(main)/console/[websiteId]/TestConsolePage.tsx:20-36
Data Payload
All collected data is sent to the backend via a POST request. The body of the request is a JSON object containing a type and a payload.
- Type: Can be
eventoridentify. - Payload: An object containing the collected data.
The following sequence diagram shows the data ingestion flow from the browser to the database.
Sources: src/tracker/index.js:151-181
A typical event payload includes:
| Field | Description | Source |
|---|---|---|
website | The website ID. | data-website-id attribute |
hostname | The hostname of the page. | window.location.hostname |
url | The URL of the page. | window.location.href |
referrer | The referrer URL. | document.referrer |
screen | The screen resolution (e.g., "1920x1080"). | window.screen |
language | The browser language. | navigator.language |
title | The page title. | document.title |
name | The name of the custom event, if any. | umami.track() argument |
data | A JSON object of custom event data. | umami.track() argument |
tag | An optional tag for the event. | data-tag attribute |
Sources: src/tracker/index.js:70-80
Backend Data Storage
The backend is responsible for receiving the data from the tracker, processing it, and storing it in the database.
Data Model
The structure of the stored data can be inferred from the data seeding scripts, which generate realistic analytics data for testing. The core entities are EventData and EventDataEntry.
Sources: scripts/seed/generators/events.ts
The following ER diagram shows the relationship between events and their associated data.
This diagram is based on the interfaces defined in the seed generator.
Sources: scripts/seed/generators/events.ts:23-60
EventData Interface
This interface represents a single event, which can be a page view or a custom event.
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier for the event. |
websiteId | string | The ID of the website this event belongs to. |
sessionId | string | The ID of the user session. |
eventType | number | The type of event (e.g., 1 for pageView, 2 for customEvent). |
urlPath | string | The path of the URL where the event occurred. |
pageTitle | string | The title of the page. |
referrerDomain | string | The domain of the referrer. |
eventName | string | The name of the custom event. |
createdAt | Date | Timestamp of when the event was created. |
Sources: scripts/seed/generators/events.ts:23-47
Event Types
Events are categorized by eventType.
| Type ID | Constant | Description |
|---|---|---|
| 1 | pageView | A user viewing a page. |
| 2 | customEvent | A custom event triggered by umami.track(). |
| 3 | linkEvent | A click on a tracked link. |
| 4 | pixelEvent | An event from a tracking pixel. |
Sources: src/lib/constants.ts:70-75, scripts/seed/generators/events.ts:5-9
Data Retrieval and Visualization
The Umami frontend uses React components to build and display analytics reports. These components fetch aggregated data from the backend.
Sources: src/app/(main)/websites/[websiteId]/(reports)/breakdown/Breakdown.tsx, src/app/(main)/websites/[websiteId]/(reports)/utm/UTM.tsx
Reporting API
Frontend components use the useResultQuery hook to fetch data for reports. This hook queries backend endpoints that return processed and aggregated data based on parameters like websiteId, startDate, and endDate.
For example, the Breakdown report component fetches data by calling useResultQuery('breakdown', ...).
The following diagram shows the data flow for rendering a report.
Frontend Components
Various React components are responsible for displaying different aspects of the collected data:
Breakdown.tsx: Displays a table of metrics broken down by selected fields (e.g., browser, OS, country). It calculates metrics like visitors, visits, views, bounce rate, and average visit duration.UTM.tsx: Shows reports for UTM parameters, including a pie chart and a list table of views per UTM tag.Goal.tsx: Tracks and displays progress towards a specific goal, showing a conversion rate and progress bar.
These components rely on internationalization files (en-US.json, etc.) for labels like "Visitors", "Bounce rate", and "Conversion rate".
Sources: src/app/(main)/websites/[websiteId]/(reports)/breakdown/Breakdown.tsx, src/app/(main)/websites/[websiteId]/(reports)/utm/UTM.tsx, src/app/(main)/websites/[websiteId]/(reports)/goals/Goal.tsx, src/components/messages.ts
Conclusion
The data flow in Umami is a streamlined process optimized for performance and privacy. It starts with a versatile client-side tracker that captures essential user interactions and sends them to a backend for storage. The data is structured into events and sessions, allowing for flexible and powerful analysis. The frontend application then queries this data through a dedicated reporting API to generate insightful and easy-to-understand visualizations for the end-user. This architecture ensures that data is collected, processed, and presented efficiently, fulfilling Umami's promise as a fast and simple analytics solution.