Claude Media
GTMコンテナの棚卸しをClaude Codeで進める — 重複・命名ゆれ・未使用の洗い出し

GTMコンテナの棚卸しをClaude Codeで進める — 重複・命名ゆれ・未使用の洗い出し

GTMからエクスポートしたコンテナJSONを、Claude Codeに書かせた小さなスクリプトで調べ、重複タグ・命名規則違反・未使用のトリガーと変数を一覧にする手順です。

Google Tag Manager(GTM)のコンテナは、何年か運用すると「コピー」が付いたタグや、誰も発火させていないトリガーが溜まります。管理画面で一つずつ開いて確かめるのは骨が折れます。

GTMはコンテナをJSONで書き出せます。このJSONをClaude Codeに読ませ、棚卸し用のスクリプトを書かせて走らせると、重複・命名ゆれ・未使用の候補が数秒で一覧になります。ここでは、書き出しから結果の読み方、片付けの反映までを手順にします。

全部を読ませず、集計は決まった処理に任せる

エクスポートしたJSONをそのままチャットに貼って「ムダを探して」と頼むと、件数の多いコンテナでは見落としが出ます。参照の有無は数えれば決まる話なので、数える部分はスクリプトにします。

役割は次のように分けると安定します。

作業担当
重複・未使用・規則違反の抽出担当スクリプト(毎回同じ結果)
抽出結果の意味づけ、名前の改善案担当Claude Code
削除・リネームの最終判断担当人

Claude Codeの強みは、スクリプトを書いて実行し、その出力を読んで次の手を決める往復にあります。コンテナのJSONはモデルに全文を食わせる対象でなく、プログラムの入力として扱います。

手順1: コンテナを書き出す

GTMの管理画面で、上部の「管理」を開き、コンテナ欄の「コンテナをエクスポート」を選びます。エクスポートするバージョンまたはワークスペースを選んで、ダウンロードします。ヘルプによると、書き出したコンテナは比較・編集・共有・バージョン管理への保存ができ、インポートで戻すこともできます。

公開中の状態を調べるなら、公開済みのバージョンを選びます。作業途中の内容を含めて調べたいときはワークスペースを選びます。

一部だけを書き出すと、選ばなかったタグやトリガーへの参照は消えます。書き出し時に警告が出るのは、選んだ項目が依存する先を外したときです。棚卸し用には、バージョン全体を書き出すのが無難です。

ファイルにはコンテナIDやタグの設定値が入ります。リポジトリに置くなら、公開しない場所か、.gitignore の対象にします。外部に渡してよい範囲の考え方は、Claudeに個人情報を入力する前に見るべき一次資料にまとめています。

手順2: 棚卸しの観点を決める

調べる項目は、次の4つに絞ります。

観点

棚卸しで調べる4つの観点

  • 重複タグ

    種別と設定値、発火条件が同じで、名前だけ違うタグです。

  • 命名規則違反

    チームで決めた書式に合わない名前です。

  • 未使用のトリガー

    どのタグの発火条件にも例外条件にも入っていないものです。

  • 参照のない変数

    {{変数名}} の形でどこからも呼ばれていないものです。

判定の根拠は、GTMのAPIリソースの定義にあります。タグには firingTriggerId と blockingTriggerId があり、前者のいずれかが真で、後者がすべて偽のときにタグが発火します。つまりトリガーのIDが、どのタグのこの2つにも現れなければ、そのトリガーは使われていません。

変数の命名例として、ヘルプは「Data Layer Variable - Product Name」のように、機能が分かる付け方を挙げています。この形を雛形にして、「種別 - 対象 - 用途」のような書式を自分のチームで決めると、命名規則違反を機械的に判定できます。

手順3: Claude Codeにスクリプトを書かせる

プロジェクトのフォルダに書き出したJSONを置き、Claude Codeを起動して、次のように頼みます。

exports/gtm-container.json を調べる Python スクリプトを scripts/gtm_audit.py に書いて。
containerVersion 配下の tag / trigger / variable を読む。出すのは次の5つ。
1. 種別・parameter・firingTriggerId・blockingTriggerId が同じタグの組
2. 名前が「種別 - 対象 - 用途」の形でないタグ・トリガー・変数
3. どのタグの firingTriggerId / blockingTriggerId にも無いトリガー
4. {{名前}} の形でどこにも参照されていない変数
5. paused が true のタグ
JSON は読み取りだけ。ファイルは書き換えない。

