Skip to documentation

Web SDK

The Kixo Web SDK auto-tracks clicks, page views, sessions, errors, scroll depth, web vitals, rage-clicks, dead-clicks, and heatmap data with a one-line embed. Network request monitoring is available as an opt-in setting. Distributed as a native ES module and works in modern browsers.

Installation

Script tag (CDN)

Add the snippet before the closing </head> tag. Note the type="module" — required because the SDK is an ES module. Session replay is code-split into a version-matched recorder chunk that only loads after replay has been enabled, so the base bundle stays small while replay is off.

html
<script
  type="module"
  src="https://cdn.kixo.io/kixo.min.js?project_id=YOUR_PROJECT_ID&api_key=YOUR_API_KEY">
</script>

Note

The SDK reads project_id and api_key from the script URL and initializes itself. To configure options in application code, drop the URL params and call Kixo.init({...}) instead — the global Kixo object is available once the module has loaded.

html
<script type="module" src="https://cdn.kixo.io/kixo.min.js"></script>
<script type="module">
  Kixo.init({
    projectId: 'YOUR_PROJECT_ID',
    apiKey:    'YOUR_API_KEY',
  });
</script>

npm

Use this when you want to configure options in application code rather than through the script URL. It exposes the same Kixo API as the CDN embed.

bash
npm install @kixo.io/web
js
import Kixo from '@kixo.io/web';

Kixo.init({
  projectId: 'YOUR_PROJECT_ID',
  apiKey: 'YOUR_API_KEY',
});

No-Code Platforms

If you are building with an AI-powered builder like Lovable, Bolt, v0, or Replit, paste the script-tag snippet directly into your builder's chat or code-injection settings. Most builders support adding scripts to the <head> of your site.

Configuration

The two-line embed uses the local analytics defaults below. Request monitoring remains opt-in. Session replay is intentionally absent from Kixo.init(): its enable switch, sampling, privacy, duration, and capture settings come only from the project dashboard.

js
Kixo.init({
  projectId: 'YOUR_PROJECT_ID',     // required
  apiKey:    'YOUR_API_KEY',         // required

  // Per-tracker toggles — all default to true except network.
  autoTrack: {
    pageViews:   true,
    clicks:      true,
    scrollDepth: true,
    sessions:    true,
    forms:       true,
    network:     false,     // opt in only when you need request telemetry
    errors:      true,
    performance: true,
    rageClicks:  true,
    deadClicks:  true,
  },

  // Heatmap recording (clicks + scroll on by default; mouse-move opt-in).
  heatmap: {
    enabled: true,
    clicks:  true,
    moves:   false,
    scroll:  true,
  },

});

Note

Project-controlled config. Dashboard settings can disable local analytics trackers. Replay has no local positive enable flag at all: configure it underSettings → Session replay, and the SDK follows the latest project policy on its next config refresh.

Auto-tracked events

With the default configuration, Kixo automatically captures these events with no additional code:

  • page_view — every navigation (initial load + SPA route changes)
  • session_start / session_end
  • click — all click interactions with element selector
  • scroll_depth — 25 / 50 / 75 / 100 % thresholds
  • rage_click — repeated clicks on the same element
  • dead_click — clicks on non-interactive elements
  • error — uncaught JavaScript exceptions + promise rejections
  • performance — page-load and Web Vitals metrics (LCP, FCP, FID, CLS, INP, TTFB)
  • network_request — optional request timing when network tracking is enabled
  • heatmap_click / scroll — heatmap data

See the full list in the Events Reference.

Custom events

Kixo.track()

Send a custom event with optional properties.

js
Kixo.track('purchase_completed', {
  product_id: 'SKU-123',
  amount: 49.99,
  currency: 'USD',
});

Typed event helpers

Sugar over Kixo.track() for the events Kixo recognizes by name (purchase, signup, subscribe_start,trial_start, cancel, upgrade,activation, share, invite). Typed wrappers buy compile-time property validation and a single source of truth for key names — backend's standard-event detector matches verbatim.

js
Kixo.trackPurchase({ amount: 49.99, currency: 'USD', productId: 'pro_yearly' });

Kixo.trackSubscriptionStart({
  plan: 'pro',
  amount: 9.99,
  currency: 'USD',
  interval: 'month',
});

