Implementing Google Adsense without affecting site performance

Recently, I have been in contact with several people who have been thanking me for posting articles that have helped them significantly with their technological struggles or in easing their issues.

Some of them have been so happy that they would like to know how to donate a bit to support the cause. While this gesture is appreciated, most of the activities on my site are non-profit.

I used to have ads displayed on my website when it was hosted on WordPress. However, after migrating to Hugo, I soon realized that despite the speed benefits, the web performance was being compromised due to ads served through Google AdSense.

I managed to significantly reduce the costs for my website, so I decided to take the step of removing ads altogether, and I have been happy with this decision.

Nobody likes websites filled with ads that make them difficult to use, let alone read, due to all the clutter. This clutter refers to ads.

Thank you for the Reader option in Safari that makes websites readable once more!

I prioritize my readers’ experience over profit, which is why one of the options provided by Google AdSense, Auto Ads, was on my blacklist from the beginning.

However, if there is a way to display something non-intrusive within the article, without impacting the overall reading experience, why not give it a try?

I heard a question posed to an expert on one of the podcasts I listened to: “When should you start monetizing a website?” The expert’s response was “as soon as possible.”

I agree with that if it is done correctly!

I tried adding “buy me a coffee” banners, but it required some extra steps to finalize that nobody wanted to follow.

Ads served in intrusive ways are the very reason why AdBlockers exist in the first place. I use AdBlockers everywhere and do not recommend anyone to go online without them.

Adblockers are doing a great job in making the internet usable again.

If I decide to resume serving ads, they need to have as minimal an impact as possible.

When I say minimal impact, I mean not only for readers (to avoid distracting them) but also for the website itself in terms of web performance.

I recently re-analyzed the ad unit offered in Google AdSense, which allows me to insert in-article ads.

Simply pasting the code somewhere in the middle of the article significantly impacts the overall performance of that specific webpage.

This wasn’t for me.

I decided to try a different approach.

I recall a recent discussion on the Hugo Discourse forum regarding lazy loading Adsense Ads, specifically Auto Ads.

I examined the code there and observed that the script is loaded after the page is rendered upon mouse movement.

This reminds me of a script delay approach that I discussed in my post Implementing JavaScript Delay for Cookie Consent Banner.

I decided to implement that in combination with in-article ads served through Google AdSense.

As tested initially, everything has been working as theoretically assumed.

Without impacting the performance on the initial load of the website, the script starts to execute after the specified event is detected:

const eventList = ["keydown", "mousemove", "wheel", "touchmove", "touchstart", "touchend"];

I opted for in-article ads and positioned them much lower, below the initial view when the website (web page) loads. In general, I don’t want to annoy my readers like other websites do by displaying ads every other paragraph or every time the screen is scrolled.

I am someone who dislikes ads, so I bear that in mind and utilize my code to show ads only once.

Naturally, incorporating ads required me to reinstate my cookie consent banner (with a delay, of course), but I restricted its display to posts where ads might be shown, excluding pages where it is unnecessary.


The in-article ad code is composed of 3 elements.

The first element is a script (redacted) that loads the ads. This script causes the biggest performance drop when loaded as is.

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-################"
     crossorigin="anonymous"></script>

The second part of the script (redacted) is a block where ads are displayed.

<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-################"
     data-ad-slot="##########"></ins>

And there is just a final, third part of it.

<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script>

I find it challenging to comprehend this, as I am not an expert in JavaScript, so I consulted ChatGPT about it:

Shortly “In JavaScript, || []).push({}); is a pattern used to ensure that a variable, typically an array, is defined before performing operations on it.”


I am using Hugo to generate my website. Using Hugo shortcodes, I created one specifically for displaying ads on my website, which I named ads-in-article.html.

Within this file, I included all three parts of the Google Ads script with some modifications. But before we explore that, let’s discuss how I insert my shortcode into my posts.

I intentionally used shortcodes instead of integrating them into the layout (theme), as this provides me with flexibility regarding when and where the ad will be displayed.

