
毎月月初に行う、ブログのアクセス解析って面倒くさくないですか?
Google アナリティクス(GA4)の画面を開き、前月1ヶ月間の総ユーザー数やセッション数を確認してスプレッドシートに入力する。 次にページ別のランキング画面を開いて、上位50記事のタイトルと数値をまた手作業でコピペする……。
いちいちこんな面倒くさいことをせずとも、
「決まった画面を開いて、決まったデータをコピーするだけなのだから、プログラムに任せられないだろうか?」
そう思い立ち、 Google Apps Script (GAS)を使って、 GA4 のデータを毎月自動でスプレッドシートに蓄積していく仕組みを作りました。
非エンジニアの私にとっては最初はハードルが高く感じましたが、一度設定してしまえば「毎月30分かかっていた手作業がほぼ無くなり、自動でレポートが完成している」という環境が手に入りました。
今回は、その設定手順について説明します。
Apps Script の準備と API の追加
それでは、実際の設定手順に入ります。
まずは、データを蓄積したい Google スプレッドシート を開きます。 上部のメニューから「拡張機能」>「 Apps Script 」をクリックすると、プログラムを書くためのエディタ画面が開きます。
GA4 のデータを取得するには、「 Analytics Data API 」という機能を使えるようにする必要があります。
- Apps Script の画面左側にあるメニューから「サービス」という文字の横にある「+」アイコンをクリックします。
- サービスの一覧から「 Google Analytics Data API 」を探して選択します。
- そのまま右下の「追加」をクリックします。

これで、プログラムから GA4 にアクセスする準備が整いました。
GA4 の「プロパティ ID」を確認する
次に、データを取得したい対象サイトの「プロパティ ID 」(通常9桁の数字)を確認します。 これはデータの住所のようなものです。
- Google アナリティクス を開き、画面左下の歯車マーク「管理」をクリックします。
- 「プロパティ設定」の中にある「プロパティの詳細」をクリックします。
- 画面右上に表示されている「プロパティ ID 」(数字のみ)をコピーして控えておきます。

