
GA4のレポートを自動化する際、APIの連携は避けて通れない道です。
この記事ではGoogle Apps Script(GAS)を使って、GA4から数値を取得し、月次でスプレッドシートに自動出力するスクリプト実装を全文解説します。
たとえば「オーガニックチャネルのみ」「/movie/というパスを含むページのみ」など、実用的な条件でフィルタしたレポートを出力したい方に向けた内容です。
1. このスクリプトでできること
- GA4 APIとGASを使って、前月分の数値を取得
- チャネルグループが「Organic Search」のセッションのみを抽出
- ランディングページのパスに「/movie/」を含むもののみを抽出
- Googleスプレッドシートにヘッダー付きで出力
- 該当する名前のシートがないときは、シートを新規作成
- なお、セッション数やユーザー数での絞り込みをしたい場合は、
metricFilterを使えば可能です(今回は非実装) - フィルターのラベル(チャネルグループ名など)は「GA4のUIで表示されている名称」と完全一致する必要があります(大文字・スペース含む)。
例えば「Organic」と「Organic Search」は別物として扱われるためご注意を。
2. 実行環境と注意点
このスクリプトは、Google Apps Scriptの管理画面(https://script.google.com) から実行することができます。
使用前に以下の準備を行ってください:
- Google Cloud コンソールでGA4 APIを有効化する
- プロジェクトを作成し、「APIとサービス」>「ライブラリ」から
Google Analytics Data APIを有効にします。
- プロジェクトを作成し、「APIとサービス」>「ライブラリ」から
- サービスアカウントを作成し、JSONファイルを取得
- Google Cloud コンソールの「認証情報」画面に入り「サービスアカウントを管理」リンクをクリック。さらに画面上の「+サービスアカウントを作成」をクリックしてサービスアカウントを作成します。
- 次に画面左ナビから「サービスアカウント」に入り、画面上の「鍵」のリンクをクリック。
画面下にある「キーを追加」のプルダウンから「新しい鍵を作成」を選択して、キーのタイプは「Json」を選択してください。 - すると自動的にJsonファイルがダウンロードされるので必ず保管しておいてください。
(※スクリプト設定時に使用します)
- GA4の管理画面でプロパティIDを用意する
- 管理画面の「プロパティの詳細」画面右上に書かれている数字のみのIDです。
「G-xxxxxxxxx」で始まる測定IDではないので、ご注意ください。
- 管理画面の「プロパティの詳細」画面右上に書かれている数字のみのIDです。
- Googleスプレッドシートを用意する
- 出力先となるスプレッドシートを作成し、ID(下記URLの【ここがID】の部分)とデータを出力させたいシート名をメモしておきます。
※例:https://docs.google.com/spreadsheets/d/【ここがID】/edit
- 出力先となるスプレッドシートを作成し、ID(下記URLの【ここがID】の部分)とデータを出力させたいシート名をメモしておきます。
- GASエディタにスクリプトを貼り付け、画面左ナビにある[サービス +]の「+」ボタンから「Google Analytics Data API(v1beta)」を追加します。
※これを行わないと「AnalyticsData is not defined」というエラーになります。
3. コード全文とロジック
以下にGASスクリプトのサンプルと、スクリプト使用上の注意点を書いています。
期間・フィルタ条件などは皆さま各自で書き換えてご使用ください。
GASスクリプト使用上の注意点
設定時の注意
const propertyId = 'YOUR_GA4_PROPERTY_ID'; // ← 数字のみ(例: 265085688)
const sheetId = 'YOUR_SPREADSHEET_ID'; // ← スプレッドシートID上記の部分に、先ほど準備した、GA4のプロパティIDと、スプレッドシートのIDを入れてください。
const serviceAccount = {
"type": "service_account",
"project_id": "your-project-id",
"private_key_id": "xxxxxxxxxxxxxxxxxxxx",
"private_key": "-----BEGIN PRIVATE KEY-----\\nYOUR_KEY\\n-----END PRIVATE KEY-----\\n",
"client_email": "your-service-account@your-project.iam.gserviceaccount.com",
"client_id": "123456789012345678901",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/your-service-account%40your-project.iam.gserviceaccount.com"
};上記の各行に、先ほど取得したJsonファイルの内容を入れていってください。
実行時の注意
実行するときは、必ず「runGa4ReportWithServiceAccount」の方を実行してください。
GASスクリプト全文
function runGa4ReportWithServiceAccount() {
const propertyId = 'YOUR_GA4_PROPERTY_ID'; // ← 数字のみ(例: 265085688)
const sheetId = 'YOUR_SPREADSHEET_ID'; // ← スプレッドシートID
const sheetName = 'GA4データ出力'; // ← 任意のシート名(存在しなければ自動作成)
const serviceAccount = {
"type": "service_account",
"project_id": "your-project-id",
"private_key_id": "xxxxxxxxxxxxxxxxxxxx",
"private_key": "-----BEGIN PRIVATE KEY-----\\nYOUR_KEY\\n-----END PRIVATE KEY-----\\n",
"client_email": "your-service-account@your-project.iam.gserviceaccount.com",
"client_id": "123456789012345678901",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/your-service-account%40your-project.iam.gserviceaccount.com"
};
const now = new Date();
const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);
const endOfLastMonth = new Date(now.getFullYear(), now.getMonth(), 0);
const startDate = Utilities.formatDate(lastMonth, Session.getScriptTimeZone(), 'yyyy-MM-dd');
const endDate = Utilities.formatDate(endOfLastMonth, Session.getScriptTimeZone(), 'yyyy-MM-dd');
const jwt = createJwt(
{ alg: 'RS256', typ: 'JWT' },
{
iss: serviceAccount.client_email,
scope: 'https://www.googleapis.com/auth/analytics.readonly',
aud: serviceAccount.token_uri,
exp: Math.floor(Date.now() / 1000) + 3600,
iat: Math.floor(Date.now() / 1000)
},
serviceAccount.private_key
);
const tokenResponse = UrlFetchApp.fetch(serviceAccount.token_uri, {
method: 'post',
contentType: 'application/x-www-form-urlencoded',
payload: {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: jwt
}
});
const accessToken = JSON.parse(tokenResponse.getContentText()).access_token;
const url = `https://analyticsdata.googleapis.com/v1beta/properties/${propertyId}:runReport`;
const payload = {
dateRanges: [{ startDate, endDate }],
dimensions: [
{ name: 'landingPage' },
{ name: 'sessionDefaultChannelGroup' }
],
metrics: [
{ name: 'sessions' },
{ name: 'engagementRate' }
],
dimensionFilter: {
andGroup: {
expressions: [
{
filter: {
fieldName: 'sessionDefaultChannelGroup',
stringFilter: {
value: 'Organic Search',
matchType: 'EXACT'
}
}
},
{
filter: {
fieldName: 'landingPage',
stringFilter: {
value: '/movie/',
matchType: 'CONTAINS'
}
}
}
]
}
}
};
const response = UrlFetchApp.fetch(url, {
method: 'post',
contentType: 'application/json',
headers: {
Authorization: 'Bearer ' + accessToken
},
payload: JSON.stringify(payload)
});
const json = JSON.parse(response.getContentText());
const spreadsheet = SpreadsheetApp.openById(sheetId);
let sheet = spreadsheet.getSheetByName(sheetName);
if (!sheet) {
sheet = spreadsheet.insertSheet(sheetName);
} else {
sheet.clearContents();
}
const headers = json.dimensionHeaders.map(h => h.name)
.concat(json.metricHeaders.map(h => h.name));
sheet.appendRow(headers);
if (json.rows && json.rows.length > 0) {
json.rows.forEach(row => {
const dims = row.dimensionValues.map(d => d.value);
const metrics = row.metricValues.map((m, i) => {
return i === 1 // engagementRate
? (parseFloat(m.value) * 100).toFixed(2) + '%'
: m.value;
});
sheet.appendRow(dims.concat(metrics));
});
} else {
sheet.appendRow(['該当データなし']);
}
Logger.log('GA4データ出力完了');
}
function createJwt(header, claimSet, privateKey) {
const encode = (obj) =>
Utilities.base64EncodeWebSafe(JSON.stringify(obj)).replace(/=+$/, '');
const encodedHeader = encode(header);
const encodedClaim = encode(claimSet);
const signatureInput = `${encodedHeader}.${encodedClaim}`;
const signature = Utilities.base64EncodeWebSafe(
Utilities.computeRsaSha256Signature(signatureInput, privateKey)
).replace(/=+$/, '');
return `${signatureInput}.${signature}`;
}
GASとPythonどちらを使うべき?
GASはGoogleスプレッドシートとの親和性が高く、ノーコード寄りの環境でも扱いやすいのが特徴です。
ただし、より柔軟な条件設定やログの記録、条件別での分岐出力などを行いたい場合は、Pythonの方が優れています。
👉 Python版はこちら(Google Colabでの使用がおすすめです)
まとめ
GA4からオーガニック流入かつ特定パスに限定したセッションデータを、前月分のみ自動で抽出し、Googleスプレッドシートに転記するGASスクリプトをご紹介しました。
「レポート作成の手間を減らしたい」「定型条件で毎月データを取り出したい」──そんな方はぜひご活用ください。


