[Next.js] Google Analytics コンポーネントではオプションが設定できないので、今は自作して対応しよう
next.js では、next/third-parties を使うことによって Google Analytics や Google Maps Embed などのサードパーティーライブラリを効率よく導入することができます。
Next.js | Third Party Libraries
ただし、Google Analytics の場合は、2024 年の 9 月の段階では利用しない方がいいケースがあります。それが、send pageview events を false
にしたり、共通パラメーターを設定したい場合です。デフォルトパラメータを設定しない場合は、Third Party Libraries | Google Analytics を参照して導入しても特に問題はありません。
改善提案 は Next.js に出していますので、そのうち改善される可能性はあります。
では、なぜ利用しない方がいいケースがあるのか見ていきましょう。
config
の第 3 引数に対応をしていない
GoogleAnalytics コンポーネントは、gtag の Google Analytics コンポーネントでは、内部的に gtag.js を使っています。
この gtag の config
は gtag のドキュメントでは、第 3 引数も設定できるようになっており、この引数にオブジェクトを設定することによって、send pageview events を false
にしたり、全てのイベントで共有して設定したいパラメーター(例: ユーザーの権限)を設定することができます。
ただし、Next.js Third Party Libraries の GoogleAnalytics コンポーネントでは、引数の gaId
のみを gtag の config
に渡すようになっています。そのため、send pageview events を false
にしたり、共通パラメーターを設定することができません。
Next.js の Google Analytics コンポーネントのコード
export function GoogleAnalytics(props: GAParams) {
const { gaId, dataLayerName = 'dataLayer' } = props
if (currDataLayerName === undefined) {
currDataLayerName = dataLayerName
}
useEffect(() => {
// performance.mark is being used as a feature use signal. While it is traditionally used for performance
// benchmarking it is low overhead and thus considered safe to use in production and it is a widely available
// existing API.
// The performance measurement will be handled by Chrome Aurora
performance.mark('mark_feature_usage', {
detail: {
feature: 'next-third-parties-ga',
},
})
}, [])
return (
<>
<Script
id="_next-ga-init"
dangerouslySetInnerHTML={{
__html: `
window['${dataLayerName}'] = window['${dataLayerName}'] || [];
function gtag(){window['${dataLayerName}'].push(arguments);}
gtag('js', new Date());
// gtag に第 3 引数が設定されていない
gtag('config', '${gaId}');`,
}}
/>
<Script
id="_next-ga"
src={`https://www.googletagmanager.com/gtag/js?id=${gaId}`}
/>
</>
)
}
もし、send pageview events を false
にしたり、共通パラメーターを設定したい場合は、GoogleAnalytics を使わずに、gtag.js を直接使いましょう。
import Script from 'next/script';
import { useMemo } from 'react';
type Props = {
/**
* Google AnalyticsのトラッキングID
* @example G-XXXXXXXXXX
*/
gaId: string,
/**
* Google Analytics の設定オプション
* キーは camelCase 形式で指定し、内部で snake_case に変換されます。
* @example { sendPageView: false, customParam: 'value' }
*/
options: Record<string, string | number | boolean>
}
const OriginalGoogleAnalytics = ({ gaId, options }: Props) => {
const snakeCaseOptions = useMemo(() => convertKeysToSnakeCase(options), [options]);
return (
<>
<Script
src={`https://www.googletagmanager.com/gtag/js?id=${gaId}`}
strategy="afterInteractive"
/>
<Script
id="ga-init"
strategy="afterInteractive"
>
{`
window.dataLayer = window.dataLayer || [];
function gtag(){window.dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${gaId}', ${JSON.stringify(snakeCaseOptions)});
`}
</Script>
</>
);
}
export default OriginalGoogleAnalytics;
const toSnakeCase = (str: string) => str.replace(/([A-Z])/g, '_$1').toLowerCase();
const convertKeysToSnakeCase = (obj: Record<string, string | number | boolean>) => {
return Object.entries(obj).reduce((acc, [key, value]) => {
acc[toSnakeCase(key)] = value;
return acc;
}, {} as Record<string, string | number | boolean>);
}
Discussion