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
consentlcookie, and held-back tags are released without a reload. - Re-open the preferences: render
<a href="#consentl">Cookie settings</a>anywhere, or callwindow.Consentl?.open("prefs")from a button. Clicks are handled ondocument, so elements rendered later work too. - Your own analytics or features that need consent:
consentl:changefires 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.htmlitself are requested by the browser before consent; mark them withtype="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).
Related guides
Stuck? Write to [email protected] — we answer in English on business days.