マキモノ
Google Workspace無料✅ 公式検証済みv1.0.0 / 更新

サイトのGA4測定ID・Search Consoleプロパティを人に画面を開かせず特定する

公開GTMコンテナからの測定ID抽出と、DWD impersonateによる全量取得。HTTP 200でも権限範囲の一覧を全量と誤認する事故の検知方法まで。

出品者: kim@orgiast.jp📖 読込 約3,227トークン (約5円)💰 コスパ 12倍
トークン節約メーター90%節約
ゼロからAIに作らせた場合約4.2万トークン
このMDを読ませた場合約4,300トークン

約3.8万トークンの節約 (API料金換算で約57円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。

この巻物について

「サイトのGA4測定ID・Search Consoleプロパティを人に画面を開かせず特定する」は、Google WorkspaceカテゴリのAI指示書(MDファイル)です。公開GTMコンテナからの測定ID抽出と、DWD impersonateによる全量取得。HTTP 200でも権限範囲の一覧を全量と誤認する事故の検知方法まで。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約3.8万トークン(API料金換算で約57円)・90%のトークンを節約できます。

カテゴリ
Google Workspace
対応AI
claude-code、cursor、codex-cli
ライセンス
商用利用可 (再販不可)
価格
無料
ゼロから開発時
約4.2万トークン
この巻物使用時
約4,300トークン
節約量
約3.8万トークン (約57円)
更新日
2026-09-24

使い方 (AIに渡す3つの方法)

いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。

⬇ .md をダウンロード
claude "https://makimono-md.vercel.app/api/v1/files/ga4-id-search-console/raw を読み込んで、この指示書どおりに実装して"
claude-codecursorcodex-cliライセンス: 商用利用可 (再販不可)

中身

サイトの GA4 測定ID・Search Console プロパティを、人に管理画面を開かせずに特定する

「このサイトの GA4 測定ID が分からない」「既存プロパティがあるのか新規作成が要るのか」を、 依頼者に画面キャプチャを取らせずに AI 側で確定させる手順。 最大の落とし穴は「API が 200 を返したのに答えが間違っている」ケースで、それをどう検知するかまで書く。


0. 結論(先に読む)

知りたいこと認証取得方法
サイトに今入っている測定ID不要本番HTMLを grep
GTM コンテナの中の測定ID不要公開コンテナ JSON を grep
そのプロパティが誰の所有か / 全プロパティ一覧必要サービスアカウント + ドメイン全体の委任(DWD)で本人を impersonate
直近のアクセス数必要Analytics Data API runReport

「存在しない」と断定してよいのは、本人を impersonate したトークンで一覧を取ったときだけ。


1. 認証ゼロで取れるところまで取る

1-1. 本番HTMLの計測タグ

curl -s https://<対象ドメイン>/ | grep -oE "G-[A-Z0-9]{6,12}|GTM-[A-Z0-9]{4,10}|UA-[0-9]{4,12}-[0-9]{1,4}"

1-2. GTM コンテナの中身(ここを飛ばす人が多い)

GTM コンテナIDさえ分かれば、コンテナ設定は認証なしで誰でも取得できる公開 JSON。 中に GA4 タグの測定IDが vtp_tagId":"G-..." の形で入っている。

curl -s "https://www.googletagmanager.com/gtm.js?id=GTM-XXXXXXX" \
  | grep -oE "G-[A-Z0-9]{6,12}|UA-[0-9]{4,12}-[0-9]{1,4}|AW-[0-9]{6,15}" | sort -u

重要: GTM 経由で読み込まれるタグは、保存済みHTMLの全文検索では絶対に拾えない。 「旧サイトのHTMLを全文検索したが UA しか無かった」という調査報告は、この理由でほぼ必ず取りこぼしている。 実例: HTML検索では UA しか出なかったサイトで、GTM コンテナを開いたら GA4 測定IDが入っていた。

1-3. アカウント番号の一致を手がかりにする

旧 UA の測定ID UA-<数字>-1 の <数字> は GA アカウントIDそのもの。 後述の一覧に accounts/<同じ数字> があれば、UA と GA4 が同居している=そこが探しているアカウント。 これは「既存プロパティを流用してよいか」の決定的な証拠になる。


2. 認証が要る部分:必ず impersonate で取る

2-1. 二つの認証方式の違い(ここが事故の温床)

方式見える範囲網羅性
SA 自身(sub なし)その SA が明示的にユーザー追加されたものだけなし
DWD impersonate(sub に本人のメール)本人が見られるもの全部あり

一覧API(Search Console の sites、GA の accountSummaries、Drive の files.list など)は トークンの持ち主の権限範囲しか返さない。これは仕様であって不具合ではない。

実害の例: 依頼者に「サービスアカウントを追加して」と頼み、1プロパティだけ追加された状態で一覧を取得。 API は 200 を返し 1件だけ返した。それを「アカウントにはこれしか無い」と報告したが、 実際には 12件あった。HTTP 200 は答えが正しい保証にならない。

2-2. セットアップ(一度きり)

  1. サービスアカウントを作り、鍵 JSON を取得
  2. Workspace 管理コンソールでドメイン全体の委任にそのクライアントIDを登録し、スコープを許可
    • URL: https://admin.google.com/ac/owl/domainwidedelegation
    • クリック順: メニュー → セキュリティ → アクセスとデータ管理 → API管理 → ドメイン全体の委任の管理
    • スコープ: https://www.googleapis.com/auth/analytics.readonly, https://www.googleapis.com/auth/webmasters.readonly
    • 既存スコープを消さずに追記する(消すと既存の自動化が全部止まる)
    • この登録に API は存在しない。人が画面でやる唯一の作業
  3. GCP プロジェクトで対象 API を有効化
    • analyticsadmin.googleapis.com / searchconsole.googleapis.com / analyticsdata.googleapis.com

管理コンソールの /ac/... 系パスに /a/<ドメイン>/ を挟むと 404 になる。 ドキュメント系ホストの URL 規約をそのまま当てはめないこと。

2-3. 実装(Node・依存ゼロ)

import { readFileSync } from 'node:fs';
import { createSign } from 'node:crypto';

const key = JSON.parse(readFileSync('<鍵JSONのパス>', 'utf8'));
const b64 = (o) => Buffer.from(typeof o === 'string' ? o : JSON.stringify(o)).toString('base64url');

async function getToken(scope, impersonate) {
  const now = Math.floor(Date.now() / 1000);
  const claim = { iss: key.client_email, scope, aud: 'https://oauth2.googleapis.com/token', exp: now + 3600, iat: now };
  if (impersonate) claim.sub = impersonate;          // ← これの有無が網羅性を決める
  const unsigned = `${b64({ alg: 'RS256', typ: 'JWT' })}.${b64(claim)}`;
  const sig = createSign('RSA-SHA256').update(unsigned).sign(key.private_key, 'base64url');
  const res = await fetch('https://oauth2.googleapis.com/token', {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: new URLSearchParams({
      grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
      assertion: `${unsigned}.${sig}`,
    }),
  });
  const body = await res.text();
  if (!res.ok) throw new Error(`HTTP ${res.status} ${body}`);
  return JSON.parse(body).access_token;
}

叩くエンドポイント:

  • GA4 一覧: GET https://analyticsadmin.googleapis.com/v1beta/accountSummaries?pageSize=200
  • ストリーム(測定ID): GET https://analyticsadmin.googleapis.com/v1beta/properties/<id>/dataStreams → webStreamData.measurementId と webStreamData.defaultUri
  • Search Console 一覧: GET https://www.googleapis.com/webmasters/v3/sites → siteUrl が sc-domain: 始まりならドメイン型、https://…/ ならURLプレフィックス型
  • アクセス数: POST https://analyticsdata.googleapis.com/v1beta/properties/<id>:runReport
    { "dateRanges": [{"startDate": "30daysAgo", "endDate": "today"}],
      "metrics": [{"name": "activeUsers"}, {"name": "sessions"}, {"name": "screenPageViews"}] }
    

3. 誤答を防ぐ3つのガード(これが本体)

ガード1: impersonate を先に試す

SA 直接が先に成功すると、劣化した答えのまま完了してしまう。順序を固定する。

const MODES = [
  { sub: USER_EMAIL, label: 'impersonate(全量)',        exhaustive: true  },
  { sub: null,       label: 'SA 自身(権限範囲のみ)',     exhaustive: false },
];
// exhaustive:true が成功したらそこで打ち切る

ガード2: 出力に網羅性を明示する

### impersonate <本人>(本人が見える全量): HTTP 200
サイト 12 件 / 網羅性: あり

網羅性 なし の一覧に「存在しない」と書かせない。レポート本文にもこの1行を必ず持ち込む。

ガード3: 既知の値によるサニティチェック

「出てくるはずのもの」を先に宣言し、無ければ自分で警告を出す。

const EXPECTED = ['<対象ドメイン>', '<関連ドメイン>'];
const missing = EXPECTED.filter((d) => !found.some((s) => s.includes(d)));
if (missing.length) console.log(`⚠ サニティ警告: ${missing.join(', ')} が一覧に無い → 権限範囲不足の疑い`);

1件しか返らない一覧は原則疑う。 関連する既知ドメインが1つも出てこないのは、 「無い」よりも「見えていない」である確率のほうがはるかに高い。


4. エラー文の読み分け

レスポンス意味対処
unauthorized_client (401, トークン取得時)DWD にそのスコープが未登録管理コンソールでスコープ追記
SERVICE_DISABLED (403)GCP プロジェクトで API が無効その API を有効化
Permission denied to enable service (403)SA に API 有効化権限が無い権限のある人が1クリック、または SA にロール付与
200 だが件数が不自然に少ない権限範囲が狭いimpersonate に切り替える(← 最も危険。エラーが出ない)

5. チェックリスト

  • 本番HTMLを grep した
  • GTM コンテナの公開 JSON を grep した(HTML検索だけで「無い」と言っていないか)
  • 旧 UA のアカウント番号と GA アカウントIDを突き合わせた
  • impersonate トークンで一覧を取った(SA 直接ではない)
  • 出力に「網羅性: あり/なし」を明示した
  • 既知ドメインのサニティチェックが通った
  • ストリームURLが対象ドメインを向いているか確認した(旧サイト用プロパティの流用はデータが混ざる)
  • 本番HTMLにタグが無いのにデータが流れていないか確認した(別経路からの送信=二重計測の予兆)

よくある質問

+「サイトのGA4測定ID・Search Consoleプロパティを人に画面を開かせず特定する」とは何ですか?

公開GTMコンテナからの測定ID抽出と、DWD impersonateによる全量取得。HTTP 200でも権限範囲の一覧を全量と誤認する事故の検知方法まで。

+どれくらいトークン(費用)を節約できますか?

ゼロから開発すると約4.2万トークンかかりますが、この巻物を使えば約4,300トークンで済みます。差し引き約3.8万トークン(API料金換算で約57円)・90%の節約です。

+どうやって使いますか?

無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。

+どのAIツールに対応していますか?

claude-code、cursor、codex-cli に対応しています。

+商用利用できますか?

ライセンスは「商用利用可 (再販不可)」です。

🤝 自分でAIを動かすのは、まだ不安…という方へ

この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。

AI代行堂を見る →

関連する巻物

この巻物、誰かのトークンも救えます

𝕏 で節約レシートをシェア