「JSONは読み取りだけ」と添えるのは、元ファイルを誤って整形し直されるのを防ぐためです。依頼文の中の配列名(containerVersion の下の tag など)は、手元のエクスポートを開いて確かめてから書いてください。この記事のスクリプトは、その形を前提にしています。

次のコードが、同じ依頼で作るスクリプトの一例です。書き出し済みの実ファイルで動くかは、各自で確かめる必要があります。

scripts/gtm_audit.py の全文
import json, re, sys
from collections import defaultdict
 
data = json.load(open(sys.argv[1], encoding="utf-8"))
cv = data.get("containerVersion", data)
tags = cv.get("tag", [])
triggers = cv.get("trigger", [])
variables = cv.get("variable", [])
NAME_RULE = re.compile(r"^(GA4|Ads|FB|HTML) - .+ - .+$")
 
# 1. 重複タグ: type・parameter・発火/例外トリガーが同じ
groups = defaultdict(list)
for t in tags:
    key = json.dumps([t.get("type"), t.get("parameter"),
                      sorted(t.get("firingTriggerId", [])),
                      sorted(t.get("blockingTriggerId", []))], sort_keys=True)
    groups[key].append(t["name"])
print("## 重複タグ")
for names in groups.values():
    if len(names) > 1:
        print("-", " / ".join(names))
 
# 2. 命名規則違反
print("## 命名規則違反")
for kind, items in (("tag", tags), ("trigger", triggers), ("variable", variables)):
    for x in items:
        if not NAME_RULE.match(x["name"]):
            print(f"- {kind}: {x['name']}")
 
# 3. どのタグからも使われていないトリガー
used = set()
for t in tags:
    used.update(t.get("firingTriggerId", []))
    used.update(t.get("blockingTriggerId", []))
print("## 未使用トリガー")
for tr in triggers:
    if tr["triggerId"] not in used:
        print(f"- {tr['name']} (id {tr['triggerId']})")
 
# 4. どこにも {{名前}} で参照されていない変数
body = json.dumps({"tag": tags, "trigger": triggers, "variable": variables},
                  ensure_ascii=False)
print("## 参照のない変数")
for v in variables:
    if "{{" + v["name"] + "}}" not in body:
        print(f"- {v['name']}")
 
print("## 停止中のタグ")
for t in tags:
    if t.get("paused"):
        print(f"- {t['name']}")

重複タグの判定は、種別・設定値・発火トリガー・例外トリガーの一致で決めています。tagId や名前は比べていません。設定値の並び順が違うだけのタグは、別物として扱われます。

実行して出力を確かめる

python3 scripts/gtm_audit.py exports/gtm-container.json

架空の小さなコンテナ(タグ3、トリガー3、変数2)で走らせた出力は、次のとおりです。

## 重複タグ
- GA4 - page_view - All / GA4 pageview copy
## 命名規則違反
- tag: GA4 pageview copy
- tag: old tag
- trigger: All Pages
- trigger: Click - CTA
- trigger: Click - old
- variable: GA4 ID
- variable: Unused Const
## 未使用トリガー
- Click - old (id 12)
## 参照のない変数
- Unused Const
## 停止中のタグ
- old tag

最初の重複タグは、片方が「コピー」として作られた形です。命名規則の違反が多く出るのは、規則を後から決めたコンテナでは自然な結果です。全件を一度に直そうとせず、新規作成分から守る運用に切り替えるかを先に決めます。

手順4: 出力をClaude Codeに読ませて整理案を作る

一覧が出たら、そのまま続けて頼みます。

出力を読んで、削除してよさそうなものと、確認が要るものに分けて。
命名規則違反は、改名案を「現在の名前 → 新しい名前」の表にして。

一覧の項目それぞれに、人が確認する理由が付きます。たとえば「未使用トリガー」の候補は、いまは使われていなくても、季節キャンペーン用に残してあるかもしれません。名前から目的が読み取れない項目は、削除候補にせず確認候補に回すよう、指示に書いておくと安全です。

非対話で毎回同じ結果を出したいとき

