View as markdown

LiveLayerTracker

The visitor tracking class. Resolves a stable identity (FingerprintJS + localStorage fallback), then optionally auto-tracks page views, clicks, scroll depth. Conversations carry the same visitor ID, so your CRM sees one continuous timeline.

ts
import { LiveLayerTracker } from "@livelayer/sdk";

const tracker = new LiveLayerTracker({
  agentId: "agt_abc123",
  apiBase: "https://livelayer.app",
  autoTrack: true,
  autoTrackClicks: true,
});

const visitor = await tracker.init();
// → { id: "vis_abc123", isReturning: true, sessionCount: 4 }

For the script-tag version (drop-in HTML), see Visitor tracking.

Constructor

ts
interface TrackerConfig {
  agentId: string;
  apiBase?: string;
  autoTrack?: boolean;
  autoTrackClicks?: boolean;
}
NameTypeDescription
agentId*stringRequired for scoping events to your account. Match the agentId you use elsewhere.
apiBasestringAPI base URL. Default: same origin.
autoTrackbooleanAuto-track page views and SPA navigation. Default: true.
autoTrackClicksbooleanAuto-track clicks on interactive elements. Default: true.

Methods

ts
async init(): Promise<VisitorInfo | null>
identify(attributes: Partial<VisitorAttrs>): void
track(eventName: string, data?: Record<string, unknown>): void
destroy(): void
NameTypeDescription
init() => Promise<VisitorInfo | null>Bootstrap the tracker. Resolves visitor identity, sets up auto-tracking. Returns visitor info or null if blocked entirely.
identify(attrs) => voidAttach attributes to the current visitor (email, name, plan, custom fields). Subsequent events carry these.
track(name, data?) => voidTrack a custom event with optional payload.
destroy() => voidClean up: flush pending events, remove auto-track listeners. Call on logout or unmount.

Visitor info shape

ts
interface VisitorInfo {
  id: string;              // "vis_abc123"
  isReturning: boolean;    // True on subsequent sessions
  sessionCount: number;    // Total resolved sessions for this visitor
}

Common patterns

React app — boot once, reuse

tsx
"use client";
import { LiveLayerTracker, type VisitorInfo } from "@livelayer/sdk";
import { createContext, useContext, useEffect, useState, type ReactNode } from "react";

const Ctx = createContext<{ tracker: LiveLayerTracker | null; visitor: VisitorInfo | null }>({
  tracker: null,
  visitor: null,
});

export function TrackerProvider({ children, agentId }: { children: ReactNode; agentId: string }) {
  const [tracker, setTracker] = useState<LiveLayerTracker | null>(null);
  const [visitor, setVisitor] = useState<VisitorInfo | null>(null);

  useEffect(() => {
    const t = new LiveLayerTracker({ agentId });
    t.init().then((v) => {
      setTracker(t);
      setVisitor(v);
    });
    return () => t.destroy();
  }, [agentId]);

  return <Ctx.Provider value={{ tracker, visitor }}>{children}</Ctx.Provider>;
}

export function useTracker() {
  return useContext(Ctx);
}

Use it from any component:

tsx
const { tracker, visitor } = useTracker();

if (visitor?.isReturning) {
  // Show "Welcome back" banner
}

const onCheckout = () => {
  tracker?.track("checkout_started", { plan: "pro", amount: 29 });
};

Identify after login

When you know who the user is, attach attributes:

ts
async function onLogin(user: { email: string; name: string; plan: string }) {
  tracker.identify({
    email: user.email,
    name: user.name,
    plan: user.plan,
  });
}

The visitor ID stays the same; the new attributes attach to it. Conversations from this point forward carry these attributes through the agent transcript and your dashboard.

Track custom events alongside auto-tracking

ts
// Auto-tracking captures page views and clicks automatically.
// Add domain-specific events on top.
tracker.track("watched_demo_video", {
  videoId: "intro-2026",
  durationSeconds: 47,
});

tracker.track("started_trial", {
  source: "homepage_hero_cta",
});

Opting out

Visitors who opt out (e.g., GDPR consent banner choice):

ts
tracker.destroy();

This stops sending events and removes all auto-track listeners. Re-init when the visitor opts back in.

Do Not Track is respected automatically — no events fire when navigator.doNotTrack === "1".

Excluding sensitive elements

Mark any element with data-ll-private="true" to exclude it from auto-tracked clicks:

html
<section data-ll-private="true">
  <input name="ssn" />
  <button>Save</button>  <!-- Click on this won't be tracked -->
</section>

Event batching and delivery

  • Events are queued client-side.
  • Flush triggers: every 5 seconds, OR when the queue reaches 50 events, OR when the page unloads.
  • Failed POSTs retry with exponential backoff: 1s, 2s, 4s, 8s.
  • Events that can't be delivered after 5 retries are dropped (no permanent buffer).