目次
Next.jsでGoogle Analyticsを使えるようにする
Next.jsとはVercelが作成しているReactのフレームワークです。面倒な設定を書かなくてもすぐに使えるZero Configを標榜しており、実際にwebpackやTypeScriptと一緒にReactを書く際にも特別な準備は不要です。SSRにも対応しており、Reactで開発するならNext.jsかFacebook製のCreate React Appを使うのがスタンダードになってます。
私は実務でNext.jsを使っており、このフレームワークはとても便利だと思っています。私はNext.jsの大ファンなので、Reactでの開発時にNext.jsを使う現場が増えるといいなと思って記事を書いています。
関連記事: Next.js + esa.io + VercelでJAMStackな爆速ブログを構築する
この記事では、Next.jsでReactアプリケーションを作成する時に、Google Analytics(以下、GA)の設定をする方法をご紹介します。一通り設定した後、TypeScript化していきます。
基本的にはNext.jsのExampleを参考にしています。ただ、実務で使うとこれだけでは足りないところがあるので、記事内では実務への橋渡しとなるような内容を盛り込んでいます。
なお、Google Analyticsのアカウント取得方法やスニペットの取得方法は記載していません。
Google AnalyticsのIDを.envに記述する
まず、ルートディレクトリに.env
ファイルを作成し、GAのIDを.env
に記述します。
NEXT_PUBLIC_GOOGLE_ANALYTICS_ID=UA-SOME_ANALYTICS_ID-1
Next.jsでは、.env
に記述した環境変数をprocess.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_ID
で取得できます。この値はビルド時に注入されます。これが最初の設定です。
NEXT_PUBLIC_
という接頭辞をつけると、ブラウザにも露出する値になります。
GAイベントを発火させる関数を作成する
次に、GAイベントを発火させる関数を作成します。関数はsrc/lib/gtag.js
というファイルに記述していきます。
export const GA_ID = process.env.NEXT_PUBLIC_GOOGLE_ANALYTICS_ID
// IDが取得できない場合を想定する
export const existsGaId = GA_ID !== ''
// PVを測定する
export const pageview = (path) => {
window.gtag('config', GA_ID, {
page_path: path,
})
}
// GAイベントを発火させる
export const event = ({action, category, label, value = ''}) => {
if (!existsGaId) {
return
}
window.gtag('event', action, {
event_category: category,
event_label: JSON.stringify(label)
value,
})
}
このファイルではgtag
というGAのメソッドをラップする関数を作ります。
pageview
という関数でページビューを送信するには、config
コマンドを使用します。引数でパスを受け取り、page_path
でURLのパスを送信します。
event
という関数でGAイベントを送信する関数を記述します。例えば、DOMのクリックイベントやSubmitのイベントなどを取得する時に使います。
なお、GAに関する詳しい内容はGoogleの公式ドキュメントをご覧ください。
- ページビューの測定
- Google アナリティクスのイベントを測定する
- イベントについて(イベント名の区別に対する記述がある)
_document.jsxにGAのスクリプトを書き込む
_document.jsx
は全てのページで共通のHTMLを書くコンポーネントです。この_document.jsx
にGA用のscriptタグを記述します。
import Document, { Head, Main, NextScript } from 'next/document'
import { existsGaId, GA_ID } from '~/src/lib/gtag'
export default class MyDocument extends Document {
render() {
return (
<html lang="ja">
<Head>
{/* Google Analytics */}
{existsGaId && (
<>
<script async src={`https://www.googletagmanager.com/gtag/js?id=${GA_ID}`} />
<script
dangerouslySetInnerHTML={{
__html: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '${GA_ID}', {
page_path: window.location.pathname,
});`,
}}
/>
</>
)}
</Head>
<body>
<Main />
<NextScript />
</body>
</html>
)
}
}
なお、_document.jsx
はサイト内で共通のmetaタグ(<meta property="og:type" content="website" />
など)を記述するような使い方をします。
_app.jsにPVをカウントするイベントを記述する
Next.js製のサイトはSPAであるため、ページを遷移するときにJavaScriptでURLを書き換えます。その際、Google Analyticsはアクセスした最初のページしかページビュー測定のイベントを送信しません。つまり、ユーザーがサイト内を回遊したときの各ページのPVを測定できないのです。
この問題は、Next.jsのRouterを使えば解決できます。RouterのURL書き換えが完了した時に発火するrouteChangeComplete
イベントのコールバックとしてpageview関数を設定します。
これをpages/_app.js
に記述します。
import React from 'react'
import * as gtag from '~/src/lib/gtag'
const App = ({ Component, pageProps }) => {
useEffect(() => {
if (!gtag.existsGaId) {
return
}
const handleRouteChange = (path) => {
gtag.pageview(path)
}
router.events.on('routeChangeComplete', handleRouteChange)
return () => {
router.events.off('routeChangeComplete', handleRouteChange)
}
}, [router.events])
return <Component {...pageProps} />
}
これで、ページ遷移時のPVイベントをGAに送信できました。
_app.js
の記述は長くなりがちなので、Custom Hooks に切り出しておくと便利です。
import { useEffect } from 'react'
import { useRouter } from 'next/router'
import * as gtag from '~/src/lib/gtag'
export default function usePageView() {
useEffect(() => {
if (!gtag.existsGaId) {
return
}
const handleRouteChange = (path) => {
gtag.pageview(path)
}
router.events.on('routeChangeComplete', handleRouteChange)
return () => {
router.events.off('routeChangeComplete', handleRouteChange)
}
}, [router.events])
}
_app.js
は以下のようにリファクタリングできます。
import React from 'react'
import * as gtag from '~/src/lib/gtag'
import usePageView from '~/src/hooks/usePageView'
const App = ({ Component, pageProps }) => {
usePageView()
return <Component {...pageProps} />
}
GAイベントをReactコンポーネントに設定する
では、実際にReactコンポーネントでGAイベントの設定をしましょう。以下ではContactコンポーネントでのボタンをクリックした時に、inputタグに入力されたメッセージをGAに送信します。
import React from 'react'
import Layout from '../components/Layout'
import * as gtag from '../lib/gtag'
const Contact = () => {
const [message, setMessage] = React.useState('')
const handleInput = e => setMessage(e.target.value)
const handleSubmit = e => {
e.preventDefault()
gtag.event({
action: 'submit_form',
category: 'Contact',
label: message,
})
setMessage('')
}
return (
<Layout>
<h1>This is the Contact page</h1>
<form onSubmit={handleSubmit}>
<label>
<span>Message:</span>
<textarea onChange={handleInput} value={message} />
</label>
<button type="submit">submit</button>
</form>
</Layout>
)
}
export default Contact
今回はhandleSubmitの中でeventを発火しています。同様にclickイベントならhandleClick
の中に、onChangeイベントならhandleChangeの中に
event`関数を記述します。Reactでは取得したいイベントに応じて、GAイベントを柔軟に記述できます。
ここまででNext.jsでGoogle Analyticsを使うための設定ができました。以下では、より実務に即した内容をご紹介します。
TypeScript対応をする
実務ではReactとTypeScriptの環境で開発している方も多いと思います。そのような方のために、Next.js + Google Analytics + TypeScriptの対応方法をご紹介します。
なお、GAに関するメソッドのために@types/google.analyticsという型定義があります。しかし、型定義ではga
というメソッドにしか対応しておらず、gtag
という書き方は存在しないのです。
そこで、このライブラリを参照しながらTS用の対応をすることにしました。
windowからGAイベントのプロパティを使うための型定義を書く
Next.jsでTypeScriptを使えるようにすると、ルートディレクトリにnext-env.d.ts
というファイルが作成されます。これはNext.jsでTSを使うなら必須のファイルで、削除してはいけません。
前の章でlib/gtag.js
にwindow.gtag()
をラップする関数を作りましたね。
gtag.js
をgtag.ts
に書き換えると、windowオブジェクトにgtagというプロパティは存在しないという意味のエラーが表示されます。
TS2339: Property 'gtag' does not exist on type 'Window'.
TypeScriptでwindowにプロパティを追加するために、next-env.d.ts
にWindowオブジェクトはgtagというプロパティを持っているのだという型定義を記述しましょう。
interface Window {
// pageviewのため
gtag(type: 'config', googleAnalyticsId: string, { page_path: string })
// eventのため
gtag(
type: 'event',
eventAction: string,
fieldObject: {
event_label: string
event_category: string
value?: string
}
)
}
これでgtag.ts
でエラーが出なくなりました。
発火させるイベントを型で管理する
TypeScriptに対応したため、gtagをラップする関数に型をつけていきます。
まず、gtag.js
の拡張子をgtag.ts
に変更します。そして、1行目の import 文を加えます。
import { Event } from 'src/types/googleAnalytics/event'
export const event = ({action, category, label}: Event) => {
if (!existsGaId) {
return
}
window.gtag('event', action, {
event_category: category,
event_label: JSON.stringify(label)
})
}
この時点では、src/types/googleAnalytics/event.ts
を作成していないため、型Event
をインポートできずエラーになります。
そこで、src/types/googleAnalytics/event.ts
を作成し、以下のように記述します。
type ContactEvent = {
action: 'submit_form'
category: 'contact'
label: string
}
type ClickEvent = {
action: 'click'
category: 'other'
label: string
}
export type Event = ContactEvent | ClickEvent
event.ts
でGAイベントで送信する値に予め型をつけることにより、イベント設定時のスペルミスや値がundefinedになるミスを未然に防ぐことができます。
こうすることでEvent.jsがサイト全体のGAイベントのドキュメント代わりになります。
しかも、イベント名等のタイポにより GA イベントが発火しないミスを未然に防ぐこともできます。
まとめ
Next.jsでGoogle Analyticsを使えるようにした上で、TypeScriptに対応しました。
Next.jsを本番環境で使用する場合、Google Analyticsは必須です。Google Analyticsを使ってユーザー行動を取得し、プロダクトの改善にぜひ役立ててください。
日本でNext.jsが現場で使われるケースが増えることを願っています。