0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

外部リンク73本が全部未計測だった。GA4とSearch Consoleの「0」を6通り読み違えた記録

0
Last updated at Posted at 2026-09-02

「このリンク、誰も踏んでいない」とずっと思っていました。実際には、外部リンク73本にクリック計測のコードが1行も入っていなかっただけでした。

そこから自分の計測を全部洗い直したら、「0」の読み違いが6種類出てきました。6件とも、GA4 と Search Console が表示していた数字自体は正しいです。壊れていたのは読み方のほうでした。

しかもそのうち2件は、すでに施策の No-Go を確定させる直前まで行っていました。エラーは1件も出ていません。0 はエラーにならないからです。

この記事は、その6件と、最後に見つかった「本物の 0」1件の実測記録です。

前提

  • 対象:個人で運営している静的サイト数本(資格学習サイト takken.mainichi-lab.com と、方言の辞書サイト hogen.mainichi-lab.com ほか)
  • 計測:GA4 3プロパティ + Search Console(ドメインプロパティ)
  • 期間:2026年8月〜9月2日
  • 収益:現時点で実質ゼロ。だから「効いた/効かなかった」の判定を間違えると、次に何を作るかを丸ごと間違える

0-1. 「測る仕掛けが無い」0

一番多かったのがこれでした。

外部リンクのクリック数がずっと 0 だったので「誰も踏んでいない」と思っていました。実際は onclick も GA4 イベントも一切実装されていなかっただけです。

リンクの張り先ごとに grep で数えました。

grep -roE 'href="https?://[^"]+"' . --include="*.html" \
  | grep -oE 'https?://[^/"]+' | sort | uniq -c | sort -rn
張り先 本数 クリック計測
記事プラットフォーム 42 なし
ASP(A8) 20 なし
楽天アフィリエイト 11 なし

合計73本。1本も計測していませんでした。

GA4 の画面には「イベント数 0」と正しく出ます。0 が出る以上、レポートは何も間違っていません。「まだ何も送っていない」と「送ったが 0 だった」は、GA4 の画面上で区別が付かないというのが本質でした。

対策として全リンクに委譲ハンドラを1本入れました。

document.addEventListener('click', (e) => {
  const a = e.target.closest('a[href^="http"]');
  if (!a) return;
  const host = new URL(a.href, location.href).host;
  if (host === location.host) return;      // 内部リンクは対象外
  if (typeof gtag !== 'function') return;  // 未ロードでも例外を投げない
  gtag('event', 'outbound_click', {
    dest_host: host,
    dest_url: a.href,
    from_page: location.pathname,
  });
}, { capture: true });

ポイントは3つです。

  1. 委譲にする。リンクは後から増えるので、個別に付けると必ず付け忘れます(実際73本のうち手作業で付いていたのは0本でした)
  2. gtag が無くても例外を投げない。広告ブロッカーで gtag が落ちている環境で、計測コードがUIを壊すのが最悪です
  3. dest_host を別パラメータで持つ。URL全文だけだとカーディナリティが高すぎて、GA4のレポートで束ねられません

0-2. 「まだ測れていない」0

新しく12ページ公開した翌日に Search Console を開いたら、12面中11面が表示 0 でした。

「新設ページのSEOは効かなかった」と判定しかけて、止めました。理由は2つあります。

  • Search Console のデータには約2日のラグがある。9月2日時点で最新のデータ日は 8月30日でした
  • 日付境界が太平洋時間(PT)。8月31日 00:19 JST に公開したページが、Search Console 上では 8月30日に計上されていました

つまり公開後に「表示され得た日数」は最大1日。この 0 は「効かなかった 0」ではなく 「まだ露出していない 0」 です。ここで No-Go を確定させていたら、まだ何も起きていない施策を失敗として畳んでいました。

判定日を6日後にずらしました。

0-3. 「期間が違う」0

Search Console の検索パフォーマンスの URL に、期間パラメータを付けて開いていました。

.../performance/search-analytics?resource_id=sc-domain%3Aexample.com
  &start_date=2026-08-20&end_date=2026-09-02

このパラメータは無視されます。 既定の28日間にフォールバックしていて、実際に返っていたのは 8/3〜8/30 でした。指定した14日間ではなく、28日間の合計を「直近の数字」として読んでいたことになります。

確かめ方は1つだけです。

&breakdown=date

日別に落とせば、先頭行と末尾行で実際の期間が分かり、同時に最後にデータがある日も分かります。以後、期間を触ったら必ず最初に breakdown=date を見るようにしました。

0-4. 「粒度が違う」数字

コミットメッセージに「あるページのクエリが表示20・平均掲載順位6.6」と自分で書いていました。

後から breakdown=page で確認したら、そのページの28日間の表示回数は 0。ページ表に1行も出てきません。

20という数字は、そのクエリに対するサイト全体の表示回数でした。クエリ単位の数字を、ページ単位の実績として引き継いでいたわけです。

Search Console はクエリ・ページ・国・デバイスで別々に集計します。クエリの数字とページの数字を掛け合わせた行は存在しません(フィルタを掛ければ交差は取れますが、素の表を並べただけでは交差になりません)。

0-5. 「二重に数えた」数字

逆方向の間違いもありました。

同じアフィリエイトリンクのクリックで、aff_clickrakuten_click の2つのイベントが同時に飛んでいるサイトが1本ありました。片方は旧実装の残骸です。

