ConsentLayer
Guides

Remix Integration

This guide shows how to integrate ConsentLayer with a Remix application (works on both Remix v2 and React Router v7).

1. Install the SDK

npm install @consentlayer/sdk

2. Add the banner script in app/root.tsx

// app/root.tsx
import {
  Links,
  Meta,
  Outlet,
  Scripts,
  ScrollRestoration,
} from "@remix-run/react";

export default function App() {
  return (
    <html lang="en">
      <head>
        <meta charSet="utf-8" />
        <Meta />
        <Links />
        <script src="https://b.consentlayer.com/YOUR_PROJECT_KEY/banner.js" />
      </head>
      <body>
        <Outlet />
        <ScrollRestoration />
        <Scripts />
      </body>
    </html>
  );
}

Use a plain <script> tag — not Remix's <Scripts /> component, which is reserved for the app's own bundle. The banner needs to run before any client code, so put it directly in <head> before <Scripts />.

Remix renders app/root.tsx on the server, so the tag is emitted as static HTML. The browser runs it synchronously while parsing <head>, before any tracking scripts can fire.

Like Next.js App Router, Remix server-renders by default. Any component that reads consent state needs to be mounted before it tries to render — gate it behind a flag so server HTML matches the first client render:

// app/components/ConsentArea.tsx
import { useEffect, useState } from "react";
import { ConsentLayerProvider, ConsentGate } from "@consentlayer/sdk/react";

export function ConsentArea({ children }: { children: React.ReactNode }) {
  const [mounted, setMounted] = useState(false);
  useEffect(() => setMounted(true), []);
  if (!mounted) return null;
  return (
    <ConsentLayerProvider>
      <ConsentGate category="statistics">{children}</ConsentGate>
    </ConsentLayerProvider>
  );
}

Use it in any route:

// app/routes/_index.tsx
import { ConsentArea } from "../components/ConsentArea";
import { Analytics } from "../components/Analytics";

export default function Index() {
  return (
    <main>
      <h1>My site</h1>
      <ConsentArea>
        <Analytics />
      </ConsentArea>
    </main>
  );
}
import { useConsent } from "@consentlayer/sdk/react";

export function CookieLink() {
  const { showPreferences } = useConsent();
  return <button onClick={showPreferences}>Manage cookies</button>;
}

Or use the class hook anywhere (no JS, no hooks):

<a href="#" className="consentlayer-open-preferences">Manage cookies</a>

5. Verify it works

npm run dev
  1. Banner appears on first load
  2. Accept all → banner disappears, cl_consent cookie set
  3. Reload → no banner, gated component still renders
  4. Manage cookies link → preferences modal opens
  5. Toggle a category off + save → gated component re-renders the fallback