siteline Start free trial Log in

Install SiteLine on React

See your data

The HTML script tag will record pageviews in many React apps because it patches history. It is still the wrong default inside a TypeScript SPA. Use @siteline.tools/react, which wraps @siteline.tools/tracker. You mount one component. You call track() from click handlers. You do not paste a second snippet on every route file.

If your router is Next.js App Router, read the manual pageview step. The core tracker hooks popstate and patches pushState / replaceState. Some App Router navigations bypass those. Empty in-app pageviews are that gap, not a broken site id.

Full SDK surface: React docs. Event limits: custom events.

1. Enable the analytics site

In SiteLine, enable analytics on the domain (Sites list → Enable analytics, or Add analytics). Open Install. Copy the public site id. Add every hostname the app is served from, including preview hosts, to the allowlist. Events from a host that is not listed never ingest.

You still need a SiteLine origin for endpoint. That is https://YOUR_SITELINE_ORIGIN/api/analytics/event, or a same-origin path if you already proxy collect.

No account yet: register.

2. Install both packages

The React package does not bundle the core. Install both.

npm install @siteline.tools/react @siteline.tools/tracker
pnpm add @siteline.tools/react @siteline.tools/tracker

3. Mount <Analytics /> once

Put it near the root. It calls init() on mount and records the initial pageview.

import { Analytics } from '@siteline.tools/react';

export function App() {
    return (
        <>
            <Analytics
                siteId="YOUR_SITE_ID"
                endpoint="https://YOUR_SITELINE_ORIGIN/api/analytics/event"
            />
            {/* your app */}
        </>
    );
}

Do not mount it inside a page that remounts on every navigation. One init. The tracker ignores a second init().

Options (all optional except siteId):

Outbound and download flags emit billable custom events. Leave them off unless you need them.

4. Track named product events

import { useAnalytics } from '@siteline.tools/react';

export function SignupButton() {
    const { track } = useAnalytics();

    return (
        <button
            type="button"
            onClick={() => track('signup_clicked', { plan: 'starter' })}
        >
            Start trial
        </button>
    );
}

track requires a name. Properties are optional. At most 10 keys, key length ≤ 64, string values ≤ 256, values string | number | boolean. Extra keys are dropped; long strings are truncated. Client and ingest both enforce this.

Keep names lowercase and stable. Goals match event name exactly. Signup Clicked and signup_clicked are different goals.

5. Send pageviews on App Router changes

If client navigations do not appear as pageviews, add a tiny listener and call trackPageview():

import { useAnalytics } from '@siteline.tools/react';
import { useEffect } from 'react';
import { usePathname, useSearchParams } from 'next/navigation';

export function AnalyticsPageviews() {
    const { trackPageview } = useAnalytics();
    const pathname = usePathname();
    const searchParams = useSearchParams();

    useEffect(() => {
        trackPageview();
    }, [pathname, searchParams, trackPageview]);

    return null;
}

Mount that next to <Analytics />, not instead of it. <Analytics /> still owns init().

You do not need this helper on a plain Vite SPA that uses pushState the way the tracker expects. Add it when Live shows the first load and then goes quiet during in-app routing.

6. Confirm ingest

Load the app, click something that fires track, open SiteLine Live (about 30 minutes of visitors, pageviews, top pages). Then check the Events breakdown for your custom names.

If nothing arrives:

Collect is POST /api/analytics/event (alias POST /js/event). The tracker prefers keepalive fetch with credentials: 'omit'.

Vanilla core

Outside React, import the tracker directly:

import { init, track } from '@siteline.tools/tracker';

init({
    siteId: 'YOUR_SITE_ID',
    endpoint: 'https://YOUR_SITELINE_ORIGIN/api/analytics/event',
});

track('purchase', { value: 49 });

Do not mix the HTML script tag and the SDK on the same page. Two inits, two pageviews.

FAQ

Do I still need the script tag?

No. <Analytics /> is the install. The script snippet is for HTML sites. Using both double-counts pageviews.

Are React events extra billable volume?

Yes. Pageviews and custom events both count. Goals you define in the dashboard do not emit extra events. Auto outbound/download tracking does.

Why is endpoint optional if omitting it is dangerous?

The default is a relative /api/analytics/event. That posts to your origin. Unless you reverse-proxy that path to SiteLine, those requests 404 in your app. Set an absolute collect URL, or proxy both script and collect as in the proxy guide.