Autocapture
Kitbase automatically captures key user interactions without any manual instrumentation. From the moment you install the SDK, you get pageviews, sessions, clicks, scroll depth, outbound links, and more -- all out of the box.
Every auto-tracked event is sent on the __analytics channel and can be individually toggled on or off via configuration. No cookies are used; sessions are managed client-side with UUIDs.
Configuration
SDK initialization
Pass analytics options when creating the Kitbase instance. All flags default to true unless noted.
import { init } from '@kitbase/analytics';
const kitbase = init({
sdkKey: 'YOUR_SDK_KEY',
analytics: {
autoTrackPageViews: true, // screen_view events
trackBfcacheRestore: true, // screen_view on bfcache restore (back/forward in MPAs)
autoTrackOutboundLinks: true, // outbound_link events
autoTrackClicks: true, // click events
autoTrackScrollDepth: true, // scroll_depth events
autoTrackVisibility: true, // data-kb-track-visibility events
autoTrackWebVitals: false, // web_vitals events (opt-in)
autoDetectFrustration: true, // rage_click and dead_click events
}
});Script tag configuration
If you load Kitbase via a <script> tag, set the global config object before the SDK loads:
<script>
window.KITBASE_CONFIG = {
sdkKey: 'YOUR_SDK_KEY',
analytics: {
autoTrackPageViews: true,
autoTrackClicks: false, // disable click tracking
}
};
</script>
<script src="https://kitbase.dev/lite.js"></script>Any option you omit defaults to true.
Auto-Tracked Events Reference
The table below is a quick-reference summary. Detailed sections for each event follow.
| Event | Config Flag | Channel | Fires When |
|---|---|---|---|
session_start | -- (always on) | __analytics | New session begins |
session_end | -- (always on) | __analytics | Session times out (server-generated) |
screen_view | autoTrackPageViews, trackBfcacheRestore | __analytics | Page navigation or bfcache restore |
click | autoTrackClicks | __analytics | User clicks interactive element |
outbound_link | autoTrackOutboundLinks | __analytics | User clicks external link |
scroll_depth | autoTrackScrollDepth | __analytics | User leaves a page |
rage_click | autoDetectFrustration | __analytics | 3+ clicks within 1s in same area |
dead_click | autoDetectFrustration | __analytics | Click with no DOM response within 1s |
web_vitals | autoTrackWebVitals | __analytics | Once per page load (opt-in) |
revenue | -- (explicit call) | __analytics | trackRevenue() is called |
session_start
Fired when a new session begins. A session starts on the first page load or after 30 minutes of inactivity (configurable).
| Field | Value |
|---|---|
| Channel | __analytics |
| Event | session_start |
| Config | Always enabled |
Tags:
Standard enrichment tags only (see Server-Side Enrichment below).
Session management API:
| Method | Returns | Description |
|---|---|---|
kitbase.getSession() | Session | Full session object |
kitbase.getSessionId() | string | Current session UUID |
kitbase.reset() | void | End current session and start a new one |
Example payload:
{
"channel": "__analytics",
"event": "session_start",
"client_timestamp": 1707840000000,
"client_session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tags": {}
}session_end
Fired server-side when a session times out (no new events received within the session timeout window). This event is not sent by the SDK -- it is generated by the Kitbase backend.
| Field | Value |
|---|---|
| Channel | __analytics |
| Event | session_end |
| Config | Always enabled |
Computed fields:
| Field | Type | Description |
|---|---|---|
duration | number | Session duration in milliseconds (last event timestamp minus session start timestamp) |
bounce | boolean | true if the session had only one page view |
path | string | Last viewed page path (exit page) |
The session_end event inherits the device, geo, UTM, and referrer data from the session. It is used to compute bounce rate, average session duration, and exit pages in the analytics dashboard.
Server-generated
Unlike other auto-tracked events, session_end is created entirely by the backend. The SDK does not send this event. It fires after the session timeout (default 30 minutes) with no further activity.
screen_view
Fired on every page navigation -- initial load, History API calls (pushState, replaceState), and popstate events. Also fired when the browser restores a page from the back-forward cache (bfcache), which is common on MPA sites where back/forward navigation does not re-execute scripts.
| Field | Value |
|---|---|
| Channel | __analytics |
| Event | screen_view |
| Config | autoTrackPageViews (default true); bfcache restore controlled by trackBfcacheRestore (default true) |
Tags:
| Tag | Type | Description |
|---|---|---|
__path | string | window.location.pathname |
__title | string | document.title |
__referrer | string | document.referrer |
__utm_source | string | UTM source parameter (if present) |
__utm_medium | string | UTM medium parameter (if present) |
__utm_campaign | string | UTM campaign parameter (if present) |
__utm_term | string | UTM term parameter (if present) |
__utm_content | string | UTM content parameter (if present) |
SPA support:
The SDK automatically patches history.pushState and history.replaceState so that client-side navigation in React Router, Vue Router, Angular Router, Next.js, Nuxt, and any other History API-based router triggers a screen_view without additional configuration.
bfcache restore (MPA sites):
On multi-page sites (e.g., Astro without View Transitions), pressing the browser back or forward button may restore the page from the back-forward cache instead of reloading it. Since scripts do not re-execute in this case, pageviews would otherwise be missed. When trackBfcacheRestore is enabled (the default), the SDK listens for the pageshow event with event.persisted === true and sends a screen_view. Set trackBfcacheRestore: false to disable this behavior.
Manual page view tracking:
kitbase.trackPageView({
path: '/custom-path',
referrer: 'https://example.com',
title: 'Custom Page Title',
});Example payload:
{
"channel": "__analytics",
"event": "screen_view",
"client_timestamp": 1707840012000,
"client_session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tags": {
"__path": "/pricing",
"__title": "Pricing - Kitbase",
"__referrer": "https://google.com",
"__utm_source": "google",
"__utm_medium": "cpc"
}
}click
Fired when a user clicks an interactive element.
| Field | Value |
|---|---|
| Channel | __analytics |
| Event | click |
| Config | autoTrackClicks (default true) |
Tags:
| Tag | Type | Description |
|---|---|---|
__tag | string | HTML tag name (e.g. button, a, ion-button) |
__id | string | Element id attribute |
__class | string | Element className |
__text | string | Text content (trimmed, max 100 characters) |
__href | string | href attribute (if present) |
__path | string | window.location.pathname |
Detected elements:
The SDK listens for clicks on the following interactive elements:
a,button,input,select,textarea[role="button"],[role="link"],[role="menuitem"],[role="tab"]- Custom elements (any element whose tag name contains
-, e.g.ion-button,my-dropdown)
Shadow DOM support:
The SDK uses composedPath() to traverse Shadow DOM boundaries. When a matched element lives inside a Shadow DOM, the custom-element host is reported.
No double-counting
When autoTrackOutboundLinks is also enabled, clicks on external links are handled by the outbound_link event and skipped by click tracking. Similarly, elements with a data-kb-track-click attribute fire only the named event, not the generic click.
Example payload:
{
"channel": "__analytics",
"event": "click",
"client_timestamp": 1707840045000,
"client_session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tags": {
"__tag": "button",
"__id": "signup-btn",
"__class": "btn btn-primary",
"__text": "Start Free Trial",
"__path": "/pricing"
}
}outbound_link
Fired when a user clicks or keyboard-activates (Enter/Space) a link pointing to an external domain (different hostname).
| Field | Value |
|---|---|
| Channel | __analytics |
| Event | outbound_link |
| Config | autoTrackOutboundLinks (default true) |
Tags:
| Tag | Type | Description |
|---|---|---|
__url | string | Full destination URL |
__text | string | Link text content (trimmed) |
Example payload:
{
"channel": "__analytics",
"event": "outbound_link",
"client_timestamp": 1707840060000,
"client_session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tags": {
"__url": "https://github.com/kitbase-dev",
"__text": "View on GitHub"
}
}scroll_depth
Fired when the user navigates away from a page (or closes the tab). Reports the maximum scroll depth reached during the page visit.
| Field | Value |
|---|---|
| Channel | __analytics |
| Event | scroll_depth |
| Config | autoTrackScrollDepth (default true) |
Tags:
| Tag | Type | Description |
|---|---|---|
__depth | number | Maximum scroll depth as a percentage (0--100) |
__path | string | window.location.pathname |
Trigger: Flushed on beforeunload, history.pushState, and popstate. Scroll position is sampled using requestAnimationFrame throttling to avoid scroll jank.
Example payload:
{
"channel": "__analytics",
"event": "scroll_depth",
"client_timestamp": 1707840120000,
"client_session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tags": {
"__depth": 72,
"__path": "/blog/getting-started"
}
}rage_click
Fired when the SDK detects 3 or more clicks within 1 second in the same area (30px radius) -- a strong signal of user frustration.
| Field | Value |
|---|---|
| Channel | __analytics |
| Event | rage_click |
| Config | autoDetectFrustration (default true) |
Tags:
| Tag | Type | Description |
|---|---|---|
__selector | string | CSS selector of the clicked element |
__tag | string | HTML tag name (e.g. button, div) |
__id | string | Element id attribute |
__class | string | Element className |
__text | string | Text content (trimmed, max 100 characters) |
__click_count | number | Number of rapid clicks detected |
__path | string | window.location.pathname |
Example payload:
{
"channel": "__analytics",
"event": "rage_click",
"client_timestamp": 1707840300000,
"client_session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tags": {
"__selector": "button.submit-btn",
"__tag": "button",
"__id": "submit-btn",
"__class": "submit-btn btn-primary",
"__text": "Submit",
"__click_count": 5,
"__path": "/checkout"
}
}Frustration analytics
Rage clicks are surfaced in the Frustration Signals dashboard, which shows top pages and elements by frustration score. The frustration score is calculated as rage_clicks * 3 + dead_clicks.
dead_click
Fired when the SDK detects a click on an interactive element that produces no DOM change within 1 second -- suggesting the user expected something to happen but nothing did. Uses a MutationObserver to watch for child list, attribute, and character data changes.
| Field | Value |
|---|---|
| Channel | __analytics |
| Event | dead_click |
| Config | autoDetectFrustration (default true) |
Tags:
| Tag | Type | Description |
|---|---|---|
__selector | string | CSS selector of the clicked element |
__tag | string | HTML tag name (e.g. button, a) |
__id | string | Element id attribute |
__class | string | Element className |
__text | string | Text content (trimmed, max 100 characters) |
__path | string | window.location.pathname |
Example payload:
{
"channel": "__analytics",
"event": "dead_click",
"client_timestamp": 1707840310000,
"client_session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tags": {
"__selector": "div.card-header",
"__tag": "div",
"__id": "",
"__class": "card-header",
"__text": "Premium Plan",
"__path": "/pricing"
}
}Frustration analytics
Dead clicks are surfaced alongside rage clicks in the Frustration Signals dashboard. Use them to identify UI elements that look clickable but aren't, so you can improve your design.
revenue
Fired when trackRevenue() is called. Included here for completeness since it uses the internal __analytics channel.
| Field | Value |
|---|---|
| Channel | __analytics |
| Event | revenue |
Tags:
| Tag | Type | Description |
|---|---|---|
__revenue | number | Revenue amount |
__currency | string | Currency code (default 'USD') |
| + custom tags | Any additional tags passed via the tags option |
Usage:
kitbase.trackRevenue({
amount: 49.99,
currency: 'USD',
tags: {
plan: 'pro',
interval: 'monthly',
},
});Example payload:
{
"channel": "__analytics",
"event": "revenue",
"client_timestamp": 1707840200000,
"client_session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tags": {
"__revenue": 49.99,
"__currency": "USD",
"plan": "pro",
"interval": "monthly"
}
}web_vitals
Fired once per page load when Core Web Vitals metrics have been collected. This event is opt-in and must be explicitly enabled.
| Field | Value |
|---|---|
| Channel | __analytics |
| Event | web_vitals |
| Config | autoTrackWebVitals (default false) |
Tags (only collected metrics are included):
| Tag | Type | Description |
|---|---|---|
__lcp | number | Largest Contentful Paint -- loading performance (ms) |
__cls | number | Cumulative Layout Shift -- visual stability (score) |
__inp | number | Interaction to Next Paint -- interactivity (ms) |
__fcp | number | First Contentful Paint -- first render (ms) |
__ttfb | number | Time to First Byte -- server response time (ms) |
Usage:
const kitbase = init({
sdkKey: 'YOUR_SDK_KEY',
analytics: {
autoTrackWebVitals: true,
}
});A 30-second timeout ensures the event is sent even if some metrics never fire (e.g., INP requires user interaction). Only metrics that were successfully collected are included in the tags.
Example payload:
{
"channel": "__analytics",
"event": "web_vitals",
"client_timestamp": 1707840500000,
"client_session_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"tags": {
"__lcp": 1250,
"__cls": 0.05,
"__inp": 180,
"__fcp": 800,
"__ttfb": 120
}
}Data Attribute Events
Data attributes let you fire named events directly from HTML -- no JavaScript required. Annotate any element and the SDK handles the rest. These work with Angular, React, vanilla HTML, or any framework.
Custom channel
Unlike the automatic events above that always use the __analytics channel, data-attribute events use the channel you specify (defaulting to engagement).
data-kb-track-click
Track custom named click events without writing JavaScript.
| Field | Value |
|---|---|
| Channel | User-specified (default engagement) |
| Event | Value of the data-kb-track-click attribute |
| Config | autoTrackClicks (default true) |
HTML attributes:
| Attribute | Required | Default | Description |
|---|---|---|---|
data-kb-track-click | Yes | -- | Event name to fire |
data-kb-click-channel | No | engagement | Channel for the event |
Tags:
| Tag | Type | Description |
|---|---|---|
__path | string | window.location.pathname |
Example:
<!-- Basic usage -->
<button data-kb-track-click="CTA Clicked">Sign Up Now</button>
<!-- With custom channel -->
<button
data-kb-track-click="Add to Cart"
data-kb-click-channel="ecommerce"
>
Add to Cart
</button>When an element has data-kb-track-click, the generic click auto-tracking is skipped for that element to avoid double-counting. The SDK uses closest() to find the nearest annotated ancestor, so child elements inside an annotated parent are also covered.
data-kb-track-visibility
Track how long elements are visible in the viewport. The event fires when the tracked element leaves the viewport, is removed from the DOM, or the user navigates away.
| Field | Value |
|---|---|
| Channel | User-specified (default engagement) |
| Event | Value of the data-kb-track-visibility attribute |
| Config | autoTrackVisibility (default true) |
HTML attributes:
| Attribute | Required | Default | Description |
|---|---|---|---|
data-kb-track-visibility | Yes | -- | Event name to fire |
data-kb-visibility-channel | No | engagement | Channel for the event |
data-kb-visibility-threshold | No | 0.5 | IntersectionObserver threshold (0--1) |
Tags:
| Tag | Type | Description |
|---|---|---|
duration_seconds | number | Total visible time, rounded to whole seconds |
duration_ms | number | Total visible time in milliseconds |
Example:
<!-- Track a section with default settings -->
<section data-kb-track-visibility="Pricing Section Viewed">
...
</section>
<!-- Custom channel and threshold -->
<section
data-kb-track-visibility="Hero Banner Viewed"
data-kb-visibility-channel="marketing"
data-kb-visibility-threshold="0.75"
>
...
</section>The SDK uses IntersectionObserver to detect enter/leave viewport transitions and MutationObserver to pick up dynamically added or removed elements. Visibility data is flushed on beforeunload, history.pushState, popstate, and element removal.
Common Fields on All Auto-Tracked Events
Every auto-tracked event includes the following fields in its payload:
| Field | Type | Description |
|---|---|---|
channel | string | Event channel -- always __analytics for auto-tracked events, user-specified for data-attribute events |
event | string | Event name (e.g. screen_view, click) |
client_timestamp | number | Date.now() when the event was created |
client_session_id | string | UUID v4, rotated after the session timeout (default 30 min inactivity) |
tags | object | Merged super properties + event-specific tags |
user_id | string | Present only if the user has been identified via kitbase.identify(...) |
Server-Side Enrichment
All events -- both auto-tracked and manually tracked -- are enriched server-side before storage. These enrichment tags are available as first-class filter dimensions in the dashboard.
Browser and OS:
| Tag | Description |
|---|---|
__browser | Browser name (Chrome, Firefox, Safari, Edge) |
__browser_version | Browser version string |
__os | Operating system (Windows, macOS, iOS, Android, Linux) |
__os_version | OS version string |
Device:
| Tag | Description |
|---|---|
__device | Device type: desktop, mobile, or tablet |
__brand | Device brand (Apple, Samsung, Google, etc.) |
__model | Device model (iPhone 15, Pixel 8, Galaxy S24, etc.) |
Geolocation (from IP):
| Tag | Description |
|---|---|
__country | Country name |
__region | Region or state |
__city | City name |
Privacy
IP addresses are used only for geolocation enrichment and are not stored. See Analytics Guide — Privacy for details.
Bot Filtering
Kitbase automatically filters bot traffic so your analytics stay clean. No configuration is needed.
The following are detected and excluded:
| Category | Examples |
|---|---|
| Headless browsers | Puppeteer, Playwright, PhantomJS |
| Testing tools | Selenium, WebDriver, Cypress |
| HTTP clients | curl, wget, Postman, HTTPie |
| Search crawlers | Googlebot, Bingbot, DuckDuckBot, Yandex, Baidu |
| Social crawlers | Twitterbot, Facebookbot, LinkedInBot |
| Monitoring tools | UptimeRobot, Pingdom, New Relic |
Bot detection runs automatically on every incoming event. Detected bot traffic is silently discarded before it reaches your dashboard or analytics queries.
Disabling Specific Auto-Track Features
You can selectively disable any auto-track feature while keeping the rest active. Set the corresponding flag to false in your configuration.
Disable a single feature
const kitbase = init({
sdkKey: 'YOUR_SDK_KEY',
analytics: {
autoTrackClicks: false, // disable click tracking
// everything else remains enabled by default
}
});Disable multiple features
const kitbase = init({
sdkKey: 'YOUR_SDK_KEY',
analytics: {
autoTrackClicks: false,
autoTrackScrollDepth: false,
autoTrackOutboundLinks: false,
// only pageviews and visibility remain active
}
});Disable all auto-tracking
If you want full manual control, disable every flag:
const kitbase = init({
sdkKey: 'YOUR_SDK_KEY',
analytics: {
autoTrackPageViews: false,
trackBfcacheRestore: false,
autoTrackOutboundLinks: false,
autoTrackClicks: false,
autoTrackScrollDepth: false,
autoTrackVisibility: false,
autoTrackWebVitals: false,
autoDetectFrustration: false,
}
});You can still track events manually using kitbase.track(...), kitbase.trackPageView(...), and kitbase.trackRevenue(...).
Script tag configuration
<script>
window.KITBASE_CONFIG = {
sdkKey: 'YOUR_SDK_KEY',
analytics: {
autoTrackPageViews: true,
autoTrackOutboundLinks: false, // disabled
autoTrackClicks: false, // disabled
autoTrackScrollDepth: true,
autoTrackVisibility: true,
}
};
</script>Configuration reference
| Flag | Event(s) Controlled | Default |
|---|---|---|
autoTrackPageViews | screen_view | true |
trackBfcacheRestore | screen_view (bfcache restore) | true |
autoTrackOutboundLinks | outbound_link | true |
autoTrackClicks | click, data-kb-track-click | true |
autoTrackScrollDepth | scroll_depth | true |
autoTrackVisibility | data-kb-track-visibility | true |
autoTrackWebVitals | web_vitals | false |
autoDetectFrustration | rage_click, dead_click | true |