React

Troubleshooting

"Provider not found" Error

Symptom: useConsentManager must be used within a ConsentManagerProvider error.

Fix: Ensure the component calling useConsentManager() (or any c15t hook) is rendered inside a ConsentManagerProvider:

// Wrong — hook is outside the provider
function App() {
  const { consents } = useConsentManager(); // throws
  return <ConsentManagerProvider options={...}>...</ConsentManagerProvider>;
}

// Correct — hook is inside the provider
function App() {
  return (
    <ConsentManagerProvider options={...}>
      <MyComponent /> {/* useConsentManager works here */}
    </ConsentManagerProvider>
  );
}

Possible causes:

  1. Opt-out jurisdiction — In CCPA/opt-out regions, the banner is not shown because tracking is allowed by default. Check model from useConsentManager() — if it's 'opt-out', the banner is intentionally hidden.

  2. Consent already given — If the user has already made a consent choice, the banner won't reappear. Clear cookies or use resetConsents() to test again.

  3. activeUI is 'none' — Something is explicitly setting activeUI to 'none'. Check the DevTools panel for the current consent state.

  4. Backend not responding — In 'c15t' mode, the banner waits for the backend /init response. Check the Network tab for failed requests to your backendURL.

// Debug: check what the consent manager sees
const { activeUI, model, isLoadingConsentInfo } = useConsentManager();
console.log({ activeUI, model, isLoadingConsentInfo });

Symptom: Consent is lost after page reload.

Possible causes:

  1. Incognito/private mode — Some browsers restrict cookie storage in private browsing.

  2. Cookie settings — In 'offline' mode, consent is stored in cookies. Ensure cookies are not being blocked by browser settings or extensions.

  3. Different domains — Cookies are domain-scoped. If your dev server uses a different domain than production, consent won't carry over.

  4. Backend errors — In 'c15t' mode, check that the backend is saving consent successfully. Enable debug: true in provider options to see detailed logs.

Scripts Not Loading

Symptom: Third-party scripts configured in the scripts option don't load after consent is granted.

Checklist:

  1. Wrong category name — The category on the script must match one of the consentCategories names. For example, 'measurement' not 'analytics'.

  2. Consent condition not met — Use has('measurement') to verify the category is actually consented.

  3. Script error — Check the browser DevTools Console for script loading errors. The onError callback can help debug:

{
  id: 'analytics',
  src: 'https://...',
  category: 'measurement',
  onError: ({ error }) => console.error('Script failed:', error),
}
  1. Ad blocker — Browser extensions may block the script regardless of consent. The anonymizeId option (default: true) helps avoid pattern-based blocking.

SSR Hydration Mismatch

Symptom: React hydration warnings, consent banner flashes briefly, or consent state differs between server and client.

Fixes:

  1. Missing ssrData — Ensure you're passing the SSR data Promise to the provider:
<ConsentManagerProvider
  options={{
    mode: 'hosted',
    backendURL: '...',
    ssrData: fetchSSRData({ backendURL: '...', headers }),
  }}
>
  1. Stale cache — If using a CDN or caching layer, ensure the SSR data is fresh per-request and not shared across users.

  2. Debug with useSSRStatus — Check if SSR data was actually consumed:

const { ssrDataUsed, ssrSkippedReason } = useSSRStatus();

See Server-Side Utilities for full SSR setup.

TypeScript Errors

Common import issues:

// Components and hooks — main entry point
import { ConsentManagerProvider, useConsentManager } from '@c15t/react';

// Server utilities — separate entry point
import { fetchSSRData } from '@c15t/react/server';

// Headless (hooks only, no components)
import { useConsentManager } from '@c15t/react/headless';

If you see type errors after updating, try:

rm -rf node_modules/.cache
bun install

Still Stuck?

  • Enable debug: true in provider options for verbose console logging
  • Use the DevTools panel to inspect live consent state
  • Check the GitHub issues for known bugs