このとき、レポートで両方を足すとクリック数がちょうど2倍になります。しかも「2倍」は一見それらしい数字なので、気づく手がかりがありません。

見つけ方は単純で、本番のDOMで gtag をスタブに差し替えて1回クリックするだけです。

// 本番ページの devtools で。実HITは1件も送らない
const sent = [];
window.gtag = (...args) => sent.push(args);
// …実際にリンクを1回クリック…
console.log(sent);   // 1クリックで2件出たら二重送信

「実装したから送られているはず」と「1クリックで何件送られるか」は別の問いです。後者は本番でしか確かめられません。

0-6. 「基準を知らない」0

最後は Qiita 自体の話です。この1本前に投稿した記事が、2.2日で PV 544 / LGTM 0 / ストック 0 でした。

「読まれているのに反応が1件も無い=中身が刺さっていない」と読みかけました。

その前に、比較対象を実測しました。Qiita API は認証を付けると自分の記事の page_views_count が返ります(無認証だと null)。他人の記事のPVは非公開ですが、LGTM とフォロワー数は誰でも取れます。

# 同じタグの直近1週間の記事を200本取る
curl -s -H "Authorization: Bearer $TOKEN" \
  "https://qiita.com/api/v2/items?query=tag:ClaudeCode+created:%3E2026-08-25&per_page=100&page=1"

結果(ClaudeCode タグ・2026/08/27〜09/02・n=200):

指標
LGTM 中央値 0
LGTM が 0 の記事の割合 69.5%
LGTM 5以上の記事の割合 6.5%

LGTM 0 は例外ではなく中央値でした。

さらに、LGTM 5以上の記事(13本)と LGTM 0 の記事で著者のフォロワー数を比べると、

著者フォロワー数の中央値 本文長の中央値
LGTM 5以上 109 4,654字
LGTM 0 0.5 5,348字

本文長では差が付かず(LGTM 0 の群のほうがむしろ長い。14,529字で19 LGTM の記事もありました)、フォロワー数のほうにはっきり差が出ました。相関であって因果ではありませんが、少なくとも「0 だから中身が悪い」という読み方は、この分布の上では支持されません。

比較対象を取る前に自分の 0 を解釈しようとしたのが間違いでした。


本物の 0

ここまでの6件は読み違いでしたが、1件だけ本物の 0 がありました。

その 544 PV の記事から、自分のサイトへの流入は 0 です。

実測項目(2026/08/31〜09/02)
記事のPV 544
はてなブックマーク数(bookmark.hatenaapis.com/count/entry 0
GA4:qiita.com からの参照セッション(自分の3プロパティ合計) 0
記事から張った先(別サービスの記事)の全期間PV 12

理由は測る前から構造で決まっていました。その記事に置いた外部リンクは1本だけで、しかも GA4 を入れていない別サービス宛てだったからです。GA4 を入れているサイトへのリンクは、記事中に1本もありませんでした。

つまり「送客が 0 だった」のではなく、送客が発生し得ない設計だった。0-1 とまったく同じ間違いを、今度はリンクの張り先でやっていたことになります。

ついでに rel も確かめました。

curl -s "https://qiita.com/<user>/items/<id>" \
  | grep -oE '<a[^>]*href="https://[^"]*"[^>]*rel="[^"]*"' | head
# => rel="nofollow noopener"

外部の記事プラットフォーム側も同じく rel="nofollow" でした。SEO評価は渡りません。 外部プラットフォームは被リンク源ではなく、referrer を運ぶ導線として見るのが正しかったです。referrer 自体は noopener では落ちません(noreferrer なら落ちる)。したがってリンク先に GA4 が入っていれば qiita.com / referral として計上されます。入れていれば、の話ですが。

判定前チェックリスト

同じことを繰り返さないように、数字を読む前に通すリストを作りました。

  • その指標を送るコードは実在するか(本番DOMで1回発火させて確認したか)
  • 1アクションで何件送っているか(二重送信していないか)
  • データの最終日はいつか(Search Console は約2日ラグ・PT境界)
  • その期間指定は本当に効いているかbreakdown=date で実期間を見たか)
  • その数字の粒度は何か(クエリ/ページ/サイト全体を混ぜていないか)
  • 比較対象の分布を取ったか(0 が異常値なのか中央値なのか)
  • 測りたい経路にリンクは存在するか(0 は「踏まれなかった」ではなく「無かった」かもしれない)

6件は、それぞれ別の行に対応しています。逆に言うと、1行でも飛ばすとどれかを踏みます。


計測は、実装より読み方のほうが壊れやすいという話でした。特に 0 は「異常が無い顔をした異常」 なので、エラーにならないぶん厄介です。

なお、こうやって数字を洗い直す作業自体を自動化した記録(実装とプロンプトを全部載せています)は別途こちらにまとめてあります → https://note.com/fujiken818/n/n7f126d2e8522?utm_source=qiita&utm_medium=article&utm_campaign=note_ai_980&utm_content=qiita_002


この記事でやった「外部リンクと計測の全数チェック」は、他の方のサイトでも単発の監査として引き受けています(1サイト ¥55,000)。表示速度ではなく、可読性・タップ標的・重複・計測もれを実測して、直す順に並べるやり方です。見る項目と料金の目安 → https://mainichi-lab.com/contact?utm_source=qiita&utm_medium=article&utm_campaign=work_inquiry&utm_content=qiita_002_contact

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?