Cookie consent banner
A site-styled banner that asks for consent before Statlark’s analytics cookie is set — and holds the tracker until the visitor accepts. Paste a variant, load the controller, and it handles the rest: it shows the banner only where consent is required, remembers the choice, and injects the tracker only on Accept.
You need this when you run Statlark in its default cookie modefor visitors in the EU / UK, where an analytics cookie needs prior consent. If you’d rather skip the banner entirely, run cookieless mode instead — it sets no cookies and needs no consent (at the cost of some cross-session attribution). This page is for keeping full cookie-mode analytics and being compliant.
It’s your banner (your site is the data controller); Statlark just styles it and wires the behavior. Not legal advice — confirm it fits your situation with your own counsel.
Install
Two paste steps. If you already have the plain tracker snippet on this site, the consent controller replaces it (it loads the tracker for you, after consent).
1. Paste one banner variant just before </body>, and replace the placeholder href="/privacy" with your real cookie/privacy policy URL:
<!-- Statlark consent · bar — full-width strip anchored to the bottom of the viewport. Paste before </body>.
Markup + one scoped <style>; no JS, no requests. Statlark's consent controller binds the [data-slk-consent]
hooks, shows/hides via the [hidden] attribute, and owns persistence + geo. Dark theme: add slk-consent--dark.
Restyle via --slk-consent-* custom properties (README.md). -->
<div class="slk-consent slk-consent--bar" role="region" aria-label="Cookie consent">
<div class="slk-consent__inner">
<div class="slk-consent__msg">
<p class="slk-consent__text">We use cookies to measure traffic and see which marketing earns revenue. None are set until you choose. <a class="slk-consent__link" href="/privacy">Cookie policy</a></p><!-- ← replace href with your cookie/privacy policy URL -->
<details class="slk-consent__details">
<summary>Details</summary>
<p>One first-party analytics cookie (from Statlark) remembers your visit and links payments to the marketing source that brought you here. No advertising, no cross-site tracking. You can change your choice anytime under “Cookie settings”.</p>
</details>
</div>
<div class="slk-consent__actions">
<button type="button" data-slk-consent="reject">Reject</button>
<button type="button" data-slk-consent="accept">Accept</button>
</div>
</div>
<!-- Optional attribution, off by default — uncomment to credit Statlark (place inside .slk-consent__msg to keep it under the message):
<a class="slk-consent__statlark" href="https://statlark.com"><svg viewBox="0 0 22 22" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M3 14 L11 7 L9 13 Z"/><path fill-rule="evenodd" d="M13 5a6 6 0 1 0 0 12 6 6 0 1 0 0-12Zm1.5 3.2a1 1 0 1 0 0 2 1 1 0 1 0 0-2Z"/><path d="M11 6 Q13 4 15 6 L13 8 Z"/><path d="M18.5 9.5 L21 10.2 L18.6 11 Z"/></svg><span>Analytics by <b>Statlark</b></span></a>
-->
</div>
<style>
.slk-consent.slk-consent--bar{position:fixed;left:0;right:0;bottom:0;z-index:var(--slk-consent-z,2147483000);box-sizing:border-box;background:var(--slk-consent-bg,#fff);color:var(--slk-consent-fg,#232046);border-top:1px solid var(--slk-consent-border,#d7dee5);box-shadow:var(--slk-consent-shadow,0 -4px 16px rgba(35,32,70,.06));font:inherit;font-family:var(--slk-consent-font,inherit);font-size:var(--slk-consent-size,14px);line-height:1.5;padding:14px max(20px,env(safe-area-inset-right)) max(14px,env(safe-area-inset-bottom)) max(20px,env(safe-area-inset-left));animation:slk-consent-in .2s cubic-bezier(.22,1,.36,1)}
.slk-consent.slk-consent--bar[hidden]{display:none}
.slk-consent--bar *{box-sizing:border-box}
.slk-consent--bar .slk-consent__inner{max-width:1120px;margin:0 auto;display:flex;align-items:center;gap:16px 28px;flex-wrap:wrap}
.slk-consent--bar .slk-consent__msg{flex:1 1 400px;min-width:240px}
.slk-consent--bar p{margin:0;text-wrap:pretty}
.slk-consent--bar .slk-consent__link{color:var(--slk-consent-accent,var(--slk-consent-brand,#c24417));text-decoration:underline;text-underline-offset:2px}
.slk-consent--bar .slk-consent__link:hover{text-decoration-thickness:2px}
.slk-consent--bar .slk-consent__details summary{cursor:pointer;list-style:none;display:inline-flex;align-items:center;margin-top:4px;color:var(--slk-consent-muted,#5b6b8a);font-size:.93em;font-weight:600}
.slk-consent--bar .slk-consent__details summary::-webkit-details-marker{display:none}
.slk-consent--bar .slk-consent__details summary::before{content:"";width:.4em;height:.4em;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(-45deg);margin-right:.55em;transition:transform 160ms cubic-bezier(.22,1,.36,1)}
.slk-consent--bar .slk-consent__details[open] summary::before{transform:rotate(45deg) translate(-1px,-1px)}
.slk-consent--bar .slk-consent__details p{color:var(--slk-consent-muted,#5b6b8a);font-size:.93em;margin:.45em 0 0;max-width:70ch}
.slk-consent--bar .slk-consent__actions{display:flex;gap:10px;margin-left:auto;flex:none}
.slk-consent--bar .slk-consent__actions button{font:inherit;font-family:var(--slk-consent-font,inherit);font-size:1em;font-weight:600;line-height:1;min-height:44px;padding:.6em 1.5em;background:var(--slk-consent-btn-bg,var(--slk-consent-brand,#232046));color:var(--slk-consent-btn-fg,#fff);border:0;border-radius:var(--slk-consent-btn-radius,10px);cursor:pointer;transition:background 160ms cubic-bezier(.22,1,.36,1),transform 120ms cubic-bezier(.22,1,.36,1)}
.slk-consent--bar .slk-consent__actions button:hover{background:var(--slk-consent-btn-hover,var(--slk-consent-brand,#322f52))}
.slk-consent--bar .slk-consent__actions button:active{transform:translateY(.5px)}
.slk-consent--bar :is(button,summary,a):focus-visible{outline:2px solid var(--slk-consent-accent,var(--slk-consent-brand,#e55a2b));outline-offset:2px}
.slk-consent--bar .slk-consent__statlark{display:inline-flex;align-items:center;gap:.45em;margin-top:10px;font-size:.8em;color:var(--slk-consent-muted,#5b6b8a);text-decoration:none}
.slk-consent--bar .slk-consent__statlark:hover{text-decoration:underline}
.slk-consent--bar .slk-consent__statlark svg{width:1.3em;height:1.3em;flex:none}
.slk-consent--bar .slk-consent__statlark b{font-weight:700}
.slk-consent.slk-consent--dark{--slk-consent-bg:#232046;--slk-consent-fg:#fbf7f0;--slk-consent-muted:#9c9ab8;--slk-consent-border:#322f52;--slk-consent-accent:var(--slk-consent-brand,#ee6b3d);--slk-consent-btn-bg:var(--slk-consent-brand,#edf1f5);--slk-consent-btn-fg:#232046;--slk-consent-btn-hover:#fff;--slk-consent-shadow:0 -4px 16px rgba(0,0,0,.35)}
@keyframes slk-consent-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@media (max-width:600px){.slk-consent--bar .slk-consent__actions{width:100%;margin-left:0}.slk-consent--bar .slk-consent__actions button{flex:1 1 0}}
@media (prefers-reduced-motion:reduce){.slk-consent.slk-consent--bar{animation:none}.slk-consent--bar *{transition-duration:0s!important}}
@media print{.slk-consent.slk-consent--bar{display:none}}
</style>2. Load the controller with your site id. Use data-policy="eu" to show the banner only to EU/UK visitors (elsewhere the tracker just runs), or data-policy="all" to ask everyone:
<!-- 2) Load the consent controller INSTEAD of the tracker. It injects
script.js only after the visitor accepts — nothing before. -->
<script defer src="https://statlark.com/consent.js"
data-website-id="sl_xxxx" data-policy="eu"></script>That’s it. No cookie is set and no tracking happens until the visitor accepts. (With data-policy="eu" the controller makes one cookielessrequest to Statlark’s edge to check the visitor’s region — it stores nothing on the device and sets no cookie.) The choice is remembered in localStorage (strictly-necessary storage, itself exempt from consent), and a Cookie settings control lets them change it later.
Choose a variant
Same behavior in all of them — pick the shape that fits your site. Dark theme is the same markup plus slk-consent--dark on the root.
Corner
A compact floating card, bottom-left by default (add slk-consent--right for bottom-right). Quieter than the bar.
<!-- Statlark consent · corner — compact floating card, bottom-left by default. Paste before </body>.
Add slk-consent--right for bottom-right, slk-consent--dark for dark. Markup + one scoped <style>; no JS,
no requests. Statlark's controller binds the [data-slk-consent] hooks and toggles [hidden].
Restyle via --slk-consent-* custom properties (README.md). -->
<div class="slk-consent slk-consent--corner" role="region" aria-label="Cookie consent">
<p class="slk-consent__text">We use cookies to measure traffic and see which marketing earns revenue. None are set until you choose. <a class="slk-consent__link" href="/privacy">Cookie policy</a></p><!-- ← replace href with your cookie/privacy policy URL -->
<details class="slk-consent__details">
<summary>Details</summary>
<p>One first-party analytics cookie (from Statlark) remembers your visit and links payments to the marketing source that brought you here. No advertising, no cross-site tracking. You can change your choice anytime under “Cookie settings”.</p>
</details>
<div class="slk-consent__actions">
<button type="button" data-slk-consent="reject">Reject</button>
<button type="button" data-slk-consent="accept">Accept</button>
</div>
<!-- Optional attribution, off by default — uncomment to credit Statlark:
<a class="slk-consent__statlark" href="https://statlark.com"><svg viewBox="0 0 22 22" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M3 14 L11 7 L9 13 Z"/><path fill-rule="evenodd" d="M13 5a6 6 0 1 0 0 12 6 6 0 1 0 0-12Zm1.5 3.2a1 1 0 1 0 0 2 1 1 0 1 0 0-2Z"/><path d="M11 6 Q13 4 15 6 L13 8 Z"/><path d="M18.5 9.5 L21 10.2 L18.6 11 Z"/></svg><span>Analytics by <b>Statlark</b></span></a>
-->
</div>
<style>
.slk-consent.slk-consent--corner{position:fixed;left:16px;bottom:max(16px,env(safe-area-inset-bottom));z-index:var(--slk-consent-z,2147483000);box-sizing:border-box;width:min(360px,calc(100vw - 32px));background:var(--slk-consent-bg,#fff);color:var(--slk-consent-fg,#232046);border:1px solid var(--slk-consent-border,#d7dee5);border-radius:var(--slk-consent-radius,12px);box-shadow:var(--slk-consent-shadow,0 12px 32px rgba(35,32,70,.14),0 2px 8px rgba(35,32,70,.06));font:inherit;font-family:var(--slk-consent-font,inherit);font-size:var(--slk-consent-size,14px);line-height:1.5;padding:18px;animation:slk-consent-in .2s cubic-bezier(.22,1,.36,1)}
.slk-consent.slk-consent--corner[hidden]{display:none}
.slk-consent--corner *{box-sizing:border-box}
.slk-consent--corner.slk-consent--right{left:auto;right:16px}
.slk-consent--corner p{margin:0;text-wrap:pretty}
.slk-consent--corner .slk-consent__link{color:var(--slk-consent-accent,var(--slk-consent-brand,#c24417));text-decoration:underline;text-underline-offset:2px}
.slk-consent--corner .slk-consent__link:hover{text-decoration-thickness:2px}
.slk-consent--corner .slk-consent__details summary{cursor:pointer;list-style:none;display:inline-flex;align-items:center;margin-top:6px;color:var(--slk-consent-muted,#5b6b8a);font-size:.93em;font-weight:600}
.slk-consent--corner .slk-consent__details summary::-webkit-details-marker{display:none}
.slk-consent--corner .slk-consent__details summary::before{content:"";width:.4em;height:.4em;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(-45deg);margin-right:.55em;transition:transform 160ms cubic-bezier(.22,1,.36,1)}
.slk-consent--corner .slk-consent__details[open] summary::before{transform:rotate(45deg) translate(-1px,-1px)}
.slk-consent--corner .slk-consent__details p{color:var(--slk-consent-muted,#5b6b8a);font-size:.93em;margin:.45em 0 0}
.slk-consent--corner .slk-consent__actions{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:14px}
.slk-consent--corner .slk-consent__actions button{font:inherit;font-family:var(--slk-consent-font,inherit);font-size:1em;font-weight:600;line-height:1;min-height:44px;padding:.6em 1em;background:var(--slk-consent-btn-bg,var(--slk-consent-brand,#232046));color:var(--slk-consent-btn-fg,#fff);border:0;border-radius:var(--slk-consent-btn-radius,10px);cursor:pointer;transition:background 160ms cubic-bezier(.22,1,.36,1),transform 120ms cubic-bezier(.22,1,.36,1)}
.slk-consent--corner .slk-consent__actions button:hover{background:var(--slk-consent-btn-hover,var(--slk-consent-brand,#322f52))}
.slk-consent--corner .slk-consent__actions button:active{transform:translateY(.5px)}
.slk-consent--corner :is(button,summary,a):focus-visible{outline:2px solid var(--slk-consent-accent,var(--slk-consent-brand,#e55a2b));outline-offset:2px}
.slk-consent--corner .slk-consent__statlark{display:inline-flex;align-items:center;gap:.45em;margin-top:12px;font-size:.8em;color:var(--slk-consent-muted,#5b6b8a);text-decoration:none}
.slk-consent--corner .slk-consent__statlark:hover{text-decoration:underline}
.slk-consent--corner .slk-consent__statlark svg{width:1.3em;height:1.3em;flex:none}
.slk-consent--corner .slk-consent__statlark b{font-weight:700}
.slk-consent.slk-consent--dark{--slk-consent-bg:#232046;--slk-consent-fg:#fbf7f0;--slk-consent-muted:#9c9ab8;--slk-consent-border:#322f52;--slk-consent-accent:var(--slk-consent-brand,#ee6b3d);--slk-consent-btn-bg:var(--slk-consent-brand,#edf1f5);--slk-consent-btn-fg:#232046;--slk-consent-btn-hover:#fff;--slk-consent-shadow:0 12px 32px rgba(0,0,0,.5),0 2px 8px rgba(0,0,0,.3)}
@keyframes slk-consent-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.slk-consent.slk-consent--corner{animation:none}.slk-consent--corner *{transition-duration:0s!important}}
@media print{.slk-consent.slk-consent--corner{display:none}}
</style>Modal
A centered dialog over a scrim for a deliberate choice; becomes a bottom sheet on mobile. The controller adds the focus trap, Esc-to-close, and focus return.
<!-- Statlark consent · modal — centered dialog over a scrim; bottom sheet on small screens. Paste before </body>.
Markup + one scoped <style>; no JS, no requests. Statlark's controller binds the [data-slk-consent] hooks,
toggles [hidden], and owns the dialog behavior: focus trap, initial focus on .slk-consent__card, Esc = close
without a choice, focus returned to the trigger. Dark theme: add slk-consent--dark to the ROOT.
Restyle via --slk-consent-* custom properties (README.md). -->
<div class="slk-consent slk-consent--modal">
<div class="slk-consent__card" role="dialog" aria-modal="true" aria-labelledby="slk-consent-title" aria-describedby="slk-consent-desc" tabindex="-1">
<h2 class="slk-consent__title" id="slk-consent-title">Cookies on this site</h2>
<p class="slk-consent__text" id="slk-consent-desc">We use cookies to measure traffic and see which marketing earns revenue. None are set until you choose. <a class="slk-consent__link" href="/privacy">Cookie policy</a></p><!-- ← replace href with your cookie/privacy policy URL -->
<details class="slk-consent__details">
<summary>Details</summary>
<p>One first-party analytics cookie (from Statlark) remembers your visit and links payments to the marketing source that brought you here. No advertising, no cross-site tracking. You can change your choice anytime under “Cookie settings”.</p>
</details>
<div class="slk-consent__actions">
<button type="button" data-slk-consent="reject">Reject</button>
<button type="button" data-slk-consent="accept">Accept</button>
</div>
<!-- Optional attribution, off by default — uncomment to credit Statlark:
<a class="slk-consent__statlark" href="https://statlark.com"><svg viewBox="0 0 22 22" width="14" height="14" fill="currentColor" aria-hidden="true"><path d="M3 14 L11 7 L9 13 Z"/><path fill-rule="evenodd" d="M13 5a6 6 0 1 0 0 12 6 6 0 1 0 0-12Zm1.5 3.2a1 1 0 1 0 0 2 1 1 0 1 0 0-2Z"/><path d="M11 6 Q13 4 15 6 L13 8 Z"/><path d="M18.5 9.5 L21 10.2 L18.6 11 Z"/></svg><span>Analytics by <b>Statlark</b></span></a>
-->
</div>
</div>
<style>
.slk-consent.slk-consent--modal{position:fixed;inset:0;z-index:var(--slk-consent-z,2147483000);box-sizing:border-box;display:flex;align-items:center;justify-content:center;padding:24px;background:var(--slk-consent-scrim,rgba(20,18,31,.4));font:inherit;font-family:var(--slk-consent-font,inherit);font-size:var(--slk-consent-size,14px);line-height:1.5;animation:slk-consent-fade .2s cubic-bezier(.22,1,.36,1)}
.slk-consent.slk-consent--modal[hidden]{display:none}
.slk-consent--modal *{box-sizing:border-box}
.slk-consent--modal .slk-consent__card{width:100%;max-width:440px;background:var(--slk-consent-bg,#fff);color:var(--slk-consent-fg,#232046);border:1px solid var(--slk-consent-border,#d7dee5);border-radius:var(--slk-consent-radius,16px);box-shadow:var(--slk-consent-shadow,0 12px 32px rgba(35,32,70,.18),0 2px 8px rgba(35,32,70,.08));padding:24px;animation:slk-consent-rise .2s cubic-bezier(.22,1,.36,1);outline:none}
.slk-consent--modal .slk-consent__title{margin:0 0 6px;font-size:1.3em;font-weight:700;letter-spacing:-.01em}
.slk-consent--modal p{margin:0;text-wrap:pretty}
.slk-consent--modal .slk-consent__link{color:var(--slk-consent-accent,var(--slk-consent-brand,#c24417));text-decoration:underline;text-underline-offset:2px}
.slk-consent--modal .slk-consent__link:hover{text-decoration-thickness:2px}
.slk-consent--modal .slk-consent__details summary{cursor:pointer;list-style:none;display:inline-flex;align-items:center;margin-top:8px;color:var(--slk-consent-muted,#5b6b8a);font-size:.93em;font-weight:600}
.slk-consent--modal .slk-consent__details summary::-webkit-details-marker{display:none}
.slk-consent--modal .slk-consent__details summary::before{content:"";width:.4em;height:.4em;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(-45deg);margin-right:.55em;transition:transform 160ms cubic-bezier(.22,1,.36,1)}
.slk-consent--modal .slk-consent__details[open] summary::before{transform:rotate(45deg) translate(-1px,-1px)}
.slk-consent--modal .slk-consent__details p{color:var(--slk-consent-muted,#5b6b8a);font-size:.93em;margin:.45em 0 0}
.slk-consent--modal .slk-consent__actions{display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-top:18px}
.slk-consent--modal .slk-consent__actions button{font:inherit;font-family:var(--slk-consent-font,inherit);font-size:1em;font-weight:600;line-height:1;min-height:44px;padding:.6em 1em;background:var(--slk-consent-btn-bg,var(--slk-consent-brand,#232046));color:var(--slk-consent-btn-fg,#fff);border:0;border-radius:var(--slk-consent-btn-radius,10px);cursor:pointer;transition:background 160ms cubic-bezier(.22,1,.36,1),transform 120ms cubic-bezier(.22,1,.36,1)}
.slk-consent--modal .slk-consent__actions button:hover{background:var(--slk-consent-btn-hover,var(--slk-consent-brand,#322f52))}
.slk-consent--modal .slk-consent__actions button:active{transform:translateY(.5px)}
.slk-consent--modal :is(button,summary,a):focus-visible{outline:2px solid var(--slk-consent-accent,var(--slk-consent-brand,#e55a2b));outline-offset:2px}
.slk-consent--modal .slk-consent__statlark{display:inline-flex;align-items:center;gap:.45em;margin-top:14px;font-size:.8em;color:var(--slk-consent-muted,#5b6b8a);text-decoration:none}
.slk-consent--modal .slk-consent__statlark:hover{text-decoration:underline}
.slk-consent--modal .slk-consent__statlark svg{width:1.3em;height:1.3em;flex:none}
.slk-consent--modal .slk-consent__statlark b{font-weight:700}
.slk-consent.slk-consent--dark{--slk-consent-bg:#232046;--slk-consent-fg:#fbf7f0;--slk-consent-muted:#9c9ab8;--slk-consent-border:#322f52;--slk-consent-accent:var(--slk-consent-brand,#ee6b3d);--slk-consent-btn-bg:var(--slk-consent-brand,#edf1f5);--slk-consent-btn-fg:#232046;--slk-consent-btn-hover:#fff;--slk-consent-scrim:rgba(0,0,0,.55);--slk-consent-shadow:0 12px 32px rgba(0,0,0,.5),0 2px 8px rgba(0,0,0,.3)}
@keyframes slk-consent-fade{from{opacity:0}to{opacity:1}}
@keyframes slk-consent-rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@media (max-width:600px){.slk-consent.slk-consent--modal{padding:0;align-items:flex-end}.slk-consent--modal .slk-consent__card{max-width:none;border-radius:16px 16px 0 0;border-left:0;border-right:0;border-bottom:0;padding-bottom:max(22px,env(safe-area-inset-bottom));animation:slk-consent-rise .22s cubic-bezier(.22,1,.36,1)}}
@media (prefers-reduced-motion:reduce){.slk-consent.slk-consent--modal,.slk-consent--modal .slk-consent__card{animation:none}.slk-consent--modal *{transition-duration:0s!important}}
@media print{.slk-consent.slk-consent--modal{display:none}}
</style>Notice (non-EU)
A lighter notice-onlystrip with a single “Got it” — for regions where you inform rather than ask. The tracker runs immediately; the notice just tells people. Never use a modal for a notice.
<!-- Statlark consent · notice — the lighter, notice-only variant for non-EU contexts: one "Got it", no choice
recorded. Non-blocking by design (bar shown here; the same slk-consent--notice modifier works on the corner
card — see README.md). Never use a modal for a notice. Markup + one scoped <style>; no JS, no requests.
Dark theme: add slk-consent--dark. Restyle via --slk-consent-* custom properties (README.md). -->
<div class="slk-consent slk-consent--bar slk-consent--notice" role="region" aria-label="Cookie notice">
<div class="slk-consent__inner">
<p class="slk-consent__text">We use cookies to measure traffic and see which marketing earns revenue. <a class="slk-consent__link" href="/privacy">Cookie policy</a></p><!-- ← replace href with your cookie/privacy policy URL -->
<div class="slk-consent__actions">
<button type="button" data-slk-consent="close">Got it</button>
</div>
</div>
</div>
<style>
.slk-consent.slk-consent--notice{position:fixed;left:0;right:0;bottom:0;z-index:var(--slk-consent-z,2147483000);box-sizing:border-box;background:var(--slk-consent-bg,#fff);color:var(--slk-consent-fg,#232046);border-top:1px solid var(--slk-consent-border,#d7dee5);box-shadow:var(--slk-consent-shadow,0 -4px 16px rgba(35,32,70,.06));font:inherit;font-family:var(--slk-consent-font,inherit);font-size:var(--slk-consent-size,14px);line-height:1.5;padding:10px max(20px,env(safe-area-inset-right)) max(10px,env(safe-area-inset-bottom)) max(20px,env(safe-area-inset-left));animation:slk-consent-in .2s cubic-bezier(.22,1,.36,1)}
.slk-consent.slk-consent--notice[hidden]{display:none}
.slk-consent--notice *{box-sizing:border-box}
.slk-consent--notice .slk-consent__inner{max-width:1120px;margin:0 auto;display:flex;align-items:center;gap:12px 24px;flex-wrap:wrap}
.slk-consent--notice p{margin:0;flex:1 1 320px;min-width:200px;text-wrap:pretty}
.slk-consent--notice .slk-consent__link{color:var(--slk-consent-accent,var(--slk-consent-brand,#c24417));text-decoration:underline;text-underline-offset:2px}
.slk-consent--notice .slk-consent__link:hover{text-decoration-thickness:2px}
.slk-consent--notice .slk-consent__actions{margin-left:auto;flex:none}
.slk-consent--notice .slk-consent__actions button{font:inherit;font-family:var(--slk-consent-font,inherit);font-size:1em;font-weight:600;line-height:1;min-height:44px;padding:.6em 1.5em;background:var(--slk-consent-btn-bg,var(--slk-consent-brand,#232046));color:var(--slk-consent-btn-fg,#fff);border:0;border-radius:var(--slk-consent-btn-radius,10px);cursor:pointer;transition:background 160ms cubic-bezier(.22,1,.36,1),transform 120ms cubic-bezier(.22,1,.36,1)}
.slk-consent--notice .slk-consent__actions button:hover{background:var(--slk-consent-btn-hover,var(--slk-consent-brand,#322f52))}
.slk-consent--notice .slk-consent__actions button:active{transform:translateY(.5px)}
.slk-consent--notice :is(button,a):focus-visible{outline:2px solid var(--slk-consent-accent,var(--slk-consent-brand,#e55a2b));outline-offset:2px}
.slk-consent.slk-consent--dark{--slk-consent-bg:#232046;--slk-consent-fg:#fbf7f0;--slk-consent-muted:#9c9ab8;--slk-consent-border:#322f52;--slk-consent-accent:var(--slk-consent-brand,#ee6b3d);--slk-consent-btn-bg:var(--slk-consent-brand,#edf1f5);--slk-consent-btn-fg:#232046;--slk-consent-btn-hover:#fff;--slk-consent-shadow:0 -4px 16px rgba(0,0,0,.35)}
@keyframes slk-consent-in{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@media (max-width:600px){.slk-consent--notice .slk-consent__actions{width:100%;margin-left:0}.slk-consent--notice .slk-consent__actions button{width:100%}}
@media (prefers-reduced-motion:reduce){.slk-consent.slk-consent--notice{animation:none}.slk-consent--notice *{transition-duration:0s!important}}
@media print{.slk-consent.slk-consent--notice{display:none}}
</style>Cookie settings (re-open)
Lets a visitor change their choice later. Drop the footer-style link next to your Privacy · Terms links; an optional floating pill is commented out in the snippet. It appears once the banner has been shown, so visitors can always reopen it.
<!-- Statlark consent · re-open control — lets a visitor change their cookie choice later.
Default form: a footer-style "Cookie settings" link (a real <button>) that inherits your footer's colour and
font — drop it next to Privacy · Terms. Optional form: a floating corner pill (commented out below), for
sites that want an always-visible control; bottom-LEFT by default so it doesn't collide with chat widgets.
Statlark's controller binds [data-slk-consent="reopen"] and only shows these after a choice exists; it also
exposes window.__slkConsent.open() if you'd rather wire your own trigger. No JS here, no requests. -->
<button type="button" class="slk-consent-reopen" data-slk-consent="reopen">
<svg viewBox="0 0 24 24" width="15" height="15" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 2a10 10 0 1 0 10 10 4 4 0 0 1-5-5 4 4 0 0 1-5-5"/><path d="M8.5 8.5v.01"/><path d="M16 15.5v.01"/><path d="M12 12v.01"/><path d="M11 17v.01"/><path d="M7 14v.01"/></svg>
Cookie settings
</button>
<!-- Floating pill (opt-in; off by default — the footer link above is the primary). Icon-only, so it keeps an
aria-label. Add slk-consent-reopen--right to move it bottom-right, slk-consent-reopen--dark for dark sites.
<button type="button" class="slk-consent-reopen slk-consent-reopen--pill" data-slk-consent="reopen" aria-label="Cookie settings" title="Cookie settings">
<svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 2a10 10 0 1 0 10 10 4 4 0 0 1-5-5 4 4 0 0 1-5-5"/><path d="M8.5 8.5v.01"/><path d="M16 15.5v.01"/><path d="M12 12v.01"/><path d="M11 17v.01"/><path d="M7 14v.01"/></svg>
</button>
-->
<style>
.slk-consent-reopen{display:inline-flex;align-items:center;gap:.45em;padding:0;background:none;border:0;color:inherit;font:inherit;font-family:var(--slk-consent-font,inherit);font-size:var(--slk-consent-size,inherit);line-height:inherit;text-decoration:none;cursor:pointer}
.slk-consent-reopen[hidden]{display:none}
.slk-consent-reopen svg{width:1.1em;height:1.1em;flex:none}
.slk-consent-reopen:hover{text-decoration:underline;text-underline-offset:2px}
.slk-consent-reopen:focus-visible{outline:2px solid var(--slk-consent-accent,var(--slk-consent-brand,#e55a2b));outline-offset:2px}
.slk-consent-reopen.slk-consent-reopen--pill{position:fixed;left:16px;bottom:max(16px,env(safe-area-inset-bottom));z-index:var(--slk-consent-z,2147483000);padding:.62em;background:var(--slk-consent-bg,#fff);color:var(--slk-consent-fg,#232046);border:1px solid var(--slk-consent-border,#d7dee5);border-radius:999px;box-shadow:var(--slk-consent-shadow,0 2px 8px rgba(35,32,70,.10));transition:border-color 160ms cubic-bezier(.22,1,.36,1)}
.slk-consent-reopen--pill svg{display:block;width:1.25em;height:1.25em}
.slk-consent-reopen--pill:hover{text-decoration:none;border-color:var(--slk-consent-fg,#232046)}
.slk-consent-reopen--pill:active{transform:translateY(.5px)}
.slk-consent-reopen.slk-consent-reopen--right{left:auto;right:16px}
.slk-consent-reopen.slk-consent-reopen--dark{--slk-consent-bg:#232046;--slk-consent-fg:#fbf7f0;--slk-consent-border:#322f52;--slk-consent-accent:var(--slk-consent-brand,#ee6b3d);--slk-consent-shadow:0 2px 8px rgba(0,0,0,.4)}
@media (prefers-reduced-motion:reduce){.slk-consent-reopen,.slk-consent-reopen *{transition-duration:0s!important}}
@media print{.slk-consent-reopen.slk-consent-reopen--pill{display:none}}
</style>Configure the controller
Everything is a data-* attribute on the consent.js script tag.
data-website-id— your site id (sl_…). Required; passed to the tracker it injects.data-policy—eu(default: banner only where consent is required; the tracker runs immediately elsewhere) ·all(ask every visitor) ·off(disable gating, for testing).data-on-reject—none(default: no tracking on reject) ·cookieless(fall back to cookieless mode so you still get anonymous, cookie-free analytics from visitors who decline).data-consent-countries— override which countries get the banner (comma-separated ISO codes). Default is the EU-27 + EEA + UK.data-consent-max-age-days— how long a choice is remembered before re-asking. Default365.data-api/data-tracker-src/data-geo— advanced: point at a first-party proxy or pinned tracker version.
Restyle it
It ships on Statlark’s palette and inherits your site’s font. Recolour the whole thing — both buttons, the link, and the focus rings — with one property:
.slk-consent, .slk-consent-reopen { --slk-consent-brand: #123B2A; }Finer control is available via the individual --slk-consent-* properties (see the package README). Keep Accept and Rejectvisually equal — rejecting must be as easy as accepting — and keep the policy link real; those aren’t style choices, they’re the rules that keep the banner valid.
How it stays compliant
- Nothing before consent.The tracker script isn’t even loaded until Accept — no cookie, no network request to Statlark.
- Reject is equal to Accept — same size, weight, and colour, by construction — and a stored choice is honoured until it expires or the visitor changes it.
- Geo is cookieless.To decide where the banner is due, the controller reads a country from Statlark’s edge — it stores nothing on the device and sets no cookie.
- Separately from cookies, disclose Statlark in your privacy policy — GDPR applies to the analytics either way.
Not sure you need a banner at all? Cookieless mode skips it entirely.