Consentl with Nuxt
Add the Consentl loader to Nuxt 3 and 4 with app.head and tagPriority 0, so it renders before every other script.
- Loader first in <head>
- Yes
The loader must be the first script in <head> and synchronous. Nuxt's head manager
(Unhead) sorts <head> tags by weight; lower weights render first:
| Tag | Weight |
|---|---|
| charset | −20 |
| viewport | −15 |
| title | 10 |
| async script | 30 |
| sync script | 50 |
| stylesheet | 60 |
| Nuxt module entry | 80 |
tagPriority: 0 places the loader before every other script. "critical" (weight 42) would still
come after async scripts.
nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
script: [
{
src: `https://api.consentl.com/v1/loader.js?k=${process.env.NUXT_PUBLIC_CONSENTL_SITE_KEY}&l=en`,
tagPosition: "head",
tagPriority: 0,
},
],
},
},
});
Language per request (@nuxtjs/i18n)
Use the same options in app.vue:
const { locale } = useI18n();
useHead({
script: [{ src: computed(() => `https://api.consentl.com/v1/loader.js?k=${key}&l=${locale.value}`), tagPosition: "head", tagPriority: 0 }],
});
Changing the language on the client does not reload the banner; the new language applies on the next full page load.
Other tags (app.head or useHead)
Give every tag that must wait for consent type: "text/plain" and its Consentl category. Nuxt
writes it as it is, the browser does not download it, and Consentl runs it once after consent:
script: [
{ src: loader, tagPosition: "head", tagPriority: 0 }, // the Consentl loader, as above
{ src: "https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX", type: "text/plain", "data-consentl": "analytics" },
{
innerHTML: "window.dataLayer=window.dataLayer||[];function gtag(){dataLayer.push(arguments)}gtag('js',new Date());gtag('config','G-XXXXXXX');",
type: "text/plain",
"data-consentl": "analytics",
},
],
A plain { src, async: true } tag is held on the Business plan too, and runs only once even though
Nuxt adds a second copy of it while the page starts, but the browser downloads it before consent.
In our test (Nuxt 4.6, a Google tag): plain async tag, one request before consent and one run
after it; type: "text/plain", no request before consent and one run after it.
Check that it works
View the page source: the loader is the first <script> in <head>. Then follow the checks in
Any website. Client-side navigation needs nothing extra, and
Nuxt's page data (__NUXT_DATA__, window.__NUXT__) is never held back. Tested with Nuxt 4.6.
Consent Mode needs the Pro plan or higher, automatic blocking of known trackers the Business plan.
Tags written in the page HTML (for example through app.head) are requested before consent unless
you mark them as shown in Other tags (see also
Any website).
Limitations
- Do not add the loader a second time from a component or plugin: it must load once per document.
- 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.