jump to content

React Integration

Integrate the the platform cookie banner into React or Next.js, including a useConsent hook, TypeScript declarations, and App Router or Pages Router setup.

View as Markdown

This guide shows how to integrate the the platform cookie banner into a React application, build a useConsent hook for consent-aware rendering, and handle Next.js-specific requirements.

npm install @probo/cookie-banner

The themed banner is a Web Component. Register it once and place the custom element in your layout.

  1. Create a CookieBanner component

    // src/components/CookieBanner.tsx
    import { useEffect } from "react";
    import { registerCookieBanner } from "@probo/cookie-banner";
    
    let registered = false;
    
    export function CookieBanner() {
      useEffect(() => {
        if (!registered) {
          registerCookieBanner();
          registered = true;
        }
      }, []);
    
      return (
        <probo-cookie-banner
          banner-id="YOUR_BANNER_ID"
          base-url="https://your-probo-instance.com/api/cookie-banner/v1/"
          position="bottom-left"
        />
      );
    }
    
  2. Add it to your layout with a settings link

    Render <CookieBanner /> once at the root of your application, and place <probo-settings-link> in your header or footer so visitors can reopen preferences:

    // src/App.tsx
    import { CookieBanner } from "./components/CookieBanner";
    
    export default function App() {
      return (
        <>
          {/* your app */}
          <CookieBanner />
          <footer>
            <probo-settings-link>Cookie settings</probo-settings-link>
          </footer>
        </>
      );
    }
    

The banner handles everything from there — it fetches the configuration, shows the consent dialog when needed, and records consent. Under CCPA the dialog starts closed; the settings link shows “Your Privacy Choices” with the official opt-out icon and opens the Privacy Choices panel.

If TypeScript complains about the <probo-cookie-banner> JSX element, add a type declaration:

// src/probo.d.ts
declare namespace JSX {
  interface IntrinsicElements {
    "probo-cookie-banner": React.DetailedHTMLProps<
      React.HTMLAttributes<HTMLElement> & {
        "banner-id": string;
        "base-url": string;
        position?:
          | "bottom-left"
          | "bottom-right"
          | "bottom-center"
          | "top-left"
          | "top-right"
          | "top-center";
        lang?: string;
      },
      HTMLElement
    >;
    "probo-settings-link": React.DetailedHTMLProps<
      React.HTMLAttributes<HTMLElement>,
      HTMLElement
    >;
    "probo-acknowledge-button": React.DetailedHTMLProps<
      React.HTMLAttributes<HTMLElement>,
      HTMLElement
    >;
    "probo-privacy-choices": React.DetailedHTMLProps<
      React.HTMLAttributes<HTMLElement>,
      HTMLElement
    >;
  }
}

Use the Consent Manager API to build a React hook that gives components reactive access to consent state.

// src/hooks/useConsent.ts
import { useSyncExternalStore } from "react";
import { getConsent } from "@probo/cookie-banner/consent";

const consent = getConsent();

function subscribe(onStoreChange: () => void): () => void {
  return consent.subscribe(onStoreChange);
}

function getSnapshot(): Record<string, boolean> {
  return consent.getAll();
}

function getServerSnapshot(): Record<string, boolean> {
  return {};
}

export function useConsent(): Record<string, boolean> {
  return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
}

This hook re-renders the component whenever consent state changes — on initial resolution and after the visitor updates their preferences.

import { useConsent } from "../hooks/useConsent";

export function AnalyticsLoader() {
  const consent = useConsent();

  if (!consent.analytics) {
    return null;
  }

  return <ThirdPartyAnalytics />;
}
import { useConsent } from "../hooks/useConsent";

export function ChatWidget() {
  const consent = useConsent();

  if (!consent.functional) {
    return <p>Enable functional cookies to use live chat.</p>;
  }

  return <LiveChat />;
}

For code that runs outside of React’s render cycle — event handlers, side effects, or non-React modules — use getConsent() directly instead of the hook:

import { getConsent } from "@probo/cookie-banner/consent";

export function trackEvent(name: string) {
  if (getConsent().has("analytics")) {
    analytics.track(name);
  }
}

See the Consent Manager API reference for the full API.

