> ## Documentation Index
> Fetch the complete documentation index at: https://docs.bily.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# React

> Add Bily to React and track each route without duplicating page views.

Add one Bily component inside your router. It starts the SDK and tracks later route changes without duplicating the automatic initial page view.

Do not add a raw Bily script tag anywhere else in the application. `init()` loads the script for you.

## Install Bily

```bash theme={null}
npm install @bilyai/js
```

## Track every route once

This example uses React Router. It remembers the initial URL so it does not send a second `PageView`, then ignores repeated calls for the same URL.

```tsx src/BilyTracking.tsx theme={null}
import { useEffect, useRef } from "react";
import { useLocation } from "react-router-dom";
import { init, track } from "@bilyai/js";

const BILY_SCRIPT_URL =
  "https://tracking.example.com/b.js?shop=store.example.com";

export function BilyTracking() {
  const location = useLocation();
  const previousUrl = useRef<string | null>(null);

  useEffect(() => {
    init({ scriptUrl: BILY_SCRIPT_URL });
  }, []);

  useEffect(() => {
    const currentUrl = window.location.href;

    if (previousUrl.current === null) {
      previousUrl.current = currentUrl;
      return;
    }

    if (currentUrl === previousUrl.current) return;
    previousUrl.current = currentUrl;

    track("PageView", {
      sourceUrl: currentUrl,
      pageTitle: document.title,
    });
  }, [location.pathname, location.search, location.hash]);

  return null;
}
```

Mount the component once inside the router so `useLocation()` can observe committed routes.

```tsx src/App.tsx theme={null}
import { BrowserRouter } from "react-router-dom";
import { BilyTracking } from "./BilyTracking";
import { AppRoutes } from "./AppRoutes";

export function App() {
  return (
    <BrowserRouter>
      <BilyTracking />
      <AppRoutes />
    </BrowserRouter>
  );
}
```

Repeated `init()` calls with the same URL are safe. One component keeps ownership clear, while the URL guard prevents React development checks from creating duplicate route events.

## Track successful actions

Call `track()` only after the user action succeeds.

```tsx src/LaunchCampaignButton.tsx theme={null}
import { track } from "@bilyai/js";

export function LaunchCampaignButton({ campaignId }: { campaignId: string }) {
  async function handleClick() {
    await launchCampaign(campaignId);
    track("campaign_launched", { campaign_id: campaignId });
  }

  return <button onClick={handleClick}>Launch campaign</button>;
}
```

<Card title="Verify React tracking" icon="circle-check" href="/guides/verification">
  Check the initial view, later routes, and action events without duplicates.
</Card>
