Event Tracking
Relevant source files
The following files were used as context for generating this wiki page:
Event Tracking is a core feature of Umami that allows for the collection of user interactions beyond simple page views. It provides a flexible mechanism to capture custom events, such as button clicks, form submissions, or any other user-driven action on a website. This system is composed of a client-side JavaScript tracker, a data ingestion API endpoint, and a database schema for persisting event data.
The tracking can be implemented automatically for certain interactions or manually via a JavaScript API. Events can also include custom data payloads, enabling rich, detailed analytics of user behavior. This data is then processed and stored for visualization and analysis within the Umami dashboard.
Architecture Overview
The Event Tracking system follows a simple, three-tiered architecture: data collection on the client, data ingestion on the server, and data persistence in the database.
The following diagram illustrates the high-level data flow from the user's browser to the database.
Client-Side Tracker (tracker.js)
The client-side component is a lightweight JavaScript file (script.js, implemented in src/tracker/index.js) that is included on the tracked website. It automatically handles page view tracking and provides a global umami object for custom event tracking.
Sources: src/tracker/index.js, src/tracker/index.d.ts
Initialization
The tracker script is loaded asynchronously. It reads configuration from data-* attributes on the <script> tag itself.
| Attribute | Description | Example |
|---|---|---|
data-website-id | Required. The unique identifier for the website being tracked. | b59e9c65-ae32-47f1-8400-119fcf4861c4 |
data-host-url | The URL of the Umami instance. If not provided, it's inferred from the script's src. | https://analytics.example.com |
data-auto-track | When set to "false", it disables automatic page view tracking. Defaults to true. | false |
data-do-not-track | When set to "true", it enables client-side respect for the browser's Do Not Track setting. | true |
data-domains | A comma-separated list of domains to track. If specified, tracking will only occur on these domains. | example.com,www.example.com |
data-cache | Enables a caching mechanism to reduce the number of session lookups. | true |
data-tag | A tag to associate with all events from this tracker instance. | v2-beta |
Sources: src/tracker/index.js:23-34, src/app/(main)/console/[websiteId]/TestConsolePage.tsx:94-99
umami Object API
The tracker exposes a global window.umami object with two primary methods: track and identify.
umami.track()
This function is used to send both page view and custom event data to the Umami server. It has multiple signatures:
- Track a page view:
umami.track(); - Track a custom event by name:
umami.track('signup-button'); - Track a custom event with a data payload:
umami.track('signup-button', { type: 'trial', plan: 'pro' }); - Track with a function to modify default properties:
umami.track(props => ({ ...props, url: '/custom-path', name: 'event-name', data: { custom: 'data' } }));
Sources: src/tracker/index.js:189-195, src/tracker/index.d.ts:74-131, src/app/(main)/console/[websiteId]/TestConsolePage.tsx:19-45
umami.identify()
This function is used to associate custom data with the current session. This data is stored in the SessionData table.
umami.identify({
userId: 123,
name: 'brian',
plan: 'premium'
});
Sources: src/tracker/index.js:197-210, src/tracker/index.d.ts, src/app/(main)/console/[websiteId]/TestConsolePage.tsx:80-91
Automatic Event Tracking
The tracker can automatically capture certain events without manual calls to umami.track().
- Page Views: When
data-auto-trackis notfalse, the tracker sends a page view event on initial load and on history changes (viapushStateandreplaceState). - Clicks: The tracker adds a global click listener. If a clicked element (or its parent
<a>or<button>) has adata-umami-eventattribute, it automatically triggers a custom event. Any other attributes on the element matching the patterndata-umami-event-*are collected as the event data payload.
Example of declarative event tracking:
<button
data-umami-event="button-click"
data-umami-event-name="bob"
data-umami-event-id="123">
Send event with data
</button>
This will trigger an event named button-click with the data payload { "name": "bob", "id": "123" }.
Sources: src/tracker/index.js:106-140, src/app/(main)/console/[websiteId]/TestConsolePage.tsx:117-130
Data Ingestion (/api/send)
All tracking data from the client is sent via a POST request to the /api/send endpoint. This endpoint is responsible for validating the incoming data, enriching it with server-side information, and saving it to the database.
Sources: src/app/api/send/route.ts
Request Flow
The following sequence diagram shows the process of handling an incoming event.
Sources: src/app/api/send/route.ts
Payload Schema
The endpoint expects a JSON body with a specific structure, validated using Zod.
| Field | Type | Description | Required |
|---|---|---|---|
type | string | The type of collection. Must be 'event' or 'identify'. | Yes |
payload | object | The data payload for the event. | Yes |
payload.website | uuid | The website ID. Exactly one of website, link, or pixel must be provided. | Conditional |
payload.name | string | The name of the custom event (max 50 chars). If not present, it's a page view. | No |
payload.data | object | A JSON object of custom data for the event. | No |
payload.url | string | The URL of the page where the event occurred. | No |
payload.title | string | The title of the page. | No |
payload.referrer | string | The page referrer. | No |
payload.screen | string | The screen resolution, e.g., 1920x1080. | No |
payload.language | string | The browser language, e.g., en-US. | No |
payload.hostname | string | The hostname of the page. | No |
payload.tag | string | An optional tag for the event. | No |
Sources: src/app/api/send/route.ts:29-62
Event Types
The eventType field in the database is an integer that distinguishes between different kinds of events.
| Value | Constant | Description |
|---|---|---|
1 | pageView | A standard page view. |
2 | customEvent | A custom event triggered by umami.track('event-name') or a data-umami-event attribute. |
Sources: scripts/seed/generators/events.ts:5-8, src/app/api/send/route.ts:200-206
Database Schema
Event data is primarily stored across two tables: WebsiteEvent and EventData. The Session table holds information about the user's session.
Sources: prisma/schema.prisma
Entity Relationship Diagram
This diagram shows the relationships between the main tables involved in event tracking.
Sources: prisma/schema.prisma:41-201
WebsiteEvent Table
This table stores the core information for every event, whether it's a page view or a custom event.
| Column | Type | Description |
|---|---|---|
event_id | Uuid | Primary key for the event. |
website_id | Uuid | Foreign key to the Website table. |
session_id | Uuid | Foreign key to the Session table. |
visit_id | Uuid | Identifier for a specific visit within a session. |
created_at | Timestamptz | Timestamp of when the event occurred. |
url_path | VarChar(500) | The path of the URL where the event occurred. |
referrer_domain | VarChar(500) | The domain of the referring page. |
page_title | VarChar(500) | The title of the page. |
event_type | Integer | The type of event (1 for page view, 2 for custom event). |
event_name | VarChar(50) | The name of the custom event. |
utm_source | VarChar(255) | UTM source parameter. |
gclid | VarChar(255) | Google Click Identifier. |
fbclid | VarChar(255) | Facebook Click Identifier. |
Sources: prisma/schema.prisma:112-152, db/clickhouse/migrations/05_add_utm_clid.sql:2-37
EventData Table
This table stores the key-value pairs from the custom data payload associated with a WebsiteEvent. This allows for a flexible, schema-less structure for custom event properties.
| Column | Type | Description |
|---|---|---|
event_data_id | Uuid | Primary key. |
website_event_id | Uuid | Foreign key to the WebsiteEvent table. |
data_key | VarChar(500) | The key of the custom data property. |
string_value | VarChar(500) | The value if it is a string. |
number_value | Decimal(19, 4) | The value if it is a number. |
date_value | Timestamptz | The value if it is a date. |
data_type | Integer | An integer representing the data type (e.g., 1 for string, 2 for number). |
Sources: prisma/schema.prisma:154-171, scripts/seed/generators/events.ts:153-162