I review all my posts on my website, which are saved in Markdown files, and determine precisely where I want to insert my ad.

I insert my code simply by adding the following line:

{{% ads-in-article %}}

This solution is beneficial for one reason. Suppose you want to remove all the ads from your articles. In that case, I simply clear the content of the file ads-in-article.html and leave it blank. All blocks are rendered, but since they are empty, nothing is added or displayed.

Adding it was time-consuming considering the number of posts, but it allowed me to refine some of them and determine where the ads would be placed.

Intentionally, I ensured that the ads would be displayed below the fold of the website, whether in the desktop layout or on mobile.

Once I had this sorted out, I revisited my ads-in-article.html to make some modifications that enable me to manage the impact on the initial page load performance of the pages where ads are shown.


I had already implemented the script delay functionality for my cookie banner, but since you may not have done so yet, I will begin from the start.

In Hugo, I defined my script delayer in the file script-delay.html as a partial in my layout.

I referenced this file in my article.html (at the bottom of the file), which is a part of the layout responsible for displaying individual posts only.

{{ partial "script-delay.html" . }}

Of course, you can simply paste the content of script-delay.html into the footer of your website if you wish to make it available site-wide.

The script-delay.html file is as follows::

<script>
const autoLoadDuration = 5; //In Seconds
const eventList = ["keydown", "mousemove", "wheel", "touchmove", "touchstart", "touchend"];
const autoLoadTimeout = setTimeout(runScripts, autoLoadDuration * 1000);

eventList.forEach(function(event) {
    window.addEventListener(event, triggerScripts, { passive: true })
});

function triggerScripts() {
    runScripts();
    clearTimeout(autoLoadTimeout);
    eventList.forEach(function(event) {
         window.removeEventListener(event, triggerScripts, { passive: true });
    });
}

function runScripts() {
    document.querySelectorAll("script[delay]").forEach(function(scriptTag) {
        scriptTag.setAttribute("src", scriptTag.getAttribute("delay"));
    });
}
</script>

The script waits for user interaction or 5 seconds, before doing its action.

Its action is to change invalid code for loading JavaScript on the website into a valid one and running it.

For example, this is how the script will be loaded.

<script src="script.js" defer></script>

To prevent it from loading, we break the script as follows:

<script delay="script.js" defer></script>

This way, there is no src element (making it invalid), hence the script is not fired.

This is where the script delayer takes over by replacing delay with src and firing the script when conditions are met.


Going back to ads-in-article.html, the only thing that I changed was this part:

<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-################"
     crossorigin="anonymous"></script>

to that:

<script async delay="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-################"
     crossorigin="anonymous">

Thanks to that, the ads are shown to those who are not blocking it with AdBlockers, and the performance is not affected.

Whoever wants to click on them will, and whoever wants to block them can do so with AdBlockers. I don’t mind.

Google is suggesting anti-adblocker tactics, but I hate screens telling me to turn off adblocker to read articles. If that’s annoying me enough to make me give up the site altogether, then I prefer not to use it at all and ensure that my readers enjoy what I have to share rather than profit from them.


There is one more thing that is not advertised well but strongly suggested by Google itself. It’s a small addition to the CSS style to prevent displaying empty blocks where ads should be displayed.

ins.adsbygoogle[data-ad-status="unfilled"] {
  display: none !important;
}

And that’s all.

If you decide that you would like to serve some ads to get a small return from your investment in creating the content (time), do it the smart way and don’t let your website suffer.

Here is an example of ads served the smart way (between the horizontal lines below). If you don’t see them, don’t worry, that’s probably your browser or adblocker successfully blocking them. If you do see them, check out what they have to offer and support me if you think it’s right.


Inserted ad (if not blocked by your AdBlocker):


In the end, the content matters, but if the website is slow as well, you can have the best content available, but Google, which is the main driver of traffic to my website, will not like you.

Comments
Categories