The Tracker Script
Relevant source files
The following files were used as context for generating this wiki page:The Umami tracker script is a lightweight, privacy-focused JavaScript file responsible for collecting analytics data from a website. It is designed to be embedded into any website to track page views and custom events, which are then sent to an Umami instance for processing. The script is highly configurable through data-* attributes on the script tag itself and offers a simple public API for manual tracking.
The script is built to be fast and unobtrusive. It automatically handles page views, single-page application (SPA) route changes, and custom event tracking through declarative HTML attributes. It also respects user privacy by checking for "Do Not Track" browser settings.
Architecture and Build Process
The tracker script's source is located at src/tracker/index.js. It is a self-contained vanilla JavaScript file that avoids external dependencies to remain small and fast. The build process, orchestrated by the build-tracker script in package.json, uses Rollup to bundle and minify the source code into a distributable file.
The next.config.ts file plays a crucial role in how the tracker script is served. It defines server-side rewrites and headers. This allows for flexible deployment, such as serving the script under a custom name or proxying it from a different URL.
The following diagram illustrates the build and serving flow of the tracker script.
This diagram shows how the source tracker script is built and then served by the Next.js application, which also receives the tracking data.
Sources: src/tracker/index.js, next.config.ts, package.json:23
Script Integration
To integrate Umami tracking, a user must add a <script> tag to the <head> section of their website's HTML. The Umami application provides a simple UI to copy the correctly formatted tracking code.
Sources: src/app/(main)/websites/[websiteId]/settings/WebsiteTrackingCode.tsx:30-32, src/components/messages.ts:201
The generated script tag looks like this:
<script defer src="http://<umami-host>/script.js" data-website-id="<your-website-id>"></script>
The WebsiteTrackingCode.tsx component dynamically generates this snippet. It determines the script URL based on the environment, accommodating cloudMode or self-hosted instances. It also supports custom tracker script names defined by the TRACKER_SCRIPT_NAME environment variable.
Sources: src/app/(main)/websites/[websiteId]/settings/WebsiteTrackingCode.tsx:16-28
Server-side Naming and Routing
The next.config.ts file allows administrators to define alternative names for the tracker script via the TRACKER_SCRIPT_NAME environment variable. This can be a comma-separated list of names. The server is configured to recognize these custom names and serve the standard tracker script.
This is achieved through Next.js rewrites. For each custom name, a rewrite rule is added to map it to the default TRACKER_SCRIPT path (/script.js).
// next.config.ts
if (trackerScriptName) {
const names = trackerScriptName?.split(',').map(name => name.trim());
if (names) {
names.forEach(name => {
const normalizedSource = `/${name.replace(/^\/+/, '')}`;
rewrites.push({
source: normalizedSource,
destination: TRACKER_SCRIPT,
});
headers.push({
source: normalizedSource,
headers: trackerHeaders,
});
});
}
}
Sources: next.config.ts:114-131
Initialization and Configuration
The tracker script initializes itself by reading configuration from data-* attributes on the <script> tag. If data-auto-track is not set to false, the script will automatically track the first page view once the document is fully loaded.
Sources: src/tracker/index.js:21-34, 218-224
The following configuration options are available:
| Attribute | Description | Default |
|---|---|---|
data-website-id | Required. The unique ID for the website to track. | null |
data-host-url | The base URL of the Umami instance. If not provided, it's inferred from the script's src. | Inferred from currentScript.src |
data-auto-track | When false, disables automatic page view tracking. | true |
data-do-not-track | When true, enables tracking for users with the DNT header enabled. By default, DNT is respected. | false |
data-domains | A comma-separated list of domains to track. If specified, tracking will only occur on these domains. | '' (all domains) |
data-exclude-search | When true, URL search parameters will be excluded from tracking. | false |
data-exclude-hash | When true, the URL hash will be excluded from tracking. | false |
data-tag | A tag to associate with all events from this tracker instance. | undefined |
data-before-send | A global function name. This function will be called with the payload before it's sent, allowing for modification. | null |
data-fetch-credentials | The credentials option for the fetch API call. | 'omit' |
Sources: src/tracker/index.js:21-34
Data Collection and Tracking Logic
The script automatically collects page views and can be configured to track custom events.
Automatic Tracking
- Page Views: If
data-auto-trackis enabled, the script sends a page view event on initial load. - SPA Navigation: The script hooks into
history.pushStateandhistory.replaceStateto detect URL changes in Single-Page Applications. When a URL change is detected, it waits 300ms and then sends a new page view event. - Click Events: The script listens for all clicks on the document. It looks for a
data-umami-eventattribute on the clicked element or its parents.
Sources: src/tracker/index.js:77-93, 107-142, 218-224
The following diagram shows the flow for automatic event tracking.
This diagram shows how the tracker script handles click events to automatically track custom events.
Sources: src/tracker/index.js:107-142
Manual Tracking (window.umami)
The tracker exposes a global window.umami object with functions for manual tracking. This is useful for tracking events that are not tied to clicks or for identifying users.
| Function | Description |
|---|---|
umami.track(name, data) | Manually tracks an event. name can be a string for the event name, or a function that returns a payload object. data is an optional object with custom event data. |
umami.identify(id, data) | Associates subsequent events with a user identity. id is a string to identify the user. data is an object with user properties. |
Sources: src/tracker/index.js:195-216, 226-231
The TestConsolePage.tsx file provides excellent examples of how to use this API:
// Example of tracking a custom event with data
window.umami.track('track-event-with-data', {
test: 'test-data',
boolean: true,
number: 1,
});
// Example of identifying a user
window.umami.identify({
userId: 123,
name: 'brian',
});
Sources: src/app/(main)/console/[websiteId]/TestConsolePage.tsx:23-40, 94-111
Data Transmission
All collected data is sent to the Umami server via a POST request to the collection endpoint.
Endpoint Configuration
The collection endpoint is determined in the following order:
- A hardcoded
__COLLECT_API_ENDPOINT__placeholder (replaced at build time). - The URL is constructed from the
hostUrland a placeholder__COLLECT_API_ENDPOINT__. - If
COLLECT_API_ENDPOINTis set innext.config.ts, requests to that path are rewritten to/api/send.
Sources: src/tracker/index.js:37-39, next.config.ts:69-79
Payload Structure
The send function constructs a JSON payload containing the event type (event or identify) and the collected data.
A standard page view payload includes:
website: The website ID.hostname: The hostname of the page.screen: The screen resolution (e.g.,1920x1080).language: The browser language (e.g.,en-US).title: Thedocument.title.url: The current page URL.referrer: The referring URL.tag: The optional tag fromdata-tag.id: The optional user identity.
Sources: src/tracker/index.js:59-69
Sending Process
The following sequence diagram shows how data is sent from the client to the server.
This diagram shows the sequence of events when the tracker sends data to the server, including the optional beforeSend hook.
Sources: src/tracker/index.js:159-193
Privacy Considerations
The tracker is designed with privacy in mind.
- Do Not Track: It respects the browser's
doNotTracksetting by default. Tracking is disabled ifdoNotTrackis1or'yes'. This can be overridden by settingdata-do-not-track="true"on the script tag. - Anonymity: The script does not collect personally identifiable information (PII) by default and does not use cookies. All user identification is opt-in via the
identify()function.