Next.jsでGoogle Adsenseを使った広告配信
妙にハマりまくったので、とりあえず現状について覚書 参考 https://yuyauver98.me/no-slot-size-for-availablewidth0/ https://mao-tss.medium.co […]
広告ここから
広告ここまで
目次
妙にハマりまくったので、とりあえず現状について覚書
参考
- https://yuyauver98.me/no-slot-size-for-availablewidth0/
- https://mao-tss.medium.com/fix-google-adsense-loading-issues-with-react-f338cbd61ac4
- https://blog.35d.jp/2020-04-12-notion-blog-google-adsense
- https://github.com/vercel/next.js/discussions/18801
- https://github.com/vercel/next.js/discussions/14395
pages/_document.tsx
Google Adsenseのscriptタグをここで読ませます。react-helmet
を使えばまとめられる気もしますが、ライブラリ化するわけでもないので今はこれでよしとしています。
<Html>
<Head>
<script
async
src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"
data-ad-client="ca-pub-xxxxxxx"
></script>
</Head>
@types/window.d.ts
で型を拡張
window
にadsbygoogle
が追加されるので、型を定義しておきます。
/* eslint-disable no-var */
interface Window {
prerenderReady: boolean;
adsbygoogle: {[key: string]: unknown}[]
}
declare global {
var window: Window;
}
コンポーネントを作成
react-adsenseのコードなどを参考にコンポーネントを作ります。
import React, {CSSProperties, FC, useEffect} from 'react'
export type GoogleAdsenseProps = {
className?: string;
style?: CSSProperties;
client: string;
slot: string;
layout?: string;
layoutKey?: string;
format?: string;
responsive?: string;
};
export const GoogleAdsense: FC<GoogleAdsenseProps> = ({
className = '',
style = {display: 'block'},
format = 'auto',
layout = '',
layoutKey = '',
responsive = 'false',
client,
slot,
}) => (
<ins className={`${className} adsbygoogle`}
style={style}
data-ad-client={client}
data-ad-slot={slot}
data-ad-layout={layout}
data-ad-layout-key={layoutKey}
data-ad-format={format}
data-full-width-responsive={responsive}></ins>
);
pages/_app.tsx
でイベント発火
あとはwindow.addsbygoogle
を実行するフックを追加します。
const useGoogleAdsense = () => {
const loadAd = useCallback(() => {
(window.adsbygoogle = window.adsbygoogle || []).push({})
},[])
useEffect(() => {
if(typeof window !== 'undefined'){
const component = window.document.getElementById('__next').querySelector(`.adsbygoogle`);
if (component) {
component.addEventListener('load', loadAd);
}
}
return () => {
if(typeof window !== 'undefined'){
const component = window.document.getElementById('__next').querySelector(`.adsbygoogle`);
if (component) {
component.removeEventListener('load', loadAd);
}
}
}
}, [])
}
function MyApp({ Component, pageProps }) {
useGoogleAdsense()
return (
<Component {...pageProps} />
)
}
Next.jsアプリ配下に広告タグがあれば実行。なければ何もしないというフックにしています。
window.onload
で読み込みしているサンプルが多かったのですが、Next.jsやGatsbyでは使わない方が良さそうです。というのもこの辺りのFWを使った場合、ページ遷移時にwindow.onload
イベントが発火しない様子で、広告が表示されませんでした。
そのため今回のサンプルではちょっと手間ですが、querySelector
で要素を取得し、addEventListner
でloadイベントをセットする形を採用しています。
ページ毎にuseEffectを白化させる
もしページ遷移のたびにHookを動かしたい場合はこうします。
import { useRouter } from 'next/router';
...
const {asPath} = useRouter()
useEffect(() => {
... }, [asPath])
ある程度整理できたら、ライブラリ化できないか検討しようかなとは思っています。