Why SvelteKit Sites Need Cookie Consent

SvelteKit applications routinely set cookies that fall under privacy regulations. If your site uses Google Analytics, the _ga and _ga_* cookies are classified as analytics cookies under the ePrivacy Directive. Add a Meta Pixel and you pick up _fbp. Even session cookies like PHPSESSID or SvelteKit's own session identifiers may need disclosure depending on their purpose.

Article 5(3) of the ePrivacy Directive is clear: storing or accessing information on a user's device requires prior consent, unless the cookie is strictly necessary for the service the user requested. The GDPR reinforces this by defining what valid consent looks like - freely given, specific, informed, and unambiguous.

Failing to collect consent before setting non-essential cookies has real consequences. The CNIL fined several organisations in 2024 and 2025 specifically for dropping tracking cookies before obtaining user agreement. Enforcement bodies across Europe continue to treat cookie violations as low-hanging fruit, with cumulative GDPR fines surpassing five billion euros.

How SvelteKit Handles Cookies Differently

SvelteKit is a full-stack framework that renders pages on the server before sending HTML to the browser. This server-side rendering (SSR) model means your code runs in two environments: the Node.js server and the user's browser.

That dual environment creates a specific problem for cookie consent. Code that checks document.cookie will throw an error during SSR because document does not exist on the server. Wrapping everything in typeof window !== 'undefined' guards can cause hydration mismatches where the server-rendered HTML does not match what the client expects.

SvelteKit provides two proper solutions for this. The onMount lifecycle function runs exclusively in the browser, making it the correct place for client-side consent logic. The browser constant from $app/environment offers a reliable check when you need conditional logic outside of lifecycle hooks.

Server-side cookie access works through hooks.server.ts, where every incoming request passes through a handle function. You can read a visitor's consent cookie here using event.cookies.get() and decide whether to inject analytics scripts into the response.

SvelteKit Cookie Consent Architecture

A compliant cookie consent setup in SvelteKit involves three files working together. Understanding where each piece fits helps you avoid the common mistakes that lead to non-compliance or broken hydration.

FileRoleRuns On
src/app.htmlBase HTML template - insert the consent script tag hereServer (template)
src/hooks.server.tsRead consent cookies on every request, conditionally modify responsesServer
src/routes/+layout.svelteRoot layout - use onMount for client-side consent initialisationServer + Client

Adding the Script to app.html

The simplest method for adding a cookie consent banner to SvelteKit is placing the consent management script directly in src/app.html. This file is the base HTML template that wraps every page. Scripts placed here load before SvelteKit hydrates the page, which means the banner can block other scripts from firing until consent is granted.

Place the script tag inside the <head> section, before %sveltekit.head%. This ensures the consent manager loads early enough to intercept tracking scripts. Kukie.io provides a single script tag for this purpose - see the SvelteKit installation guide for the exact snippet.

Reading Consent in hooks.server.ts

SvelteKit's server hooks give you access to every incoming request. By reading the consent cookie in hooks.server.ts, you can conditionally inject or withhold analytics scripts server-side. This is particularly useful if you use server-side rendering to embed tracking pixels or third-party resources directly in the HTML.

The event.cookies.get() method returns the cookie value if it exists. SvelteKit sets httpOnly and secure to true by default, so if your consent cookie needs to be readable by client-side JavaScript (which most consent solutions require), you must explicitly set httpOnly: false when creating it.

Client-Side Initialisation with onMount

For consent logic that must run in the browser - such as checking localStorage for a returning visitor's preferences or dynamically loading a consent component - use onMount in your root layout file. This lifecycle hook is guaranteed to run only in the browser, never during SSR.

Common Cookies on SvelteKit Sites

Knowing which cookies your SvelteKit application sets is the first step toward proper cookie categorisation. A typical SvelteKit project with analytics and marketing tools will set a mix of strictly necessary, analytics, and marketing cookies.

CookieCategoryPurposeConsent Required
session_idStrictly NecessaryMaintains user sessionNo
csrf_tokenStrictly NecessaryPrevents cross-site request forgeryNo
_gaAnalyticsGoogle Analytics visitor identifierYes
_ga_*AnalyticsGA4 session trackingYes
_fbpMarketingMeta Pixel browser identifierYes
_gcl_auMarketingGoogle Ads conversion linkingYes
pll_languageFunctionalStores language preferenceDepends on jurisdiction

Running a cookie scan against your live SvelteKit site reveals exactly which cookies are active. Third-party scripts often set cookies that developers are unaware of, especially when using packages installed via npm that pull in external resources.

