Table of Contents
Overview
In the previous post Comment System (Utterances), we covered the comment system. In this post, I’ll explain how to integrate Google AdSense ads for blog monetization.
Ad integration is divided into two main parts. The first is placing ads at fixed positions in the post layout (top, bottom, left, right), and the second is inserting ads in the middle of markdown content. For the latter, I developed a custom rehype plugin.
Loading the AdSense Script
The Google AdSense script is loaded in Head.astro. This script must be loaded on every page for ads to display correctly.
<!-- src/components/Head.astro -->
<script
async
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-XXXXXXXXXX"
crossorigin="anonymous"
></script>
The async attribute is used to prevent blocking page loading.
Ad Components
Individual components are created for each ad placement position. This separation allows each position’s ad to be independently modified or disabled.
src/components/ads/
├── TopAds.astro # Top of post
├── BottomAds.astro # Bottom of post
├── LeftAds.astro # Left side
├── RightAds.astro # Right side
└── InFeedAds.astro # Within content (feed)
Each component contains AdSense ad code and is placed at the appropriate position in PostLayout.astro.
<!-- src/layouts/PostLayout.astro -->
<TopAds />
<div class="container container-contents">
<div class="row">
<LeftAds />
<article class="col-lg-8 col-md-10 mx-auto" data-pagefind-body>
<slot /> <!-- Markdown content -->
<InFeedAds />
</article>
<RightAds />
</div>
<BottomAds />
</div>
ads.txt Configuration
To prevent ad fraud, public/ads.txt and public/app-ads.txt files are placed in the project. These files contain verification information provided by Google AdSense and serve to verify that “only this ad network can serve ads on this site.”
When placed in the public/ directory, they are copied as-is to the dist/ directory during build, making them accessible at https://deku.posstree.com/ads.txt.
Custom rehype-in-feed-ads Plugin
Beyond ads fixed in the layout, there are times when you want to insert ads in the middle of markdown content. For this purpose, I developed the rehype-in-feed-ads plugin.
Usage
Simply write a <!-- ad --> comment at the position where you want an ad in the markdown file.
## Section 1
Content...
<!-- ad -->
## Section 2
Content...
During build, <!-- ad --> comments are automatically replaced with AdSense ad blocks.
Plugin Implementation
The plugin recursively traverses the HAST (HTML syntax tree) to find <!-- ad --> comment nodes and replace them with ad HTML.
// src/plugins/rehype-in-feed-ads.mjs
const AD_HTML = `<div class="in-feed-ads ads-container">
<div class="ads-block ads-left">
<ins class="adsbygoogle" ... data-ad-slot="2718813593"></ins>
<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>
</div>
<div class="ads-block ads-center">
<ins class="adsbygoogle" ... data-ad-slot="6492035359"></ins>
<script>(adsbygoogle = window.adsbygoogle || []).push({});</script>
</div>
</div>`;
function replaceInChildren(children) {
const result = [];
for (const child of children) {
if (
child.type === 'raw' &&
child.value &&
child.value.trim() === '<!-- ad -->'
) {
result.push(createAdNode());
} else if (child.type === 'comment' && child.value.trim() === 'ad') {
result.push(createAdNode());
} else {
if (child.children) {
child.children = replaceInChildren(child.children);
}
result.push(child);
}
}
return result;
}
export default function rehypeInFeedAds() {
return (tree) => {
if (!tree.children) return;
tree.children = replaceInChildren(tree.children);
};
}
How It Works
Here’s a summary of how the plugin works:
- Recursively traverses the HAST tree
- When a
<!-- ad -->comment node is found, replaces it with AdSense ad HTML - Handles both
rawtype (string) andcommenttype (parsed comment)
This approach recreates the pattern of inserting ads with {% include in-feed-ads.html %} in Jekyll. Since you only need to add <!-- ad --> when writing markdown, it’s straightforward.
Conclusion
In this post, we looked at how to integrate Google AdSense ads into an Astro blog.
- Loading AdSense script in
Head.astro - Setting up ad components by position (Top, Bottom, Left, Right, InFeed)
- Preventing ad fraud with
ads.txt - Automatically converting
<!-- ad -->comments in markdown to ads with the customrehype-in-feed-adsplugin
In the next post Search Implementation with Pagefind, we’ll cover how to implement search functionality on a static site.
Series Guide
This post is part of the Jekyll to Astro migration series.
- Why I Migrated from Jekyll to Astro
- Astro Installation and Project Setup
- Content Collections and Markdown Migration
- Multilingual (i18n) Implementation
- SEO Implementation
- Image Optimization — Custom rehype Plugin
- Comment System (Utterances)
- Ad Integration (Google AdSense)
- Search Implementation with Pagefind
- Layout and Component Architecture
- GitHub Pages Deployment
- Social Share Automation Script
- Troubleshooting and Tips
Was my blog helpful? Please leave a comment at the bottom. it will be a great help to me!
App promotion
Deku.Deku created the applications with Flutter.If you have interested, please try to download them for free.