The cookie banner SDK accesses document, window, and localStorage, so it must run on the client. In the Next.js App Router, mark the component with "use client":

// src/components/CookieBanner.tsx
"use client";

import { useEffect } from "react";
import { registerCookieBanner } from "@probo/cookie-banner";

let registered = false;

export function CookieBanner() {
  useEffect(() => {
    if (!registered) {
      registerCookieBanner();
      registered = true;
    }
  }, []);

  return (
    <probo-cookie-banner
      banner-id="YOUR_BANNER_ID"
      base-url="https://your-probo-instance.com/api/cookie-banner/v1/"
      position="bottom-left"
    />
  );
}

Then render it in your root layout:

// src/app/layout.tsx
import { CookieBanner } from "../components/CookieBanner";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <CookieBanner />
      </body>
    </html>
  );
}

The useConsent hook works in any client component. Mark hooks that use it with "use client" or consume them from client components:

// src/components/AnalyticsLoader.tsx
"use client";

import { useConsent } from "../hooks/useConsent";

export function AnalyticsLoader() {
  const consent = useConsent();

  if (!consent.analytics) {
    return null;
  }

  return <ThirdPartyAnalytics />;
}

In the Pages Router, the banner component works without "use client". Render it in _app.tsx:

// pages/_app.tsx
import type { AppProps } from "next/app";
import { CookieBanner } from "../components/CookieBanner";

export default function App({ Component, pageProps }: AppProps) {
  return (
    <>
      <Component {...pageProps} />
      <CookieBanner />
    </>
  );
}

For complete control over the consent UI in React, use the headless components. Register them once and compose the Web Component building blocks in your JSX:

"use client";

import { useEffect } from "react";
import { registerHeadlessComponents } from "@probo/cookie-banner/headless";

let registered = false;

export function CustomConsentBanner() {
  useEffect(() => {
    if (!registered) {
      registerHeadlessComponents();
      registered = true;
    }
  }, []);

  return (
    <>
      <probo-cookie-banner-root
        banner-id="YOUR_BANNER_ID"
        base-url="https://your-probo-instance.com/api/cookie-banner/v1/"
      >
        <probo-banner>
          <div className="my-banner">
            <p>We use cookies to improve your experience.</p>
            <probo-accept-button>
              <button>Accept all</button>
            </probo-accept-button>
            <probo-reject-button>
              <button>Reject all</button>
            </probo-reject-button>
            <probo-customize-button>
              <button>Customize</button>
            </probo-customize-button>
            <probo-acknowledge-button>
              <button>Got it</button>
            </probo-acknowledge-button>
          </div>
        </probo-banner>

        <probo-preference-panel>
          <div className="my-preferences">
            <probo-category-list>
              <template>
                <div className="category">
                  <span data-slot="name"></span>
                  <span data-slot="description"></span>
                  <probo-category-toggle>
                    <input type="checkbox" />
                  </probo-category-toggle>
                </div>
              </template>
            </probo-category-list>
            <probo-save-button>
              <button>Save preferences</button>
            </probo-save-button>
          </div>
        </probo-preference-panel>

        <probo-privacy-choices>
          <div className="my-privacy-choices">
            <probo-reject-button>
              <button>Do Not Sell or Share My Personal Information</button>
            </probo-reject-button>
          </div>
        </probo-privacy-choices>
      </probo-cookie-banner-root>

      <probo-settings-link>Cookie settings</probo-settings-link>
    </>
  );
}

Use resolveLayout / resolveBannerText from @probo/cookie-banner/headless to show the right controls for OPT_IN, OPT_OUT, or NOTICE. See the JavaScript SDK docs for the full component reference and Layout API.

Place <probo-settings-link> in your header or footer. It is required for all embeds — there is no floating settings button.

export function Footer() {
  return (
    <footer>
      <probo-settings-link>Cookie settings</probo-settings-link>
    </footer>
  );
}

Put your default label as children (shown for non-CCPA visitors). Under CCPA the SDK always replaces the content with the statutory “Your Privacy Choices” label and official opt-out icon, and opens the Privacy Choices panel. Style the host for font size and color:

probo-settings-link {
  font-size: 14px;
  color: #334155;
  text-decoration: underline;
}

See Settings link for full behavior by regulation.

Ultima actualizare: