Documentation

Everything you need to add YaliTrack to any website or app.

Quick Start

Add YaliTrack to any website in under 2 minutes. One script tag captures clicks, pageviews, scroll depth, and frustration signals automatically.

Step 1: Get your API key

Create an account at yalitrack.com/signup. You will receive an API key that looks like yt_live_abc123...

Step 2: Add the script

Paste this before the closing </head> tag on every page you want to track:

html
<script src="https://cdn.yalitrack.com/v1/track.js"
  data-key="yt_live_YOUR_API_KEY"
  data-auto-track="true"
  async defer></script>

Step 3: Verify

Visit your website, click around, then check your YaliTrack dashboard. Events appear within 10 seconds.

What gets tracked automatically:

  • Every click (element, text, coordinates, CSS selector)
  • Every pageview (URL, referrer, UTM params, SPA navigation)
  • Scroll depth (25%, 50%, 75%, 100% thresholds)
  • Frustration signals (rage clicks, dead clicks, error clicks)
  • Session and anonymous user identification
  • Device, browser, OS, country (enriched server-side)

Script Tag Configuration

Every option can be set as a data- attribute on the script tag. Here is every attribute explained:

html
<script src="https://cdn.yalitrack.com/v1/track.js"
  data-key="yt_live_YOUR_API_KEY"
  data-auto-track="true"
  data-api-url="https://api.yalitrack.com"
  data-debug="false"
  async defer></script>
AttributeRequiredDefaultDescription
data-keyYesYour project API key. Get it from the dashboard after creating a project. Looks like yt_live_abc123...
data-auto-trackNotrueWhen true: automatically captures all clicks, pageviews, scroll depth, and frustration signals. No code needed.

When false: nothing is tracked automatically. You must call YaliTrack.track() and YaliTrack.page() manually. Use this when you want full control over what gets tracked, or when you need user consent before tracking.
data-api-urlNohttps://api.yalitrack.comThe API endpoint where events are sent. Only change this if you are self-hosting or using a proxy.
data-debugNofalseWhen true: logs every tracked event to the browser console. Useful during development to verify events are firing correctly.

When false: silent. No console output.

What Each Auto-Track Feature Does

Click Tracking

Captures every click on the page. For each click, YaliTrack records: the CSS selector of the element (e.g. button.cta > span), the text content of the element (e.g. "Sign Up"), the X/Y coordinates of the click, the HTML tag (button, a, div, etc.), and the href if it was a link.

This powers: click heatmaps, element-level analytics, dead click detection.

Pageview Tracking

Fires a pageview event every time a new page loads. For single-page apps (React, Next.js, Vue), it automatically hooks into history.pushState, history.replaceState, and the popstate event, so client-side route changes are tracked without any extra code.

Each pageview captures: full URL, path, page title, referrer, UTM parameters (source, medium, campaign, content, term), and page load time in milliseconds.

Duplicate pageviews for the same URL are automatically deduplicated.

Scroll Depth Tracking

Measures how far users scroll down each page. Fires events at four thresholds: 25%, 50%, 75%, and 100%. Each threshold fires only once per page per session to avoid duplicate counting.

Example: if a user scrolls to 60% and then back up, the 25% and 50% events fire but 75% does not. If they later scroll to 80%, the 75% event fires.

Scroll events are debounced (500ms) to avoid performance impact.

Frustration Detection

Three types of frustration are detected automatically:

  • Rage clicks: When a user clicks the same element 3 or more times within 2 seconds. This means something they expect to work is not responding. Common causes: broken button, slow API with no loading state, JavaScript error.
  • Dead clicks: When a user clicks an element that is not interactive (not a link, button, or input) and no navigation or state change happens within 500ms. This means the user thought something was clickable but it was not. Common causes: underlined text that looks like a link, images that look like buttons.
  • Error clicks: When a click triggers a JavaScript error within 500ms. The user interacted with something and it broke. Common causes: API errors, null reference exceptions, third-party script conflicts.

