Getting started

ConsentLoop is a consent layer that costs your site nothing: a ~1.5 KB loader on the critical path, the full widget (~12.1 KB gzip, UI + logic + styles) only when a banner actually needs to render. No dependencies, no network calls, no layout shift.

1. Install

npm i consentloop
pnpm add consentloop
npm i consentloop @consentloop/react
<!-- The smart loader: ~1.5 KB, handles returning visitors without downloading the UI -->
<script defer src="https://cdn.jsdelivr.net/npm/consentloop/dist/consentloop.loader.min.js" data-gcm></script>

2. Run it

Declare your categories and start the loop. necessary is added automatically and always granted.

import * as ConsentLoop from "consentloop";

ConsentLoop.run({
  categories: {
    necessary: { required: true },
    analytics: {
      services: { ga4: { label: "Google Analytics 4" } },
      autoClear: [/^_ga/, "_gid"], // cookies wiped if consent is withdrawn
    },
    marketing: {},
  },
  googleConsentMode: true,
});
import { ConsentProvider } from "@consentloop/react";

export default function App() {
  return (
    <ConsentProvider
      config={{
        categories: { analytics: {}, marketing: {} },
        googleConsentMode: true,
      }}
    >
      <YourApp />
    </ConsentProvider>
  );
}
<script>
  window.consentloopConfig = {
    categories: { necessary: { required: true }, analytics: {}, marketing: {} },
    googleConsentMode: true,
  };
</script>
<script defer src="https://cdn.jsdelivr.net/npm/consentloop/dist/consentloop.loader.min.js"></script>

3. Gate your scripts

Anything that sets cookies waits for its category. Change type to text/plain, move src to data-consent-src:

<!-- before -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXX"></script>

<!-- after: runs only once "analytics" is accepted -->
<script type="text/plain" data-consent="analytics" async
        data-consent-src="https://www.googletagmanager.com/gtag/js?id=G-XXXX"></script>

<!-- embeds too: iframes, imgs, pixels -->
<iframe data-consent="marketing" data-consent-src="https://www.youtube.com/embed/xyz"></iframe>

That’s the whole integration. Details and live demo: Script & embed gating →

What you get by default

Next steps