Tracker Setup
The Tally tracker is a ~3KB JavaScript file that runs in the browser. It tracks page views, scroll depth, focus time, SPA navigation, and sends periodic pings — all without cookies (beyond a first-party session ID) or fingerprinting.
Installation
Add the script to your site:
<script
src="https://your-tally-server.com/t.js"
data-site="yoursite.com"
data-token="your-site-token"
></script>
The
src
must point to your self-hosted Tally instance. The
data-site
attribute identifies which site the events belong to. The
data-token
attribute is used for origin validation.
Where does the collect URL come from?
The tracker derives the collect endpoint from its own
src
attribute, so cross-origin embeds work correctly (e.g., your site at
example.com
sends events to
tally.example.com
).
What it tracks
Page views
Automatically sent on page load. Includes the page path, title, full URL, and referrer.
Scroll depth
Tracks how far down the page the user scrolls, as a percentage (0–100). Updates are throttled
to one beacon every 5 seconds. The maximum scroll depth is sent with the
exit
event.
Focus time
Measures how long the page is visible (not hidden) in milliseconds. Uses the Page Visibility API. Reported on page exit and SPA navigation.
SPA navigation
Automatically detects navigation in single-page applications by intercepting:
-
history.pushState— React Router, Vue Router, etc. -
history.replaceState— Some frameworks use this for navigation -
popstate— Browser back/forward buttons -
hashchange— Hash-based SPA routes (#/about)
On SPA navigation, the tracker sends an
exit
event for the old page and a
pageview
for the new page.
Exit events
Sent on
pagehide
(covers tab close, navigation away, and browser shutdown). Includes final scroll depth and
total focus time.
Pings
A heartbeat ping is sent every 15 seconds while the page is visible. This is used for realtime visitor tracking.
Session management
The tracker creates a UUID and stores it in a first-party cookie named
tally_sid
with a 30-day expiry. This cookie is not
HttpOnly
— the tracker manages it entirely client-side. The server never sets cookies.
The session ID is sent with every event as
session_id
. The server uses it to group page views into sessions.
Event format
Events are sent as JSON POST to
/collect
:
{
"type": "pageview",
"session_id": "uuid",
"site_id": "yoursite.com",
"site_token": "your-token",
"page_path": "/blog/post",
"page_title": "My Blog Post",
"page_url": "https://example.com/blog/post?utm_source=twitter",
"referrer": "https://twitter.com",
"timestamp": 1716300000000
}
No configuration needed
The tracker has no options, no configuration object, and no API. You add the script tag and it starts tracking immediately. This is by design — analytics should be simple.