Kixo.trackSignup({ method: 'google' });
Kixo.trackTrialStart({ plan: 'pro', days: 14 });
Kixo.trackCancel({ plan: 'pro', reason: 'too_expensive' });
Kixo.trackUpgrade({ fromPlan: 'free', toPlan: 'pro' });
Kixo.trackActivation({ event: 'first_post_published' });
Kixo.trackShare({ channel: 'twitter', contentId: 'post_123' });
Kixo.trackInvite({ channel: 'email', recipientCount: 5 });

Kixo.identify()

Associate the current device with a known user. Reserved standard property keys carry a $-prefix (Mixpanel convention) so they namespace away from your own custom traits and promote to the dashboard's profile columns — see the Standard property catalog below for the full 37-key list.

js
Kixo.identify('user_123', {
  $email:  'jane@example.com',     // identity
  $name:   'Jane Doe',              // identity
  $plan:   'pro',                   // subscription pack
  $lifetime_orders: 12,             // e-commerce pack
  signup_source: 'twitter_ad',      // custom trait
});

Kixo.setUserProperty() — tag a user for segmentation

Attach arbitrary key/value attributes to the current user. Values can be strings, numbers, or booleans — the boolean form is the cleanest way to tag a user for later targeting in segments, email campaigns, or chat queries.

js
// Tag a user as subscribed — instant segment "Subscribed users"
Kixo.setUserProperty('subscribe', true);

// Mark a VIP — used in campaign targeting + chat ("show me VIPs")
Kixo.setUserProperty('vip', true);

// Numeric and string values work too
Kixo.setUserProperty('plan_tier', 'enterprise');
Kixo.setUserProperty('lifetime_orders', 42);

// Bulk-set
Kixo.setUserProperties({ subscribe: true, plan_tier: 'enterprise' });

Properties persist in localStorage across reloads and auto-attach to subsequent events. Use them in chat with prompts like "build an email campaign for users where subscribe is true" — Kixo synthesizes a segment + drafts the template automatically. Cleared on Kixo.reset().

Kixo.group()

Associate the user with a company or organization.

js
Kixo.group('company_456', {
  name: 'Acme Inc',
  plan: 'enterprise',
});

Kixo.reset()

Clear identity, super-properties, and the persisted queue. Call this on logout so subsequent events are not attributed to the previous user.

js
Kixo.reset();

Standard property catalog

Reserved property keys carry a $ prefix so they namespace away from your custom traits. Kixo's catalog covers 37 keys across 3 universal packs (identity, geo, lifecycle) and 5 B2B vertical packs (subscription, e-commerce, media, marketplace, loyalty). Set whichever apply to your product — the dashboard adapts and renders only the packs you populate.

Identity

Always relevant. Sets the profile header columns.

KeyTypeDescription
$emailstringPrimary email, often the merge key for identity stitching.
$phonestringE.164 phone number.
$namestringFull display name.
$first_namestringGiven name.
$last_namestringFamily name.
$avatar_urlstringFull URL to the user's avatar image.

Geo

Geographic context.

KeyTypeDescription
$countrystringISO 3166 country code.
$citystringCity name.
$regionstringState or province.
$timezonestringIANA zone like America/Los_Angeles.
$languagestringIETF tag like en or ru-RU.
$localestringFull locale identifier.

Lifecycle

When did we see them.

KeyTypeDescription
$createdISO8601Signup or account creation time.
$last_seenISO8601Last engagement time.

Subscription

Set if your product has plans.

KeyTypeDescription
$planstringTier slug — free, pro, enterprise.
$subscription_statusstringactive / trial / cancelled / past_due.
$trial_endsISO8601When the current trial expires.
$mrrnumberMonthly recurring revenue in account currency.
$subscription_startedISO8601When the current subscription began.

E-commerce

Set if you sell products.

KeyTypeDescription
$lifetime_ordersnumberCount of completed orders.
$lifetime_revenuenumberTotal spend.
$aovnumberAverage order value.
$last_purchaseISO8601Most recent successful purchase.
$first_purchaseISO8601First successful purchase.
$cart_abandoned_countnumberLifetime count of cart abandonments.

Media

Set if you publish content.

KeyTypeDescription
$content_tierstringfree / premium / paid.
$subscribed_categoriesCSV string or arrayCategories the user follows.
$watch_time_totalnumberLifetime watch time in seconds.
$last_playedISO8601Most recent playback start.

Marketplace

Set if you're a two-sided platform.

KeyTypeDescription
$seller_tierstringSeller-side tier slug.
$buyer_tierstringBuyer-side tier slug.
$listings_countnumberActive listings the user owns.
$reviews_countnumberReviews the user has received.
$verifiedbooleanKYC status.

