The Stack
How to add AdSense to Ghost — including the ads.txt trap
Ghost is a publisher-native platform, so you'd expect ads to be easy. The loader is — but ads.txt, the custom-domain rule, and theme re-uploads trip up almost everyone. Here's the version that actually serves ads and passes verification.
Ghost is built for exactly this — writers who want to publish and get paid. So it’s a little surprising that AdSense on Ghost has three sharp edges the glossy tutorials skip: where ads.txt really goes, the custom-domain rule, and the fact that re-uploading your theme silently deletes your ad files. Get those right and the rest is genuinely easy.
Step 1 — Load AdSense via Code Injection
Ghost gives you a first-class place for head scripts, so you don’t touch theme files for the loader. Go to Settings → Code Injection → Site Header (newer admin: Settings → Advanced → Code Injection) and paste the loader once:
<script async
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-0000000000000000"
crossorigin="anonymous"></script>
Site Header content is output inside <head> on every page, which is exactly where AdSense wants it. This single tag both verifies your site and powers Auto ads if you enable them in the AdSense dashboard.
Ghost(Pro) requirement: you must be on a custom domain. AdSense won’t verify a
*.ghost.iosubdomain, so connect your domain first or verification will fail no matter what you paste.
Step 2 — ads.txt: the trap everyone hits
AdSense throttles fill until it can confirm you own the inventory via ads.txt at your site root. Ghost has no root-file upload and no admin setting for it — and this is where people lose an afternoon.
The file goes in your active theme’s root folder, and Ghost serves it at the site root:
- Self-hosted: place it at
content/themes/your-theme/ads.txt, then restart Ghost. - Ghost(Pro) (no filesystem access): download your theme zip from Settings → Design → Change theme, unzip it, drop
ads.txtinto the theme’s root folder, re-zip, and re-upload.
google.com, pub-0000000000000000, DIRECT, f08c47fec0942fa0
After deploy, confirm it resolves at https://yoursite.com/ads.txt. Two things bite here:
- Theme root ≠ install root. The file lives inside the theme, not next to your Ghost content directory.
- A theme update or switch wipes it. Because it lives in the theme, any time you change or update the theme,
ads.txt(and any template ad edits) disappear — re-add them every time.
One more crawl trap: if your robots.txt blocks Google’s Mediapartners-Google crawler, AdSense reports “ads.txt not found” even when the file is there, because it can’t fetch it. Don’t block that agent.
Step 3 — Place ad units in posts
For manual placements, use the HTML card: in the editor type /html, then paste a complete unit — including the per-unit push() right inside the same card. Wrap it in a reserved-height container so the page doesn’t jump when the ad fills (the single biggest thing you control for CLS):
<div class="ad-slot" style="min-height:280px;display:flex;align-items:center;justify-content:center;">
<ins class="adsbygoogle"
style="display:block"
data-ad-client="ca-pub-0000000000000000"
data-ad-slot="1234567890"
data-ad-format="auto"
data-full-width-responsive="true"></ins>
</div>
<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>
Don’t repeat the loader in the card — it’s already site-wide from Step 1. Match the min-height to the unit you expect (see the reserve table in the placement guide).
For the same placement on every post (e.g. always after the content), the HTML card won’t do it — that needs a theme edit: drop the ad block after the {{content}} helper in post.hbs, then re-zip and re-upload the theme. Which, again, you’ll re-do after every theme change.
Step 4 — Auto ads (the low-effort path)
If you’d rather not hand-place units, Auto ads is the officially recommended Ghost route: the single Step-1 loader lets Google place ads algorithmically once you enable formats under Ads → By site → Auto ads. The tradeoff is control — Auto ads can land awkwardly on some themes and are hard to reserve space for since positions aren’t known in advance, so they trade a little CLS for zero setup. Use AdSense’s per-site controls to exclude bad spots, and prefer manual units where placement matters.
Step 5 — Consent Mode v2 for EEA/UK traffic
If you get any European, UK, or Swiss visitors, Google requires a certified consent management platform (CMP) with IAB TCF v2.2, and the consent signal must load before the ad script. Two options on Ghost:
- Easiest: enable AdSense’s own built-in consent message under Privacy & messaging → GDPR/EU — it’s a certified CMP and needs no extra code.
- Manual: paste your CMP and Consent Mode default above the AdSense loader in the same Site Header field — order within that field matters, consent first.
Skipping this isn’t just a compliance risk; Google will throttle serving to unconsented EEA traffic, so it’s a revenue issue too.
One version note: AMP is gone
Ghost’s built-in AMP was deprecated for years and is fully removed in Ghost 6.0. Don’t build an AdSense strategy around Ghost AMP pages — serve ads on your standard responsive pages. On a lean Ghost theme those pages are already fast, and speed is what makes each impression more viewable and more valuable. That’s the same reason a fast stack pays off twice — once in hosting cost, once in ad revenue. If you’re weighing platforms, here’s the same setup on Astro, where the landmine is Partytown instead of ads.txt.
FAQ
- Can you run Google AdSense on a Ghost blog?
- Yes. You add the AdSense loader script through Ghost's Code Injection (Settings → Code Injection → Site Header), which powers Auto ads site-wide, and drop manual ad units into posts with the HTML card. The one requirement on Ghost(Pro) is that your site must be on a custom domain — the default yoursite.ghost.io subdomain won't verify with AdSense.
- Where does the ads.txt file go on Ghost?
- In your active theme's root folder, not the Ghost install root — that distinction is where most people get it wrong. On self-hosted Ghost, place it at content/themes/your-theme/ads.txt. On Ghost(Pro), download your theme zip, add ads.txt to the theme root, re-zip, and re-upload it. Ghost then serves the file at yoursite.com/ads.txt. Because it lives inside the theme, switching or updating themes removes it — re-add it each time.
- Does Ghost still support AMP for AdSense?
- No. Ghost's built-in AMP was deprecated for years and is fully removed in Ghost 6.0, so don't build an AdSense strategy around Ghost AMP pages. Serve ads on your standard responsive pages instead — which, on a fast Ghost theme, already give you the Core Web Vitals that make ads more viewable.
Keep reading
- Add AdSense to Astro The same setup on a static-first stack, with the Partytown landmine to avoid.
- Where to put ads (without wrecking your page) The placements and reserved-space rules that protect Core Web Vitals.
- You don't need WordPress to run an ad site Why a lean, fast stack beats WordPress on cost and speed.