A lightweight script that automatically tracks pageviews, sessions, clicks, scroll depth, and custom events on your website.
Add the following snippet before the closing </head> tag on every page you want to track.
<script defer
data-site-id="YOUR_TRACKING_ID"
data-api-url="https://www.sessionstory.io/api/events"
src="https://www.sessionstory.io/tracker.min.js"></script>
Replace YOUR_TRACKING_ID with the tracking ID from your site's settings page in the dashboard. The script is lightweight (< 4 KB) and loads asynchronously with defer, so it won't affect page load performance.
Configure the tracker via data-* attributes on the script tag.
| Attribute | Required | Description |
|---|---|---|
| data-site-id | Yes | Your site's tracking ID (found in site settings). |
| data-api-url | No | Event ingestion endpoint. Defaults to https://www.sessionstory.io/api/events. |
| data-debug | No | Set to "true" to log all events to the browser console. |
| data-allow-localhost | No | Set to "true" to enable tracking on localhost (disabled by default). |
The tracker automatically captures the following events with no additional code:
Tracked on every page load and SPA navigation. Duplicate pageviews for the same URL within 1 second are automatically throttled.
Every click is captured with the element's CSS selector, tag name, visible text, link href, and page coordinates.
Fires at 25%, 50%, 75%, and 100% scroll milestones. Resets on each page navigation.
Detected when a user clicks the same area 3+ times within 500ms — a signal of frustration.
Detected when a click on an interactive element (button, link) produces no DOM change or navigation within 1 second.
Track conversions, signups, purchases, or any other action with sessionstory.track().
// Track a simple event
window.sessionstory.track('signup');
// Track with custom data
window.sessionstory.track('purchase', {
amount: 49.99,
plan: 'pro',
currency: 'USD'
});
| Argument | Type | Description |
|---|---|---|
| eventName | string | Required. Name of the event (e.g. "signup", "purchase"). |
| data | object | Optional. Arbitrary key-value data attached to the event. |
Custom events with numeric data properties can be used for revenue tracking — configure which event and property to use in your site's settings.
Link anonymous visitors to known users with sessionstory.identify().
// After user logs in
window.sessionstory.identify('user_123', {
name: 'Jane Doe',
email: '[email protected]',
plan: 'pro'
});
| Argument | Type | Description |
|---|---|---|
| userId | string | Required. Your internal user ID. |
| traits | object | Optional. User properties (name, email, plan, etc.). |
The tracker automatically detects client-side navigations in single-page applications. It patches history.pushState, history.replaceState, and listens for popstate events to track pageviews on route changes.
No additional configuration is needed for React, Vue, Next.js, Nuxt, or any other SPA framework.
UTM parameters are automatically captured from the landing page URL and attached to the session. The following parameters are tracked:
utm_sourceutm_mediumutm_campaignutm_termutm_contentUTM values are stored in sessionStorage so they persist across SPA navigations but reset when the browser tab is closed.
The landing page referrer is also captured once per session and sent alongside UTM data.
Visitor & session IDs are stored as first-party cookies (ss_vid for 1 year, ss_sid for 30 minutes rolling). Cookies are scoped to the root domain so they work across subdomains.
Event batching — events are queued in memory and flushed every 5 seconds or when 20 events accumulate, whichever comes first. When the user leaves the page, remaining events are sent via navigator.sendBeacon to avoid data loss.
Bot filtering — the tracker detects headless browsers, automation tools (Selenium, Puppeteer, Playwright), and common bot user agents, and disables tracking automatically.
Iframe protection — the tracker does not run inside iframes to prevent duplicate tracking from embedded content.