自動取得するためのプログラムコード
Apps Script のエディタ画面に最初から書かれている文字をすべて消去し、以下のコードを貼り付けます。
このプログラムは、1行目の PROPERTY_ID をご自身のものに書き換えるだけで、そのまま使えます。
javascript// ↓ここに、ご自身のGA4プロパティID(数字のみ)を「半角のシングルクォーテーション」で囲んで入力してください const PROPERTY_ID = '123456789'; // 毎月自動実行するプログラム function runMonthlyReport() { const today = new Date(); // 先月の1日から月末までの日付を取得 const firstDay = new Date(today.getFullYear(), today.getMonth() - 1, 1); const lastDay = new Date(today.getFullYear(), today.getMonth(), 0); const startDate = Utilities.formatDate(firstDay, Session.getScriptTimeZone(), 'yyyy-MM-dd'); const endDate = Utilities.formatDate(lastDay, Session.getScriptTimeZone(), 'yyyy-MM-dd'); appendOverallData(startDate, endDate); appendPageRankingData(startDate, endDate); } // ①サイト全体データの処理 function appendOverallData(startDate, endDate) { const sheetName = '全体データ'; let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName); // シートが無ければ見出しを作成 if (!sheet) { sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet(sheetName); sheet.appendRow(['年月', '総ユーザー数', '新規ユーザー数', 'セッション数', '表示回数', 'エンゲージメント率', '平均エンゲージメント時間(秒)']); sheet.getRange("A1:G1").setFontWeight("bold").setBackground("#f3f3f3"); sheet.setFrozenRows(1); } // APIにリクエストする内容(どの期間の、何のデータを取得するか) const request = { dateRanges: [{ startDate: startDate, endDate: endDate }], dimensions: [{ name: 'yearMonth' }], metrics: [ { name: 'totalUsers' }, { name: 'newUsers' }, { name: 'sessions' }, { name: 'screenPageViews' }, { name: 'engagementRate' }, { name: 'averageSessionDuration' } ] }; const response = AnalyticsData.Properties.runReport(request, 'properties/' + PROPERTY_ID); // 取得したデータをシートの最下部に追記 if (response.rows) { const rows = response.rows.map(row => { const ym = row.dimensionValues[0].value; return [ ym.substring(0, 4) + '/' + ym.substring(4, 6), Number(row.metricValues[0].value), Number(row.metricValues[1].value), Number(row.metricValues[2].value), Number(row.metricValues[3].value), (row.metricValues[4].value * 100).toFixed(2) + '%', Number(row.metricValues[5].value).toFixed(1) ]; }); sheet.getRange(sheet.getLastRow() + 1, 1, rows.length, rows[0].length).setValues(rows); } } // ②ページ別ランキングの処理 function appendPageRankingData(startDate, endDate) { const sheetName = 'ページランキング推移'; let sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName); // シートが無ければ見出しを作成 if (!sheet) { sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet(sheetName); sheet.appendRow(['年月', 'ページタイトル', 'ページパス', '総ユーザー数', '新規ユーザー数', 'セッション数', '表示回数', 'エンゲージメント率', '平均エンゲージメント時間(秒)']); sheet.getRange("A1:I1").setFontWeight("bold").setBackground("#f3f3f3"); sheet.setFrozenRows(1); } // APIにリクエストする内容 const request = { dateRanges: [{ startDate: startDate, endDate: endDate }], dimensions: [{ name: 'yearMonth' }, { name: 'pageTitle' }, { name: 'pagePath' }], metrics: [ { name: 'totalUsers' }, { name: 'newUsers' }, { name: 'sessions' }, { name: 'screenPageViews' }, { name: 'engagementRate' }, { name: 'averageSessionDuration' } ], orderBys: [{ metric: { metricName: 'sessions' }, desc: true }], // セッション数が多い順 limit: 50 // 上位50件まで }; const response = AnalyticsData.Properties.runReport(request, 'properties/' + PROPERTY_ID); // 取得したデータをシートの最下部に追記 if (response.rows) { const rows = response.rows.map(row => { const ym = row.dimensionValues[0].value; return [ ym.substring(0, 4) + '/' + ym.substring(4, 6), row.dimensionValues[1].value, // ページタイトル row.dimensionValues[2].value, // ページパス Number(row.metricValues[0].value), Number(row.metricValues[1].value), Number(row.metricValues[2].value), Number(row.metricValues[3].value), (row.metricValues[4].value * 100).toFixed(2) + '%', Number(row.metricValues[5].value).toFixed(1) ]; }); sheet.getRange(sheet.getLastRow() + 1, 1, rows.length, rows[0].length).setValues(rows); } }
コードは何をしているのか?
一見すると複雑に見えますが、やっていることはとてもシンプルです。
- いつのデータを?: プログラムの前半で、先月1ヶ月間という期間を指定しています。
- 何のデータを?:
dimensions(切り口:年月やページタイトルなど)とmetrics(数値:ユーザー数やセッション数など)を指定して、 GA4 に「このデータが欲しい」とリクエスト(お願い)を出しています。 - どこに書くか?:
sheet.getRange(sheet.getLastRow() + 1, ...)で、シートの一番下の行を探して、そこに取得したデータを順番に貼り付けています。
この getLastRow() + 1 (最後の行の1つ下)という処理があるおかげで、毎月データが上書きされることなく、下へ下へと蓄積されていく仕組みになっています。
注意点として、 Google Analytics Data API には 1日のリクエスト上限などの制限があります。 しかし、月に1回、個人のブログ規模のデータを取得するだけであれば、制限に引っかかることはまずありませんのでご安心ください。
毎月自動で実行するための「タイマー設定」
コードを保存したら、最後にこのプログラムを毎月自動で動かすための「トリガー(引き金)」を設定します。
GA4 のデータは、月末に締められてから完全に確定するまで数日かかることがあります。 そのため、毎月5日の深夜 に前月分のデータを自動取得する設定にするのが安全です。
- Apps Script の画面左側のメニューにある時計のアイコン(「トリガー」)をクリックします。
- 右下の青いボタン「トリガーを追加」をクリックします。
- 以下のように設定します。
- 実行する関数を選択:
runMonthlyReport - 実行するデプロイを選択:
Head - イベントのソースを選択:
時間主導型 - 時間ベースのトリガーのタイプを選択:
月ベースのタイマー - 月の日を選択:
5日 - 時刻を選択:
午前0時~1時(お好みで)
- 実行する関数を選択:
- 「保存」をクリックします。
初回保存時のみ「 Google が確認していません」というセキュリティ警告が出ることがあります。 その場合は、「詳細」>「(プロジェクト名)に移動(安全ではないページ)」>「許可」の順に進めてください。

おわりに:仕組み化がもたらす安心感
これで設定は完了です。これ以降は、私が何もしなくても、毎月5日になると自動的に前月のアクセスデータがスプレッドシートに追記されるようになりました。
毎月の手作業がなくなったことで、単純に「面倒な時間が減った」というだけでなく、コピペミスや取得漏れといった「人為的なミスが絶対に起きない」という圧倒的な安心感を得ることができました。
ナビゲーションリンクを配列で管理したとき にも感じましたが、「機械にできることは機械に任せる」という設計は、人間がより本質的な「分析」や「考えること」に集中するための、極めて合理的なアプローチだと実感しています。
メインブログでは、今回作成したシートをもとにして、さらに詳しい分析を行う手順についても紹介できればと思います。