Blocking Scripts Until Consent Is Given

The legal requirement under both the GDPR and ePrivacy Directive is that non-essential cookies must not be set until the user actively consents. Simply showing a banner is not enough - you must actually prevent tracking scripts from executing.

There are two main approaches in SvelteKit. The first is conditional script loading, where you wrap your analytics initialisation inside an onMount callback that first checks whether consent has been granted. The second approach uses a consent management platform that automatically rewrites <script> tags to a neutral type attribute (such as type="text/plain") and only restores them after consent.

If you use Google Tag Manager, configure the trigger to fire only on a consent initialisation event. This way, GTM itself loads but none of its tags execute until the consent signal is received.

Google Consent Mode v2 Integration

Google Consent Mode v2 allows Google tags to adjust their behaviour based on consent state. In a SvelteKit application, you initialise Consent Mode in your app.html with default values set to denied, then update the consent state after the user interacts with your banner. This gives you cookieless modelling for analytics data while remaining compliant.

SvelteKit-Specific Pitfalls to Avoid

Several mistakes are unique to SvelteKit's architecture. Avoiding them saves debugging time and prevents compliance gaps.

Content Security Policy conflicts. SvelteKit supports CSP headers through its configuration. If you enable a strict CSP, external consent scripts may be blocked. You will need to add the consent script's domain to your script-src directive, or use a nonce-based approach.

Hydration mismatches from conditional rendering. If your server renders a page assuming no consent (hiding analytics) but the client finds an existing consent cookie and immediately shows analytics, the HTML will differ. Use onMount to defer consent-dependent UI changes to the client, keeping the server render consistent.

Prerendered pages ignoring consent. SvelteKit can prerender static pages at build time. Prerendered pages cannot read cookies at request time because there is no server handling the request. For prerendered routes, all consent logic must be handled client-side through the banner script in app.html.

SPA navigation not re-triggering consent checks. SvelteKit uses client-side navigation between pages by default. If your consent banner only initialises on full page loads, users who navigate via links may bypass consent checks on subsequent pages. Place the banner script in app.html or the root layout to avoid this.

Compliance Across Jurisdictions

Your SvelteKit site likely serves visitors from multiple countries. The consent requirements differ significantly depending on where your visitors are located.

Under the GDPR, prior opt-in consent is mandatory for all non-essential cookies. The UK GDPR and PECR mirror this requirement. In the United States, the CCPA/CPRA follows an opt-out model - you can set cookies by default but must provide a clear mechanism for users to refuse. Brazil's LGPD, Canada's PIPEDA, and South Africa's POPIA each have their own consent frameworks.

Geo-targeted banners solve this by detecting visitor location and showing the appropriate consent interface. A visitor from Germany sees a GDPR-compliant opt-in banner, while a visitor from California sees a CCPA-style opt-out notice. Kukie.io supports region-based rules that handle this automatically.

Frequently Asked Questions

Does SvelteKit set any cookies by default?

SvelteKit itself does not set cookies unless your application code explicitly creates them. Session cookies, authentication tokens, and CSRF tokens are set by your own server logic, not the framework.

Can I add a cookie banner to a prerendered SvelteKit site?

Yes. Place the consent script in src/app.html so it loads on every page regardless of whether the page was prerendered or server-rendered. All consent logic runs client-side in this setup.

Where should I put the cookie consent script in SvelteKit?

The recommended location is inside the <head> of src/app.html, before the %sveltekit.head% placeholder. This ensures the script loads before any other head content or tracking scripts.

Do I need cookie consent if my SvelteKit app only uses session cookies?

Strictly necessary cookies - those required for the service the user explicitly requested - are exempt from consent under the ePrivacy Directive. If your session cookies serve only authentication or security purposes, consent is not required for those specific cookies.

How do I block Google Analytics in SvelteKit until consent is given?

Either wrap your GA4 initialisation inside an onMount that checks consent state first, or use Google Consent Mode v2 with default values set to denied. A consent management platform can also handle script blocking automatically.

Will a cookie banner slow down my SvelteKit site?

A lightweight consent script adds minimal overhead. Asynchronous loading prevents it from blocking page rendering. Running a Core Web Vitals test before and after installation confirms the actual impact on your site.

Take Control of Your Cookie Compliance

If you are not sure which cookies your SvelteKit site sets, start with a free scan. Kukie.io detects, categorises, and helps you manage every cookie - so your visitors get a clear choice, and you stay on the right side of the law.

Start Free - Scan Your Website