Layers

SDK — React Router

Install `@layers/client` for React Router v6 (BrowserRouter) and v7 (data router + framework mode). Auto-screen via the router hooks.

View as Markdown

React Router has two materially different shapes today — v6 (the classic BrowserRouter + Routes + Route JSX tree) and v7 (the data router with loaders + the optional framework mode that enables SSR). The SDK install is the same; the integration touchpoints differ.

Install

npm i @layers/client

v6 — BrowserRouter

Wrap the router with a Layers provider. Use useLocation in a tracker component to fire screen() on every route change.

src/main.tsx
import { LayersClient } from '@layers/client';
import { BrowserRouter, Routes, Route, useLocation } from 'react-router-dom';
import { createContext, useContext, useEffect, useState } from 'react';

const LayersContext = createContext<LayersClient | null>(null);
const useLayers = () => useContext(LayersContext);

function PageTracker() {
  const layers = useLayers();
  const { pathname } = useLocation();
  useEffect(() => {
    layers?.screen(pathname).catch(() => {});
  }, [layers, pathname]);
  return null;
}

function LayersProvider({ children }: { children: React.ReactNode }) {
  const [client, setClient] = useState<LayersClient | null>(null);
  useEffect(() => {
    const c = new LayersClient({
      apiKey: 'unused',
      appId: import.meta.env.VITE_LAYERS_APP_ID,
      environment: import.meta.env.MODE === 'production' ? 'production' : 'development',
    });
    c.init().then(() => setClient(c));
  }, []);
  return <LayersContext.Provider value={client}>{children}</LayersContext.Provider>;
}

createRoot(document.getElementById('root')!).render(
  <BrowserRouter>
    <LayersProvider>
      <PageTracker />
      <Routes>{/* … */}</Routes>
    </LayersProvider>
  </BrowserRouter>,
);

PageTracker must mount inside the router context (so useLocation resolves) and inside LayersProvider (so it can read the client). Render it once near the root.

v7 — Data router (createBrowserRouter)

The hooks are the same; what changes is where you mount the provider. With createBrowserRouter, your route tree is configuration — wrap the <RouterProvider>:

import { createBrowserRouter, RouterProvider } from 'react-router-dom';

const router = createBrowserRouter([
  // … your routes
]);

function App() {
  return (
    <LayersProvider>
      <RouterProvider router={router} />
    </LayersProvider>
  );
}

Page tracking still uses useLocation — render <PageTracker /> from a route element (typically the root layout component).

v7 — Framework mode (SSR)

React Router v7 framework mode runs the route tree on the server. Same SSR rules as Next.js apply:

  • Never initialize the SDK on the server. Use a useEffect-based provider, identical to the Next.js App Router pattern.
  • For server-side event firing (post-purchase webhooks, etc.) call POST /v1/events — the partner-API forwarding surface — from your loader/action functions.
app/root.tsx
import { useEffect, useState } from 'react';
import { Outlet, useLocation } from 'react-router';
import { LayersClient } from '@layers/client';

export default function Root() {
  const [client, setClient] = useState<LayersClient | null>(null);
  const { pathname } = useLocation();

  useEffect(() => {
    const c = new LayersClient({
      apiKey: 'unused',
      appId: import.meta.env.VITE_LAYERS_APP_ID,
      environment: import.meta.env.MODE === 'production' ? 'production' : 'development',
    });
    c.init().then(() => setClient(c));
  }, []);

  useEffect(() => {
    client?.screen(pathname).catch(() => {});
  }, [client, pathname]);

  return <Outlet />;
}

Tracking events

Same LayersClient API as every other JS environment:

const layers = useLayers();
layers?.track('purchase_success', { revenue: 19.99, currency: 'USD' });

See Standard events for canonical event names; events outside that list are stored but not relayed to CAPI.

Verifying the install

curl -X POST https://api.layers.com/v1/projects/$PROJECT_ID/sdk-apps/$APP_ID/verify-tracking \
  -H "Authorization: Bearer $LAYERS_API_KEY"

See verify-tracking.

See also

On this page