Loyalty

Set for engagement and rewards programs.

KeyTypeDescription
$loyalty_pointsnumberCurrent redeemable points balance.
$vip_levelstringVIP tier slug.
$referral_countnumberSuccessful referrals attributed to this user.

Tip

Don't see your pattern? Use bare keys for custom traits. They surface in the dashboard's Custom Traits panel without polluting the profile columns. The 5 vertical packs above are opinionated guesses at the most common B2B shapes — customer-specific terminology (e.g. shipping_plan) stays bare.

Super-properties

Per-session key/value pairs auto-attached to every outbound event. Different from identify() traits (which describe the identity); super-properties describe session context — active A/B variant, build flavor, opted-in feature flags, affiliate ref. Persisted in localStorage across reloads; cleared on reset(). Per-event properties on track() always win on key collision.

js
Kixo.setSuperProperty('build_flavor', 'beta');
Kixo.setSuperProperties({ ab_variant: 'B', referrer_campaign: 'autumn-launch' });

// Sugar for A/B tracking — keys as 'experiment_<id>' so backend
// can run direct WHERE filters on experiment analysis.
Kixo.setExperimentVariant('checkout_v2', 'variant_a');

Kixo.unsetSuperProperty('build_flavor');
Kixo.clearSuperProperties();

Heatmaps

Heatmap recording is on by default — clicks and scroll depth, both sampled at 100 %. Mouse movement is opt-in (high-volume; enable per- page if useful).

js
Kixo.init({
  projectId: 'YOUR_PROJECT_ID',
  apiKey:    'YOUR_API_KEY',
  heatmap:   { moves: true },  // turn on full-resolution mouse-move
});

Session replay

Session replay records an rrweb DOM snapshot and mutation stream so the dashboard can reconstruct the page as a scrubbable session alongside the event trail. It is a DOM reconstruction rather than a screen-video recording. Replay is off by default. Enable it for the project under Dashboard → Settings → Session replay; no application-code change is required. When enabled, the recorder is fetched from a separate version-matched chunk after replay is enabled.

Note

The dashboard is the source of truth. Set Enable replay, Mask inputs, maximum duration, and the advanced capture controls there. captureOnCellular is stored in the same project policy for iOS and Android; browsers do not expose a dependable Wi-Fi-versus-cellular signal, so the Web SDK reports and ignores that native-only restriction.

What gets masked

Replay is designed to be safe to turn on. Three layers protect sensitive content, all on by default:

  • Input masking is project-controlled — while Dashboard's Mask inputs setting is on (the default), typed characters are replaced with asterisks before they leave the browser. Turn it off only for a specific, low-sensitivity need; identity, authentication, and payment fields remain masked.
  • The data-kixo-mask attribute blocks an element and its entire subtree. Put it on any container that may hold personal or confidential content; the replay contains a placeholder, not that subtree's text or DOM content.
    html
    <div data-kixo-mask>
      <!-- payment fields, account numbers, private messages… -->
      <!-- captured as a blank placeholder, never as pixels -->
    </div>
  • Sensitive fields are always masked — inputs that look like a password, card number, CVV, SSN, secret, or token (by type, name, id, or autocomplete) are masked even when the project'sMask inputs setting is off. Visible text and serialized DOM attributes also pass through Kixo's PII sanitizer before upload.

Data collection

The SDK captures the trackers enabled in your integration and project settings, plus the events and properties your application sends.

Where recordings go

The SDK gzips rrweb events into bounded segments, asks Kixo for a project-scoped signed upload URL, and uploads those segments directly to replay storage. Open the reconstructed session under Replay → Sessions; it links to the same session's analytics trail.

Note

Replay is subject to your plan. How many sessions are captured and retained depends on your project plan; on lower tiers Kixo still records lightweight session metadata so the session shows up in your lists and analytics.

Feature flags

Check flag values at runtime via Kixo.getFeatureFlag().

js
const variant = Kixo.getFeatureFlag('new_checkout');

if (variant === 'enabled') {
  showNewCheckout();
} else {
  showLegacyCheckout();
}

Delivery and offline behavior

The SDK queues events locally, sends them in batches, and retries transient failures with backoff. If collection is paused from project settings, new events are not sent until collection is enabled again.

Diagnostics

Read-only health snapshot — useful for "why aren't my events flowing?" debugging in dev tools.

js
const diag = Kixo.diagnostics();
console.log(diag);