These frustration signals are used to calculate a frustration score per page (0 to 100) visible in your dashboard.

Session and Identity

Session ID: A unique UUID generated per browser tab and stored in sessionStorage. It resets when the tab is closed. Not a cookie.

Anonymous ID: A unique UUID generated per browser and stored in localStorage. It persists across sessions on the same device. Not a cookie. Not shared across websites.

User ID: Set when you call YaliTrack.identify('user_123'). Links the anonymous ID to a known user so you can see their full journey from first visit to conversion.

Event Batching and Delivery

Events are queued in memory and sent in batches to minimize network requests. Batches are sent:

  • Every 5 seconds automatically
  • When the queue reaches 20 events
  • When the user leaves the page (via beforeunload and visibilitychange events)
  • When you call YaliTrack.flush() manually

Events are sent using navigator.sendBeacon() which is reliable even during page unload. Falls back to XMLHttpRequest if sendBeacon is unavailable.

Page Leave Tracking

When a user leaves a page, YaliTrack fires a page_leave event that includes the time spent on that page in seconds. This allows you to calculate accurate time-on-page metrics without relying on the next pageview timestamp.

SDK Init Options (JavaScript API)

If you use the JavaScript API instead of the script tag, these are all the options for YaliTrack.init():

javascript
YaliTrack.init({
  apiKey: 'yt_live_YOUR_API_KEY',  // Required. Your project API key.

  // Optional settings:
  apiUrl: 'https://api.yalitrack.com',  // API endpoint. Change only if self-hosting.
  autoTrack: true,         // Master switch. Set false to disable all auto-capture.
  autoPageViews: true,     // Track pageviews automatically (including SPA navigation).
  autoClicks: true,        // Track every click with element details.
  autoScroll: true,        // Track scroll depth at 25/50/75/100%.
  autoFrustration: true,   // Detect rage clicks, dead clicks, error clicks.
  debug: false,            // Log events to browser console.
});
OptionTypeDefaultDescription
apiKeystringrequiredYour project API key from the dashboard.
apiUrlstringhttps://api.yalitrack.comAPI endpoint. Only change if proxying or self-hosting.
autoTrackbooleantrueMaster switch. When false, disables autoPageViews, autoClicks, autoScroll, and autoFrustration all at once. Use this for consent-first tracking.
autoPageViewsbooleantrueAuto-track page loads and SPA client-side navigation. When false, call YaliTrack.page() manually.
autoClicksbooleantrueAuto-track every click with element selector, text, tag, coordinates, and href.
autoScrollbooleantrueTrack scroll depth at 25%, 50%, 75%, 100% thresholds. Each fires once per page per session.
autoFrustrationbooleantrueDetect rage clicks (3+ clicks in 2s), dead clicks (click on non-interactive element), and error clicks (click triggers JS error).
debugbooleanfalseWhen true, logs [YaliTrack] messages to console for every queued and flushed event. Turn off in production.

Common Configurations

Track everything automatically (default)

Just add the script with your key. Everything else is handled.

html
<script src="https://cdn.yalitrack.com/v1/track.js"
  data-key="yt_live_YOUR_API_KEY"
  async defer></script>

Note: data-auto-track defaults to true, so you don't need to include it.

Manual tracking only (consent-first)

Load the SDK but track nothing until the user consents.

html
<script src="https://cdn.yalitrack.com/v1/track.js"
  data-key="yt_live_YOUR_API_KEY"
  data-auto-track="false"
  async defer></script>

<script>
  // After user clicks "Accept" on your consent banner:
  document.getElementById('accept-btn').addEventListener('click', function() {
    YaliTrack.page();  // Start tracking manually
  });
</script>

Debug mode during development

See every event in the browser console to verify tracking works.

html
<script src="https://cdn.yalitrack.com/v1/track.js"
  data-key="yt_live_YOUR_API_KEY"
  data-auto-track="true"
  data-debug="true"
  async defer></script>

