Skip to main content
Initialize Iris once at the root of your application, then call start() to begin tracking.

Basic setup

Add Iris to your root layout (app/layout.tsx):
app/layout.tsx
'use client';
import { useEffect } from 'react';
import { Iris } from '@bigchill101/iris';

const analytics = new Iris({
  host: 'https://analytics.yourdomain.com',
  siteId: 'my-site',
  autocapture: { pageviews: true, clicks: true, webvitals: true },
});

export default function RootLayout({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    analytics.start();
    return () => analytics.stop();
  }, []);

  return <html><body>{children}</body></html>;
}

What start() does

Calling analytics.start() performs the following based on your autocapture config:
Autocapture optionEffect when true
autocapture.pageviewsFires an initial $pageview event, patches history.pushState for SPA navigation, and listens to popstate for back/forward
autocapture.clicksAttaches a global click listener that captures $click events on buttons, links, and submit inputs
autocapture.webvitalsHooks into the web-vitals library to automatically emit $web_vital events for LCP, INP, and CLS
The autocapture option defaults to false. You must explicitly opt in to each feature by setting the corresponding property to true, or pass autocapture: false to disable all autocapture.

Stopping Iris

Call analytics.stop() to clean up listeners — useful for hot module replacement in development:
analytics.stop();
stop() does the following:
  • Calls transport.destroy() which flushes any queued events and clears the flush timer
  • Restores the original history.pushState (undoes the SPA patch)
  • Resets the module-level pushStatePatched guard so a new instance can re-patch
  • Removes the popstate listener
Only one Iris instance should call start() at a time. A module-level guard prevents duplicate history.pushState patches if multiple instances are created.

Build docs developers (and LLMs) love