Tracking Script
Kitbase provides a lightweight tracking script for web analytics and event tracking. It is privacy-friendly, requires no cookies by default, and works on any website -- static HTML, single-page applications (SPAs), and server-side rendered (SSR) frameworks alike.
Installation
Script Tag (Simplest)
Add these two snippets to your HTML <head> section:
<script>
window.KITBASE_CONFIG = { sdkKey: 'YOUR_SDK_KEY' };
</script>
<script defer src="https://kitbase.dev/lite.js"></script>The KITBASE_CONFIG object must be set before the tracking script loads. The defer attribute ensures the script is fetched in parallel and executed after the HTML is parsed, so it never blocks page rendering.
NPM Package
For JavaScript/TypeScript projects with a build step, install the SDK as a dependency:
npm install @kitbase/analyticspnpm add @kitbase/analyticsyarn add @kitbase/analyticsThen initialize the SDK in your application entry point:
import { init } from '@kitbase/analytics';
const kitbase = init({
sdkKey: 'YOUR_SDK_KEY',
analytics: {
autoTrackPageViews: true,
trackBfcacheRestore: true,
autoTrackOutboundLinks: true,
autoTrackClicks: true,
autoTrackScrollDepth: true,
autoTrackVisibility: true,
},
});Lite Build
For a smaller bundle size (~12KB vs ~50KB), use the lite build which excludes offline queue support:
import { init } from '@kitbase/analytics/lite';The lite build has the same API surface for analytics and event tracking. Only the offline queue module (offline config) is removed.
Configuration Reference
Below is the full configuration object with every available option and its default value.
const kitbase = init({
// ── Core ───────────────────────────────────────────────
sdkKey: 'YOUR_SDK_KEY', // Required. SDK API key from the dashboard.
debug: false, // Enable console logging for troubleshooting.
baseUrl: 'https://api.kitbase.dev', // API endpoint. Override for self-hosted.
storage: localStorage, // Storage backend for the anonymous ID.
// Set to `null` to disable persistence.
storageKey: 'kitbase_anonymous_id', // Key used in the storage backend.
// ── Analytics ──────────────────────────────────────────
analytics: {
autoTrackPageViews: true, // Fire `screen_view` on every navigation.
trackBfcacheRestore: true, // Fire `screen_view` on bfcache restore (back/forward in MPAs).
autoTrackOutboundLinks: true, // Fire `outbound_link` for external link clicks.
autoTrackClicks: true, // Fire `click` for interactive element clicks.
autoTrackScrollDepth: true, // Fire `scroll_depth` when the user leaves a page.
autoTrackVisibility: true, // Observe `data-kb-track-visibility` elements.
},
// ── Offline Queue ──────────────────────────────────────
offline: {
enabled: false, // Queue events when offline, sync when back.
maxQueueSize: 1000, // Maximum events held in the queue.
flushInterval: 30000, // Flush interval in milliseconds (30 s).
flushBatchSize: 50, // Events sent per batch.
maxRetries: 3, // Retry attempts before an event is dropped.
retryBaseDelay: 1000, // Base delay for exponential backoff (1 s).
},
});Configuration Options Summary
| Option | Type | Default | Description |
|---|---|---|---|
sdkKey | string | -- | Required. SDK API key from your dashboard. |
debug | boolean | false | Enable verbose console logging. |
baseUrl | string | 'https://api.kitbase.dev' | API endpoint. Override for self-hosted deployments. |
storage | Storage | null | localStorage | Storage backend for anonymous ID persistence. Set to null to disable. |
storageKey | string | 'kitbase_anonymous_id' | Key name used in the storage backend. |
analytics
| Option | Type | Default | Description |
|---|---|---|---|
autoTrackPageViews | boolean | true | Automatically track page views on navigation. |
trackBfcacheRestore | boolean | true | Track a pageview when the browser restores a page from the back-forward cache (bfcache). Important for MPA sites where back/forward navigation does not re-execute scripts. |
autoTrackOutboundLinks | boolean | true | Track clicks on links to external domains. |
autoTrackClicks | boolean | true | Track clicks on interactive elements. |
autoTrackScrollDepth | boolean | true | Report maximum scroll depth when the user leaves. |
autoTrackVisibility | boolean | true | Observe elements with data-kb-track-visibility. |
offline
| Option | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enable the offline event queue. |
maxQueueSize | number | 1000 | Maximum events to hold in the queue. |
flushInterval | number | 30000 | Interval between automatic flushes (ms). |
flushBatchSize | number | 50 | Events sent per flush batch. |
maxRetries | number | 3 | Retry attempts before an event is dropped. |
retryBaseDelay | number | 1000 | Base delay for exponential backoff (ms). |
What the Script Does (Behind the Scenes)
When the tracking script loads, it performs the following sequence of actions automatically. Understanding this lifecycle helps you debug issues and reason about the data you see in the dashboard.
1. Generates an Anonymous ID
A UUID v4 is generated and stored in localStorage under the key kitbase_anonymous_id. This ID persists across page loads so the same browser is recognized as the same visitor without cookies. If storage is set to null, the ID is regenerated on every page load.
2. Starts a Session
A session_start event is fired with a new session ID (UUID v4). The session remains active as long as events arrive within 30 minutes of inactivity. After 30 minutes of inactivity, the next interaction starts a fresh session.
3. Listens for Page Navigations
The SDK patches history.pushState and listens for the popstate event. This means route changes in single-page applications are detected automatically -- no framework-specific code is needed.
4. Tracks Page Views
A screen_view event is fired on the initial page load and on every subsequent navigation (pushState or popstate). Each event includes the page path, document title, referrer, and any UTM parameters present in the URL.
5. Monitors Clicks on Interactive Elements
A global click listener watches for clicks on interactive elements: <a>, <button>, <input>, <select>, <textarea>, elements with ARIA roles (button, link, menuitem, tab), and custom elements (any tag name containing a hyphen). The SDK uses composedPath() to traverse Shadow DOM boundaries, so web components are fully supported.
6. Tracks Outbound Links
When a user clicks (or keyboard-activates with Enter/Space) a link pointing to an external domain, an outbound_link event is fired with the full URL and the link text. Outbound link clicks are not double-counted by the generic click tracker.
7. Measures Scroll Depth
The SDK tracks the maximum scroll depth reached on each page. A scroll_depth event with a percentage (0--100) is flushed when the user navigates away (beforeunload, pushState, popstate). Scroll tracking uses requestAnimationFrame throttling to avoid scroll jank.
8. Observes Element Visibility
Elements annotated with data-kb-track-visibility are observed using IntersectionObserver. When such an element leaves the viewport (or is removed from the DOM, or the user navigates away), an event is fired reporting how long the element was visible. A MutationObserver picks up dynamically added and removed elements.
9. Filters Bots Automatically
Before sending any events, the SDK checks for signals that indicate non-human traffic. Events are silently discarded when the page is loaded by:
- Headless browsers -- Puppeteer, Playwright, PhantomJS
- Testing tools -- Selenium, WebDriver
- HTTP clients -- curl, wget, Postman
- Search engine crawlers -- Googlebot, Bingbot, Yandex, Baidu
- Social media crawlers -- Facebook, Twitter/X, Slack, LinkedIn
No configuration is required. Your analytics will only include real user traffic.
10. Enriches Data Server-Side
The raw events sent by the browser contain minimal data. The Kitbase backend enriches every event with:
| Enrichment | Source | Fields |
|---|---|---|
| User agent parsing | User-Agent header | Device type, browser, browser version, OS, OS version, brand, model |
| IP geolocation | Client IP address | Country, region, city |
| UTM parameters | URL query string | utm_source, utm_medium, utm_campaign, utm_term, utm_content |
These enriched fields are stored as dedicated columns and available as first-class filter dimensions in the dashboard.
Accessing the SDK After Load (Script Tag)
When using the script tag method, the SDK instance is exposed on window.kitbase after the script finishes loading.
Tracking Custom Events
window.kitbase.track({
channel: 'engagement',
event: 'Button Clicked',
tags: { button_id: 'cta-header' },
});Identifying Users
window.kitbase.identify({
userId: 'user_123',
traits: {
email: 'user@example.com',
name: 'Jane Doe',
plan: 'premium',
},
});Tracking Revenue
window.kitbase.trackRevenue({
amount: 49.99,
currency: 'USD',
orderId: 'order-123',
});Waiting for the Script
Because the tracking script uses defer, it is guaranteed to execute after the DOM is parsed. If you need to call SDK methods from an inline script, use DOMContentLoaded:
<script>
document.addEventListener('DOMContentLoaded', function () {
window.kitbase.track({
channel: 'engagement',
event: 'Page Loaded',
});
});
</script>Data Attribute Events
The SDK supports declarative event tracking through HTML data attributes. No JavaScript is required -- annotate elements and the SDK handles the rest.
Track Clicks
Add data-kb-track-click to fire a named event when the element is clicked:
<button data-kb-track-click="CTA Clicked">Sign Up Now</button>
<!-- With a custom channel (default: "engagement") -->
<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 click to avoid double-counting.
Track Visibility
Add data-kb-track-visibility to measure how long a section is visible:
<section data-kb-track-visibility="Pricing Section Viewed">
...
</section>
<!-- With custom channel and threshold -->
<div
data-kb-track-visibility="Hero Banner Viewed"
data-kb-visibility-channel="marketing"
data-kb-visibility-threshold="0.75"
>
...
</div>| 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). |
Content Security Policy (CSP)
If your site uses a Content Security Policy, add the following directives to allow the tracking script and its API calls:
script-src 'self' https://kitbase.dev;
connect-src 'self' https://api.kitbase.dev;Subresource Integrity (SRI)
For additional security, you can verify the script has not been tampered with by using Subresource Integrity:
<script
src="https://kitbase.dev/lite.js"
integrity="sha384-..."
crossorigin="anonymous"
defer
></script>Contact support for the current SRI hash, or compute it yourself against the hosted script.
Framework Integration Tips
React / Next.js
Use the NPM package. Initialize the SDK in your root layout or App component so it runs once on mount:
// app/layout.tsx (Next.js App Router) or _app.tsx (Pages Router)
import { init } from '@kitbase/analytics';
const kitbase = init({ sdkKey: 'YOUR_SDK_KEY' });Vue / Nuxt
Use the NPM package. Initialize in a plugin or in app.vue:
// plugins/kitbase.client.ts (Nuxt 3)
import { init } from '@kitbase/analytics';
export default defineNuxtPlugin(() => {
const kitbase = init({ sdkKey: 'YOUR_SDK_KEY' });
return { provide: { kitbase } };
});Angular
Use the NPM package. Initialize in an Angular service and inject it where needed. See the Angular SDK documentation for a full guide.
// kitbase.service.ts
import { Injectable } from '@angular/core';
import { init } from '@kitbase/analytics';
@Injectable({ providedIn: 'root' })
export class KitbaseService {
public readonly client = init({ sdkKey: 'YOUR_SDK_KEY' });
}Static Sites
Use the script tag method in your HTML <head>. No build step required:
<!DOCTYPE html>
<html>
<head>
<script>
window.KITBASE_CONFIG = { sdkKey: 'YOUR_SDK_KEY' };
</script>
<script defer src="https://kitbase.dev/lite.js"></script>
</head>
<body>
<!-- Your site content -->
</body>
</html>Further Reading
- Proxy / Custom Domain -- Route requests through your own domain to bypass ad blockers
- Analytics -- Pageviews, sessions, bounce rate, and revenue tracking
- Autocapture -- Full reference of every automatic event and its payload
- Custom Events -- Track events with channels, tags, and notifications
- Identify Users -- Anonymous tracking and identity resolution
- JavaScript SDK -- Offline support and advanced features