Consentl with React, Vue, Angular and other single-page apps

Put the Consentl loader in index.html, not in a component, for single-page apps built with Vite, Create React App or the Angular CLI.

Loader first in <head>
Yes

In a single-page app, components mount too late for consent: Google Consent Mode defaults and prior blocking must be in place before any other script runs. Put the loader in the HTML entry file as the first element in <head>, synchronous:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <script src="https://api.consentl.com/v1/loader.js?k=SITE_KEY&l=en"></script>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>My app</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>
Tool File
Vite (React, Vue, Svelte, Solid) index.html in the project root
Create React App public/index.html
Angular CLI src/index.html

In your app code

  • Route changes: nothing to do. The runtime stays loaded, the choice is stored in the first-party consentl cookie, and held-back tags are released without a reload.
  • Re-open the preferences: render <a href="#consentl">Cookie settings</a> anywhere, or call window.Consentl?.open("prefs") from a button. Clicks are handled on document, so elements rendered later work too.
  • Your own analytics or features that need consent: consentl:change fires on every page view with the current choices and again on every change, so start things only once:
let started = false;
const maybeStart = (c) => {
  if (c.analytics && !started) {
    started = true;
    startAnalytics();
  }
};
document.addEventListener("consentl:change", (e) => maybeStart(e.detail));
if (window.Consentl) maybeStart(window.Consentl.get());
  • Scripts your app inserts later are held back when they match a known tracker (Business plan) or a blocking rule from the dashboard. On Free and Pro, check consent in your code as above.
  • Tags written in index.html itself are requested by the browser before consent; mark them with type="text/plain" data-consentl="…" (see Any website).

Check that it works

View the page source of the built app: the loader is the first <script> in <head>. Then follow the checks in Any website.

Limitations

  • Do not load the loader from a component or inject it again on navigation.
  • A language change without a full reload keeps the banner in its first language until the next page load.
  • If you send a Content Security Policy, allow https://api.consentl.com (see Any website).

Stuck? Write to [email protected] — we answer in English on business days.