定期的に棚卸しするなら、Claude Codeの非対話モード(-p)が使えます。使えるツールを絞ると、読み取りとスクリプト実行だけに権限が限られます。

claude -p "scripts/gtm_audit.py を exports/gtm-container.json に実行し、
削除候補と確認候補に分けて表にして" \
  --allowedTools "Read,Bash(python3 scripts/gtm_audit.py *)"

--allowedTools は、確認なしで使えるツールを指定するフラグです。Bash(...) の形で、実行できるコマンドをパターンで絞れます。-p の基本はClaude Code -pモードでスクリプトやパイプラインを自動化する基本で扱っています。

手順5: 片付けをGTMに反映する

反映の方法は2通りあります。

くらべる

反映の2つの経路

件数が少ないとき

管理画面で直す

一覧を見ながら、タグやトリガーを開いて削除・改名します。公開前にプレビューで確かめ、バージョンを切って公開します。

改名が数十件あるとき

JSONを編集して取り込む

名前の置換などをJSONに加え、インポートします。取り込み先は新しいワークスペースにします。

インポートでは、既存のワークスペースに入れる場合に「上書き」か「統合」を選びます。ヘルプによると、上書きは既存のタグ・トリガー・変数をすべて消して、取り込む側に置き換えます。取り込み前に新しいコンテナバージョンが作られます。統合では、同名で中身が違う項目を上書きするか、名前を変えて取り込むかを選びます。

取り込む前の確認画面には、追加・変更・削除される件数が出ます。「詳細な変更を表示」で一覧も見られます。この画面で想定した件数と合うかを確かめてから確定します。

名前の変更は、タグの発火条件には影響しません。ただし、変数の名前を変えると {{旧名}} で呼んでいた箇所が壊れます。JSONを編集するなら、変数名の置換は参照側も同時に直す必要があります。

命名規則をCLAUDE.mdに置いて、次回から使い回す

命名規則はスクリプトの正規表現に埋め込まず、CLAUDE.mdに書いておくと、規則を変えたときにClaude Codeが両方を直せます。

## GTM の棚卸し
- exports/ の JSON は読み取り専用。編集するときは別名で保存する
- 名前の書式は「種別 - 対象 - 用途」(例: GA4 - page_view - All)
- 棚卸しは scripts/gtm_audit.py で行い、削除は候補の提示までにとどめる

規則を変えたら、このファイルを直してから「スクリプトのNAME_RULEも合わせて」と頼みます。

このスクリプトで分からないこと

静的な集計は、参照の見落としと、見えない参照の両方を起こします。

  • カスタムJavaScriptやテンプレートの中の参照は、{{名前}} の文字列検索では拾えない書き方がありえます。「参照のない変数」は削除候補であって、削除してよいという結論ではありません
  • 組み込み変数(Page URLなど)は、variable の配列に入らないため、この一覧には出ません
  • ほかのコンテナや、外部のサイト側のコードから呼ばれているものは、JSONだけでは見えません
  • 実際に発火したかは別の話です。条件が真にならないトリガーは、IDが使われていても動いていません。実際の発火は、プレビューモードで確かめます

Consent Mode周りのタグは、発火条件の意味を読まないと棚卸しできません。同意設定の照合は、ClaudeでConsent Modeの実装を棚卸しする手順で別に扱っています。

規模が大きいときの選択肢

管理画面のエクスポートは手作業です。複数のコンテナを定期的に調べるなら、Tag Manager APIでタグ・トリガー・変数などの設定データを取得する方法があります。APIはアカウント、コンテナ、ワークスペース、タグ、トリガー、変数、バージョンなどのリソースを扱います。認可と登録の手順が要るため、エクスポートで足りる規模なら手作業のほうが早く済みます。

契約しているツールの棚卸しも同じ型です。請求データとログを突き合わせる進め方は、SaaSの棚卸しをClaudeで進める手順にあります。

まとめ

コンテナの棚卸しは、数える作業をスクリプトに任せ、意味づけをClaude Codeに任せ、削除を人が決める三段に分けると進みます。4つの観点で出た候補は、未使用でも季節用や他コンテナ向けかもしれず、削除の前にプレビューでの発火確認と公開前のバージョン保存を挟むのが安全です。

この記事を共有:XはてブLinkedIn