neputa note

AstroのサイトでGoogle Adsenseを遅延読み込みする

初稿:

- 3 min read -

img of AstroのサイトでGoogle Adsenseを遅延読み込みする

記事概要

  • 先日のBloggerからAstroへ移行した記事の別途詳細

※参考 - Blog移行記事

BlogをBloggerからAstroへ移行した

10年以上の期間お世話になったGoogle Bloggerに別れを告げ、この度AstroでBlogサイトを構築し移行した。Astroは静的サイトを手軽に開発できる軽量フレームワーク。無料のテンプレートをベースにカスタマイズを行った。それなりの作業ボリュームとなったので、詳細は別記事に分け、今回は移行作業全体をまとめる。

目的

  • Astroで構築したWebサイトにGoogle Adsenseの遅延読み込みを実装する
  • 前回、GoogleアナリティクスをPartytownで遅延読み込みする実装を行ったがAdsenseには適用できなかった
  • 例としてディスプレイ広告(バナー)を扱う
  • JavaScriptのobserverを使用し、広告が描画エリアに入るタイミングでAdsenseのJSをロードする

用語説明

Astro とは?

Astroは、ブログやマーケティング、eコマースなど、コンテンツ駆動のウェブサイトを作成するためのウェブフレームワークです。Astroは、新しいフロントエンドアーキテクチャを開拓し、他のフレームワークと比較してJavaScriptのオーバーヘッドと複雑さを低減することで知られています。高速でSEOに優れたウェブサイトが必要なら、Astroが最適です。 Astro公式Docs より引用をDeepLで翻訳

作業環境

  • OS - Ubuntu-22.04LTS on WSL2
  • Node.js - v20.14.0
  • pnpm - v9.4.0
  • Astro - v4.11.3

作業詳細

  • Google Adsenseを表示するcomponentを作成する
  • 実装のポイントは以下
    • isProdでデバッグ時にAdsenseのテストモードをオンにする(デバッグ時の不要なリクエスト防止)
    • init関数でobserverを定義し、ads-containerが描画エリアに入ったらheadにスクリプトタグを追加する
    • スクリプトタグの is:inline data-astro-rerun は、AstroのViewTransitions使用時にページ遷移先でも処理を走らせるために設定
GoogleAdsense.astro
---
const isProd = import.meta.env.PROD
const adsClientId = 'ca-pub-0000000000000000'
const adsBannerId = '0000000000'
---

<div class='ads-container'>
  <p>広告</p>
  <div>
    <ins class="adsbygoogle" style="display:block" data-ad-client={adsClientId} data-ad-slot={adsBannerId} data-ad-format="auto" data-full-width-responsive="true" />

{
  isProd ? (
    <script is:inline data-astro-rerun>
      (adsbygoogle = window.adsbygoogle || []).push({});
    </script>
  ) : (
    <script is:inline data-astro-rerun>
      window.adsbygoogle = window.adsbygoogle || [];
      const adBreak = adConfig = function(o) {
        adsbygoogle.push(o);
      }
    </script>
  )
}
  </div>
</div>

<script is:inline data-astro-rerun define:vars={{ adsClientId, isProd }}>
  function init() {
    const adElement = document.querySelector('.ads-container');
    const observer = new IntersectionObserver(function (entries) {
      if (entries[0].isIntersecting) {
        let ad = document.createElement('script');
        ad.type = 'text/javascript';
        ad.async = true;
        ad.src =
          'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=' + adsClientId;
        ad.crossOrigin = 'anonymous';
        if (!isProd) {
          ad.dataset.adbreakTest='on';
        }
        document.head.appendChild(ad);
        observer.disconnect();
      }
    })
    if (adElement) {
      observer.observe(adElement);
    }
  }
  init();
</script>
  • […slug].astroにcomponentを設置する
[...slug].astro
---
import { type CollectionEntry, getCollection } from 'astro:content'
import BlogPost from '../../layouts/BlogPost.astro'
import GoogleAdsense from '@/components/widgets/GoogleAdsense'

export async function getStaticPaths() {
  const posts = await getCollection('blog')
  return posts.map((post: any) => ({
    params: { slug: post.slug },
    props: post
  }))
}
type Props = CollectionEntry<'blog'>

const post = Astro.props
const { Content } = await post.render()
---

<BlogPost {...post.data}>
  <Content />
  <GoogleAdsense />
</BlogPost>

以上

目次