How to add a cookie consent banner to a Ghost site
In Ghost, paste the snippet in Settings, then Advanced, then Code injection, in the Site header field, and save; Ghost prints it inside the head of every page. Mark the Google tag or Meta Pixel you add to the same field, and add a Cookie preferences link to the secondary navigation with a small footer script, since Ghost rewrites navigation URLs.Steps
Where to paste the snippet in Ghost
Ghost prints custom code on every page through its ghost_head and ghost_foot helpers, which every theme includes. In Ghost Admin, go to Settings, then Advanced, then Code injection. Paste the snippet at the top of the Site header field and click Save:
html<script src="https://cookiequiet.com/cq.js" data-site="YOUR_SITE_KEY" data-consent-mode="1" data-auto-block="1" defer></script>
Site header code is injected into the head; Site footer code is injected before the closing body tag. The snippet belongs in the header so it runs before any tag you add. Code injection survives theme changes and theme updates, which is why it beats editing the theme's default.hbs.
How to handle the tags you add
Ghost sets no third-party analytics by itself. Its own cookies for signed-in members and for the admin are strictly necessary. The tags that need consent are the ones you paste, and they go in the same fields, below the snippet:
Marked (nothing loads before consent):
html<script type="text/plain" data-cq-category="analytics" src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXXX"></script><script type="text/plain" data-cq-category="analytics">window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}gtag('js', new Date());gtag('config', 'G-XXXXXXX');</script>
The Meta Pixel base code gets data-cq-category="marketing"; remove its noscript image, which would load without JavaScript. Marked tags work in the Site footer field too.
Consent Mode (the Google tag loads with denied defaults): place Google's default consent block as an inline script between the snippet and the Google tag, as in the Google Analytics 4 guide. Cookiequiet pushes the same defaults as soon as it runs and the update after each choice.
Embeds in posts. The editor's embed cards (YouTube, Vimeo, X) print plain iframes, which load at once. For a video that must wait for consent, use an HTML card with the iframe written with data-cq-src instead of src; see YouTube embeds and consent. Comment systems or newsletter widgets added through code injection follow the marking rule.
Portal and members. Ghost's membership features (Portal, sign-in links, the newsletter) are first-party and necessary; list their cookies under Necessary in the cookie table, which the cookie scanner fills in for you.
How to add the Cookie preferences link
Go to Settings, then Navigation, and add an item labelled "Cookie preferences" to the Secondary navigation, which most themes print in the footer, with the URL #cq-preferences. Ghost turns navigation URLs into absolute URLs, so the printed link ends with #cq-preferences rather than being exactly that string; add this handler to the Site footer field so the click opens the preferences centre anyway:
html<script>document.addEventListener('click', function (e) {var a = e.target.closest ? e.target.closest('a') : null;if (a && a.hash === '#cq-preferences' && window.Cookiequiet) {e.preventDefault();window.Cookiequiet.showPreferences();}});</script>
If you maintain your own theme, a plain <a href="#cq-preferences" data-cq-show-preferences> in default.hbs needs no handler. The floating preferences button in the banner settings is the third option.
How to test
- Open the site in a private window and click Reject all.
- Check the cookies in the developer tools:
cq_consentand Ghost's own, no_ga, no_fbp. - Clear the cookies, click Accept all, reload: the marked tags run.
- Click the Cookie preferences link: the preferences centre opens.
- Check the consent log in the dashboard.
What is specific to Ghost
- Ghost(Pro) and self-hosted use the same Code injection settings; nothing depends on the hosting.
- Per-post code injection exists in the post settings; it is printed after the site-wide header code, so a tag added there still sees the snippet first.
- Themes. Changing the theme keeps the code injection. Only the footer handler assumes the theme prints the secondary navigation; if it does not, add the link to the primary navigation or use the floating button.
- Ghost's official Google Analytics integration guide tells you to paste the Google tag in the Site header field; do that below the snippet, marked or with the default consent block.