Open your browser DevTools console. You will see messages like: [YaliTrack] Queued: pageview (1 in queue) and [YaliTrack] Flushing 3 events.

Track pageviews only (no clicks or scroll)

For minimal tracking, use the JavaScript API:

javascript
YaliTrack.init({
  apiKey: 'yt_live_YOUR_API_KEY',
  autoPageViews: true,
  autoClicks: false,
  autoScroll: false,
  autoFrustration: false,
});

Custom API endpoint (proxy or self-host)

If you proxy the API through your own domain to avoid ad blockers:

html
<script src="https://cdn.yalitrack.com/v1/track.js"
  data-key="yt_live_YOUR_API_KEY"
  data-api-url="https://yoursite.com/analytics"
  async defer></script>

Set up a reverse proxy on your server: /analytics/*https://api.yalitrack.com/*

Platform Guides

Step-by-step instructions for every platform.

Plain HTML / Any Website

Works on any website. Just paste before </head>:

html
<!DOCTYPE html>
<html>
<head>
  <title>My Website</title>
  <!-- YaliTrack -->
  <script src="https://cdn.yalitrack.com/v1/track.js"
    data-key="yt_live_YOUR_API_KEY"
    data-auto-track="true"
    async defer></script>
</head>
<body>
  <!-- your content -->
</body>
</html>

WordPress

Two options:

Option A: Theme Header (recommended)

Go to Appearance > Theme File Editor > header.php. Paste before </head>:

html
<script src="https://cdn.yalitrack.com/v1/track.js"
  data-key="yt_live_YOUR_API_KEY"
  data-auto-track="true"
  async defer></script>

Option B: functions.php

Add to your theme's functions.php:

php
function yalitrack_script() {
  echo '<script src="https://cdn.yalitrack.com/v1/track.js"
    data-key="yt_live_YOUR_API_KEY"
    data-auto-track="true"
    async defer></script>';
}
add_action('wp_head', 'yalitrack_script');

Option C: Plugin

Use any "Insert Headers and Footers" plugin (like WPCode). Paste the script tag in the Header section.

Shopify

Go to Online Store > Themes > Actions > Edit Code > theme.liquid. Find the </head> tag and paste just before it:

html
<!-- YaliTrack Analytics -->
<script src="https://cdn.yalitrack.com/v1/track.js"
  data-key="yt_live_YOUR_API_KEY"
  data-auto-track="true"
  async defer></script>

This tracks every page in your store including product pages, cart, and checkout (if on your domain).

Wix

Go to Settings > Custom Code > Add Custom Code. Paste the script, set placement to Head, and apply to All Pages:

html
<script src="https://cdn.yalitrack.com/v1/track.js"
  data-key="yt_live_YOUR_API_KEY"
  data-auto-track="true"
  async defer></script>

Squarespace

Go to Settings > Advanced > Code Injection. Paste in the Header field:

html
<script src="https://cdn.yalitrack.com/v1/track.js"
  data-key="yt_live_YOUR_API_KEY"
  data-auto-track="true"
  async defer></script>

Webflow

Go to Project Settings > Custom Code > Head Code. Paste the script and publish.

html
<script src="https://cdn.yalitrack.com/v1/track.js"
  data-key="yt_live_YOUR_API_KEY"
  data-auto-track="true"
  async defer></script>

Next.js

Use the Next.js Script component in your root layout:

tsx
// app/layout.tsx
import Script from 'next/script';

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <head>
        <Script
          src="https://cdn.yalitrack.com/v1/track.js"
          data-key="yt_live_YOUR_API_KEY"
          data-auto-track="true"
          strategy="afterInteractive"
        />
      </head>
      <body>{children}</body>
    </html>
  );
}

Important: Do not use a raw <script> tag in Next.js. Use the <Script> component from next/script or the script will be stripped.

React (Vite / Create React App)

Add to your index.html in the <head>:

html
<script src="https://cdn.yalitrack.com/v1/track.js"
  data-key="yt_live_YOUR_API_KEY"
  data-auto-track="true"
  async defer></script>

Or use the NPM package for more control:

bash
npm install @yali/track
tsx
// App.tsx
import { YaliTrack } from '@yali/track';
import { useEffect } from 'react';

function App() {
  useEffect(() => {
    YaliTrack.init({ apiKey: 'yt_live_YOUR_API_KEY' });
  }, []);

  return <div>...</div>;
}

Vue.js / Nuxt

For Vue, add to index.html. For Nuxt, use nuxt.config.ts:

typescript
// nuxt.config.ts
export default defineNuxtConfig({
  app: {
    head: {
      script: [{
        src: 'https://cdn.yalitrack.com/v1/track.js',
        'data-key': 'yt_live_YOUR_API_KEY',
        'data-auto-track': 'true',
        async: true,
        defer: true,
      }]
    }
  }
})

Angular

Add to src/index.html before </head>:

html
<script src="https://cdn.yalitrack.com/v1/track.js"
  data-key="yt_live_YOUR_API_KEY"
  data-auto-track="true"
  async defer></script>

Server-Side (Node.js, Python, Go, etc.)

Use the REST API directly from any backend language:

bash
curl -X POST https://api.yalitrack.com/v1/events \
  -H "Authorization: Bearer yt_live_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"event": "purchase", "user_id": "user_123", "properties": {"amount": 49.99}}'
python
# Python
import requests

requests.post('https://api.yalitrack.com/v1/events',
  headers={'Authorization': 'Bearer yt_live_YOUR_API_KEY'},
  json={'event': 'purchase', 'user_id': 'user_123', 'properties': {'amount': 49.99}}
)
javascript
// Node.js
await fetch('https://api.yalitrack.com/v1/events', {
  method: 'POST',
  headers: {
    'Authorization': 'Bearer yt_live_YOUR_API_KEY',
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    event: 'purchase',
    user_id: 'user_123',
    properties: { amount: 49.99 },
  }),
});

Google Tag Manager

Create a new Custom HTML Tag in GTM and paste:

html
<script src="https://cdn.yalitrack.com/v1/track.js"
  data-key="yt_live_YOUR_API_KEY"
  data-auto-track="true"
  async defer></script>

Set the trigger to All Pages and publish.

SDK Reference

All available methods on the YaliTrack global object.

YaliTrack.init(options)

Initialize tracking. Call once, typically in your layout or app entry point.

javascript
YaliTrack.init({
  apiKey: 'yt_live_YOUR_API_KEY',  // Required
  apiUrl: 'https://api.yalitrack.com',  // Custom API URL (optional)
  autoTrack: true,          // Enable all auto-tracking (default: true)
  autoPageViews: true,      // Auto-track pageviews (default: true)
  autoClicks: true,         // Auto-track clicks (default: true)
  autoScroll: true,         // Auto-track scroll depth (default: true)
  autoFrustration: true,    // Detect rage/dead/error clicks (default: true)
  debug: false,             // Console logging (default: false)
});

YaliTrack.track(eventName, properties?)

Track a custom event.

javascript
YaliTrack.track('signup', { method: 'google', plan: 'pro' });
YaliTrack.track('purchase', { amount: 49.99, currency: 'USD' });
YaliTrack.track('feature_used', { feature: 'export_csv' });

YaliTrack.identify(userId, traits?)

Link an anonymous visitor to a known user. Call after login or signup.

javascript
YaliTrack.identify('user_123', {
  email: 'jane@example.com',
  name: 'Jane Doe',
  plan: 'pro',
  company: 'Acme Inc',
});

YaliTrack.page(url?, properties?)

Manually track a pageview. Called automatically if autoPageViews is on.

javascript
YaliTrack.page();  // Uses current URL
YaliTrack.page('/virtual-page', { section: 'onboarding' });

YaliTrack.flush()

Send all queued events immediately. Useful before redirects.

javascript
YaliTrack.flush();
window.location.href = '/thank-you';

YaliTrack.reset()

Clear user identity. Call on logout.

javascript
function handleLogout() {
  YaliTrack.reset();
  window.location.href = '/login';
}

API Reference

Base URL: https://api.yalitrack.com

All requests need Authorization: Bearer YOUR_API_KEY

POST/v1/events

Track a single event.

json
{
  "event": "purchase",
  "user_id": "user_123",
  "anonymous_id": "anon_abc",
  "properties": { "plan": "pro", "amount": 39.00 },
  "timestamp": "2026-03-18T12:00:00Z"
}
POST/v1/events/batch

Send up to 500 events at once.

json
{
  "events": [
    { "event": "pageview", "properties": { "page": "/pricing" } },
    { "event": "click", "properties": { "button": "upgrade" } }
  ]
}
POST/v1/identify

Create or update a user profile.

json
{
  "user_id": "user_123",
  "anonymous_id": "anon_abc",
  "traits": { "email": "jane@example.com", "plan": "pro" }
}

React / Next.js Hooks

Install: npm install @yali/track

<YaliTrackProvider>

Wrap your app to initialize tracking.

tsx
import { YaliTrackProvider } from '@yali/track/react';

export default function Layout({ children }) {
  return (
    <YaliTrackProvider apiKey="yt_live_YOUR_API_KEY">
      {children}
    </YaliTrackProvider>
  );
}

useYaliPageView()

Track page views on route changes.

tsx
import { useYaliPageView } from '@yali/track/react';

function PricingPage() {
  useYaliPageView();  // Tracks when this page mounts
  return <div>...</div>;
}

useYaliTrack()

Access track, identify, and reset from any component.

tsx
import { useYaliTrack } from '@yali/track/react';

function UpgradeButton() {
  const { track, identify } = useYaliTrack();

  return (
    <button onClick={() => {
      track('upgrade_clicked', { plan: 'pro' });
    }}>
      Upgrade
    </button>
  );
}

Custom Events Guide

Beyond auto-capture, track business events that matter to you.

Common Events to Track

javascript
// Authentication
YaliTrack.track('signup', { method: 'google' });
YaliTrack.track('login', { method: 'email' });
YaliTrack.track('logout');

// E-commerce
YaliTrack.track('add_to_cart', { product: 'Widget', price: 29.99 });
YaliTrack.track('checkout_started', { items: 3, total: 89.97 });
YaliTrack.track('purchase', { order_id: 'ORD-123', total: 89.97 });

// SaaS
YaliTrack.track('trial_started', { plan: 'pro' });
YaliTrack.track('feature_used', { feature: 'ai_analyst' });
YaliTrack.track('upgrade', { from: 'free', to: 'pro' });
YaliTrack.track('churned', { reason: 'too_expensive' });

// Content
YaliTrack.track('article_read', { title: 'How to...', category: 'guides' });
YaliTrack.track('video_played', { title: 'Demo', duration: 120 });
YaliTrack.track('newsletter_subscribed', { source: 'blog_footer' });

Privacy & GDPR

GDPR Compliance

  • All data stored on EU servers (Hetzner, Finland)
  • No data shared with third parties
  • No cookies required (uses sessionStorage + localStorage)
  • IP addresses hashed with daily-rotating salt before storage
  • Data Processing Agreement (DPA) available on request
  • Data deletion API for right-to-erasure (GDPR Art. 17)
  • No cookie consent banner needed when running cookieless

Disable Tracking

Initialize without auto-tracking and enable it after consent:

javascript
// Start without tracking
YaliTrack.init({
  apiKey: 'yt_live_YOUR_API_KEY',
  autoTrack: false,
});

// After user consents:
YaliTrack.page();  // Track manually from here

Need help?

Contact us at hello@yalitrack.com

Start Free