---
title: Scripts
description: Load vendor scripts by consent category in a React app with
  ConsentProvider, and clear stored data or reload the page when a visitor
  withdraws consent.
group: frameworks
lastModified: "2026-10-10T16:01:45+01:00"
---
## Register vendor scripts

Pass vendor loaders to `ConsentProvider` through `options.scripts`. The
provider loads each script when its category is allowed and removes it when
the category is denied. The [quickstart](/docs/frameworks/react/quickstart)
registers PostHog this way in `src/consent.tsx`:

```tsx title="src/consent.tsx"
import { posthog } from '@c15t/integrations/posthog';
import {
	ConsentBanner,
	ConsentDialog,
	ConsentDialogLink,
	ConsentProvider,
	manifest,
} from 'c15t/react';
import type { ReactNode } from 'react';

const options = {
	// The policy the build downloaded from VITE_C15T_BACKEND_URL.
	mode: manifest(),
	scripts: [
		posthog({
			id: 'phc_your_project_key',
			initOptions: { cookieless_mode: 'never' },
			loadMode: 'after-consent',
		}),
	],
};

export const Consent = ({ children }: { children: ReactNode }) => (
	<ConsentProvider options={options}>
		{children}
		<ConsentBanner />
		<ConsentDialog />
		<footer>
			<ConsentDialogLink>Privacy settings</ConsentDialogLink>
		</footer>
	</ConsentProvider>
);
```

Each helper from `@c15t/integrations` sets its own category and a stable `id`.
Remove every other loader for the same vendor, such as a `<script>` tag in
`index.html` or an SDK you initialize at module level, so the vendor loads
once and only through c15t. [Integrations](/docs/integrations/overview) lists
every helper, and [building integrations](/docs/integrations/building-integrations)
covers a vendor without one.

## What happens when consent changes

* **Allowed.** The script loads, or its SDK is started, the first time its
  category is allowed.
* **Denied later.** The provider removes the script element. Code that already
  ran keeps running, so after the visitor turns off a category they had
  allowed, the provider reloads the page once the save finishes. Set
  `reloadOnConsentRevoked: false` only if every gated vendor stops itself.
* **`alwaysLoad` helpers.** Some integrations, such as the Google Consent Mode
  helpers by default, load before consent and pass the visitor's choice to the
  vendor. Read the vendor's guide; a category on a script does not always mean
  zero requests.

## When the script loader downloads

The script loader is a separate chunk, downloaded only when `scripts` is not
empty. `ConsentProvider` loads it when it mounts. The Next.js and TanStack
Start `ConsentRoot` start the download earlier, during their first render,
when the visitor's consent already lets a script run.

## Embeds and other requests

Scripts cover vendor code c15t loads for you. For the rest:

* [Embeds](/docs/frameworks/react/embeds) keeps iframes out of the page with
  `ConsentGate` or the iframe blocker.
* [Network blocker](/docs/frameworks/react/network-blocker) holds `fetch` and
  XHR calls that match a rule until their category is allowed.

## Clear stored data after revocation

Removing a script does not delete the cookies or storage entries it wrote. Add
`clearOnRevocation` to the provider options to delete the entries you list for
each category when it is denied. The option is read once, when the provider
mounts. [Clear on revocation](/docs/frameworks/react/clear-on-revocation) covers
configuration and browser limits.

## Let visitors turn off one vendor

A visitor can allow marketing and still switch off one vendor in it. Pass
`vendors` to the provider options. Helpers from `@c15t/integrations` already carry
their vendor slug. See [vendor consent](/docs/frameworks/react/vendor-consent).

To send your own events only to allowed integrations, see
[send events only to allowed integrations](/docs/integrations/overview#send-events-only-to-allowed-integrations).

## Check the scripts

Open DevTools Network in a private window, filter by each vendor's domain and
reload.

1. Before a choice under an opt-in policy, no vendor script loads.
2. Allow one category. Only that category's vendors load.
3. Turn the category off. The page reloads and the vendor stays absent.
4. Reload again. The rejection holds.

[Verify consent](/docs/guides/verify-consent) has the full checklist.
