Skip to content

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:

html
<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:

bash
npm install @kitbase/analytics
bash
pnpm add @kitbase/analytics
bash
yarn add @kitbase/analytics

Then initialize the SDK in your application entry point:

typescript
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:

typescript
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.

typescript
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

OptionTypeDefaultDescription
sdkKeystring--Required. SDK API key from your dashboard.
debugbooleanfalseEnable verbose console logging.
baseUrlstring'https://api.kitbase.dev'API endpoint. Override for self-hosted deployments.
storageStorage | nulllocalStorageStorage backend for anonymous ID persistence. Set to null to disable.
storageKeystring'kitbase_anonymous_id'Key name used in the storage backend.

analytics

OptionTypeDefaultDescription
autoTrackPageViewsbooleantrueAutomatically track page views on navigation.
trackBfcacheRestorebooleantrueTrack 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.
autoTrackOutboundLinksbooleantrueTrack clicks on links to external domains.
autoTrackClicksbooleantrueTrack clicks on interactive elements.
autoTrackScrollDepthbooleantrueReport maximum scroll depth when the user leaves.
autoTrackVisibilitybooleantrueObserve elements with data-kb-track-visibility.

offline

OptionTypeDefaultDescription
enabledbooleanfalseEnable the offline event queue.
maxQueueSizenumber1000Maximum events to hold in the queue.
flushIntervalnumber30000Interval between automatic flushes (ms).
flushBatchSizenumber50Events sent per flush batch.
maxRetriesnumber3Retry attempts before an event is dropped.
retryBaseDelaynumber1000Base 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.

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:

EnrichmentSourceFields
User agent parsingUser-Agent headerDevice type, browser, browser version, OS, OS version, brand, model
IP geolocationClient IP addressCountry, region, city
UTM parametersURL query stringutm_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

javascript
window.kitbase.track({
  channel: 'engagement',
  event: 'Button Clicked',
  tags: { button_id: 'cta-header' },
});

Identifying Users

javascript
window.kitbase.identify({
  userId: 'user_123',
  traits: {
    email: 'user@example.com',
    name: 'Jane Doe',
    plan: 'premium',
  },
});

Tracking Revenue

javascript
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:

html
<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:

html
<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:

html
<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>
AttributeRequiredDefaultDescription
data-kb-track-visibilityYes--Event name to fire.
data-kb-visibility-channelNo'engagement'Channel for the event.
data-kb-visibility-thresholdNo0.5IntersectionObserver 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:

html
<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:

tsx
// 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:

typescript
// 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.

typescript
// 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:

html
<!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

Released under the MIT License.