---
title: "AI経由で人が来はじめる日を見逃さない ― pixelstomotors.com の計測を3つに絞り Claude につないだ"
slug: catch-first-ai-referred-visitors-claude-connector
date: 2026-11-06
day: 453
meta_description: "pixelstomotors.com の計測を、AI が読んだ数・AI のリンクから来た人・サイト名の検索の3つに絞って毎日残し、Claude.ai から読めるようにした。11日間で AI の依頼読み92回、リンクから来た人2回、検索0回。"
tags: [アクセス解析, MCP, Claude, ChatGPT, Search Console, Cloudflare Workers, サイト改善]
ai_consult: true
series: "ひとり研究所の裏側"
---

**pixelstomotors.com では、AI に読まれたあと人が来はじめたかを見るための数字を3つ（AI の利用者の依頼で読みに来た数・AI のリンクから来た人の数・サイト名で検索して来た人の数）に絞り、毎日集計して Claude.ai から直接読めるようにしました。** 2026年10月26日から11月5日までの11日間では、ChatGPT や Claude が利用者に頼まれて読みに来たのが92回あったのに対し、AI の答えのリンクから来た人は2回、サイト名の検索から来た人は0回でした。

この改修で、次のことが変わりました。

- AI に読まれてから人が来るまでの、どの段階で止まっているかが毎日分かるようになった。今は、AI は読みに来ているのに、答えの中のリンクから人が来る段階で止まっている
- Claude に分析を頼むとき、鍵の置き場所や表の使い分けを説明しなくてよくなった。Claude.ai に足したコネクタ「PTMの計測」から、数字と、その数字の読み方（何が混ざりうるか）を Claude が直接受け取る
- 時間：前回の分析（LOG451）は、数字を取って集計して報告するまで Claude だけで約10分かかった。今は3つの数字が1回の呼び出しで返る。分析全体で何分縮むかは、11月16日の分析で測る
- 見逃していた数え漏れが見つかった。クローラー（ページを自動で読みに回るプログラム）の表は、10月25日からのような長い期間を指定すると、記録の一部しか数えていなかった。日ごとに集計して残す形にしたので、これからは漏れない

きっかけは、ブログ「無駄と文化」の記事 [自作AIエージェントの開発をやめた](https://blog.mudatobunka.org/entry/2026/11/05/100000)（2026年11月5日）です。生のデータを AI に渡しても「冬はおでんが売れる」のような当たり前のことしか返ってこず、前に進んだのは、見る指標を決めて合意し、毎日集計する仕組みを作り、データの集め方を見直したときだった、という話でした。筆者は自作の AI エージェントをやめ、Claude.ai につなぐ部品（MCP）として作り直しています。このサイトの計測も、項目を広く取ったせいで、改善の効果を確かめようとしても対象の数が足りず「判断できない」が続いていました。そこで同じ3つのこと（見る数字を決める・集め方を疑う・Claude につなぐ）を、自分のサイトでやりました。

pixelstomotors.com は、ロボットとフィジカルAI（現実の物を動かす AI）の研究を、ひとりで記録して公開しているサイトです。記事はおもに AI が読む前提で書いていて、人がページを見るのは1日20回前後です。

| やったこと | なぜ | 結果 |
|---|---|---|
| 見る数字を3つに絞った | 何を見れば「AI 経由で人が来はじめた」と言えるかを決めるため | AI の依頼読み・AI のリンクからの来訪・サイト名の検索 |
| 3つの数字に混ざりものがないかを、実データで確かめた | 自分や Claude の試し、機械の閲覧が混ざると読み違えるため | ボタン経由の読みは2回だけ。11/3 の Claude の読み12回は確かめの可能性が高い。クローラーの表の数え漏れが見つかった |
| 3つの数字を日ごとに集計して残す仕組みを作った | 毎回、生の記録を数え直すと遅く、黙って数え漏らすため | 日本時間で日付が変わると、前の日の分が自動で残る |
| 計測を Claude.ai につなぐ部品（MCP サーバー）を作った | 分析のたびに、Claude が鍵の場所や表の落とし穴を思い出さなくて済むようにするため | Claude.ai のコネクタ「PTMの計測」から6つの道具が使える |
| サイト名の検索の数を Search Console から毎日取る仕組みを作った | 3つ目の数字はサイトの中では取れないため | Google の組織の設定で鍵が作れず、当面は週の分析で手で記録する |

AI に読まれてから人が来るまでの3つの段階と、11日間の数字は、次の図で日ごとに見られます。

【図解】LOG453_three_numbers.html


## 作業ログ ― ブログ記事を読んで、見る数字を3つに絞った

ここから下は作業ログです。コード・コマンド・出力は全量で載せます。この記事の「見込める効果」は、断りのない限り見込みで、確かめた数字ではありません。


### ブログ記事「自作AIエージェントの開発をやめた」から、このサイトに使えることを3つ拾った

ブログ記事の感想を Claude に聞いたあと、エイイチは続けてこう聞きました。

> 今の自分のサイトに使えることはありましたか？

Claude が挙げたのは、次の3つです。

1. 見る数字を絞って、先に決める。このサイトの自前の計測（10月18日に入れた、ページごとの読まれ方を数える仕組み）は、最初は広く取る方針だったので項目が多い。そのぶん、10月28日に入れた改善 No.01 は、どれも対象が30に届かず判断できないままだった。一方で、エイイチがいま知りたいことは11月5日にはっきりしていた。AI に調べられることで、人の来訪や知名度がいつ増えはじめるか
2. データの集め方を疑う。記事の「AIで読む」ボタンの利用は619回に見えたが、約500回は Amazon のクローラーだった（LOG451）。人と機械を後から分けたせいで、最初の1週の数が人の数として使えなくなったこともある
3. 計測を Claude につなぐ部品（MCP）として作る。今の計測は、鍵を Mac の外付けドライブ（KIOXIA）から読み、表の仕組みを知ったうえで集計する手順を踏む。Claude は鍵のことを忘れて「計測が止まっているかも」と誤って報告したこと（10月28日）と、自前の計測より先に Search Console を開いたこと（11月2日）がある

3つ目は、受託の売り物の見本にもなる。お客さんのサイトに計測を入れ、そのお客さんの Claude.ai に計測をつなぐ部品として渡す形です。


### 見る数字を、AI の依頼読み・AI のリンクからの来訪・サイト名の検索の3つに決めた

AI に読まれてから人が来るまでを、3つの段階に分けました。

| 段階 | 数字 | 中身 | 取れる場所 |
|---|---|---|---|
| 1 | AI の利用者の依頼で読みに来た数 | ChatGPT・Claude・Perplexity などが、利用者に頼まれてページを読みに来た回数。学習や検索のために巡回するクローラーは入れない | サイトの配信の記録（`cr/`） |
| 2 | AI のサービスのリンクから来た人の数 | chatgpt.com などのリンクから来た表示のうち、人の操作（マウス・指・キー）があったもの | ページ上の計測の記録（`ev/`） |
| 3 | サイト名で検索して来た人の数 | Google でサイト名（Pixels to Motors・pixelstomotors など）を検索して来たクリック | Search Console |

エイイチの返事は次のとおりです。

> 絞る数字をこの三つでいい
>
> 三つ目は、計測をClaudeにつなぐ部品（MCP）として作る
> これも進めていいよ。どうせいずれ必要そうだね。

Search Console は、Google 検索でサイトがどんな言葉で何回表示され、何回押されたかを見られる Google の無料の道具です（[Google Search Console](https://search.google.com/search-console/about)）。数字は2〜3日遅れて出て、検索した人の少ない言葉は伏せて返します。


## 作業ログ ― 3つの数字に機械や自分の閲覧が混ざっていないかを確かめた

数え方を決める前に、Mac 連携のシェルから自前の計測の表を取り、混ざりものを探しました。鍵は KIOXIA の `p2m_stats_key.txt` から変数に読み込み、画面には出していません。


### 自前の計測の表を取ったコマンドと出力（2026-11-06 15:27ごろ）

```text
$ cd $HOME && mkdir -p kpi_check && cd kpi_check && K=$(tr -d '\n\r ' < $HOME/mnt/KIOXIA/p2m_stats_key.txt); for q in "cr-stats?format=json&since=2026-10-25" "ev-stats?format=json&since=2026-10-26&who=human" "ev-stats?format=json&since=2026-10-26&who=unknown" "ev-stats?format=json&since=2026-10-26&who=bot"; do f=$(echo $q | tr '?&=' '___'); curl -s -H "Authorization: Bearer $K" "https://pixelstomotors.com/api/$q" > $f.json; echo $f $(wc -c < $f.json); done
python3 - <<'PY'
import json
d=json.load(open('cr-stats_format_json_since_2026-10-25.json'))
for b in d['byBot']:
  if any(x in b['bot'] for x in ['User','Perplexity','Search','その他']): print(b)
print(d['truncated'])
for k in ['ev-stats_format_json_since_2026-10-26_who_human','ev-stats_format_json_since_2026-10-26_who_unknown','ev-stats_format_json_since_2026-10-26_who_bot']:
  e=json.load(open(k+'.json')); print(k, e['counted'])
  print(' refs', [r for r in e['referrers'] if any(s in r['from'] for s in ['chatgpt','openai','perplexity','claude','gemini','copilot','bing'])])
  print(' utm', e['utmSources'][:10])
PY

cr-stats_format_json_since_2026-10-25 28193
ev-stats_format_json_since_2026-10-26_who_human 29699
ev-stats_format_json_since_2026-10-26_who_unknown 9715
ev-stats_format_json_since_2026-10-26_who_bot 20735
{'bot': 'OAI-SearchBot', 'who': 'OpenAI（ChatGPT の検索）', 'visits': 437, 'pages': 135, 'records': 113, 'verified': 434, 'unverified': 3, 'errors': 1, 'last': '2026-11-05'}
{'bot': 'ChatGPT-User', 'who': 'ChatGPT（利用者の依頼で読む）', 'visits': 88, 'pages': 48, 'records': 42, 'verified': 78, 'unverified': 10, 'errors': 0, 'last': '2026-11-05'}
{'bot': 'その他', 'who': 'その他（「AIで読む」経由で、名乗りが一覧にない読み手）', 'visits': 73, 'pages': 52, 'records': 50, 'verified': 3, 'unverified': 70, 'errors': 2, 'last': '2026-11-05'}
{'bot': 'PerplexityBot', 'who': 'Perplexity（検索）', 'visits': 65, 'pages': 23, 'records': 17, 'verified': 0, 'unverified': 65, 'errors': 0, 'last': '2026-11-05'}
{'bot': 'Claude-User', 'who': 'Claude（利用者の依頼で読む）', 'visits': 17, 'pages': 16, 'records': 12, 'verified': 0, 'unverified': 17, 'errors': 0, 'last': '2026-11-03'}
True
ev-stats_format_json_since_2026-10-26_who_human 275
 refs [{'from': 'chatgpt.com（リンクの印）', 'count': 2}, {'from': 'www.bing.com', 'count': 2}]
 utm [{'source': 'chatgpt.com', 'count': 2}]
ev-stats_format_json_since_2026-10-26_who_unknown 101
 refs []
 utm []
ev-stats_format_json_since_2026-10-26_who_bot 3361
 refs [{'from': 'bing.com', 'count': 1}]
 utm []
```


### 利用者の依頼で読む AI は ChatGPT-User と Claude-User だけで、Perplexity は依頼で読んでいなかった

上の出力の読み方です。

- ChatGPT-User（ChatGPT が利用者に頼まれて読む）は88回。そのうち Cloudflare が本物と確かめられなかったものが10回ある。名乗りはまねできるので、この10回は数に入れないことにした
- Claude-User（Claude が利用者に頼まれて読む）は17回で、Cloudflare は Claude-User を確かめない（確かめた0・確かめられなかった17）。全部を数に入れる
- PerplexityBot の65回は Perplexity の検索のための巡回で、利用者の依頼で読む Perplexity-User は0回だった。1つ目の数字には入れない
- AI のリンクから人が来たのは、人の表示275回のうち、chatgpt.com の印が付いた2回だけだった。機械・操作なしの表示に AI のリンクはなかった（bing.com は検索なので入れない）
- 「truncated True」が出ている。10月25日から数えた表は、記録が多すぎて一部しか数えていなかった


### ChatGPT-User の読みは、「AIで読む」ボタン経由がほとんどない

ChatGPT-User と Claude-User が読んだページと、「AIで読む」ボタンの印（`?via=`）が付いた読みを、クローラーの表から取りました。

```text
# 1回目：5つの日付 × 4つのクローラーをまとめて取ろうとしたが、1回が長く、120秒で打ち切られた（10/25 と 10/28 の分だけ取れた）
$ cd $HOME/kpi_check && K=$(tr -d '\n\r ' < $HOME/mnt/KIOXIA/p2m_stats_key.txt); for d in 2026-10-25 2026-10-28 2026-11-01 2026-11-03 2026-11-05; do for b in ChatGPT-User Claude-User Perplexity-User PerplexityBot; do curl -s -H "Authorization: Bearer $K" "https://pixelstomotors.com/api/cr-stats?format=json&since=$d&bot=$b" > c_${d}_$b.json; done; done
Command timed out after 120000ms.

# 2回目：11/1 からの ChatGPT-User だけを取った（1回に約11秒）
$ cd $HOME/kpi_check && K=$(tr -d '\n\r ' < $HOME/mnt/KIOXIA/p2m_stats_key.txt); time curl -s -m 100 -H "Authorization: Bearer $K" "https://pixelstomotors.com/api/cr-stats?format=json&since=2026-11-01&bot=ChatGPT-User" > s1101_chat.json; wc -c s1101_chat.json

real	0m11.325s
user	0m0.141s
sys	0m0.133s
12574 s1101_chat.json

# 取れたファイルを読む
$ cd $HOME/kpi_check && python3 - <<'PY'
import json
for f in ['c_2026-10-25_ChatGPT-User.json','c_2026-10-25_Claude-User.json','c_2026-10-25_PerplexityBot.json','s1101_chat.json']:
  j=json.load(open(f))
  bot=j['bot']
  print('==',f,'trunc',j['truncated'],'total',j['total'])
  print(' pages',[(p['path'],p['visits']) for p in j['byPage'][:12]])
  print(' via',[(v['via'],v['visits'],v['bots']) for v in j['byVia']])
PY
```

```text
== c_2026-10-25_ChatGPT-User.json trunc True total 19252
 pages [('/', 27), ('/record/beyond-imitation-learning', 4), ('/record/from-sim-series-to-lp', 3), ('/record/pixelstomotors-com-domain', 2), ('/record/microfactory-fairino-fr3', 2), ('/record/serving-robot-observation-sheet', 2), ('/record/serving-robot-cost-subsidy', 2), ('/serving-robot-one-less-staff', 2), ('/record/openpi-remote-inference-first-run', 2), ('/record/video-patterns-and-try-it', 2), ('/record/serving-robot-video-ledger', 2), ('/record/pi05-libero-benchmark-first-run', 2)]
 via [('gemini', 296, 'Amazonbot 257、その他 39'), ('copy', 283, 'Amazonbot 253、その他 30'), ('chatgpt', 61, 'Googlebot 55、その他 3、Amazonbot 2、ChatGPT-User 1'), ('claude', 3, 'Claude-User 1、その他 1、Amazonbot 1')]
== c_2026-10-25_Claude-User.json trunc True total 19252
 pages [('/robots.txt', 2), ('/record/what-i-think-now-page', 1), ('/record/making-explainer-video-with-ai', 1), ('/consult', 1), ('/llms.txt', 1), ('/record/gamepad-moves-mecharm-270-pymycobot-version', 1), ('/record/serving-robot-faceoff-staff-resolves', 1), ('/record/ai-reads-more-than-people', 1), ('/record/retrained-pi05-still-needs-human-corrections', 1), ('/record/building-a-physical-ai-lab-at-home', 1), ('/gpu-buy-or-rent', 1), ('/record/openpi-remote-inference-first-run', 1)]
 via [('gemini', 296, 'Amazonbot 257、その他 39'), ('copy', 283, 'Amazonbot 253、その他 30'), ('chatgpt', 61, 'Googlebot 55、その他 3、Amazonbot 2、ChatGPT-User 1'), ('claude', 3, 'Claude-User 1、その他 1、Amazonbot 1')]
== c_2026-10-25_PerplexityBot.json trunc True total 19252
 pages [('/', 27), ('/robots.txt', 12), ('/record/day17', 3), ('/consult', 2), ('/record/serving-robot-stage-b-18-runs', 2), ('/record/openpi-remote-inference-first-run', 2), ('/record/serving-robot-jam-points', 1), ('/record/serving-robot-map-planner', 1), ('/record/claude-project-linked-folders', 1), ('/record/pi05-first-block-in-box', 1), ('/record/pi05-all-three-positions', 1), ('/record/explainer-video-simulation-background', 1)]
 via [('gemini', 296, 'Amazonbot 257、その他 39'), ('copy', 283, 'Amazonbot 253、その他 30'), ('chatgpt', 61, 'Googlebot 55、その他 3、Amazonbot 2、ChatGPT-User 1'), ('claude', 3, 'Claude-User 1、その他 1、Amazonbot 1')]
== s1101_chat.json trunc False total 10983
 pages [('/', 8), ('/record/beyond-imitation-learning', 4), ('/record/pi05-libero-benchmark-first-run', 2), ('/record/video-patterns-and-try-it', 1), ('/files/LOG383/18_Assets_ServiceSim_Editor_BuildHeadless.cs.txt', 1), ('/record/hakobu-4koma-english-without-redrawing', 1), ('/llms.txt', 1), ('/record/retrained-pi05-still-needs-human-corrections', 1), ('/record/serving-robot-jam-detection-without-path-lines', 1), ('/record/rewind-and-correct-pi05', 1), ('/record/decisions-api-grasp-check', 1), ('/record/serving-robot-observation-sheet', 1)]
 via [('gemini', 352, 'Amazonbot 308、その他 44'), ('copy', 342, 'Amazonbot 309、その他 33'), ('chatgpt', 67, 'Googlebot 61、その他 3、Amazonbot 2、ChatGPT-User 1'), ('claude', 4, 'その他 2、Claude-User 1、Amazonbot 1')]
```

- ボタンの印の付いた読み（via）の大半は Amazonbot と Googlebot で、ChatGPT-User は1回、Claude-User は1回だけだった。ChatGPT-User の読みは、ほとんどが記事のボタンを押さずに、だれかが ChatGPT に質問して起きたものと見られる
- ChatGPT-User が一番多く読んだのはトップ（/）の27回。エイイチが自分で ChatGPT にこのサイトのことを聞いた分も、ここに入りうる。見分ける方法はない
- 10月25日からの表は total 19,252 で truncated True。11月1日からの表は total 10,983 で truncated False。数えるページの上限（40回）に、長い期間だと届いてしまう


### 11/3 の Claude-User 12回は、確かめの読みの可能性が高い

日ごとに数え直すと（下の「作業ログ ― 3つの数字を日ごとに集計して R2 に残す」）、Claude-User は11月3日に12回あり、ほかの日は0〜1回でした。読んだページは `/llms.txt`（AI 向けのサイトの案内）と、いろいろな記録を1件ずつです。11月3日は、トップに「このサイトの楽しみ方」を入れた日で、その確かめで Claude にサイトを読ませた分が入っている可能性が高いと見ています。

Claude が WebFetch（Claude の、ページを読む道具）でサイトを読むと Claude-User として記録されるかを確かめようとしましたが、この作業環境からは pixelstomotors.com を WebFetch で開けませんでした（許可された住所の一覧にない）。数の読み方の説明（下の MCP の `how_to_read`）に、自分や Claude の試しが混ざりうることを書いておくことにしました。


## 作業ログ ― 3つの数字を日ごとに集計して R2 に残す

これまでの計測の表（`/api/ev-stats`・`/api/cr-stats`）は、開くたびに、R2 に1件ずつ置いた記録をすべて数え直していました。記録は1日に約2,000件ずつ増えるので、期間が長いほど遅くなり、上限に届くと黙って一部だけを数えます。そこで、3つの数字だけを1日ずつ数えて残す形にしました。


### Cloudflare Workers と R2 は、このサイトの入口と保管庫

pixelstomotors.com は Cloudflare の上で動いています（[Cloudflare Workers](https://developers.cloudflare.com/workers/)・[Cloudflare R2](https://developers.cloudflare.com/r2/)）。

| 言葉 | このサイトでの意味 |
|---|---|
| Workers | サイトの入口のプログラム（`worker/index.js`）。ページを返し、計測の記録を受け取り、数の表を作る。5分ごとに決まった処理も動かせる（scheduled） |
| R2 | Cloudflare のファイルの保管庫。計測の記録は `p2m-messages` に1件ずつ空のファイルとして置き、中身は付箋（customMetadata）に書いている |
| 秘密の値 | Workers に渡す鍵（`STATS_KEY` など）。コードにも GitHub にも入れず、Cloudflare に置く |

日ごとの集計は R2 の `p2m-messages` の `kpi/{日付}.json` に置きます。置き場所は、作る前に MASTER の保存先の表に足しました（エイイチ）。

- ねらい：3つの数字を、毎回生の記録から数え直さずに読めるようにする
- 変わったこと：日本時間で日付が変わったあとの最初の5分ごとの処理が、前の日の分を数えて `kpi/{日付}.json` に残す。今日の分だけは、読むたびに数える
- 見込める効果：期間を長くしても数え漏れがなく、読むのが速い。10月26日から11月6日までの12日分を最初に作ったときは、1回目の呼び出しで10日分、2回目で残りを作った（1回で作るのは10日分まで）


### worker/kpi.js（3つの数字を1日ずつ数えて残すコード・全文）

```js
// 主に見る3つの数字を、日ごとに集計して残す（2026-11-06）。
// サイトの今のねらいは「AI に調べられることで、人の来訪や知名度がいつ増えはじめるか」を見ること。
// そのために見る数字を3つに絞った（エイイチ 2026-11-06）：
//   1. aiReads      AI の利用者の依頼で読みに来た数（ChatGPT-User・Claude-User・Perplexity-User・MistralAI-User）
//   2. aiReferrals  AI のサービス（chatgpt.com など）のリンクから来た人の数（人の操作があった表示だけ）
//   3. nameSearch   サイト名で検索して来た人の数（Search Console の数。ここでは集計できないので、別に記録したものを返す）
//
// 置き場所は R2（p2m-messages）の kpi/{日付}.json。日本時間で1日が終わったら、5分ごとの scheduled が前の日の分を作る。
// 元の記録（cr/{日付}/・ev/{日付}/）は読むだけで、変えない。
// 作り直すときは kpi/{日付}.json を消すか、KPI_VERSION を上げる（版が古いものは読むときに作り直す）。

export const KPI_VERSION = 1;
export const KPI_FIRST_DAY = '2026-10-26'; // 人と機械を分け始めた日（それより前の来訪の数は人の数として使えない）

// 1. 利用者の依頼で読む AI（学習・検索のための巡回は入れない）
const AI_USER_BOTS = new Set(['ChatGPT-User', 'Claude-User', 'Perplexity-User', 'MistralAI-User']);
// 読んだ数に入れないページ（読む前の確かめ）
const AI_READ_SKIP = new Set(['/robots.txt']);

// 2. AI のサービスの住所（referrer のホスト）と、リンクに付く印（utm_source）
const AI_HOSTS = {
  'chatgpt.com': 'ChatGPT', 'chat.openai.com': 'ChatGPT',
  'perplexity.ai': 'Perplexity', 'www.perplexity.ai': 'Perplexity',
  'claude.ai': 'Claude',
  'gemini.google.com': 'Gemini', 'bard.google.com': 'Gemini',
  'copilot.microsoft.com': 'Copilot', 'copilot.cloud.microsoft': 'Copilot',
  'chat.deepseek.com': 'DeepSeek', 'grok.com': 'Grok', 'you.com': 'You.com',
  'felo.ai': 'Felo', 'www.genspark.ai': 'Genspark', 'genspark.ai': 'Genspark', 'phind.com': 'Phind', 'www.phind.com': 'Phind',
};
const AI_UTM = {
  'chatgpt.com': 'ChatGPT', 'chatgpt': 'ChatGPT', 'openai': 'ChatGPT',
  'perplexity': 'Perplexity', 'perplexity.ai': 'Perplexity',
  'claude.ai': 'Claude', 'claude': 'Claude',
  'gemini': 'Gemini', 'gemini.google.com': 'Gemini',
  'copilot.com': 'Copilot', 'copilot': 'Copilot', 'copilot.microsoft.com': 'Copilot',
};
export const aiSourceOf = (r, us) => AI_HOSTS[r] || AI_UTM[us] || '';

const jstDay = (ms) => new Date(ms + 9 * 3600e3).toISOString().slice(0, 10);
export const todayJst = () => jstDay(Date.now());
export const addDays = (day, n) => { const d = new Date(day + 'T00:00:00Z'); d.setUTCDate(d.getUTCDate() + n); return d.toISOString().slice(0, 10); };
export const weekOf = (day) => { const d = new Date(day + 'T00:00:00Z'); d.setUTCDate(d.getUTCDate() - ((d.getUTCDay() + 6) % 7)); return d.toISOString().slice(0, 10); };
const inc = (o, k, n = 1) => { o[k] = (o[k] || 0) + n; return o; };
const topOf = (o, n) => Object.entries(o).sort((a, b) => b[1] - a[1]).slice(0, n).map(([k, v]) => ({ key: k, count: v }));

async function listAll(env, prefix) {
  const out = [];
  let cursor;
  do {
    const r = await env.MESSAGES.list({ prefix, cursor, include: ['customMetadata'], limit: 1000 });
    for (const o of r.objects) out.push(o);
    cursor = r.truncated ? r.cursor : undefined;
  } while (cursor);
  return out;
}

// 1日分を元の記録から数える
export async function computeKpiDay(env, day) {
  // 1. AI の利用者の依頼で読みに来た数（cr/）
  const ai = { total: 0, byBot: {}, unverifiedChatGPT: 0, viaButton: 0, pages: {} };
  for (const o of await listAll(env, `cr/${day}/`)) {
    const m = o.customMetadata || {};
    if (!AI_USER_BOTS.has(m.b) || AI_READ_SKIP.has(m.p)) continue;
    // ChatGPT-User は Cloudflare が本物かを確かめられる。確かめられなかったもの（偽物が混ざりうる）は数に入れず、別に数える
    if (m.b === 'ChatGPT-User' && m.ok === '0') { ai.unverifiedChatGPT++; continue; }
    ai.total++; inc(ai.byBot, m.b); inc(ai.pages, m.p);
    if (m.v) ai.viaButton++; // 記事の「AIで読む」ボタンから（エイイチ・Claude の試しが混ざりうる）
  }
  // 2. AI のサービスのリンクから来た人（ev/。同じ表示を送り直したものは n が最大の1件）
  const views = new Map();
  for (const o of await listAll(env, `ev/${day}/`)) {
    const m = o.customMetadata || {};
    if (!m.v) continue;
    const prev = views.get(m.v);
    if (!prev || Number(m.n) >= Number(prev.n)) views.set(m.v, m);
  }
  const ref = { total: 0, bySource: {}, landing: {}, notHuman: 0 };
  let humanViews = 0, humanEntries = 0;
  for (const m of views.values()) {
    const isHuman = m.k === 'h';
    if (isHuman) humanViews++;
    if (isHuman && !m.f) humanEntries++;
    const src = aiSourceOf(m.r || '', m.us || '');
    if (!src) continue;
    if (!isHuman) { ref.notHuman++; continue; } // 機械・操作なしの表示は数に入れない（別に数える）
    ref.total++; inc(ref.bySource, src); inc(ref.landing, m.p);
  }
  return {
    version: KPI_VERSION, day, week: weekOf(day), madeAt: new Date().toISOString(),
    aiReads: { total: ai.total, byBot: ai.byBot, viaButton: ai.viaButton, unverifiedChatGPTExcluded: ai.unverifiedChatGPT, topPages: topOf(ai.pages, 20) },
    aiReferrals: { total: ref.total, bySource: ref.bySource, landing: topOf(ref.landing, 20), notHumanExcluded: ref.notHuman },
    context: { humanViews, humanEntriesFromOutside: humanEntries },
  };
}

// 残してある1日分を読む（なければ作って残す。今日の分は途中なので残さない）
export async function getKpiDay(env, day, { create = true } = {}) {
  const today = todayJst();
  if (day >= today) return { ...(await computeKpiDay(env, day)), partial: true };
  const obj = await env.MESSAGES.get(`kpi/${day}.json`);
  if (obj) {
    try { const d = await obj.json(); if (d.version === KPI_VERSION) return d; } catch { /* 壊れていたら作り直す */ }
  }
  if (!create) return null;
  const d = await computeKpiDay(env, day);
  await env.MESSAGES.put(`kpi/${day}.json`, JSON.stringify(d), { httpMetadata: { contentType: 'application/json' } });
  return d;
}

// 3. サイト名で検索して来た人（Search Console の数。週ごとに kpi-sc/{週の月曜}.json に記録したもの）
export async function getNameSearch(env, since, until) {
  const out = [];
  const r = await env.MESSAGES.list({ prefix: 'kpi-sc/', limit: 1000 });
  for (const o of r.objects) {
    const w = o.key.slice('kpi-sc/'.length, -'.json'.length);
    if (w < weekOf(since) || w > until) continue;
    const obj = await env.MESSAGES.get(o.key);
    if (obj) { try { out.push(await obj.json()); } catch { /* 読めないものは飛ばす */ } }
  }
  return out.sort((a, b) => a.week.localeCompare(b.week));
}

// 期間の数をまとめる。足りない日は作る（1回で作るのは maxCreate 日まで。残りは次に読んだときに作る）
export async function kpiRange(env, since, until, { maxCreate = 10 } = {}) {
  since = since < KPI_FIRST_DAY ? KPI_FIRST_DAY : since;
  const today = todayJst();
  if (until > today) until = today;
  const days = [];
  let created = 0, pending = [];
  for (let d = since; d <= until; d = addDays(d, 1)) {
    let k = await getKpiDay(env, d, { create: false });
    if (!k && created < maxCreate) { k = await getKpiDay(env, d); created++; }
    if (k) days.push(k); else pending.push(d);
  }
  const weeks = new Map();
  for (const k of days) {
    const w = weeks.get(k.week) || { week: k.week, days: 0, aiReads: 0, aiReadsViaButton: 0, aiReferrals: 0, humanViews: 0, aiReadsByBot: {}, aiReferralsBySource: {} };
    w.days++; w.aiReads += k.aiReads.total; w.aiReadsViaButton += k.aiReads.viaButton; w.aiReferrals += k.aiReferrals.total; w.humanViews += k.context.humanViews;
    for (const [b, n] of Object.entries(k.aiReads.byBot)) inc(w.aiReadsByBot, b, n);
    for (const [s, n] of Object.entries(k.aiReferrals.bySource)) inc(w.aiReferralsBySource, s, n);
    weeks.set(k.week, w);
  }
  const nameSearch = await getNameSearch(env, since, until);
  return {
    since, until, pendingDays: pending,
    byWeek: [...weeks.values()].map((w) => ({ ...w, nameSearch: (nameSearch.find((x) => x.week === w.week) || {}).clicks ?? null })),
    byDay: days.map((k) => ({ day: k.day, partial: !!k.partial, aiReads: k.aiReads.total, aiReadsViaButton: k.aiReads.viaButton, aiReferrals: k.aiReferrals.total, humanViews: k.context.humanViews, aiReadsByBot: k.aiReads.byBot, aiReferralsBySource: k.aiReferrals.bySource })),
    detailDays: days,
    nameSearch,
  };
}

// 5分ごとの scheduled から：前の日の分がまだなければ作る
export async function kpiCron(env) {
  const y = addDays(todayJst(), -1);
  if (await env.MESSAGES.head(`kpi/${y}.json`)) return 'kpi: ok';
  await getKpiDay(env, y);
  return `kpi: made ${y}`;
}
```


### worker/index.js の入口の部分（kpi・MCP・Search Console をつないだあと）

```js
// サイトの入口。ほとんどのページは作っておいた静的ファイル（dist/）をそのまま返す。
// ここで処理するのは3つだけ:
// - /pixelstomotors/…   旧 URL の形。/pixelstomotors を外した URL へ 301 で転送する
// - /media/{ファイル名}  記事・4コマの画像と動画を R2（p2m-media）から返す（GitHub には入れないため）
// - /api/message         メッセージフォームの送信を R2（p2m-messages）に保存し、メールで知らせる
// - /api/hk-event        更新を知らせるハコブくんが「出た・押された・あとで見に来た」を R2（p2m-messages の hk-events/）に1件ずつ残す
// - /api/hk-stats        その記録を日ごと・更新ごとに数えて見せる（数だけ。誰かは分からない）
// - /api/ev              サイトの使われ方（1回のページ表示ごとの、読んだ深さ・押したもの・迷い）を R2（p2m-messages の ev/）に残す
// - /api/ev-stats        その記録を週ごと・ページごとに数えて見せる（数だけ。誰かは分からない）
// - ページ・llms.txt・全文の Markdown など  静的ファイルを返す。検索エンジン・AI のクローラーが読みに来たら、R2（p2m-messages の cr/）に1件ずつ残す
// - /api/cr-stats        その記録を、どのクローラーが・いつ・どのページを読んだかで数えて見せる（2026-10-25）
// - /api/kpi-stats       主に見る3つの数字（AI の依頼読み・AI のリンクからの来訪・サイト名の検索）を日ごと・週ごとに見せる（worker/kpi.js。2026-11-06）
// - /mcp/{鍵}            サイトの計測を Claude につなぐ部品（MCP サーバー。worker/mcp.js。2026-11-06）
// - 5分ごとの scheduled  SNS の予約投稿の時刻が来ていたら GitHub Actions を起こす（worker/sns_cron.js）。前の日の3つの数字がまだなければ集計して残す（worker/kpi.js）
//
// 守り（2026-10-23）
// - 数の表（/api/hk-stats・/api/ev-stats・/api/cr-stats）は、鍵（Cloudflare の秘密の値 STATS_KEY）を付けたときだけ見られる。鍵がなければ 404
// - 送信の口（/api/message・/api/hk-event・/api/ev）は、このサイトのページから送られたものだけ受け取る
// - 同じ送信元からの送りすぎは、Cloudflare の流量制限（wrangler.jsonc の ratelimits）で断る。送信元の IP アドレスは数えるためだけに使い、記録しない
// - フォームには人には見えない欄（website）を置き、そこが埋まった送信は保存せずに受け取ったふりをする（自動投稿の対策）
// - このファイルが返す応答には、内容の種類を推測させない指定（nosniff）を付ける。ページ側の指定は public/_headers
import { EmailMessage } from 'cloudflare:email';
import { snsCron } from './sns_cron.js';
import { kpiCron, kpiRange, todayJst, addDays } from './kpi.js';
import { handleMcp } from './mcp.js';
import { gscRefresh } from './gsc.js';

export default {
  async fetch(request, env, ctx) {
    const url = new URL(request.url);
    if (url.pathname.startsWith('/mcp/')) return secured(await handleMcp(request, env, url, { evStats, crStats, hkStats }));
    if (url.pathname.startsWith('/api/') || url.pathname.startsWith('/media/') || url.pathname === '/pixelstomotors' || url.pathname.startsWith('/pixelstomotors/')) {
      return secured(await route(request, env, url));
    }
    // 古い住所・まちがった住所への訪問を、今のページへ恒久転送する（2026-10-30。クローラーの「返せなかったページ」から）
    const moved = movedTo(url.pathname);
    if (moved) {
      const to = new URL(moved, url);
      to.search = url.search;
      // クローラーの記録にも残す（返した結果 301。どの古い住所に来たかが分かるように）
      try {
        const bot = crawlerOf(request, url);
        if (bot) ctx.waitUntil(crRecord(request, env, url, bot, 301).catch(() => {}));
      } catch { /* 数え損ねても転送はする */ }
      return secured(Response.redirect(to.toString(), 301));
    }
    let res = await env.ASSETS.fetch(request);
    // 記事の全文ページ（/record/{slug}.md。2026-11-01）は、検索では記事ページを正とする（canonical）。文字コードも付ける
    const full = res.ok && url.pathname.match(/^\/record\/([^/]+)\.md$/);
    if (full) {
      res = new Response(res.body, res);
      res.headers.set('Content-Type', 'text/markdown; charset=utf-8');
      res.headers.set('Link', `<https://pixelstomotors.com/record/${full[1]}>; rel="canonical"`);
    }
    // 検索エンジン・AI のクローラーが読みに来たか（記録の失敗でページを止めない）
    // 記事の「AIで読む」から来た全文ページ（?via=chatgpt など）は、名乗りが一覧にない読み手（Gemini など）も「その他」として残す（2026-11-01）
    try {
      // TOP の「このサイトの楽しみ方」から来た /llms.txt?via=… も同じく数える（2026-11-03）
      const via = (/^\/record\/[^/]+\.md$/.test(url.pathname) || (/^\/record\/[^/.]+$/.test(url.pathname) && url.searchParams.get('via') === 'gemini') || url.pathname === '/llms.txt' || url.pathname === '/llms' || url.pathname === '/llms.html') && AI_VIA.has(url.searchParams.get('via') || '') ? url.searchParams.get('via') : '';
      const bot = crawlerOf(request, url) || (via ? 'その他' : null);
      if (bot) ctx.waitUntil(crRecord(request, env, url, bot, res.status, via).catch(() => {}));
    } catch { /* 数え損ねてもページは返す */ }
    return res;
  },
  // 5分ごと（wrangler.jsonc の triggers）：SNS の予約投稿の時刻が来ていたら、GitHub Actions を起こす（worker/sns_cron.js）
  async scheduled(event, env, ctx) {
    ctx.waitUntil(snsCron(env, event.scheduledTime).then((m) => console.log('sns-cron:', m), (e) => console.error('sns-cron:', e.message)));
    // 前の日の分を作ったとき（1日1回）だけ、Search Console からサイト名の検索の数も取り直す（worker/gsc.js）
    ctx.waitUntil(kpiCron(env).then(async (m) => {
      console.log(m);
      if (m.startsWith('kpi: made')) console.log('gsc:', JSON.stringify(await gscRefresh(env)));
    }).catch((e) => console.error('kpi-cron:', e.message)));
  },
};
```


### worker/index.js の route（数の表の住所を振り分ける部分）

```js
async function route(request, env, url) {
    // 旧 URL の形（/pixelstomotors/…）で来たら、/pixelstomotors を外した URL へ恒久転送する
    if (url.pathname === '/pixelstomotors' || url.pathname.startsWith('/pixelstomotors/')) {
      const to = new URL(url.pathname.slice('/pixelstomotors'.length) || '/', url);
      to.search = url.search;
      return Response.redirect(to.toString(), 301);
    }
    if (url.pathname.startsWith('/media/')) return media(request, env, url);
    if (url.pathname === '/api/message') return guarded(request, env, url, 'RL_MESSAGE', () => message(request, env));
    if (url.pathname === '/api/hk-event') return guarded(request, env, url, 'RL_EVENT', () => hkEvent(request, env));
    if (url.pathname === '/api/ev') return guarded(request, env, url, 'RL_EVENT', () => evRecord(request, env, url));
    if (url.pathname === '/api/hk-stats') return (await statsAllowed(request, env, url)) ? hkStats(request, env, url) : notFound();
    if (url.pathname === '/api/ev-stats') return (await statsAllowed(request, env, url)) ? evStats(request, env, url) : notFound();
    if (url.pathname === '/api/cr-stats') return (await statsAllowed(request, env, url)) ? crStats(request, env, url) : notFound();
    if (url.pathname === '/api/kpi-stats') return (await statsAllowed(request, env, url)) ? kpiStats(request, env, url) : notFound();
    return env.ASSETS.fetch(request);
}
```


### worker/index.js の kpiStats（/api/kpi-stats の表）

```js
// ───────── 主に見る3つの数字（2026-11-06。集計は worker/kpi.js）─────────
async function kpiStats(request, env, url) {
  if (request.method !== 'GET') return new Response('Method Not Allowed', { status: 405 });
  const day = (k, d) => (/^\d{4}-\d{2}-\d{2}$/.test(url.searchParams.get(k) || '') ? url.searchParams.get(k) : d);
  const today = todayJst();
  // ?sc=refresh で Search Console からサイト名の検索の数を取り直す（?since= の週から。最初の埋め戻し用）
  if (url.searchParams.get('sc') === 'refresh') {
    try { return json(await gscRefresh(env, { since: day('since', '') })); } catch (e) { return json({ ok: false, error: e.message }, 500); }
  }
  const data = await kpiRange(env, day('since', addDays(today, -28)), day('until', today));
  if (url.searchParams.get('format') === 'json') {
    return new Response(JSON.stringify(data), { headers: { 'content-type': 'application/json; charset=utf-8', 'x-robots-tag': 'noindex', 'cache-control': 'no-store' } });
  }
  const esc = (s) => String(s).replace(/[&<>"]/g, (ch) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[ch]));
  const kv = (o) => Object.entries(o || {}).sort((a, b) => b[1] - a[1]).map(([k, v]) => `${k} ${v}`).join('、');
  const table = (cols, list) => list.length
    ? `<div class="wrap"><table><tr>${cols.map(([, h]) => `<th>${h}</th>`).join('')}</tr>${list.map((r) => `<tr>${cols.map(([k, , f]) => `<td>${esc(f ? f(r[k], r) : (r[k] ?? '-'))}</td>`).join('')}</tr>`).join('')}</table></div>`
    : '<p>まだ記録がありません。</p>';
  const html = `<!doctype html><html lang="ja"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex">
<title>3つの数字</title><style>body{font:14px/1.7 -apple-system,'Noto Sans JP',sans-serif;margin:24px;color:#242424;background:#f7f7f7}
h1{font-size:20px}h2{font-size:16px;margin-top:28px}.wrap{overflow-x:auto}table{border-collapse:collapse;background:#fff}th,td{border:1px solid #ddd;padding:6px 10px;text-align:left;white-space:nowrap}th{background:#eee}p{color:#555}</style></head><body>
<h1>3つの数字</h1><p>AI に調べられることで、人の来訪や知名度がいつ増えはじめるかを見るための数。日付は日本時間、週は月曜はじまり。${esc(data.since)} 〜 ${esc(data.until)}（?since=・?until= で変える）。${data.pendingDays.length ? ` 集計がまだの日が ${data.pendingDays.length} 日ある（開き直すと作る）。` : ''}</p>
<p>AI の依頼読み：ChatGPT-User・Claude-User・Perplexity-User などが読んだページの数（「AIで読む」ボタン経由はエイイチ・Claude の試しが混ざりうる）。AI のリンクから：chatgpt.com などのリンクから来た、人の操作があった表示。サイト名の検索：Search Console から週ごとに記録したクリック数。</p>
<h2>週ごと</h2>${table([['week', '週（月曜）'], ['days', '日数'], ['aiReads', 'AI の依頼読み'], ['aiReadsViaButton', 'うちボタン経由'], ['aiReferrals', 'AI のリンクから来た人'], ['nameSearch', 'サイト名の検索（クリック）'], ['humanViews', '人の表示（参考）'], ['aiReadsByBot', '依頼読みの内訳', kv], ['aiReferralsBySource', 'リンクの内訳', kv]], [...data.byWeek].reverse())}
<h2>日ごと</h2>${table([['day', '日付', (v, r) => v + (r.partial ? '（途中）' : '')], ['aiReads', 'AI の依頼読み'], ['aiReadsViaButton', 'うちボタン経由'], ['aiReferrals', 'AI のリンクから来た人'], ['humanViews', '人の表示（参考）'], ['aiReadsByBot', '依頼読みの内訳', kv], ['aiReferralsBySource', 'リンクの内訳', kv]], [...data.byDay].reverse())}
</body></html>`;
  return new Response(html, { headers: { 'content-type': 'text/html; charset=utf-8', 'x-robots-tag': 'noindex', 'cache-control': 'no-store' } });
}
```


### worker/index.js の変更の差分（3つのコミットの合計）

ついでに、更新を知らせるハコブくんの記録の表（`/api/hk-stats`）の画面が、前の変更の残りもの（`data.errors` という、その表にはない値を読む行）で開けなくなっていたのを直しました。数の JSON は前から出ていて、画面だけが落ちていました。

```diff
diff --git a/worker/index.js b/worker/index.js
index 97496c6..bbe919f 100644
--- a/worker/index.js
+++ b/worker/index.js
@@ -9,7 +9,9 @@
 // - /api/ev-stats        その記録を週ごと・ページごとに数えて見せる（数だけ。誰かは分からない）
 // - ページ・llms.txt・全文の Markdown など  静的ファイルを返す。検索エンジン・AI のクローラーが読みに来たら、R2（p2m-messages の cr/）に1件ずつ残す
 // - /api/cr-stats        その記録を、どのクローラーが・いつ・どのページを読んだかで数えて見せる（2026-10-25）
-// - 5分ごとの scheduled  SNS の予約投稿の時刻が来ていたら GitHub Actions を起こす（worker/sns_cron.js）
+// - /api/kpi-stats       主に見る3つの数字（AI の依頼読み・AI のリンクからの来訪・サイト名の検索）を日ごと・週ごとに見せる（worker/kpi.js。2026-11-06）
+// - /mcp/{鍵}            サイトの計測を Claude につなぐ部品（MCP サーバー。worker/mcp.js。2026-11-06）
+// - 5分ごとの scheduled  SNS の予約投稿の時刻が来ていたら GitHub Actions を起こす（worker/sns_cron.js）。前の日の3つの数字がまだなければ集計して残す（worker/kpi.js）
 //
 // 守り（2026-10-23）
 // - 数の表（/api/hk-stats・/api/ev-stats・/api/cr-stats）は、鍵（Cloudflare の秘密の値 STATS_KEY）を付けたときだけ見られる。鍵がなければ 404
@@ -19,10 +21,14 @@
 // - このファイルが返す応答には、内容の種類を推測させない指定（nosniff）を付ける。ページ側の指定は public/_headers
 import { EmailMessage } from 'cloudflare:email';
 import { snsCron } from './sns_cron.js';
+import { kpiCron, kpiRange, todayJst, addDays } from './kpi.js';
+import { handleMcp } from './mcp.js';
+import { gscRefresh } from './gsc.js';
 
 export default {
   async fetch(request, env, ctx) {
     const url = new URL(request.url);
+    if (url.pathname.startsWith('/mcp/')) return secured(await handleMcp(request, env, url, { evStats, crStats, hkStats }));
     if (url.pathname.startsWith('/api/') || url.pathname.startsWith('/media/') || url.pathname === '/pixelstomotors' || url.pathname.startsWith('/pixelstomotors/')) {
       return secured(await route(request, env, url));
     }
@@ -59,6 +65,11 @@ export default {
   // 5分ごと（wrangler.jsonc の triggers）：SNS の予約投稿の時刻が来ていたら、GitHub Actions を起こす（worker/sns_cron.js）
   async scheduled(event, env, ctx) {
     ctx.waitUntil(snsCron(env, event.scheduledTime).then((m) => console.log('sns-cron:', m), (e) => console.error('sns-cron:', e.message)));
+    // 前の日の分を作ったとき（1日1回）だけ、Search Console からサイト名の検索の数も取り直す（worker/gsc.js）
+    ctx.waitUntil(kpiCron(env).then(async (m) => {
+      console.log(m);
+      if (m.startsWith('kpi: made')) console.log('gsc:', JSON.stringify(await gscRefresh(env)));
+    }).catch((e) => console.error('kpi-cron:', e.message)));
   },
 };
 
@@ -101,6 +112,7 @@ async function route(request, env, url) {
     if (url.pathname === '/api/hk-stats') return (await statsAllowed(request, env, url)) ? hkStats(request, env, url) : notFound();
     if (url.pathname === '/api/ev-stats') return (await statsAllowed(request, env, url)) ? evStats(request, env, url) : notFound();
     if (url.pathname === '/api/cr-stats') return (await statsAllowed(request, env, url)) ? crStats(request, env, url) : notFound();
+    if (url.pathname === '/api/kpi-stats') return (await statsAllowed(request, env, url)) ? kpiStats(request, env, url) : notFound();
     return env.ASSETS.fetch(request);
 }
 
@@ -308,15 +320,6 @@ async function hkStats(request, env, url) {
   const byDay = new Map(), byWeek = new Map(), byItem = new Map(), byW = new Map();
   for (const r of rows) { add(byDay, r.day, r.e); add(byWeek, weekOf(r.day), r.e); add(byItem, r.id, r.e); add(byW, r.w, r.e); }
   const KIND_JA = { n: '機械の印なし', b: '機械', o: '印なし（10/28より前）' };
-  // 「AIで読む」経由（?via=）。押した AI ごとに、実際に読みに来たのはだれか（2026-11-01）
-  const viaMap = new Map();
-  for (const r of rows) {
-    if (!r.v) continue;
-    const e = viaMap.get(r.v) || { via: r.v, visits: 0, records: new Set(), bots: new Map(), last: '' };
-    e.visits++; e.records.add(r.p); count(e.bots, r.b); if (r.day > e.last) e.last = r.day; viaMap.set(r.v, e);
-  }
-  const viaWeeks = new Map();
-  for (const r of rows) { if (!r.v) continue; const w = viaWeeks.get(r.week) || new Map(); count(w, r.v); viaWeeks.set(r.week, w); }
   const data = {
     total: rows.length,
     who: who || null,
@@ -346,7 +349,6 @@ h1{font-size:20px}h2{font-size:16px;margin-top:28px}table{border-collapse:collap
 <h2>日ごと</h2>${table('日付', data.byDay, 'day')}
 <h2>更新ごと</h2>${table('更新', data.byItem, 'id')}
 <h2>画面の幅（pc＝広い／sp＝スマホ）</h2>${table('幅', data.byWidth, 'w')}
-<h2>返せなかったページ（400以上）</h2>${table([['path', 'ページ'], ['status', '返した結果'], ['visits', '回数'], ['bots', 'クローラー'], ['last', '最後の日']], data.errors)}
 <p>記録の件数：${data.total}</p></body></html>`;
   return new Response(html, { headers: { 'content-type': 'text/html; charset=utf-8', 'x-robots-tag': 'noindex', 'cache-control': 'no-store' } });
 }
@@ -501,15 +503,6 @@ async function evStats(request, env, url) {
     }
   }
   const top = (map, n, key) => [...map].sort((a, b) => b[1] - a[1]).slice(0, n).map(([k, v]) => ({ [key]: k, count: v }));
-  // 「AIで読む」経由（?via=）。押した AI ごとに、実際に読みに来たのはだれか（2026-11-01）
-  const viaMap = new Map();
-  for (const r of rows) {
-    if (!r.v) continue;
-    const e = viaMap.get(r.v) || { via: r.v, visits: 0, records: new Set(), bots: new Map(), last: '' };
-    e.visits++; e.records.add(r.p); count(e.bots, r.b); if (r.day > e.last) e.last = r.day; viaMap.set(r.v, e);
-  }
-  const viaWeeks = new Map();
-  for (const r of rows) { if (!r.v) continue; const w = viaWeeks.get(r.week) || new Map(); count(w, r.v); viaWeeks.set(r.week, w); }
   const data = {
     total: rows.length, counted: counted.length, truncated, since: since || null, week: week || null, who: who || null,
     byWeek,
@@ -672,3 +665,32 @@ ${table([['week', '週（月曜）'], ['total', '合計'], ['via', '内訳']], d
 <p>記録の件数：${data.total}</p></body></html>`;
   return new Response(html, { headers: { 'content-type': 'text/html; charset=utf-8', 'x-robots-tag': 'noindex', 'cache-control': 'no-store' } });
 }
+
+// ───────── 主に見る3つの数字（2026-11-06。集計は worker/kpi.js）─────────
+async function kpiStats(request, env, url) {
+  if (request.method !== 'GET') return new Response('Method Not Allowed', { status: 405 });
+  const day = (k, d) => (/^\d{4}-\d{2}-\d{2}$/.test(url.searchParams.get(k) || '') ? url.searchParams.get(k) : d);
+  const today = todayJst();
+  // ?sc=refresh で Search Console からサイト名の検索の数を取り直す（?since= の週から。最初の埋め戻し用）
+  if (url.searchParams.get('sc') === 'refresh') {
+    try { return json(await gscRefresh(env, { since: day('since', '') })); } catch (e) { return json({ ok: false, error: e.message }, 500); }
+  }
+  const data = await kpiRange(env, day('since', addDays(today, -28)), day('until', today));
+  if (url.searchParams.get('format') === 'json') {
+    return new Response(JSON.stringify(data), { headers: { 'content-type': 'application/json; charset=utf-8', 'x-robots-tag': 'noindex', 'cache-control': 'no-store' } });
+  }
+  const esc = (s) => String(s).replace(/[&<>"]/g, (ch) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' }[ch]));
+  const kv = (o) => Object.entries(o || {}).sort((a, b) => b[1] - a[1]).map(([k, v]) => `${k} ${v}`).join('、');
+  const table = (cols, list) => list.length
+    ? `<div class="wrap"><table><tr>${cols.map(([, h]) => `<th>${h}</th>`).join('')}</tr>${list.map((r) => `<tr>${cols.map(([k, , f]) => `<td>${esc(f ? f(r[k], r) : (r[k] ?? '-'))}</td>`).join('')}</tr>`).join('')}</table></div>`
+    : '<p>まだ記録がありません。</p>';
+  const html = `<!doctype html><html lang="ja"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="robots" content="noindex">
+<title>3つの数字</title><style>body{font:14px/1.7 -apple-system,'Noto Sans JP',sans-serif;margin:24px;color:#242424;background:#f7f7f7}
+h1{font-size:20px}h2{font-size:16px;margin-top:28px}.wrap{overflow-x:auto}table{border-collapse:collapse;background:#fff}th,td{border:1px solid #ddd;padding:6px 10px;text-align:left;white-space:nowrap}th{background:#eee}p{color:#555}</style></head><body>
+<h1>3つの数字</h1><p>AI に調べられることで、人の来訪や知名度がいつ増えはじめるかを見るための数。日付は日本時間、週は月曜はじまり。${esc(data.since)} 〜 ${esc(data.until)}（?since=・?until= で変える）。${data.pendingDays.length ? ` 集計がまだの日が ${data.pendingDays.length} 日ある（開き直すと作る）。` : ''}</p>
+<p>AI の依頼読み：ChatGPT-User・Claude-User・Perplexity-User などが読んだページの数（「AIで読む」ボタン経由はエイイチ・Claude の試しが混ざりうる）。AI のリンクから：chatgpt.com などのリンクから来た、人の操作があった表示。サイト名の検索：Search Console から週ごとに記録したクリック数。</p>
+<h2>週ごと</h2>${table([['week', '週（月曜）'], ['days', '日数'], ['aiReads', 'AI の依頼読み'], ['aiReadsViaButton', 'うちボタン経由'], ['aiReferrals', 'AI のリンクから来た人'], ['nameSearch', 'サイト名の検索（クリック）'], ['humanViews', '人の表示（参考）'], ['aiReadsByBot', '依頼読みの内訳', kv], ['aiReferralsBySource', 'リンクの内訳', kv]], [...data.byWeek].reverse())}
+<h2>日ごと</h2>${table([['day', '日付', (v, r) => v + (r.partial ? '（途中）' : '')], ['aiReads', 'AI の依頼読み'], ['aiReadsViaButton', 'うちボタン経由'], ['aiReferrals', 'AI のリンクから来た人'], ['humanViews', '人の表示（参考）'], ['aiReadsByBot', '依頼読みの内訳', kv], ['aiReferralsBySource', 'リンクの内訳', kv]], [...data.byDay].reverse())}
+</body></html>`;
+  return new Response(html, { headers: { 'content-type': 'text/html; charset=utf-8', 'x-robots-tag': 'noindex', 'cache-control': 'no-store' } });
+}
```


### 偽の R2 で kpi.js と mcp.js を動かした確かめ

本番に出す前に、R2 のふりをする小さな部品を作り、1日分の記録を置いて数え方を確かめました。置いた記録は、ChatGPT-User の確かめられた読み1回・確かめられなかった読み1回・Claude-User の robots.txt・ボタン経由の Claude-User・Amazonbot・PerplexityBot、人の表示（chatgpt.com の印）・機械の表示（perplexity.ai から）・Google から来た人・サイト内の移動です。下の出力は、記事化のときにもう一度動かしたものです。

#### test_kpi_mcp.mjs

```js
import { timingSafeEqual } from "node:crypto"; crypto.subtle.timingSafeEqual = (a, b) => timingSafeEqual(Buffer.from(a), Buffer.from(b));
import { computeKpiDay, kpiRange, kpiCron, todayJst, addDays } from '/home/claude/p2m-site/worker/kpi.js';
import { handleMcp, mcpKey } from '/home/claude/p2m-site/worker/mcp.js';
// R2 のまね
const store = new Map();
const R2 = {
  async list({ prefix = '', cursor, limit = 1000 }) { const keys = [...store.keys()].filter(k => k.startsWith(prefix)).sort(); const start = cursor ? +cursor : 0; const objs = keys.slice(start, start + 3).map(k => ({ key: k, customMetadata: store.get(k).meta })); const next = start + 3; return { objects: objs, truncated: next < keys.length, cursor: String(next) }; },
  async get(k) { const v = store.get(k); return v ? { json: async () => JSON.parse(v.body) } : null; },
  async head(k) { return store.has(k) ? {} : null; },
  async put(k, body, o = {}) { store.set(k, { body, meta: o.customMetadata || {} }); },
};
const env = { MESSAGES: R2, STATS_KEY: 'testkey' };
const y = addDays(todayJst(), -1);
const put = (k, meta) => store.set(k, { body: '', meta });
put(`cr/${y}/1-a`, { b: 'ChatGPT-User', p: '/', s: '200', ok: '1' });
put(`cr/${y}/2-a`, { b: 'ChatGPT-User', p: '/record/x', s: '200', ok: '0' });
put(`cr/${y}/3-a`, { b: 'Claude-User', p: '/robots.txt', s: '200', ok: '?' });
put(`cr/${y}/4-a`, { b: 'Claude-User', p: '/record/x.md', s: '200', ok: '?', v: 'claude' });
put(`cr/${y}/5-a`, { b: 'Amazonbot', p: '/record/x.md', s: '200', ok: '1', v: 'gemini' });
put(`cr/${y}/6-a`, { b: 'PerplexityBot', p: '/', s: '200', ok: '0' });
put(`ev/${y}/1-v1-0`, { v: 'v1', n: '0', p: '/', r: '', us: 'chatgpt.com', k: 'x' });
put(`ev/${y}/2-v1-1`, { v: 'v1', n: '1', p: '/', r: '', us: 'chatgpt.com', k: 'h' });
put(`ev/${y}/3-v2-0`, { v: 'v2', n: '0', p: '/gpu', r: 'perplexity.ai', us: '', k: 'b' });
put(`ev/${y}/4-v3-0`, { v: 'v3', n: '0', p: '/a', r: 'www.google.com', us: '', k: 'h' });
put(`ev/${y}/5-v4-0`, { v: 'v4', n: '0', p: '/b', f: '/a', r: '', us: '', k: 'h' });
console.log(JSON.stringify(await computeKpiDay(env, y), null, 1));
console.log(await kpiCron(env), await kpiCron(env));
const key = await mcpKey(env);
const call = async (body, k = key) => { const u = new URL(`https://pixelstomotors.com/mcp/${k}`); const r = await handleMcp(new Request(u, { method: 'POST', body: JSON.stringify(body) }), env, u, { evStats: async () => new Response('{"x":1}'), crStats: async (req, e, uu) => new Response(JSON.stringify({ q: uu.search })), hkStats: async () => new Response('{}') }); return [r.status, r.status === 200 ? await r.json() : null]; };
console.log(await call({ jsonrpc: '2.0', id: 1, method: 'initialize', params: { protocolVersion: '2025-06-18' } }, 'wrong'));
console.log(JSON.stringify(await call({ jsonrpc: '2.0', id: 1, method: 'initialize', params: { protocolVersion: '2025-06-18' } })));
console.log(await call({ jsonrpc: '2.0', method: 'notifications/initialized' }));
console.log((await call({ jsonrpc: '2.0', id: 2, method: 'tools/list' }))[1].result.tools.map(t => t.name));
const k = await call({ jsonrpc: '2.0', id: 3, method: 'tools/call', params: { name: 'kpi', arguments: { since: addDays(y, -2) } } });
console.log(k[1].result.content[0].text.slice(0, 900));
console.log(JSON.stringify(await call({ jsonrpc: '2.0', id: 4, method: 'tools/call', params: { name: 'crawler_visits', arguments: { bot: 'ChatGPT-User' } } })));
console.log(JSON.stringify(await call({ jsonrpc: '2.0', id: 5, method: 'tools/call', params: { name: 'record_name_search', arguments: { week: '2026-11-02', clicks: 3, impressions: 40 } } })));
console.log(JSON.stringify(await call({ jsonrpc: '2.0', id: 6, method: 'tools/call', params: { name: 'record_name_search', arguments: { week: '2026-11-03', clicks: 3, impressions: 40 } } })));
const k2 = await call({ jsonrpc: '2.0', id: 7, method: 'tools/call', params: { name: 'kpi', arguments: { since: '2026-11-02' } } });
console.log(JSON.parse(k2[1].result.content[0].text).byWeek);
```

#### test_kpi_mcp.mjs の出力

```text
{
 "version": 1,
 "day": "2026-11-05",
 "week": "2026-11-02",
 "madeAt": "2026-11-06T07:18:57.271Z",
 "aiReads": {
  "total": 2,
  "byBot": {
   "ChatGPT-User": 1,
   "Claude-User": 1
  },
  "viaButton": 1,
  "unverifiedChatGPTExcluded": 1,
  "topPages": [
   {
    "key": "/",
    "count": 1
   },
   {
    "key": "/record/x.md",
    "count": 1
   }
  ]
 },
 "aiReferrals": {
  "total": 1,
  "bySource": {
   "ChatGPT": 1
  },
  "landing": [
   {
    "key": "/",
    "count": 1
   }
  ],
  "notHumanExcluded": 1
 },
 "context": {
  "humanViews": 3,
  "humanEntriesFromOutside": 2
 }
}
kpi: made 2026-11-05 kpi: ok
[ 404, null ]
[200,{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-06-18","capabilities":{"tools":{"listChanged":false}},"serverInfo":{"name":"pixelstomotors-stats","title":"Pixels to Motors のサイトの計測","version":"1.0.0"},"instructions":"pixelstomotors.com のサイトの計測。分析を始めるときは、まず how_to_read で前提を読み、次に kpi で3つの数字を見る。"}}]
[ 202, null ]
[
  'kpi',
  'site_usage',
  'crawler_visits',
  'hakobu_notice',
  'how_to_read',
  'refresh_name_search',
  'record_name_search'
]
{"note":"定義と混ざりうるものは how_to_read。byDay の partial=true は今日（途中の数）。pendingDays は集計がまだの日（もう一度呼ぶと作る）。","firstDay":"2026-10-26","since":"2026-11-03","until":"2026-11-06","pendingDays":[],"byWeek":[{"week":"2026-11-02","days":4,"aiReads":2,"aiReadsViaButton":1,"aiReferrals":1,"humanViews":3,"aiReadsByBot":{"ChatGPT-User":1,"Claude-User":1},"aiReferralsBySource":{"ChatGPT":1},"nameSearch":null}],"byDay":[{"day":"2026-11-03","partial":false,"aiReads":0,"aiReadsViaButton":0,"aiReferrals":0,"humanViews":0,"aiReadsByBot":{},"aiReferralsBySource":{}},{"day":"2026-11-04","partial":false,"aiReads":0,"aiReadsViaButton":0,"aiReferrals":0,"humanViews":0,"aiReadsByBot":{},"aiReferralsBySource":{}},{"day":"2026-11-05","partial":false,"aiReads":2,"aiReadsViaButton":1,"aiReferrals":1,"humanViews":3,"aiReadsByBot":{"ChatGPT-User":1,"Claude-User":1},"aiReferralsBySource":{"ChatGPT":1}},{"day":"2026-11-06","part
[200,{"jsonrpc":"2.0","id":4,"result":{"content":[{"type":"text","text":"{\"q\":\"?format=json&since=2026-10-30&bot=ChatGPT-User\"}"}]}}]
[200,{"jsonrpc":"2.0","id":5,"result":{"content":[{"type":"text","text":"{\"ok\":true,\"saved\":\"kpi-sc/2026-11-02.json\",\"week\":\"2026-11-02\",\"clicks\":3,\"impressions\":40,\"queries\":[],\"note\":\"\",\"source\":\"Search Console\",\"recordedAt\":\"2026-11-06T07:18:57.302Z\"}"}]}}]
[200,{"jsonrpc":"2.0","id":6,"result":{"isError":true,"content":[{"type":"text","text":"week は週の月曜の日付（YYYY-MM-DD）にする"}]}}]
[
  {
    week: '2026-11-02',
    days: 5,
    aiReads: 2,
    aiReadsViaButton: 1,
    aiReferrals: 1,
    humanViews: 3,
    aiReadsByBot: { 'ChatGPT-User': 1, 'Claude-User': 1 },
    aiReferralsBySource: { ChatGPT: 1 },
    nameSearch: 3
  }
]
```

- AI の依頼読みは2（確かめられた ChatGPT-User とボタン経由の Claude-User）。確かめられなかった ChatGPT-User と robots.txt と、学習・検索のクローラーは入っていない
- AI のリンクから来た人は1（chatgpt.com の印の人の表示）。同じ表示の送り直し（n=0 と n=1）は1件として数え、機械の perplexity.ai は別に数えている
- 鍵の違う住所は404、通知（返事のいらないもの）は202。サイト名の検索の記録は、週の月曜でない日付を断る


### 本番で /api/kpi-stats が出るまで待ち、12日分を作った

GitHub の main に push すると、Cloudflare が約1分で公開します。公開を待って表を開き、もう一度開いて残りの日を作りました。

```text
$ K=$(tr -d '\n\r ' < $HOME/mnt/KIOXIA/p2m_stats_key.txt); for i in $(seq 1 16); do c=$(curl -s -o kpi.json -w "%{http_code}" -m 60 -H "Authorization: Bearer $K" "https://pixelstomotors.com/api/kpi-stats?format=json"); echo "$i $c"; [ "$c" = 200 ] && break; sleep 10; done; head -c 600 kpi.json
1 404
2 404
3 404
4 404
5 404
6 200
{"since":"2026-10-26","until":"2026-11-06","pendingDays":["2026-11-05"],"byWeek":[{"week":"2026-10-26","days":7,"aiReads":55,"aiReadsViaButton":0,"aiReferrals":0,"humanViews":164,"aiReadsByBot":{"ChatGPT-User":52,"Claude-User":3},"aiReferralsBySource":{},"nameSearch":null},{"week":"2026-11-02","days":4,"aiReads":38,"aiReadsViaButton":2,"aiReferrals":2,"humanViews":91,"aiReadsByBot":{"ChatGPT-User":26,"Claude-User":12},"aiReferralsBySource":{"ChatGPT":2},"nameSearch":null}],"byDay":[{"day":"2026-10-26","partial":false,"aiReads":9,"aiReadsViaButton":0,"aiReferrals":0,"humanViews":52,"aiReadsByBo

# 2回目（残りの 11/5 を作った。11/6 は途中の数）
$ K=$(tr -d '\n\r ' < $HOME/mnt/KIOXIA/p2m_stats_key.txt); curl -s -m 60 -H "Authorization: Bearer $K" "https://pixelstomotors.com/api/kpi-stats?format=json" > kpi.json
$ python3 -c "
import json
d=json.load(open('kpi.json')); print('pending',d['pendingDays'])
for x in d['byDay']: print(x['day'],x['partial'],'reads',x['aiReads'],x['aiReadsByBot'],'btn',x['aiReadsViaButton'],'ref',x['aiReferrals'],'human',x['humanViews'])"
pending []
2026-10-26 False reads 9 {'ChatGPT-User': 8, 'Claude-User': 1} btn 0 ref 0 human 52
2026-10-27 False reads 13 {'ChatGPT-User': 13} btn 0 ref 0 human 17
2026-10-28 False reads 4 {'ChatGPT-User': 4} btn 0 ref 0 human 21
2026-10-29 False reads 4 {'ChatGPT-User': 4} btn 0 ref 0 human 33
2026-10-30 False reads 17 {'Claude-User': 1, 'ChatGPT-User': 16} btn 0 ref 0 human 10
2026-10-31 False reads 6 {'ChatGPT-User': 5, 'Claude-User': 1} btn 0 ref 0 human 18
2026-11-01 False reads 2 {'ChatGPT-User': 2} btn 0 ref 0 human 13
2026-11-02 False reads 7 {'ChatGPT-User': 7} btn 0 ref 1 human 30
2026-11-03 False reads 22 {'Claude-User': 12, 'ChatGPT-User': 10} btn 2 ref 1 human 25
2026-11-04 False reads 5 {'ChatGPT-User': 5} btn 0 ref 0 human 16
2026-11-05 False reads 3 {'ChatGPT-User': 3} btn 0 ref 0 human 21
2026-11-06 True reads 4 {'ChatGPT-User': 4} btn 0 ref 0 human 20
```


## 作業ログ ― 計測を Claude につなぐ部品（MCP サーバー）を作った


### MCP は、AI に外の道具やデータをつなぐための決まった形

MCP（Model Context Protocol）は、Claude などの AI が、外のサービスの道具やデータを使えるようにするための、決まったやり取りの形です（[Model Context Protocol](https://modelcontextprotocol.io/)）。サービスの側が MCP サーバーを用意すると、Claude.ai の「コネクタ」として足せて、Claude が会話の中でその道具を呼び出せます（[Claude のカスタムコネクタの説明](https://claude.com/docs/connectors/custom/remote-mcp)）。

| 言葉 | 意味 |
|---|---|
| MCP サーバー | AI に道具を貸す側のプログラム。このサイトでは `worker/mcp.js` で、住所は `https://pixelstomotors.com/mcp/{鍵}` |
| 道具（tool） | AI が呼び出せる1つの機能。名前・説明・受け取る値の形を、サーバーが AI に伝える |
| コネクタ | Claude.ai に MCP サーバーを登録したもの。このサイトのものは「PTMの計測」 |
| JSON-RPC | MCP のやり取りの書き方。`initialize`（あいさつ）・`tools/list`（道具の一覧）・`tools/call`（道具を呼ぶ）を1つずつ送り、1つずつ返す |

このサイトでの使い方は、Claude にアクセス解析を頼むとき、Claude がまず `how_to_read`（数の読み方と落とし穴）を読み、次に `kpi`（3つの数字）を呼ぶ、という順番です。ブログ記事の筆者が「事前集計済みのデータや各データに関する知識を返す MCP」にしたのと同じ考え方で、数字だけでなく、その数字を読むときの前提（Amazonbot が混ざる・人の数は10月26日から・30未満は判断しない など）も一緒に渡します。

| 道具 | 中身 |
|---|---|
| how_to_read | 3つの数字の定義、混ざりうるもの、いつからの数が使えるか、道具の使い分け |
| kpi | 3つの数字を日ごと・週ごとに返す |
| site_usage | ページごとの読まれ方・押したもの・来た所（`/api/ev-stats`。既定は人だけ） |
| crawler_visits | どのクローラーが何を読んだか（`/api/cr-stats`） |
| hakobu_notice | 更新を知らせるハコブくんの記録（`/api/hk-stats`。既定は機械の印なし） |
| refresh_name_search・record_name_search | サイト名の検索の数を Search Console から取り直す・手で書き足す（数を変えるのはこの2つだけ） |

- ねらい：分析のたびに、Claude が鍵の場所・表の使い分け・数の落とし穴を思い出さなくて済むようにする
- 変わったこと：数字と読み方を、Claude.ai のコネクタから1つの部品で受け取れる。鍵は住所の中にあり、Claude は鍵のファイルを読まない
- 見込める効果：10月28日と11月2日に起きた、鍵や表の順番の間違いが起きにくくなる。11月16日の分析で、MCP の `kpi` だけで3つの数字が出るか、同じ間違いが出ないかを確かめる

住所に鍵を入れる形にしたのは、Claude.ai のカスタムコネクタが、ログインなしで住所だけで登録できるためです。鍵は Cloudflare の秘密の値 `MCP_KEY`、なければ `STATS_KEY` から作った値で、`STATS_KEY` を変えれば住所も変わります。返すのは集計した数だけで、だれが見たかは記録していません。


### worker/mcp.js（MCP サーバーのコード・全文）

```js
// サイトの計測を Claude につなぐ部品（MCP サーバー。2026-11-06）。
// Claude.ai のコネクタとして https://pixelstomotors.com/mcp/{鍵} を登録すると、Claude が集計済みの数字と、
// その読み方（何が混ざりうるか・いつの数から使えるか）をまとめて受け取れる。
// 毎回の分析で「鍵をどこから読むか・どの表から見るか・どこに落とし穴があるか」を Claude が思い出さなくて済むようにするため。
//
// - 読むだけ（数を変える道具は record_name_search の1つだけで、Search Console の数を週ごとに書き足す）
// - 鍵は Cloudflare の秘密の値 MCP_KEY。なければ STATS_KEY から作った値（mcpKey()）を使う。鍵が違えば 404
// - 通信の形は MCP の Streamable HTTP（POST で JSON-RPC を1つ受け、JSON で1つ返す。状態は持たない）

import { kpiRange, todayJst, addDays, weekOf, KPI_FIRST_DAY } from './kpi.js';
import { gscRefresh, gscReady } from './gsc.js';

const PROTOCOLS = ['2025-06-18', '2025-03-26', '2024-11-05'];
const SERVER = { name: 'pixelstomotors-stats', title: 'Pixels to Motors のサイトの計測', version: '1.0.0' };

// 読み方の知識（道具の説明と how_to_read で返す）。数字の前提が変わったらここを直す
const GUIDE = `# Pixels to Motors（pixelstomotors.com）のサイトの計測の読み方

## いま主に見る3つの数字（2026-11-06 にエイイチが決めた）
サイトのねらい：AI に調べられることで、人の来訪や知名度がいつ増えはじめるかを見る。サイトはもともと検索で人を集める作りにしていない。
1. AI の利用者の依頼で読みに来た数（aiReads）：ChatGPT-User・Claude-User・Perplexity-User・MistralAI-User が読んだページの数。/robots.txt は数えない。ChatGPT-User のうち Cloudflare が本物と確かめられなかったものは入れず、unverifiedChatGPTExcluded に別に数える。Claude-User は Cloudflare が確かめないので全部入れる
2. AI のサービスのリンクから来た人の数（aiReferrals）：referrer が chatgpt.com などか、リンクの印 utm_source が chatgpt.com などの表示のうち、人の操作（マウス・指・キー）があったものだけ。機械・操作なしは notHumanExcluded に別に数える
3. サイト名で検索して来た人の数（nameSearch）：Search Console のサイト名（Pixels to Motors・pixelstomotors など）の検索のクリック数。今は週の分析のときに Claude が Search Console（Chrome 拡張・新旧ドメインの両方）を見て、record_name_search で週ごとに書き足す（2026-11-06 決定。API の自動取得は Google Workspace の組織のポリシーでサービスアカウントの鍵が作れず保留。鍵 GSC_SA_KEY を入れれば毎日自動に切り替わる）。数は2〜3日遅れて確定し、人数の少ない検索語は Search Console が伏せるので少なめに出る。kpi の nameSearch に週ごとの記録（byDay・検索語・検索全体のクリック allClicks）が出る

## 混ざりうるもの（数を読む前に必ず思い出す）
- aiReads の viaButton は記事の「AIで読む」ボタン経由。エイイチや Claude の試しが混ざりうる。ボタンの利用そのものは site_usage の押したもの（btn:AIで読む・場所 ai）で人のクリックを見る。crawler_visits の byVia は Amazonbot などのクローラーがボタンの行き先をたどった分が大半で、利用の数としては使えない（2026-11-05 に判明）
- aiReads には、エイイチ自身が ChatGPT・Claude にこのサイトのことを聞いた分も入りうる（見分けられない）。トップ（/）が多い日はそれを疑う
- Claude のセッションが WebFetch でサイトを読むと Claude-User として入りうる
- 人の数は 2026-10-26 から（それより前は人と機械を分けていない）。人の表示の約9割は機械なので、来訪の数は必ず人だけ（who=human）で見る
- エイイチ・Claude の確認の閲覧は ?p2m-notrack=1 を付けたブラウザでは送られない。付け忘れた自動のブラウザは navigator.webdriver で機械に入る
- crawler_visits（/api/cr-stats）は長い期間を指定すると記録が多すぎて一部しか数えない（truncated が true）。2026-10-25 からの合計は少なめに出ていた。日ごとの数は kpi（日ごとに集計して残したもの）で見る

## 数え方の決まり
- 日付は日本時間。週は月曜はじまり
- 改善の判断の基準（Project の claude/web_improvement_trial.md）：対象の数が30未満なら「判断できない」
- 見た人を見分ける番号は残さないので、「何人か」は数えられない。数は表示・訪問の回数

## 道具の使い分け
- まず kpi（3つの数字・日ごと週ごと）
- ページごとの読まれ方・押したもの・来た所は site_usage
- どのクローラーが何を読んだかは crawler_visits（期間は短く）
- 更新を知らせるハコブくんは hakobu_notice`;

const TOOLS = [
  {
    name: 'kpi',
    title: '3つの数字（日ごと・週ごと）',
    description: 'いま主に見る3つの数字を返す：AI の利用者の依頼で読みに来た数・AI のサービスのリンクから来た人の数・サイト名で検索して来た人の数（Search Console から記録した分）。日ごとに集計して残したものなので速く、数え漏れがない。混ざりうるものは how_to_read を読むこと。日付は日本時間、週は月曜はじまり。',
    inputSchema: { type: 'object', properties: {
      since: { type: 'string', description: '始めの日（YYYY-MM-DD）。省略すると28日前。2026-10-26 より前は数えない' },
      until: { type: 'string', description: '終わりの日（YYYY-MM-DD）。省略すると今日（今日は途中の数）' },
      detail: { type: 'boolean', description: 'true でよく読まれたページ・来たページなどの内訳も返す' },
    } },
    annotations: { readOnlyHint: true, openWorldHint: false },
  },
  {
    name: 'site_usage',
    title: 'サイトの使われ方（ページごと・押したもの・来た所）',
    description: 'ページ表示ごとの記録（/api/ev-stats）。週ごと・ページごとの表示・表示時間・どこまで読んだか・押したもの・リンクでない所を押した・どこから来たか・フォーム。既定は人の操作があった表示だけ（who=human）。',
    inputSchema: { type: 'object', properties: {
      since: { type: 'string', description: 'この日以降（YYYY-MM-DD）' },
      week: { type: 'string', description: 'ページごと以下の表をこの週だけに（週の月曜の日付）' },
      who: { type: 'string', enum: ['human', 'bot', 'unknown', 'old', 'all'], description: '既定 human' },
    } },
    annotations: { readOnlyHint: true, openWorldHint: false },
  },
  {
    name: 'crawler_visits',
    title: '検索エンジン・AI のクローラーの訪問',
    description: 'どのクローラーが・どのページを読んだか（/api/cr-stats）。返せなかったページ（400以上）も。長い期間を指定すると一部しか数えない（truncated）ので、since は2週間以内にする。',
    inputSchema: { type: 'object', properties: {
      since: { type: 'string', description: 'この日以降（YYYY-MM-DD）。省略すると7日前' },
      bot: { type: 'string', description: 'ページごとの表をこのクローラーだけに（例 ChatGPT-User）' },
    } },
    annotations: { readOnlyHint: true, openWorldHint: false },
  },
  {
    name: 'hakobu_notice',
    title: '更新を知らせるハコブくんの記録',
    description: 'サイトの更新を知らせてハコブくんが出た・押された・あとで見に来た数（/api/hk-stats）。既定は機械の印のない記録だけ（who=notbot）。',
    inputSchema: { type: 'object', properties: { who: { type: 'string', enum: ['notbot', 'bot', 'old', 'all'], description: '既定 notbot' } } },
    annotations: { readOnlyHint: true, openWorldHint: false },
  },
  {
    name: 'how_to_read',
    title: '計測の読み方',
    description: '数を読む前の前提：3つの数字の定義、混ざりうるもの（エイイチ・Claude の試し、Amazonbot、人と機械）、いつからの数が使えるか、道具の使い分け。分析を始めるときに最初に読む。',
    inputSchema: { type: 'object', properties: {} },
    annotations: { readOnlyHint: true, openWorldHint: false },
  },
  {
    name: 'refresh_name_search',
    title: 'サイト名の検索の数を Search Console から取り直す',
    description: '毎日自動で取っているサイト名の検索の数を、今すぐ取り直す。since を付けるとその週から（最初の埋め戻しや、数が確定したあとの取り直し用）。',
    inputSchema: { type: 'object', properties: { since: { type: 'string', description: 'この日の週から（YYYY-MM-DD）。省略すると先週から' } } },
    annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: true },
  },
  {
    name: 'record_name_search',
    title: 'サイト名の検索の数を記録する（Search Console から）',
    description: 'Search Console の API が使えないときだけ使う。Search Console で見た、サイト名（Pixels to Motors・pixelstomotors など）で検索された週の数を書き足す。同じ週を送ると上書きする。数は2〜3日遅れて出るので、週が終わって3日以上たってから記録する。',
    inputSchema: { type: 'object', required: ['week', 'clicks', 'impressions'], properties: {
      week: { type: 'string', description: '週の月曜の日付（YYYY-MM-DD）' },
      clicks: { type: 'integer', minimum: 0, description: 'サイト名の検索から来たクリック数（新旧ドメインの合計）' },
      impressions: { type: 'integer', minimum: 0, description: 'サイト名の検索で表示された回数（新旧ドメインの合計）' },
      queries: { type: 'array', items: { type: 'object', properties: { query: { type: 'string' }, clicks: { type: 'integer' }, impressions: { type: 'integer' } } }, description: '数えた検索語ごとの内訳' },
      note: { type: 'string', description: 'どのプロパティを見たか・気づいたこと' },
    } },
    annotations: { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
  },
];

const DAY = /^\d{4}-\d{2}-\d{2}$/;
const okDay = (s, d) => (DAY.test(s || '') ? s : d);

// MCP の鍵。MCP_KEY があればそれ、なければ STATS_KEY から作る（STATS_KEY を変えればこちらも変わる）
export async function mcpKey(env) {
  if (env.MCP_KEY) return env.MCP_KEY;
  if (!env.STATS_KEY) return '';
  const k = await crypto.subtle.importKey('raw', new TextEncoder().encode(env.STATS_KEY), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']);
  const sig = new Uint8Array(await crypto.subtle.sign('HMAC', k, new TextEncoder().encode('p2m-mcp-v1')));
  return [...sig.slice(0, 16)].map((b) => b.toString(16).padStart(2, '0')).join('');
}

async function sameKey(given, key) {
  if (!given || !key) return false;
  const [a, b] = await Promise.all([given, key].map((x) => crypto.subtle.digest('SHA-256', new TextEncoder().encode(x))));
  return crypto.subtle.timingSafeEqual(a, b);
}

const rpc = (id, result) => ({ jsonrpc: '2.0', id, result });
const rpcErr = (id, code, message) => ({ jsonrpc: '2.0', id: id ?? null, error: { code, message } });
const text = (o) => ({ content: [{ type: 'text', text: typeof o === 'string' ? o : JSON.stringify(o) }] });

// stats: { evStats, crStats, hkStats }（index.js の数の表。Response を返す関数）
export async function handleMcp(request, env, url, stats) {
  const given = url.pathname.slice('/mcp/'.length).replace(/\/$/, '');
  if (!(await sameKey(given, await mcpKey(env)))) return new Response('Not Found', { status: 404, headers: { 'x-robots-tag': 'noindex' } });
  const headers = { 'content-type': 'application/json; charset=utf-8', 'x-robots-tag': 'noindex', 'cache-control': 'no-store' };
  if (request.method === 'GET') return new Response('Method Not Allowed', { status: 405, headers: { allow: 'POST' } });
  if (request.method === 'DELETE') return new Response(null, { status: 204 });
  if (request.method !== 'POST') return new Response('Method Not Allowed', { status: 405, headers: { allow: 'POST' } });
  let msg;
  try { msg = JSON.parse((await request.text()).slice(0, 100000)); } catch { return new Response(JSON.stringify(rpcErr(null, -32700, 'Parse error')), { status: 400, headers }); }
  const batch = Array.isArray(msg);
  const out = [];
  for (const m of batch ? msg : [msg]) {
    const r = await one(m, env, url, stats);
    if (r) out.push(r);
  }
  if (!out.length) return new Response(null, { status: 202 }); // 通知（返事のいらないもの）だけだった
  return new Response(JSON.stringify(batch ? out : out[0]), { headers });
}

async function one(m, env, url, stats) {
  if (!m || m.jsonrpc !== '2.0' || typeof m.method !== 'string') return rpcErr(m && m.id, -32600, 'Invalid Request');
  const isNotice = !('id' in m);
  try {
    switch (m.method) {
      case 'initialize': {
        const want = m.params && m.params.protocolVersion;
        return rpc(m.id, {
          protocolVersion: PROTOCOLS.includes(want) ? want : PROTOCOLS[0],
          capabilities: { tools: { listChanged: false } },
          serverInfo: SERVER,
          instructions: 'pixelstomotors.com のサイトの計測。分析を始めるときは、まず how_to_read で前提を読み、次に kpi で3つの数字を見る。',
        });
      }
      case 'ping': return isNotice ? null : rpc(m.id, {});
      case 'tools/list': return rpc(m.id, { tools: TOOLS });
      case 'tools/call': return rpc(m.id, await call(m.params || {}, env, url, stats));
      case 'resources/list': return rpc(m.id, { resources: [] });
      case 'prompts/list': return rpc(m.id, { prompts: [] });
      default:
        if (isNotice) return null; // notifications/initialized など
        return rpcErr(m.id, -32601, `Method not found: ${m.method}`);
    }
  } catch (e) {
    return isNotice ? null : rpcErr(m.id, -32603, String(e && e.message || e));
  }
}

// index.js の数の表を、鍵を付けた形で中から呼んで JSON を受け取る
async function statsJson(fn, env, path, params) {
  const u = new URL(`https://pixelstomotors.com${path}`);
  u.searchParams.set('format', 'json');
  for (const [k, v] of Object.entries(params)) if (v) u.searchParams.set(k, v);
  const res = await fn(new Request(u, { method: 'GET' }), env, u);
  return res.json();
}

async function call(p, env, url, stats) {
  const a = p.arguments || {};
  const today = todayJst();
  switch (p.name) {
    case 'how_to_read': return text(GUIDE);
    case 'kpi': {
      const r = await kpiRange(env, okDay(a.since, addDays(today, -28)), okDay(a.until, today));
      if (!a.detail) delete r.detailDays;
      return text({ note: '定義と混ざりうるものは how_to_read。byDay の partial=true は今日（途中の数）。pendingDays は集計がまだの日（もう一度呼ぶと作る）。', firstDay: KPI_FIRST_DAY, ...r });
    }
    case 'site_usage': {
      const who = a.who === 'all' ? '' : (a.who || 'human');
      return text(await statsJson(stats.evStats, env, '/api/ev-stats', { since: okDay(a.since, ''), week: okDay(a.week, ''), who }));
    }
    case 'crawler_visits':
      return text(await statsJson(stats.crStats, env, '/api/cr-stats', { since: okDay(a.since, addDays(today, -7)), bot: String(a.bot || '').slice(0, 40) }));
    case 'hakobu_notice': {
      const who = a.who === 'all' ? '' : (a.who || 'notbot');
      return text(await statsJson(stats.hkStats, env, '/api/hk-stats', { who }));
    }
    case 'refresh_name_search': {
      if (!gscReady(env)) return { isError: true, ...text('Search Console の鍵（GSC_SA_KEY）がまだ設定されていない') };
      return text(await gscRefresh(env, { since: okDay(a.since, '') }));
    }
    case 'record_name_search': {
      if (!DAY.test(a.week || '') || weekOf(a.week) !== a.week) return { isError: true, ...text('week は週の月曜の日付（YYYY-MM-DD）にする') };
      const n = (x) => Math.max(0, Math.floor(Number(x) || 0));
      const rec = {
        week: a.week, clicks: n(a.clicks), impressions: n(a.impressions),
        queries: (Array.isArray(a.queries) ? a.queries : []).slice(0, 50).map((q) => ({ query: String(q.query || '').slice(0, 100), clicks: n(q.clicks), impressions: n(q.impressions) })),
        note: String(a.note || '').slice(0, 1000), source: 'Search Console', recordedAt: new Date().toISOString(),
      };
      await env.MESSAGES.put(`kpi-sc/${a.week}.json`, JSON.stringify(rec), { httpMetadata: { contentType: 'application/json' } });
      return text({ ok: true, saved: `kpi-sc/${a.week}.json`, ...rec });
    }
    default:
      return { isError: true, ...text(`知らない道具：${p.name}`) };
  }
}
```


### 本番の MCP サーバーに initialize・tools/list・道具の呼び出しを送った

住所は KIOXIA の `p2m_mcp_url.txt` に置き、変数に読み込んで送りました（住所の鍵は画面に出していません）。

```text
$ U=$(tr -d '\n' < $HOME/mnt/KIOXIA/p2m_mcp_url.txt)
$ curl -s -m 30 -X POST "$U" -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"t","version":"1"}}}' | head -c 250; echo
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2025-06-18","capabilities":{"tools":{"listChanged":false}},"serverInfo":{"name":"pixelstomotors-stats","title":"Pixels to Motors のサイトの計測","version":"1.0.0"},"instructions":"pixelstomo
$ curl -s -m 30 -X POST "$U" -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}' | python3 -c "import json,sys;print([t['name'] for t in json.load(sys.stdin)['result']['tools']])"
['kpi', 'site_usage', 'crawler_visits', 'hakobu_notice', 'how_to_read', 'record_name_search']
$ curl -s -m 60 -X POST "$U" -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"site_usage","arguments":{"since":"2026-11-02"}}}' | head -c 250; echo
{"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"{\"total\":1521,\"counted\":112,\"truncated\":false,\"since\":\"2026-11-02\",\"week\":null,\"who\":\"human\",\"byWeek\":[{\"week\":\"2026-11-02\",\"label\":\"2026-11-02 〜 11-08\",\
$ curl -s -m 60 -X POST "$U" -H 'content-type: application/json' -d '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"crawler_visits","arguments":{"bot":"Claude-User","since":"2026-11-03"}}}' | python3 -c "import json,sys;d=json.loads(json.load(sys.stdin)['result']['content'][0]['text']);print(d['truncated'],d['byPage'][:15])"
False [{'path': '/robots.txt', 'visits': 1, 'bots': 'Claude-User'}, {'path': '/llms.txt', 'visits': 1, 'bots': 'Claude-User'}, {'path': '/record/gamepad-moves-mecharm-270-pymycobot-version', 'visits': 1, 'bots': 'Claude-User'}, {'path': '/record/serving-robot-faceoff-staff-resolves', 'visits': 1, 'bots': 'Claude-User'}, {'path': '/record/ai-reads-more-than-people', 'visits': 1, 'bots': 'Claude-User'}, {'path': '/record/retrained-pi05-still-needs-human-corrections', 'visits': 1, 'bots': 'Claude-User'}, {'path': '/record/building-a-physical-ai-lab-at-home', 'visits': 1, 'bots': 'Claude-User'}, {'path': '/gpu-buy-or-rent', 'visits': 1, 'bots': 'Claude-User'}, {'path': '/record/openpi-remote-inference-first-run', 'visits': 1, 'bots': 'Claude-User'}, {'path': '/record/pi05-mecharm-demo-to-inference', 'visits': 1, 'bots': 'Claude-User'}, {'path': '/record/serving-robot-one-per-narrow-restaurant', 'visits': 1, 'bots': 'Claude-User'}, {'path': '/record/day103', 'visits': 1, 'bots': 'Claude-User'}, {'path': '/record/pi05-first-block-in-box', 'visits': 1, 'bots': 'Claude-User'}]
$ curl -s -m 30 -o /dev/null -w "wrongkey %{http_code}\n" -X POST "https://pixelstomotors.com/mcp/abc" -d '{}'
wrongkey 404
$ K=$(tr -d '\n\r ' < $HOME/mnt/KIOXIA/p2m_stats_key.txt); curl -s -m 60 -o /dev/null -w "hk html %{http_code}\n" -H "Authorization: Bearer $K" "https://pixelstomotors.com/api/hk-stats"
hk html 200
```


### Claude.ai にカスタムコネクタ「PTMの計測」として登録した

エイイチが Claude.ai の「カスタマイズ」の「コネクタ」から「カスタムコネクタを追加」を開き、名前を「PTMの計測」、URL に上の住所を入れ、認証は「サインインなし」のまま追加しました。

【画像】LOG453_03_custom_connector.png Claude.ai のカスタムコネクタを追加する画面。名前に「PTMの計測」、URL に MCP サーバーの住所（鍵の部分は伏せている）を入れ、認証は「サインインなし」を選んでいる

追加すると、読み取り専用の道具が5つ、書き込みの道具が1つ（このときはまだ `refresh_name_search` を足す前）として並びました。

【画像】LOG453_04_connector_tools.png 追加したコネクタ「PTMの計測」の画面。読み取り専用ツール5つ（クローラーの訪問・ハコブくんの記録・計測の読み方・3つの数字・サイトの使われ方）と、書き込みツール1つ（サイト名の検索の数を記録する）が並ぶ

登録したあと、Claude がこの会話から `how_to_read` と `kpi` を呼び、数字が返ることを確かめました。Claude.ai の道具の権限は、読むだけの5つを「常に許可」にすると、分析のたびの承認がいらなくなります。


## 作業ログ ― サイト名の検索の数を Search Console から取る

3つ目の数字は、サイトの中では取れません。Google から来た人の記録には、何という言葉で検索したかが入っていないためです。取り方は2つありました。週の分析のときに Claude が Search Console を Chrome で見て書き足すか、Search Console の API（プログラムから数字を取る口）で毎日自動で取るか。エイイチは毎日自動で取る形を選びました。

> 最初に一度だけ10分ほど手間をかけて毎日自動で取る形


### worker/gsc.js（Search Console の API でサイト名の検索の数を取るコード・全文）

Google Cloud のサービスアカウント（人ではなくプログラムが使う Google のアカウント）の鍵で Search Console を読み、サイト名の検索のクリックと表示を、今週と先週の分だけ取り直して `kpi-sc/{週の月曜}.json` に残します。数は2〜3日遅れて確定するので、毎日上書きします。鍵（`GSC_SA_KEY`）がないあいだは何もしません。

```js
// サイト名で検索して来た人の数を、Search Console の API から毎日取る（2026-11-06）。
// 主に見る3つの数字の3つ目（worker/kpi.js の nameSearch）。
//
// - 鍵は Cloudflare の秘密の値 GSC_SA_KEY（Google Cloud のサービスアカウントの JSON の中身そのもの）。
//   そのサービスアカウントのメールを、Search Console のプロパティに「制限付き」のユーザーとして足してある
// - 見るプロパティは GSC_SITES（カンマ区切り）。なければ新ドメインと旧ドメインの2つ。権限のないプロパティは飛ばして記録に残す
// - 数は2〜3日遅れて確定するので、毎日、今週と先週の分を取り直して上書きする（前の日の3つの数字を作ったときに1回だけ）
// - 置き場所は R2（p2m-messages）の kpi-sc/{週の月曜}.json（MCP の record_name_search で手で書いたものと同じ形。byDay が付く）
// - Search Console は、人数の少ない検索語を伏せて返す（匿名化）。数は少なめに出る

import { KPI_FIRST_DAY, todayJst, addDays, weekOf } from './kpi.js';

const DEFAULT_SITES = ['sc-domain:pixelstomotors.com', 'https://adaptdesign.jp/'];
// サイト名の検索とみなす検索語（RE2 の正規表現。大文字小文字は区別しない）
const NAME_RE = '(?i)pixels?\\s*to\\s*motors?|pixelstomotors|ピクセルズ\\s*トゥ|ピクセル\\s*トゥ\\s*モーター';

const b64url = (bytes) => btoa(String.fromCharCode(...new Uint8Array(bytes))).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
const b64urlText = (s) => b64url(new TextEncoder().encode(s));

async function accessToken(sa) {
  const now = Math.floor(Date.now() / 1000);
  const head = b64urlText(JSON.stringify({ alg: 'RS256', typ: 'JWT' }));
  const claim = b64urlText(JSON.stringify({ iss: sa.client_email, scope: 'https://www.googleapis.com/auth/webmasters.readonly', aud: 'https://oauth2.googleapis.com/token', iat: now, exp: now + 3600 }));
  const pem = sa.private_key.replace(/-----[^-]+-----/g, '').replace(/\s+/g, '');
  const der = Uint8Array.from(atob(pem), (c) => c.charCodeAt(0));
  const key = await crypto.subtle.importKey('pkcs8', der, { name: 'RSASSA-PKCS1-v1_5', hash: 'SHA-256' }, false, ['sign']);
  const sig = await crypto.subtle.sign('RSASSA-PKCS1-v1_5', key, new TextEncoder().encode(`${head}.${claim}`));
  const r = await fetch('https://oauth2.googleapis.com/token', {
    method: 'POST', headers: { 'content-type': 'application/x-www-form-urlencoded' },
    body: `grant_type=${encodeURIComponent('urn:ietf:params:oauth:grant-type:jwt-bearer')}&assertion=${head}.${claim}.${b64url(sig)}`,
  });
  const j = await r.json();
  if (!r.ok || !j.access_token) throw new Error(`Google の鍵の受け取りに失敗: HTTP ${r.status} ${j.error || ''}`);
  return j.access_token;
}

async function query(token, site, body) {
  const r = await fetch(`https://searchconsole.googleapis.com/webmasters/v3/sites/${encodeURIComponent(site)}/searchAnalytics/query`, {
    method: 'POST', headers: { authorization: `Bearer ${token}`, 'content-type': 'application/json' }, body: JSON.stringify(body),
  });
  const j = await r.json().catch(() => ({}));
  if (!r.ok) throw new Error(`HTTP ${r.status} ${(j.error && j.error.message) || ''}`.trim());
  return j.rows || [];
}

export const gscReady = (env) => !!env.GSC_SA_KEY;

// 1週分を取り直して残す
async function refreshWeek(env, token, sites, week) {
  const today = todayJst();
  const end = addDays(week, 6) < today ? addDays(week, 6) : addDays(today, -1);
  if (end < week) return null;
  const rec = { week, clicks: 0, impressions: 0, queries: [], byDay: {}, allClicks: 0, allImpressions: 0, sites: [], sitesFailed: [], source: 'Search Console API', note: '', recordedAt: new Date().toISOString() };
  const qmap = new Map();
  for (const site of sites) {
    try {
      const named = await query(token, site, {
        startDate: week, endDate: end, dimensions: ['date', 'query'], rowLimit: 5000,
        dimensionFilterGroups: [{ filters: [{ dimension: 'query', operator: 'includingRegex', expression: NAME_RE }] }],
      });
      for (const row of named) {
        const [day, q] = row.keys;
        rec.clicks += row.clicks; rec.impressions += row.impressions;
        const d = rec.byDay[day] || { clicks: 0, impressions: 0 }; d.clicks += row.clicks; d.impressions += row.impressions; rec.byDay[day] = d;
        const e = qmap.get(q) || { query: q, clicks: 0, impressions: 0 }; e.clicks += row.clicks; e.impressions += row.impressions; qmap.set(q, e);
      }
      // 参考：検索全体のクリックと表示（サイト名の検索がどれくらいの割合か）
      for (const row of await query(token, site, { startDate: week, endDate: end, dimensions: ['date'], rowLimit: 100 })) {
        rec.allClicks += row.clicks; rec.allImpressions += row.impressions;
      }
      rec.sites.push(site);
    } catch (e) {
      rec.sitesFailed.push(`${site}: ${e.message}`);
    }
  }
  if (!rec.sites.length) throw new Error(`どのプロパティも読めなかった（${rec.sitesFailed.join(' / ')}）`);
  rec.queries = [...qmap.values()].sort((a, b) => b.impressions - a.impressions).slice(0, 50);
  rec.note = `${week} 〜 ${end} の分（数は2〜3日遅れて確定する。人数の少ない検索語は Search Console が伏せる）`;
  await env.MESSAGES.put(`kpi-sc/${week}.json`, JSON.stringify(rec), { httpMetadata: { contentType: 'application/json' } });
  return rec;
}

// since の週から今週までを取り直す（毎日は先週と今週だけ）
export async function gscRefresh(env, { since } = {}) {
  if (!gscReady(env)) return { ok: false, reason: 'GSC_SA_KEY がない' };
  const sa = JSON.parse(env.GSC_SA_KEY);
  const sites = (env.GSC_SITES ? env.GSC_SITES.split(',') : DEFAULT_SITES).map((s) => s.trim()).filter(Boolean);
  const token = await accessToken(sa);
  const today = todayJst();
  let w = weekOf(since && since >= KPI_FIRST_DAY ? since : addDays(today, -7));
  const done = [];
  for (; w <= weekOf(today); w = addDays(w, 7)) {
    const r = await refreshWeek(env, token, sites, w);
    if (r) done.push({ week: w, clicks: r.clicks, impressions: r.impressions, sitesFailed: r.sitesFailed });
  }
  return { ok: true, account: sa.client_email, weeks: done };
}
```

#### test_gsc.mjs（偽の Google で、鍵の署名と取り方を確かめた）

```js
import { generateKeyPairSync, createVerify } from 'node:crypto';
import { gscRefresh } from '/home/claude/p2m-site/worker/gsc.js';
const { privateKey, publicKey } = generateKeyPairSync('rsa', { modulusLength: 2048 });
const sa = { client_email: 'x@p.iam.gserviceaccount.com', private_key: privateKey.export({ type: 'pkcs8', format: 'pem' }) };
const store = new Map();
const env = { GSC_SA_KEY: JSON.stringify(sa), MESSAGES: { put: async (k, v) => store.set(k, v) } };
globalThis.fetch = async (u, o) => {
  if (u.includes('oauth2')) { const jwt = decodeURIComponent(o.body.split('assertion=')[1]); const [h, c, s] = jwt.split('.'); const v = createVerify('RSA-SHA256'); v.update(`${h}.${c}`); console.log('sig ok', v.verify(publicKey, Buffer.from(s, 'base64url'))); return new Response(JSON.stringify({ access_token: 't' })); }
  const b = JSON.parse(o.body);
  if (u.includes('adaptdesign')) return new Response(JSON.stringify({ error: { message: 'User does not have sufficient permission' } }), { status: 403 });
  if (b.dimensions.length === 2) return new Response(JSON.stringify({ rows: [{ keys: [b.startDate, 'pixels to motors'], clicks: 2, impressions: 9 }] }));
  return new Response(JSON.stringify({ rows: [{ keys: [b.startDate], clicks: 5, impressions: 100 }] }));
};
console.log(JSON.stringify(await gscRefresh(env, { since: '2026-10-26' })));
console.log([...store.keys()], store.get('kpi-sc/2026-11-02.json'));
```

#### test_gsc.mjs の出力

```text
sig ok true
{"ok":true,"account":"x@p.iam.gserviceaccount.com","weeks":[{"week":"2026-10-26","clicks":2,"impressions":9,"sitesFailed":["https://adaptdesign.jp/: HTTP 403 User does not have sufficient permission"]},{"week":"2026-11-02","clicks":2,"impressions":9,"sitesFailed":["https://adaptdesign.jp/: HTTP 403 User does not have sufficient permission"]}]}
[ 'kpi-sc/2026-10-26.json', 'kpi-sc/2026-11-02.json' ] {"week":"2026-11-02","clicks":2,"impressions":9,"queries":[{"query":"pixels to motors","clicks":2,"impressions":9}],"byDay":{"2026-11-02":{"clicks":2,"impressions":9}},"allClicks":5,"allImpressions":100,"sites":["sc-domain:pixelstomotors.com"],"sitesFailed":["https://adaptdesign.jp/: HTTP 403 User does not have sufficient permission"],"source":"Search Console API","note":"2026-11-02 〜 2026-11-05 の分（数は2〜3日遅れて確定する。人数の少ない検索語は Search Console が伏せる）","recordedAt":"2026-11-06T07:18:57.409Z"}
```

- 「sig ok true」は、作った署名（JWT）が、テスト用の鍵の公開鍵で正しいと確かめられたこと
- 権限のないプロパティ（旧ドメイン）は止まらずに飛ばし、`sitesFailed` に残る


### Google Cloud の組織のポリシーで、サービスアカウントの鍵が作れなかった

エイイチが Google Cloud のプロジェクト `pixelstomotors-studio` で Google Search Console API を有効にし、サービスアカウント `p2m-search` を作りました。

【画像】LOG453_05_search_console_api_enabled.png Google Cloud の画面。Google Search Console API のステータスが「有効」になっている

鍵（JSON）を作ろうとしたところ、次の表示で止まりました。

> サービス アカウント キーの作成が無効になっています
>
> サービス アカウント キーの作成をブロックする組織ポリシーが組織に適用されています。
>
> 適用された組織ポリシーの ID: iam.disableServiceAccountKeyCreation

【画像】LOG453_06_service_account_key_blocked.png Google Cloud で鍵を作ろうとしたときの表示。サービスアカウントキーの作成をブロックする組織ポリシー iam.disableServiceAccountKeyCreation が適用されている

Google Workspace（adaptdesign.jp）の組織に、サービスアカウントの鍵を作らせない設定が最初から入っていました。このプロジェクトだけ外す手順をエイイチが試しましたが、仕事用のアカウントには組織の権限を変える権限がなく（`resourcemanager.organizations.getIamPolicy`（権限がありません））、その先は Google Workspace の管理者のアカウントから権限を付け直す作業になります。10分では終わらないので、ここで止めました。

- 決めたこと：当面は、週の分析のときに Claude が Search Console を Chrome で見て、MCP の `record_name_search` で書き足す。この道具はもうあるので、エイイチの手間はない
- 毎日自動で取るコード（`worker/gsc.js`）は残してある。鍵が作れるようになったら、Cloudflare の秘密の値 `GSC_SA_KEY` に鍵の中身を入れるだけで、毎日自動に切り替わる
- 読み方の説明（`worker/mcp.js` の `GUIDE`）と p2m-site の README を、この形に書き換えた（commit d456aa3）


### 10/26 の週と 11/2 の週のサイト名の検索は、新旧ドメインとも0だった

Claude が Chrome で Search Console を開き、検索語を正規表現（文字の並びの決まりで探す書き方）で絞りました。

| プロパティ | 期間 | 絞り方 | クリック | 表示 |
|---|---|---|---|---|
| sc-domain:pixelstomotors.com | 10/26〜11/1 | `(?i)pixels?\s*to\s*motors?\|pixelstomotors\|ピクセル` | 0 | 0 |
| sc-domain:pixelstomotors.com | 10/15〜11/5 | `(?i)pixel\|motor\|ピクセル\|p2m` | 0 | 0 |
| sc-domain:pixelstomotors.com | 10/15〜11/5 | 絞りなし | 41 | 2,250 |
| sc-domain:pixelstomotors.com | 10/15〜11/5 | `(?i)studio\|pixel`（絞り込みが効くかの確かめ） | 0 | 295 |
| https://adaptdesign.jp/ | 10/15〜11/5 | `(?i)pixel\|motor\|ピクセル\|p2m` | 0 | 1（CSS の文字列で、サイト名の検索ではない） |

【画像】LOG453_02_search_console_name_search_zero.png Search Console の検索パフォーマンスを、サイト名を含む検索語の正規表現で絞った画面。10月15日から11月5日まで、クリック数も表示回数も0

絞りなしの上位の検索語は「3dgs」（クリック2・表示3）、「フィジカルai 研究室」（1・6）、「studio モーダル」（0・39）、「alphanist」（0・37）、「studio トグル」（0・36）で、106語のうちサイト名を含むものはありませんでした。2週ともクリック0・表示0として記録しました（11月2日の週は11月5日までの途中の数）。

ただし、本当に誰も検索していないとは限りません。10月15日から31日の新ドメインでは、プライバシーポリシーが13回押されていて、サイト名で調べた人だと見ていました（11月2日の分析）。Search Console は検索した人の少ない言葉を伏せて返すので、そうした検索は数に出てきません。**今の0は「伏せられる量より少ない」と読むのが正確で、伏せられる量を超えて数字が出はじめたら、それが知名度が上がりはじめた合図になります。**

#### record_name_search で書き足した記録（MCP の返事）

```json
{"ok":true,"saved":"kpi-sc/2026-10-26.json","week":"2026-10-26","clicks":0,"impressions":0,"queries":[],"note":"Search Console を Chrome で確認（2026-11-06）。新ドメイン sc-domain:pixelstomotors.com・旧ドメイン https://adaptdesign.jp/ とも、正規表現 (?i)pixel|motor|ピクセル|p2m の検索語は 0（旧ドメインの1表示は CSS の文字列で、サイト名の検索ではない）。正規表現の絞り込みが効くことは studio で確かめた。人数の少ない検索語は Search Console が伏せるので、伏せられた分は数えられない","source":"Search Console","recordedAt":"2026-11-06T07:11:51.972Z"}
{"ok":true,"saved":"kpi-sc/2026-11-02.json","week":"2026-11-02","clicks":0,"impressions":0,"queries":[],"note":"途中の数（11/2〜11/5 まで。Search Console は2〜3日遅れ）。新旧ドメインとも、サイト名の検索語は 0。11/16 の分析で週の確定分に取り直す","source":"Search Console","recordedAt":"2026-11-06T07:11:55.674Z"}
```


## 作業ログ ― 10/26〜11/5 の3つの数字

/api/kpi-stats から取った、10月26日から11月5日までの11日分です。

【画像】LOG453_01_kpi_stats_page.png 新しく作った数の表 /api/kpi-stats の画面。週ごとと日ごとに、AI の依頼読み・ボタン経由・AI のリンクから来た人・サイト名の検索・人の表示が並ぶ

| 週（月曜はじまり） | AI の依頼読み | うちボタン経由 | AI のリンクから来た人 | サイト名の検索 | 人の表示（参考） |
|---|---|---|---|---|---|
| 10/26〜11/1 | 55（ChatGPT-User 52・Claude-User 3） | 0 | 0 | 0 | 164 |
| 11/2〜11/5（4日） | 37（ChatGPT-User 25・Claude-User 12） | 2 | 2（どちらも ChatGPT） | 0（途中） | 92 |

| 日付 | AI の依頼読み | AI のリンクから来た人 | 人の表示 |
|---|---|---|---|
| 10/26 | 9 | 0 | 52 |
| 10/27 | 13 | 0 | 17 |
| 10/28 | 4 | 0 | 21 |
| 10/29 | 4 | 0 | 33 |
| 10/30 | 17 | 0 | 10 |
| 10/31 | 6 | 0 | 18 |
| 11/1 | 2 | 0 | 13 |
| 11/2 | 7 | 1 | 30 |
| 11/3 | 22 | 1 | 25 |
| 11/4 | 5 | 0 | 16 |
| 11/5 | 3 | 0 | 21 |

AI のリンクから来た2人が着いたページは、11月2日が `/record/hakobu-4koma-english-without-redrawing`（4コマの英語版を描き直さずに作った記録）、11月3日が `/record/decisions-api-grasp-check`（つかめたかを判断する仕組みの記録）でした。


### 3つの数字を並べて分かること・分からないこと

エイイチが聞きました。

> これによって何がわかるようになりますか？

3つの数字は、1本の流れの段になっています。AI がサイトを読む → AI が答えの中でサイトを紹介し、人がリンクを押して来る → 名前を覚えた人が、あとで自分で検索して来る。3つを並べると、どの段で止まっているかが分かります。今は1段目が週に40〜50回あるのに、2段目は週に0〜2回、3段目は0です。AI は読みに来ているのに、答えの中でリンクとして出す、または人がそれを押すところまでは、まだ届いていません。

| いまの様子 | 次にやること |
|---|---|
| 1段目が増えて、2段目が増えない | AI が引用したくなる形に直す。どの記録がよく読まれているかは kpi の日ごとの内訳（`topPages`）で分かるので、読まれている所から、冒頭に結論を置くなどの直しを始める |
| 2段目が増えはじめた | 来た人が着いたページ（`landing`）で、AI がどの話題でこのサイトを紹介しているかを見る |
| 3段目が0を抜けた | 知名度が上がりはじめた合図。いつ抜けたかを日付で残す |

エイイチは、サイトが変わるのは来年のどこかだと見ています（11月5日）。それが本当にいつ起きたかを、日付つきで確かめられるようになります。

分からないことも3つあります。

- 数が小さいうちは、エイイチや Claude の試しが混ざると読み違える。11月3日がその例
- 「何人か」は数えられない。見た人を見分ける番号を残していないので、分かるのは回数だけ
- AI がリンクを付けずに、サイトの中身を答えに使った分は、どの数字にも出ない


### kpi_20261026_20261105.json（/api/kpi-stats の出力・全量）

```json
{
    "since": "2026-10-26",
    "until": "2026-11-05",
    "pendingDays": [],
    "byWeek": [
        {
            "week": "2026-10-26",
            "days": 7,
            "aiReads": 55,
            "aiReadsViaButton": 0,
            "aiReferrals": 0,
            "humanViews": 164,
            "aiReadsByBot": {
                "ChatGPT-User": 52,
                "Claude-User": 3
            },
            "aiReferralsBySource": {},
            "nameSearch": 0
        },
        {
            "week": "2026-11-02",
            "days": 4,
            "aiReads": 37,
            "aiReadsViaButton": 2,
            "aiReferrals": 2,
            "humanViews": 92,
            "aiReadsByBot": {
                "ChatGPT-User": 25,
                "Claude-User": 12
            },
            "aiReferralsBySource": {
                "ChatGPT": 2
            },
            "nameSearch": 0
        }
    ],
    "byDay": [
        {
            "day": "2026-10-26",
            "partial": false,
            "aiReads": 9,
            "aiReadsViaButton": 0,
            "aiReferrals": 0,
            "humanViews": 52,
            "aiReadsByBot": {
                "ChatGPT-User": 8,
                "Claude-User": 1
            },
            "aiReferralsBySource": {}
        },
        {
            "day": "2026-10-27",
            "partial": false,
            "aiReads": 13,
            "aiReadsViaButton": 0,
            "aiReferrals": 0,
            "humanViews": 17,
            "aiReadsByBot": {
                "ChatGPT-User": 13
            },
            "aiReferralsBySource": {}
        },
        {
            "day": "2026-10-28",
            "partial": false,
            "aiReads": 4,
            "aiReadsViaButton": 0,
            "aiReferrals": 0,
            "humanViews": 21,
            "aiReadsByBot": {
                "ChatGPT-User": 4
            },
            "aiReferralsBySource": {}
        },
        {
            "day": "2026-10-29",
            "partial": false,
            "aiReads": 4,
            "aiReadsViaButton": 0,
            "aiReferrals": 0,
            "humanViews": 33,
            "aiReadsByBot": {
                "ChatGPT-User": 4
            },
            "aiReferralsBySource": {}
        },
        {
            "day": "2026-10-30",
            "partial": false,
            "aiReads": 17,
            "aiReadsViaButton": 0,
            "aiReferrals": 0,
            "humanViews": 10,
            "aiReadsByBot": {
                "Claude-User": 1,
                "ChatGPT-User": 16
            },
            "aiReferralsBySource": {}
        },
        {
            "day": "2026-10-31",
            "partial": false,
            "aiReads": 6,
            "aiReadsViaButton": 0,
            "aiReferrals": 0,
            "humanViews": 18,
            "aiReadsByBot": {
                "ChatGPT-User": 5,
                "Claude-User": 1
            },
            "aiReferralsBySource": {}
        },
        {
            "day": "2026-11-01",
            "partial": false,
            "aiReads": 2,
            "aiReadsViaButton": 0,
            "aiReferrals": 0,
            "humanViews": 13,
            "aiReadsByBot": {
                "ChatGPT-User": 2
            },
            "aiReferralsBySource": {}
        },
        {
            "day": "2026-11-02",
            "partial": false,
            "aiReads": 7,
            "aiReadsViaButton": 0,
            "aiReferrals": 1,
            "humanViews": 30,
            "aiReadsByBot": {
                "ChatGPT-User": 7
            },
            "aiReferralsBySource": {
                "ChatGPT": 1
            }
        },
        {
            "day": "2026-11-03",
            "partial": false,
            "aiReads": 22,
            "aiReadsViaButton": 2,
            "aiReferrals": 1,
            "humanViews": 25,
            "aiReadsByBot": {
                "Claude-User": 12,
                "ChatGPT-User": 10
            },
            "aiReferralsBySource": {
                "ChatGPT": 1
            }
        },
        {
            "day": "2026-11-04",
            "partial": false,
            "aiReads": 5,
            "aiReadsViaButton": 0,
            "aiReferrals": 0,
            "humanViews": 16,
            "aiReadsByBot": {
                "ChatGPT-User": 5
            },
            "aiReferralsBySource": {}
        },
        {
            "day": "2026-11-05",
            "partial": false,
            "aiReads": 3,
            "aiReadsViaButton": 0,
            "aiReferrals": 0,
            "humanViews": 21,
            "aiReadsByBot": {
                "ChatGPT-User": 3
            },
            "aiReferralsBySource": {}
        }
    ],
    "detailDays": [
        {
            "version": 1,
            "day": "2026-10-26",
            "week": "2026-10-26",
            "madeAt": "2026-11-06T06:33:08.421Z",
            "aiReads": {
                "total": 9,
                "byBot": {
                    "ChatGPT-User": 8,
                    "Claude-User": 1
                },
                "viaButton": 0,
                "unverifiedChatGPTExcluded": 0,
                "topPages": [
                    {
                        "key": "/",
                        "count": 3
                    },
                    {
                        "key": "/record/pixelstomotors-com-domain",
                        "count": 1
                    },
                    {
                        "key": "/record/what-i-think-now-page",
                        "count": 1
                    },
                    {
                        "key": "/record/first-video-end-to-end",
                        "count": 1
                    },
                    {
                        "key": "/record/lock-down-ai-weekly-writes",
                        "count": 1
                    },
                    {
                        "key": "/record/youtube-script-curation",
                        "count": 1
                    },
                    {
                        "key": "/record/dev-mac-free-space",
                        "count": 1
                    }
                ]
            },
            "aiReferrals": {
                "total": 0,
                "bySource": {},
                "landing": [],
                "notHumanExcluded": 0
            },
            "context": {
                "humanViews": 52,
                "humanEntriesFromOutside": 42
            }
        },
        {
            "version": 1,
            "day": "2026-10-27",
            "week": "2026-10-26",
            "madeAt": "2026-11-06T06:33:11.611Z",
            "aiReads": {
                "total": 13,
                "byBot": {
                    "ChatGPT-User": 13
                },
                "viaButton": 0,
                "unverifiedChatGPTExcluded": 7,
                "topPages": [
                    {
                        "key": "/",
                        "count": 3
                    },
                    {
                        "key": "/record/from-sim-series-to-lp",
                        "count": 2
                    },
                    {
                        "key": "/record/shorts-81-percent-swiped",
                        "count": 1
                    },
                    {
                        "key": "/record/pi05-learned-the-pauses",
                        "count": 1
                    },
                    {
                        "key": "/record/pi05-first-block-in-box",
                        "count": 1
                    },
                    {
                        "key": "/record/microfactory-fairino-fr3",
                        "count": 1
                    },
                    {
                        "key": "/record/serving-robot-observation-sheet",
                        "count": 1
                    },
                    {
                        "key": "/record/serving-robot-cost-subsidy",
                        "count": 1
                    },
                    {
                        "key": "/serving-robot-one-less-staff",
                        "count": 1
                    },
                    {
                        "key": "/record/openpi-remote-inference-first-run",
                        "count": 1
                    }
                ]
            },
            "aiReferrals": {
                "total": 0,
                "bySource": {},
                "landing": [],
                "notHumanExcluded": 0
            },
            "context": {
                "humanViews": 17,
                "humanEntriesFromOutside": 11
            }
        },
        {
            "version": 1,
            "day": "2026-10-28",
            "week": "2026-10-26",
            "madeAt": "2026-11-06T06:33:15.272Z",
            "aiReads": {
                "total": 4,
                "byBot": {
                    "ChatGPT-User": 4
                },
                "viaButton": 0,
                "unverifiedChatGPTExcluded": 0,
                "topPages": [
                    {
                        "key": "/record/microfactory-fairino-fr3",
                        "count": 1
                    },
                    {
                        "key": "/record/claude-code-api-key-billing",
                        "count": 1
                    },
                    {
                        "key": "/",
                        "count": 1
                    },
                    {
                        "key": "/record/mecharm-not-done-yet",
                        "count": 1
                    }
                ]
            },
            "aiReferrals": {
                "total": 0,
                "bySource": {},
                "landing": [],
                "notHumanExcluded": 0
            },
            "context": {
                "humanViews": 21,
                "humanEntriesFromOutside": 20
            }
        },
        {
            "version": 1,
            "day": "2026-10-29",
            "week": "2026-10-26",
            "madeAt": "2026-11-06T06:33:19.132Z",
            "aiReads": {
                "total": 4,
                "byBot": {
                    "ChatGPT-User": 4
                },
                "viaButton": 0,
                "unverifiedChatGPTExcluded": 0,
                "topPages": [
                    {
                        "key": "/record/robot-ideas-from-pain-not-robots",
                        "count": 1
                    },
                    {
                        "key": "/record/autodesk-fusion-mcp-setup",
                        "count": 1
                    },
                    {
                        "key": "/",
                        "count": 1
                    },
                    {
                        "key": "/record/serving-robot-hidden-waits",
                        "count": 1
                    }
                ]
            },
            "aiReferrals": {
                "total": 0,
                "bySource": {},
                "landing": [],
                "notHumanExcluded": 0
            },
            "context": {
                "humanViews": 33,
                "humanEntriesFromOutside": 23
            }
        },
        {
            "version": 1,
            "day": "2026-10-30",
            "week": "2026-10-26",
            "madeAt": "2026-11-06T06:33:22.950Z",
            "aiReads": {
                "total": 17,
                "byBot": {
                    "Claude-User": 1,
                    "ChatGPT-User": 16
                },
                "viaButton": 0,
                "unverifiedChatGPTExcluded": 0,
                "topPages": [
                    {
                        "key": "/",
                        "count": 3
                    },
                    {
                        "key": "/record/serving-robot-video-ledger",
                        "count": 2
                    },
                    {
                        "key": "/record/making-explainer-video-with-ai",
                        "count": 1
                    },
                    {
                        "key": "/record/from-sim-series-to-lp",
                        "count": 1
                    },
                    {
                        "key": "/series4",
                        "count": 1
                    },
                    {
                        "key": "/record/serving-robot-cost-subsidy",
                        "count": 1
                    },
                    {
                        "key": "/series8",
                        "count": 1
                    },
                    {
                        "key": "/serving-robot-one-less-staff",
                        "count": 1
                    },
                    {
                        "key": "/record/lp-demo-same-time-compare",
                        "count": 1
                    },
                    {
                        "key": "/record/six-stores-fix-the-rules",
                        "count": 1
                    },
                    {
                        "key": "/record/code-skeleton-agent-judgment",
                        "count": 1
                    },
                    {
                        "key": "/record/video-patterns-and-try-it",
                        "count": 1
                    },
                    {
                        "key": "/record/studio-to-astro-cloudflare",
                        "count": 1
                    },
                    {
                        "key": "/record/cobot-deployment-law-and-coordination",
                        "count": 1
                    }
                ]
            },
            "aiReferrals": {
                "total": 0,
                "bySource": {},
                "landing": [],
                "notHumanExcluded": 0
            },
            "context": {
                "humanViews": 10,
                "humanEntriesFromOutside": 10
            }
        },
        {
            "version": 1,
            "day": "2026-10-31",
            "week": "2026-10-26",
            "madeAt": "2026-11-06T06:33:25.644Z",
            "aiReads": {
                "total": 6,
                "byBot": {
                    "ChatGPT-User": 5,
                    "Claude-User": 1
                },
                "viaButton": 0,
                "unverifiedChatGPTExcluded": 1,
                "topPages": [
                    {
                        "key": "/record/pixelstomotors-com-domain",
                        "count": 1
                    },
                    {
                        "key": "/",
                        "count": 1
                    },
                    {
                        "key": "/record/vertical-4koma-for-shorts",
                        "count": 1
                    },
                    {
                        "key": "/consult",
                        "count": 1
                    },
                    {
                        "key": "/record/floor-plans-into-simulator",
                        "count": 1
                    },
                    {
                        "key": "/record/hakobu-4koma-swipe-format",
                        "count": 1
                    }
                ]
            },
            "aiReferrals": {
                "total": 0,
                "bySource": {},
                "landing": [],
                "notHumanExcluded": 0
            },
            "context": {
                "humanViews": 18,
                "humanEntriesFromOutside": 9
            }
        },
        {
            "version": 1,
            "day": "2026-11-01",
            "week": "2026-10-26",
            "madeAt": "2026-11-06T06:33:28.297Z",
            "aiReads": {
                "total": 2,
                "byBot": {
                    "ChatGPT-User": 2
                },
                "viaButton": 0,
                "unverifiedChatGPTExcluded": 0,
                "topPages": [
                    {
                        "key": "/",
                        "count": 1
                    },
                    {
                        "key": "/record/video-patterns-and-try-it",
                        "count": 1
                    }
                ]
            },
            "aiReferrals": {
                "total": 0,
                "bySource": {},
                "landing": [],
                "notHumanExcluded": 0
            },
            "context": {
                "humanViews": 13,
                "humanEntriesFromOutside": 6
            }
        },
        {
            "version": 1,
            "day": "2026-11-02",
            "week": "2026-11-02",
            "madeAt": "2026-11-06T06:33:31.396Z",
            "aiReads": {
                "total": 7,
                "byBot": {
                    "ChatGPT-User": 7
                },
                "viaButton": 0,
                "unverifiedChatGPTExcluded": 0,
                "topPages": [
                    {
                        "key": "/record/beyond-imitation-learning",
                        "count": 4
                    },
                    {
                        "key": "/files/LOG383/18_Assets_ServiceSim_Editor_BuildHeadless.cs.txt",
                        "count": 1
                    },
                    {
                        "key": "/record/hakobu-4koma-english-without-redrawing",
                        "count": 1
                    },
                    {
                        "key": "/",
                        "count": 1
                    }
                ]
            },
            "aiReferrals": {
                "total": 1,
                "bySource": {
                    "ChatGPT": 1
                },
                "landing": [
                    {
                        "key": "/record/hakobu-4koma-english-without-redrawing",
                        "count": 1
                    }
                ],
                "notHumanExcluded": 0
            },
            "context": {
                "humanViews": 30,
                "humanEntriesFromOutside": 28
            }
        },
        {
            "version": 1,
            "day": "2026-11-03",
            "week": "2026-11-02",
            "madeAt": "2026-11-06T06:33:34.389Z",
            "aiReads": {
                "total": 22,
                "byBot": {
                    "Claude-User": 12,
                    "ChatGPT-User": 10
                },
                "viaButton": 2,
                "unverifiedChatGPTExcluded": 0,
                "topPages": [
                    {
                        "key": "/llms.txt",
                        "count": 2
                    },
                    {
                        "key": "/record/retrained-pi05-still-needs-human-corrections",
                        "count": 2
                    },
                    {
                        "key": "/record/gamepad-moves-mecharm-270-pymycobot-version",
                        "count": 1
                    },
                    {
                        "key": "/record/serving-robot-faceoff-staff-resolves",
                        "count": 1
                    },
                    {
                        "key": "/record/ai-reads-more-than-people",
                        "count": 1
                    },
                    {
                        "key": "/record/building-a-physical-ai-lab-at-home",
                        "count": 1
                    },
                    {
                        "key": "/gpu-buy-or-rent",
                        "count": 1
                    },
                    {
                        "key": "/record/openpi-remote-inference-first-run",
                        "count": 1
                    },
                    {
                        "key": "/record/pi05-mecharm-demo-to-inference",
                        "count": 1
                    },
                    {
                        "key": "/record/serving-robot-one-per-narrow-restaurant",
                        "count": 1
                    },
                    {
                        "key": "/record/day103",
                        "count": 1
                    },
                    {
                        "key": "/record/pi05-first-block-in-box",
                        "count": 1
                    },
                    {
                        "key": "/record/serving-robot-jam-detection-without-path-lines",
                        "count": 1
                    },
                    {
                        "key": "/record/rewind-and-correct-pi05",
                        "count": 1
                    },
                    {
                        "key": "/record/decisions-api-grasp-check",
                        "count": 1
                    },
                    {
                        "key": "/record/serving-robot-observation-sheet",
                        "count": 1
                    },
                    {
                        "key": "/record/ai-chaos-control-systems-before-robots",
                        "count": 1
                    },
                    {
                        "key": "/",
                        "count": 1
                    },
                    {
                        "key": "/record/gemini-api-4koma",
                        "count": 1
                    },
                    {
                        "key": "/record/world-model-adoption-criteria-robot-arm",
                        "count": 1
                    }
                ]
            },
            "aiReferrals": {
                "total": 1,
                "bySource": {
                    "ChatGPT": 1
                },
                "landing": [
                    {
                        "key": "/record/decisions-api-grasp-check",
                        "count": 1
                    }
                ],
                "notHumanExcluded": 0
            },
            "context": {
                "humanViews": 25,
                "humanEntriesFromOutside": 18
            }
        },
        {
            "version": 1,
            "day": "2026-11-04",
            "week": "2026-11-02",
            "madeAt": "2026-11-06T06:33:38.234Z",
            "aiReads": {
                "total": 5,
                "byBot": {
                    "ChatGPT-User": 5
                },
                "viaButton": 0,
                "unverifiedChatGPTExcluded": 2,
                "topPages": [
                    {
                        "key": "/",
                        "count": 2
                    },
                    {
                        "key": "/record/pi05-libero-benchmark-first-run",
                        "count": 2
                    },
                    {
                        "key": "/record/openpi-remote-inference-first-run",
                        "count": 1
                    }
                ]
            },
            "aiReferrals": {
                "total": 0,
                "bySource": {},
                "landing": [],
                "notHumanExcluded": 0
            },
            "context": {
                "humanViews": 16,
                "humanEntriesFromOutside": 16
            }
        },
        {
            "version": 1,
            "day": "2026-11-05",
            "week": "2026-11-02",
            "madeAt": "2026-11-06T06:33:58.722Z",
            "aiReads": {
                "total": 3,
                "byBot": {
                    "ChatGPT-User": 3
                },
                "viaButton": 0,
                "unverifiedChatGPTExcluded": 0,
                "topPages": [
                    {
                        "key": "/record/physical-ai-defined-by-how-it-is-built",
                        "count": 1
                    },
                    {
                        "key": "/record/deep-dive-article-to-dialogue-video",
                        "count": 1
                    },
                    {
                        "key": "/files/LOG383/06_20261025_1545_v11_project_split.txt",
                        "count": 1
                    }
                ]
            },
            "aiReferrals": {
                "total": 0,
                "bySource": {},
                "landing": [],
                "notHumanExcluded": 0
            },
            "context": {
                "humanViews": 21,
                "humanEntriesFromOutside": 18
            }
        }
    ],
    "nameSearch": [
        {
            "week": "2026-10-26",
            "clicks": 0,
            "impressions": 0,
            "queries": [],
            "note": "Search Console \u3092 Chrome \u3067\u78ba\u8a8d\uff082026-11-06\uff09\u3002\u65b0\u30c9\u30e1\u30a4\u30f3 sc-domain:pixelstomotors.com\u30fb\u65e7\u30c9\u30e1\u30a4\u30f3 https://adaptdesign.jp/ \u3068\u3082\u3001\u6b63\u898f\u8868\u73fe (?i)pixel|motor|\u30d4\u30af\u30bb\u30eb|p2m \u306e\u691c\u7d22\u8a9e\u306f 0\uff08\u65e7\u30c9\u30e1\u30a4\u30f3\u306e1\u8868\u793a\u306f CSS \u306e\u6587\u5b57\u5217\u3067\u3001\u30b5\u30a4\u30c8\u540d\u306e\u691c\u7d22\u3067\u306f\u306a\u3044\uff09\u3002\u6b63\u898f\u8868\u73fe\u306e\u7d5e\u308a\u8fbc\u307f\u304c\u52b9\u304f\u3053\u3068\u306f studio \u3067\u78ba\u304b\u3081\u305f\u3002\u4eba\u6570\u306e\u5c11\u306a\u3044\u691c\u7d22\u8a9e\u306f Search Console \u304c\u4f0f\u305b\u308b\u306e\u3067\u3001\u4f0f\u305b\u3089\u308c\u305f\u5206\u306f\u6570\u3048\u3089\u308c\u306a\u3044",
            "source": "Search Console",
            "recordedAt": "2026-11-06T07:11:51.972Z"
        },
        {
            "week": "2026-11-02",
            "clicks": 0,
            "impressions": 0,
            "queries": [],
            "note": "\u9014\u4e2d\u306e\u6570\uff0811/2\u301c11/5 \u307e\u3067\u3002Search Console \u306f2\u301c3\u65e5\u9045\u308c\uff09\u3002\u65b0\u65e7\u30c9\u30e1\u30a4\u30f3\u3068\u3082\u3001\u30b5\u30a4\u30c8\u540d\u306e\u691c\u7d22\u8a9e\u306f 0\u300211/16 \u306e\u5206\u6790\u3067\u9031\u306e\u78ba\u5b9a\u5206\u306b\u53d6\u308a\u76f4\u3059",
            "source": "Search Console",
            "recordedAt": "2026-11-06T07:11:55.674Z"
        }
    ]
}
```


### cr_since1025_ChatGPT-User.json（/api/cr-stats?since=2026-10-25&bot=ChatGPT-User の出力・全量）

```json
{"total":19252,"truncated":true,"since":"2026-10-25","bot":"ChatGPT-User","byBot":[{"bot":"meta-externalagent","who":"Meta（AI）","visits":4748,"pages":1246,"records":498,"verified":4748,"unverified":0,"errors":26,"last":"2026-11-05"},{"bot":"Googlebot","who":"Google（検索）","visits":4745,"pages":1374,"records":741,"verified":4554,"unverified":191,"errors":27,"last":"2026-11-05"},{"bot":"Amazonbot","who":"Amazon（Alexa・AI）","visits":4347,"pages":2299,"records":1247,"verified":4347,"unverified":0,"errors":69,"last":"2026-11-05"},{"bot":"Applebot","who":"Apple（Siri・検索・AI）","visits":1729,"pages":896,"records":227,"verified":1729,"unverified":0,"errors":7,"last":"2026-11-05"},{"bot":"ClaudeBot","who":"Anthropic（学習）","visits":1218,"pages":839,"records":180,"verified":1214,"unverified":4,"errors":56,"last":"2026-11-05"},{"bot":"bingbot","who":"Bing（検索。ChatGPT の検索・Copilot も使う）","visits":682,"pages":185,"records":158,"verified":677,"unverified":5,"errors":3,"last":"2026-11-05"},{"bot":"GPTBot","who":"OpenAI（学習）","visits":616,"pages":596,"records":118,"verified":614,"unverified":2,"errors":54,"last":"2026-11-05"},{"bot":"OAI-SearchBot","who":"OpenAI（ChatGPT の検索）","visits":437,"pages":135,"records":113,"verified":434,"unverified":3,"errors":1,"last":"2026-11-05"},{"bot":"GoogleOther","who":"Google（その他）","visits":360,"pages":202,"records":62,"verified":360,"unverified":0,"errors":0,"last":"2026-11-05"},{"bot":"ChatGPT-User","who":"ChatGPT（利用者の依頼で読む）","visits":88,"pages":48,"records":42,"verified":78,"unverified":10,"errors":0,"last":"2026-11-05"},{"bot":"その他","who":"その他（「AIで読む」経由で、名乗りが一覧にない読み手）","visits":73,"pages":52,"records":50,"verified":3,"unverified":70,"errors":2,"last":"2026-11-05"},{"bot":"PerplexityBot","who":"Perplexity（検索）","visits":65,"pages":23,"records":17,"verified":0,"unverified":65,"errors":0,"last":"2026-11-05"},{"bot":"YandexBot","who":"Yandex（検索）","visits":62,"pages":27,"records":21,"verified":59,"unverified":3,"errors":0,"last":"2026-11-05"},{"bot":"Bytespider","who":"ByteDance（AI）","visits":37,"pages":7,"records":4,"verified":2,"unverified":35,"errors":0,"last":"2026-11-05"},{"bot":"Claude-User","who":"Claude（利用者の依頼で読む）","visits":17,"pages":16,"records":12,"verified":0,"unverified":17,"errors":0,"last":"2026-11-03"},{"bot":"Baiduspider","who":"Baidu（検索）","visits":8,"pages":3,"records":1,"verified":6,"unverified":2,"errors":0,"last":"2026-11-04"},{"bot":"YouBot","who":"You.com","visits":8,"pages":6,"records":4,"verified":3,"unverified":5,"errors":0,"last":"2026-11-05"},{"bot":"CCBot","who":"Common Crawl（多くの AI の学習データ）","visits":5,"pages":2,"records":0,"verified":0,"unverified":5,"errors":0,"last":"2026-11-05"},{"bot":"DuckDuckBot","who":"DuckDuckGo（検索）","visits":3,"pages":1,"records":0,"verified":3,"unverified":0,"errors":0,"last":"2026-10-31"},{"bot":"Google-CloudVertexBot","who":"Google（Vertex AI）","visits":3,"pages":1,"records":0,"verified":0,"unverified":3,"errors":0,"last":"2026-11-04"},{"bot":"Yeti","who":"Naver（検索）","visits":1,"pages":1,"records":0,"verified":0,"unverified":1,"errors":0,"last":"2026-10-25"}],"byWeek":[{"week":"2026-11-02","total":7831,"bots":"meta-externalagent 2037、Googlebot 1951、Amazonbot 1863、Applebot 778、ClaudeBot 375、bingbot 214、GPTBot 209、OAI-SearchBot 189、その他 63、PerplexityBot 42、YandexBot 28、ChatGPT-User 27、Claude-User 13、GoogleOther 12、Bytespider 12、YouBot 8、CCBot 5、Google-CloudVertexBot 3、Baiduspider 2"},{"week":"2026-10-26","total":11260,"bots":"Googlebot 2775、meta-externalagent 2649、Amazonbot 2463、Applebot 939、ClaudeBot 831、bingbot 454、GPTBot 407、GoogleOther 329、OAI-SearchBot 248、ChatGPT-User 60、YandexBot 34、Bytespider 25、PerplexityBot 23、その他 10、Baiduspider 6、Claude-User 4、DuckDuckBot 3"},{"week":"2026-10-19","total":161,"bots":"meta-externalagent 62、Amazonbot 21、Googlebot 19、GoogleOther 19、bingbot 14、Applebot 12、ClaudeBot 12、Yeti 1、ChatGPT-User 1"}],"byPage":[{"path":"/","visits":27,"bots":"ChatGPT-User"},{"path":"/record/beyond-imitation-learning","visits":4,"bots":"ChatGPT-User"},{"path":"/record/from-sim-series-to-lp","visits":3,"bots":"ChatGPT-User"},{"path":"/record/pixelstomotors-com-domain","visits":2,"bots":"ChatGPT-User"},{"path":"/record/microfactory-fairino-fr3","visits":2,"bots":"ChatGPT-User"},{"path":"/record/serving-robot-observation-sheet","visits":2,"bots":"ChatGPT-User"},{"path":"/record/serving-robot-cost-subsidy","visits":2,"bots":"ChatGPT-User"},{"path":"/serving-robot-one-less-staff","visits":2,"bots":"ChatGPT-User"},{"path":"/record/openpi-remote-inference-first-run","visits":2,"bots":"ChatGPT-User"},{"path":"/record/video-patterns-and-try-it","visits":2,"bots":"ChatGPT-User"},{"path":"/record/serving-robot-video-ledger","visits":2,"bots":"ChatGPT-User"},{"path":"/record/pi05-libero-benchmark-first-run","visits":2,"bots":"ChatGPT-User"},{"path":"/record/explainer-video-simulation-background","visits":1,"bots":"ChatGPT-User"},{"path":"/record/first-video-end-to-end","visits":1,"bots":"ChatGPT-User"},{"path":"/record/lock-down-ai-weekly-writes","visits":1,"bots":"ChatGPT-User"},{"path":"/record/youtube-script-curation","visits":1,"bots":"ChatGPT-User"},{"path":"/record/dev-mac-free-space","visits":1,"bots":"ChatGPT-User"},{"path":"/record/shorts-81-percent-swiped","visits":1,"bots":"ChatGPT-User"},{"path":"/record/pi05-learned-the-pauses","visits":1,"bots":"ChatGPT-User"},{"path":"/record/pi05-first-block-in-box","visits":1,"bots":"ChatGPT-User"},{"path":"/record/claude-code-api-key-billing","visits":1,"bots":"ChatGPT-User"},{"path":"/record/mecharm-not-done-yet","visits":1,"bots":"ChatGPT-User"},{"path":"/record/robot-ideas-from-pain-not-robots","visits":1,"bots":"ChatGPT-User"},{"path":"/record/autodesk-fusion-mcp-setup","visits":1,"bots":"ChatGPT-User"},{"path":"/record/serving-robot-hidden-waits","visits":1,"bots":"ChatGPT-User"},{"path":"/series4","visits":1,"bots":"ChatGPT-User"},{"path":"/series8","visits":1,"bots":"ChatGPT-User"},{"path":"/record/lp-demo-same-time-compare","visits":1,"bots":"ChatGPT-User"},{"path":"/record/six-stores-fix-the-rules","visits":1,"bots":"ChatGPT-User"},{"path":"/record/code-skeleton-agent-judgment","visits":1,"bots":"ChatGPT-User"},{"path":"/record/studio-to-astro-cloudflare","visits":1,"bots":"ChatGPT-User"},{"path":"/record/cobot-deployment-law-and-coordination","visits":1,"bots":"ChatGPT-User"},{"path":"/record/vertical-4koma-for-shorts","visits":1,"bots":"ChatGPT-User"},{"path":"/record/floor-plans-into-simulator","visits":1,"bots":"ChatGPT-User"},{"path":"/record/hakobu-4koma-swipe-format","visits":1,"bots":"ChatGPT-User"},{"path":"/files/LOG383/18_Assets_ServiceSim_Editor_BuildHeadless.cs.txt","visits":1,"bots":"ChatGPT-User"},{"path":"/record/hakobu-4koma-english-without-redrawing","visits":1,"bots":"ChatGPT-User"},{"path":"/llms.txt","visits":1,"bots":"ChatGPT-User"},{"path":"/record/retrained-pi05-still-needs-human-corrections","visits":1,"bots":"ChatGPT-User"},{"path":"/record/serving-robot-jam-detection-without-path-lines","visits":1,"bots":"ChatGPT-User"},{"path":"/record/rewind-and-correct-pi05","visits":1,"bots":"ChatGPT-User"},{"path":"/record/decisions-api-grasp-check","visits":1,"bots":"ChatGPT-User"},{"path":"/record/ai-chaos-control-systems-before-robots","visits":1,"bots":"ChatGPT-User"},{"path":"/record/gemini-api-4koma","visits":1,"bots":"ChatGPT-User"},{"path":"/record/world-model-adoption-criteria-robot-arm","visits":1,"bots":"ChatGPT-User"},{"path":"/record/physical-ai-defined-by-how-it-is-built","visits":1,"bots":"ChatGPT-User"},{"path":"/record/deep-dive-article-to-dialogue-video","visits":1,"bots":"ChatGPT-User"},{"path":"/files/LOG383/06_20261025_1545_v11_project_split.txt","visits":1,"bots":"ChatGPT-User"}],"byVia":[{"via":"gemini","visits":296,"records":274,"bots":"Amazonbot 257、その他 39","last":"2026-11-05"},{"via":"copy","visits":283,"records":269,"bots":"Amazonbot 253、その他 30","last":"2026-11-05"},{"via":"chatgpt","visits":61,"records":33,"bots":"Googlebot 55、その他 3、Amazonbot 2、ChatGPT-User 1","last":"2026-11-05"},{"via":"claude","visits":3,"records":1,"bots":"Claude-User 1、その他 1、Amazonbot 1","last":"2026-11-05"}],"byViaWeek":[{"week":"2026-11-02","total":627,"via":"gemini 292、copy 278、chatgpt 54、claude 3"},{"week":"2026-10-26","total":16,"via":"chatgpt 7、copy 5、gemini 4"}],"errors":[{"path":"/ai-agent","status":"404","visits":9,"bots":"meta-externalagent、Googlebot、Amazonbot","last":"2026-11-01"},{"path":"/manga","status":"404","visits":6,"bots":"ClaudeBot、GPTBot、Googlebot、OAI-SearchBot、Amazonbot","last":"2026-10-29"},{"path":"/record/x.md","status":"404","visits":6,"bots":"その他、Amazonbot","last":"2026-11-04"},{"path":"/record/%7BR_%5Bn%5D%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-10-30"},{"path":"/record/%7BR_%5Blg%5D%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-10-31"},{"path":"/files/LOG388/%7Bs.img.startsWith('/')","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-10-30"},{"path":"/files/LOG361/18_AI_%E2%80%94state-from-target.txt","status":"404","visits":4,"bots":"Googlebot、Applebot","last":"2026-10-31"},{"path":"/files/LOG361/01_camera_align.py_%E2%80%94episode.txt","status":"404","visits":4,"bots":"Applebot、Googlebot","last":"2026-11-01"},{"path":"/files/LOG395/%7Bm%5Bl%5D%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-10-31"},{"path":"/files/LOG395/%7BEI%5Bp%5D%5B0%5D%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-11-01"},{"path":"/files/LOG395/%7Be%5B0%5D%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-11-01"},{"path":"/files/LOG395/%7Bc%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-10-31"},{"path":"/files/LOG395/%7Be%5B1%5D%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-11-01"},{"path":"/files/LOG395/%7B_c%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-11-01"},{"path":"/files/LOG395/%7Bo%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-10-31"},{"path":"/files/LOG395/%7B_o%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-11-01"},{"path":"/files/LOG399/%7BCTA%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-11-02"},{"path":"/record/","status":"404","visits":4,"bots":"bingbot、Amazonbot、GPTBot","last":"2026-11-05"},{"path":"/files/LOG427/%7BLOGO%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7BEI%5Bpose%5D%5B0%5D%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Bc%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Bo%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_f(","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Bm%5Bl%5D%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_f(A4)%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_f(B4)%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_c%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_o%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Be%5B1%5D%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Be%5B0%5D%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/record/precision-is-not-learning","status":"404","visits":3,"bots":"meta-externalagent","last":"2026-10-29"},{"path":"/english-4-koma/ep9","status":"404","visits":3,"bots":"meta-externalagent","last":"2026-10-29"},{"path":"/prototype6","status":"404","visits":3,"bots":"meta-externalagent、Googlebot","last":"2026-10-29"},{"path":"/record/side-camera-pipeline-split","status":"404","visits":3,"bots":"meta-externalagent","last":"2026-10-29"},{"path":"/prototype3","status":"404","visits":3,"bots":"meta-externalagent、Googlebot","last":"2026-10-29"},{"path":"/files/LOG361/11_1_%E2%80%94via-stride.txt","status":"404","visits":3,"bots":"Googlebot、Applebot","last":"2026-11-01"},{"path":"/files/LOG361/12_1_%E2%80%94via-stride.txt","status":"404","visits":3,"bots":"Googlebot、Applebot","last":"2026-11-01"},{"path":"/files/LOG413/%7Bmedia(p)%7D","status":"404","visits":3,"bots":"ClaudeBot、Amazonbot","last":"2026-11-03"},{"path":"/files/LOG429/%7BLOGO%7D","status":"404","visits":3,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-04"},{"path":"/files/LOG378/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"ClaudeBot、GPTBot","last":"2026-10-26"},{"path":"/files/LOG382/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"ClaudeBot、GPTBot","last":"2026-10-26"},{"path":"/files/LOG385/%7B%60/%24%7BseriesPage%5B0%5D%7D%60%7D","status":"404","visits":2,"bots":"ClaudeBot、GPTBot","last":"2026-10-26"},{"path":"/prototype5","status":"404","visits":2,"bots":"meta-externalagent","last":"2026-10-28"},{"path":"/files/LOG388/%7B%60/%24%7BseriesPage%5B0%5D%7D%60%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-10-26"},{"path":"/prototype1","status":"404","visits":2,"bots":"meta-externalagent","last":"2026-10-28"},{"path":"/prototype2","status":"404","visits":2,"bots":"meta-externalagent","last":"2026-10-29"},{"path":"/manga/ep9","status":"404","visits":2,"bots":"meta-externalagent","last":"2026-10-28"},{"path":"/files/LOG361/13_1_%E2%80%94via-stride.txt","status":"404","visits":2,"bots":"Applebot、Googlebot","last":"2026-10-29"},{"path":"/files/LOG373/%7Bs.img.startsWith('/')","status":"404","visits":2,"bots":"Amazonbot","last":"2026-10-30"},{"path":"/files/LOG395/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"ClaudeBot、GPTBot","last":"2026-10-29"},{"path":"/files/LOG399/%7B%60/%24%7BseriesPage%5B0%5D%7D%60%7D","status":"404","visits":2,"bots":"ClaudeBot、GPTBot","last":"2026-10-29"},{"path":"/files/LOG371/%7B%60","status":"404","visits":2,"bots":"Amazonbot","last":"2026-11-02"},{"path":"/files/LOG373/%7Bhref(l)%7D","status":"404","visits":2,"bots":"Amazonbot","last":"2026-10-30"},{"path":"/wordpress/","status":"404","visits":2,"bots":"Googlebot","last":"2026-10-31"},{"path":"/record/%7B%60/%24%7BseriesPage%5B0%5D%7D%60%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-01"},{"path":"/files/LOG421/%7B%60/%24%7BseriesPage%5B0%5D%7D%60%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-01"},{"path":"/record/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Be%5B1%5D%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Be%5B0%5D%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_f(","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7BEI%5Bpose%5D%5B0%5D%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_f(B4)%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_f(A4)%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Bc%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Bo%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_o%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_c%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Bm%5Bl%5D%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7BLOGO%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/files/LOG425/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/files/LOG429/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/files/LOG427/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/files/LOG432/%7BLOGO%7D","status":"404","visits":2,"bots":"ClaudeBot、Amazonbot","last":"2026-11-04"},{"path":"/files/LOG431/%7BLOGO%7D","status":"404","visits":2,"bots":"ClaudeBot、Amazonbot","last":"2026-11-04"},{"path":"/BingSiteAuth.xml","status":"404","visits":1,"bots":"bingbot","last":"2026-10-25"},{"path":"/prototype4","status":"404","visits":1,"bots":"meta-externalagent","last":"2026-10-27"},{"path":"/wp-json/","status":"404","visits":1,"bots":"Googlebot","last":"2026-10-31"},{"path":"/wordpress/wp-json/","status":"404","visits":1,"bots":"Googlebot","last":"2026-10-31"},{"path":"/cms/wp-json/","status":"404","visits":1,"bots":"Googlebot","last":"2026-10-31"},{"path":"/press/","status":"404","visits":1,"bots":"Googlebot","last":"2026-10-31"},{"path":"/blog/","status":"404","visits":1,"bots":"Googlebot","last":"2026-10-31"},{"path":"/wp/wp-json/","status":"404","visits":1,"bots":"Googlebot","last":"2026-10-31"},{"path":"/wp/","status":"404","visits":1,"bots":"Googlebot","last":"2026-10-31"},{"path":"/manga/ep8","status":"404","visits":1,"bots":"Amazonbot","last":"2026-11-02"},{"path":"/record/'%7Bp%7D'","status":"404","visits":1,"bots":"GPTBot","last":"2026-11-02"},{"path":"/files/LOG427/'%7Bp%7D'","status":"404","visits":1,"bots":"GPTBot","last":"2026-11-02"},{"path":"/files/LOG432/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":1,"bots":"ClaudeBot","last":"2026-11-02"},{"path":"/record/x","status":"404","visits":1,"bots":"Amazonbot","last":"2026-11-03"},{"path":"/files/LOG437/%24%7BSITE%7D/llms.txt","status":"404","visits":1,"bots":"ClaudeBot","last":"2026-11-04"},{"path":"/record/%24%7BSITE%7D/llms.txt","status":"404","visits":1,"bots":"ClaudeBot","last":"2026-11-04"},{"path":"/manga/%E7%AC%AC1%E8%A9%B1","status":"404","visits":1,"bots":"Googlebot","last":"2026-11-04"},{"path":"/%24p","status":"404","visits":1,"bots":"Googlebot","last":"2026-11-05"},{"path":"/files/LOG445/","status":"404","visits":1,"bots":"GPTBot","last":"2026-11-05"}]}
```


### cr_since1025_Claude-User.json（/api/cr-stats?since=2026-10-25&bot=Claude-User の出力・全量）

```json
{"total":19252,"truncated":true,"since":"2026-10-25","bot":"Claude-User","byBot":[{"bot":"meta-externalagent","who":"Meta（AI）","visits":4748,"pages":1246,"records":498,"verified":4748,"unverified":0,"errors":26,"last":"2026-11-05"},{"bot":"Googlebot","who":"Google（検索）","visits":4745,"pages":1374,"records":741,"verified":4554,"unverified":191,"errors":27,"last":"2026-11-05"},{"bot":"Amazonbot","who":"Amazon（Alexa・AI）","visits":4347,"pages":2299,"records":1247,"verified":4347,"unverified":0,"errors":69,"last":"2026-11-05"},{"bot":"Applebot","who":"Apple（Siri・検索・AI）","visits":1729,"pages":896,"records":227,"verified":1729,"unverified":0,"errors":7,"last":"2026-11-05"},{"bot":"ClaudeBot","who":"Anthropic（学習）","visits":1218,"pages":839,"records":180,"verified":1214,"unverified":4,"errors":56,"last":"2026-11-05"},{"bot":"bingbot","who":"Bing（検索。ChatGPT の検索・Copilot も使う）","visits":682,"pages":185,"records":158,"verified":677,"unverified":5,"errors":3,"last":"2026-11-05"},{"bot":"GPTBot","who":"OpenAI（学習）","visits":616,"pages":596,"records":118,"verified":614,"unverified":2,"errors":54,"last":"2026-11-05"},{"bot":"OAI-SearchBot","who":"OpenAI（ChatGPT の検索）","visits":437,"pages":135,"records":113,"verified":434,"unverified":3,"errors":1,"last":"2026-11-05"},{"bot":"GoogleOther","who":"Google（その他）","visits":360,"pages":202,"records":62,"verified":360,"unverified":0,"errors":0,"last":"2026-11-05"},{"bot":"ChatGPT-User","who":"ChatGPT（利用者の依頼で読む）","visits":88,"pages":48,"records":42,"verified":78,"unverified":10,"errors":0,"last":"2026-11-05"},{"bot":"その他","who":"その他（「AIで読む」経由で、名乗りが一覧にない読み手）","visits":73,"pages":52,"records":50,"verified":3,"unverified":70,"errors":2,"last":"2026-11-05"},{"bot":"PerplexityBot","who":"Perplexity（検索）","visits":65,"pages":23,"records":17,"verified":0,"unverified":65,"errors":0,"last":"2026-11-05"},{"bot":"YandexBot","who":"Yandex（検索）","visits":62,"pages":27,"records":21,"verified":59,"unverified":3,"errors":0,"last":"2026-11-05"},{"bot":"Bytespider","who":"ByteDance（AI）","visits":37,"pages":7,"records":4,"verified":2,"unverified":35,"errors":0,"last":"2026-11-05"},{"bot":"Claude-User","who":"Claude（利用者の依頼で読む）","visits":17,"pages":16,"records":12,"verified":0,"unverified":17,"errors":0,"last":"2026-11-03"},{"bot":"Baiduspider","who":"Baidu（検索）","visits":8,"pages":3,"records":1,"verified":6,"unverified":2,"errors":0,"last":"2026-11-04"},{"bot":"YouBot","who":"You.com","visits":8,"pages":6,"records":4,"verified":3,"unverified":5,"errors":0,"last":"2026-11-05"},{"bot":"CCBot","who":"Common Crawl（多くの AI の学習データ）","visits":5,"pages":2,"records":0,"verified":0,"unverified":5,"errors":0,"last":"2026-11-05"},{"bot":"DuckDuckBot","who":"DuckDuckGo（検索）","visits":3,"pages":1,"records":0,"verified":3,"unverified":0,"errors":0,"last":"2026-10-31"},{"bot":"Google-CloudVertexBot","who":"Google（Vertex AI）","visits":3,"pages":1,"records":0,"verified":0,"unverified":3,"errors":0,"last":"2026-11-04"},{"bot":"Yeti","who":"Naver（検索）","visits":1,"pages":1,"records":0,"verified":0,"unverified":1,"errors":0,"last":"2026-10-25"}],"byWeek":[{"week":"2026-11-02","total":7831,"bots":"meta-externalagent 2037、Googlebot 1951、Amazonbot 1863、Applebot 778、ClaudeBot 375、bingbot 214、GPTBot 209、OAI-SearchBot 189、その他 63、PerplexityBot 42、YandexBot 28、ChatGPT-User 27、Claude-User 13、GoogleOther 12、Bytespider 12、YouBot 8、CCBot 5、Google-CloudVertexBot 3、Baiduspider 2"},{"week":"2026-10-26","total":11260,"bots":"Googlebot 2775、meta-externalagent 2649、Amazonbot 2463、Applebot 939、ClaudeBot 831、bingbot 454、GPTBot 407、GoogleOther 329、OAI-SearchBot 248、ChatGPT-User 60、YandexBot 34、Bytespider 25、PerplexityBot 23、その他 10、Baiduspider 6、Claude-User 4、DuckDuckBot 3"},{"week":"2026-10-19","total":161,"bots":"meta-externalagent 62、Amazonbot 21、Googlebot 19、GoogleOther 19、bingbot 14、Applebot 12、ClaudeBot 12、Yeti 1、ChatGPT-User 1"}],"byPage":[{"path":"/robots.txt","visits":2,"bots":"Claude-User"},{"path":"/record/what-i-think-now-page","visits":1,"bots":"Claude-User"},{"path":"/record/making-explainer-video-with-ai","visits":1,"bots":"Claude-User"},{"path":"/consult","visits":1,"bots":"Claude-User"},{"path":"/llms.txt","visits":1,"bots":"Claude-User"},{"path":"/record/gamepad-moves-mecharm-270-pymycobot-version","visits":1,"bots":"Claude-User"},{"path":"/record/serving-robot-faceoff-staff-resolves","visits":1,"bots":"Claude-User"},{"path":"/record/ai-reads-more-than-people","visits":1,"bots":"Claude-User"},{"path":"/record/retrained-pi05-still-needs-human-corrections","visits":1,"bots":"Claude-User"},{"path":"/record/building-a-physical-ai-lab-at-home","visits":1,"bots":"Claude-User"},{"path":"/gpu-buy-or-rent","visits":1,"bots":"Claude-User"},{"path":"/record/openpi-remote-inference-first-run","visits":1,"bots":"Claude-User"},{"path":"/record/pi05-mecharm-demo-to-inference","visits":1,"bots":"Claude-User"},{"path":"/record/serving-robot-one-per-narrow-restaurant","visits":1,"bots":"Claude-User"},{"path":"/record/day103","visits":1,"bots":"Claude-User"},{"path":"/record/pi05-first-block-in-box","visits":1,"bots":"Claude-User"}],"byVia":[{"via":"gemini","visits":296,"records":274,"bots":"Amazonbot 257、その他 39","last":"2026-11-05"},{"via":"copy","visits":283,"records":269,"bots":"Amazonbot 253、その他 30","last":"2026-11-05"},{"via":"chatgpt","visits":61,"records":33,"bots":"Googlebot 55、その他 3、Amazonbot 2、ChatGPT-User 1","last":"2026-11-05"},{"via":"claude","visits":3,"records":1,"bots":"Claude-User 1、その他 1、Amazonbot 1","last":"2026-11-05"}],"byViaWeek":[{"week":"2026-11-02","total":627,"via":"gemini 292、copy 278、chatgpt 54、claude 3"},{"week":"2026-10-26","total":16,"via":"chatgpt 7、copy 5、gemini 4"}],"errors":[{"path":"/ai-agent","status":"404","visits":9,"bots":"meta-externalagent、Googlebot、Amazonbot","last":"2026-11-01"},{"path":"/manga","status":"404","visits":6,"bots":"ClaudeBot、GPTBot、Googlebot、OAI-SearchBot、Amazonbot","last":"2026-10-29"},{"path":"/record/x.md","status":"404","visits":6,"bots":"その他、Amazonbot","last":"2026-11-04"},{"path":"/record/%7BR_%5Bn%5D%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-10-30"},{"path":"/record/%7BR_%5Blg%5D%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-10-31"},{"path":"/files/LOG388/%7Bs.img.startsWith('/')","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-10-30"},{"path":"/files/LOG361/18_AI_%E2%80%94state-from-target.txt","status":"404","visits":4,"bots":"Googlebot、Applebot","last":"2026-10-31"},{"path":"/files/LOG361/01_camera_align.py_%E2%80%94episode.txt","status":"404","visits":4,"bots":"Applebot、Googlebot","last":"2026-11-01"},{"path":"/files/LOG395/%7Bm%5Bl%5D%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-10-31"},{"path":"/files/LOG395/%7BEI%5Bp%5D%5B0%5D%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-11-01"},{"path":"/files/LOG395/%7Be%5B0%5D%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-11-01"},{"path":"/files/LOG395/%7Bc%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-10-31"},{"path":"/files/LOG395/%7Be%5B1%5D%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-11-01"},{"path":"/files/LOG395/%7B_c%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-11-01"},{"path":"/files/LOG395/%7Bo%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-10-31"},{"path":"/files/LOG395/%7B_o%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-11-01"},{"path":"/files/LOG399/%7BCTA%7D","status":"404","visits":4,"bots":"ClaudeBot、GPTBot、Amazonbot","last":"2026-11-02"},{"path":"/record/","status":"404","visits":4,"bots":"bingbot、Amazonbot、GPTBot","last":"2026-11-05"},{"path":"/files/LOG427/%7BLOGO%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7BEI%5Bpose%5D%5B0%5D%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Bc%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Bo%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_f(","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Bm%5Bl%5D%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_f(A4)%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_f(B4)%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_c%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_o%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Be%5B1%5D%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Be%5B0%5D%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/record/precision-is-not-learning","status":"404","visits":3,"bots":"meta-externalagent","last":"2026-10-29"},{"path":"/english-4-koma/ep9","status":"404","visits":3,"bots":"meta-externalagent","last":"2026-10-29"},{"path":"/prototype6","status":"404","visits":3,"bots":"meta-externalagent、Googlebot","last":"2026-10-29"},{"path":"/record/side-camera-pipeline-split","status":"404","visits":3,"bots":"meta-externalagent","last":"2026-10-29"},{"path":"/prototype3","status":"404","visits":3,"bots":"meta-externalagent、Googlebot","last":"2026-10-29"},{"path":"/files/LOG361/11_1_%E2%80%94via-stride.txt","status":"404","visits":3,"bots":"Googlebot、Applebot","last":"2026-11-01"},{"path":"/files/LOG361/12_1_%E2%80%94via-stride.txt","status":"404","visits":3,"bots":"Googlebot、Applebot","last":"2026-11-01"},{"path":"/files/LOG413/%7Bmedia(p)%7D","status":"404","visits":3,"bots":"ClaudeBot、Amazonbot","last":"2026-11-03"},{"path":"/files/LOG429/%7BLOGO%7D","status":"404","visits":3,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-04"},{"path":"/files/LOG378/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"ClaudeBot、GPTBot","last":"2026-10-26"},{"path":"/files/LOG382/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"ClaudeBot、GPTBot","last":"2026-10-26"},{"path":"/files/LOG385/%7B%60/%24%7BseriesPage%5B0%5D%7D%60%7D","status":"404","visits":2,"bots":"ClaudeBot、GPTBot","last":"2026-10-26"},{"path":"/prototype5","status":"404","visits":2,"bots":"meta-externalagent","last":"2026-10-28"},{"path":"/files/LOG388/%7B%60/%24%7BseriesPage%5B0%5D%7D%60%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-10-26"},{"path":"/prototype1","status":"404","visits":2,"bots":"meta-externalagent","last":"2026-10-28"},{"path":"/prototype2","status":"404","visits":2,"bots":"meta-externalagent","last":"2026-10-29"},{"path":"/manga/ep9","status":"404","visits":2,"bots":"meta-externalagent","last":"2026-10-28"},{"path":"/files/LOG361/13_1_%E2%80%94via-stride.txt","status":"404","visits":2,"bots":"Applebot、Googlebot","last":"2026-10-29"},{"path":"/files/LOG373/%7Bs.img.startsWith('/')","status":"404","visits":2,"bots":"Amazonbot","last":"2026-10-30"},{"path":"/files/LOG395/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"ClaudeBot、GPTBot","last":"2026-10-29"},{"path":"/files/LOG399/%7B%60/%24%7BseriesPage%5B0%5D%7D%60%7D","status":"404","visits":2,"bots":"ClaudeBot、GPTBot","last":"2026-10-29"},{"path":"/files/LOG371/%7B%60","status":"404","visits":2,"bots":"Amazonbot","last":"2026-11-02"},{"path":"/files/LOG373/%7Bhref(l)%7D","status":"404","visits":2,"bots":"Amazonbot","last":"2026-10-30"},{"path":"/wordpress/","status":"404","visits":2,"bots":"Googlebot","last":"2026-10-31"},{"path":"/record/%7B%60/%24%7BseriesPage%5B0%5D%7D%60%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-01"},{"path":"/files/LOG421/%7B%60/%24%7BseriesPage%5B0%5D%7D%60%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-01"},{"path":"/record/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Be%5B1%5D%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Be%5B0%5D%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_f(","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7BEI%5Bpose%5D%5B0%5D%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_f(B4)%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_f(A4)%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Bc%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Bo%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_o%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_c%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Bm%5Bl%5D%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7BLOGO%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/files/LOG425/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/files/LOG429/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/files/LOG427/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/files/LOG432/%7BLOGO%7D","status":"404","visits":2,"bots":"ClaudeBot、Amazonbot","last":"2026-11-04"},{"path":"/files/LOG431/%7BLOGO%7D","status":"404","visits":2,"bots":"ClaudeBot、Amazonbot","last":"2026-11-04"},{"path":"/BingSiteAuth.xml","status":"404","visits":1,"bots":"bingbot","last":"2026-10-25"},{"path":"/prototype4","status":"404","visits":1,"bots":"meta-externalagent","last":"2026-10-27"},{"path":"/wp-json/","status":"404","visits":1,"bots":"Googlebot","last":"2026-10-31"},{"path":"/wordpress/wp-json/","status":"404","visits":1,"bots":"Googlebot","last":"2026-10-31"},{"path":"/cms/wp-json/","status":"404","visits":1,"bots":"Googlebot","last":"2026-10-31"},{"path":"/press/","status":"404","visits":1,"bots":"Googlebot","last":"2026-10-31"},{"path":"/blog/","status":"404","visits":1,"bots":"Googlebot","last":"2026-10-31"},{"path":"/wp/wp-json/","status":"404","visits":1,"bots":"Googlebot","last":"2026-10-31"},{"path":"/wp/","status":"404","visits":1,"bots":"Googlebot","last":"2026-10-31"},{"path":"/manga/ep8","status":"404","visits":1,"bots":"Amazonbot","last":"2026-11-02"},{"path":"/record/'%7Bp%7D'","status":"404","visits":1,"bots":"GPTBot","last":"2026-11-02"},{"path":"/files/LOG427/'%7Bp%7D'","status":"404","visits":1,"bots":"GPTBot","last":"2026-11-02"},{"path":"/files/LOG432/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":1,"bots":"ClaudeBot","last":"2026-11-02"},{"path":"/record/x","status":"404","visits":1,"bots":"Amazonbot","last":"2026-11-03"},{"path":"/files/LOG437/%24%7BSITE%7D/llms.txt","status":"404","visits":1,"bots":"ClaudeBot","last":"2026-11-04"},{"path":"/record/%24%7BSITE%7D/llms.txt","status":"404","visits":1,"bots":"ClaudeBot","last":"2026-11-04"},{"path":"/manga/%E7%AC%AC1%E8%A9%B1","status":"404","visits":1,"bots":"Googlebot","last":"2026-11-04"},{"path":"/%24p","status":"404","visits":1,"bots":"Googlebot","last":"2026-11-05"},{"path":"/files/LOG445/","status":"404","visits":1,"bots":"GPTBot","last":"2026-11-05"}]}
```


### cr_since1101_ChatGPT-User.json（/api/cr-stats?since=2026-11-01&bot=ChatGPT-User の出力・全量）

```json
{"total":10983,"truncated":false,"since":"2026-11-01","bot":"ChatGPT-User","byBot":[{"bot":"meta-externalagent","who":"Meta（AI）","visits":3010,"pages":1048,"records":666,"verified":3010,"unverified":0,"errors":1,"last":"2026-11-06"},{"bot":"Googlebot","who":"Google（検索）","visits":2584,"pages":1210,"records":723,"verified":2556,"unverified":28,"errors":4,"last":"2026-11-06"},{"bot":"Amazonbot","who":"Amazon（Alexa・AI）","visits":2497,"pages":1577,"records":939,"verified":2497,"unverified":0,"errors":46,"last":"2026-11-06"},{"bot":"Applebot","who":"Apple（Siri・検索・AI）","visits":1095,"pages":587,"records":176,"verified":1095,"unverified":0,"errors":1,"last":"2026-11-06"},{"bot":"ClaudeBot","who":"Anthropic（学習）","visits":646,"pages":453,"records":116,"verified":642,"unverified":4,"errors":38,"last":"2026-11-06"},{"bot":"bingbot","who":"Bing（検索。ChatGPT の検索・Copilot も使う）","visits":326,"pages":117,"records":92,"verified":321,"unverified":5,"errors":1,"last":"2026-11-06"},{"bot":"GPTBot","who":"OpenAI（学習）","visits":298,"pages":287,"records":70,"verified":296,"unverified":2,"errors":35,"last":"2026-11-06"},{"bot":"OAI-SearchBot","who":"OpenAI（ChatGPT の検索）","visits":259,"pages":64,"records":53,"verified":256,"unverified":3,"errors":0,"last":"2026-11-06"},{"bot":"その他","who":"その他（「AIで読む」経由で、名乗りが一覧にない読み手）","visits":82,"pages":57,"records":55,"verified":7,"unverified":75,"errors":2,"last":"2026-11-06"},{"bot":"PerplexityBot","who":"Perplexity（検索）","visits":44,"pages":10,"records":7,"verified":0,"unverified":44,"errors":0,"last":"2026-11-06"},{"bot":"YandexBot","who":"Yandex（検索）","visits":37,"pages":19,"records":15,"verified":34,"unverified":3,"errors":0,"last":"2026-11-06"},{"bot":"ChatGPT-User","who":"ChatGPT（利用者の依頼で読む）","visits":33,"pages":22,"records":18,"verified":31,"unverified":2,"errors":0,"last":"2026-11-06"},{"bot":"Bytespider","who":"ByteDance（AI）","visits":18,"pages":5,"records":2,"verified":0,"unverified":18,"errors":0,"last":"2026-11-06"},{"bot":"GoogleOther","who":"Google（その他）","visits":17,"pages":9,"records":7,"verified":17,"unverified":0,"errors":0,"last":"2026-11-06"},{"bot":"Claude-User","who":"Claude（利用者の依頼で読む）","visits":13,"pages":13,"records":10,"verified":0,"unverified":13,"errors":0,"last":"2026-11-03"},{"bot":"YouBot","who":"You.com","visits":8,"pages":6,"records":4,"verified":3,"unverified":5,"errors":0,"last":"2026-11-05"},{"bot":"CCBot","who":"Common Crawl（多くの AI の学習データ）","visits":8,"pages":2,"records":0,"verified":0,"unverified":8,"errors":0,"last":"2026-11-06"},{"bot":"Baiduspider","who":"Baidu（検索）","visits":5,"pages":2,"records":1,"verified":3,"unverified":2,"errors":1,"last":"2026-11-06"},{"bot":"Google-CloudVertexBot","who":"Google（Vertex AI）","visits":3,"pages":1,"records":0,"verified":0,"unverified":3,"errors":0,"last":"2026-11-04"}],"byWeek":[{"week":"2026-11-02","total":9568,"bots":"meta-externalagent 2669、Amazonbot 2346、Googlebot 2120、Applebot 979、ClaudeBot 513、bingbot 243、OAI-SearchBot 243、GPTBot 210、その他 72、PerplexityBot 44、YandexBot 33、ChatGPT-User 31、Bytespider 15、GoogleOther 13、Claude-User 13、YouBot 8、CCBot 8、Baiduspider 5、Google-CloudVertexBot 3"},{"week":"2026-10-26","total":1415,"bots":"Googlebot 464、meta-externalagent 341、Amazonbot 151、ClaudeBot 133、Applebot 116、GPTBot 88、bingbot 83、OAI-SearchBot 16、その他 10、GoogleOther 4、YandexBot 4、Bytespider 3、ChatGPT-User 2"}],"byPage":[{"path":"/","visits":8,"bots":"ChatGPT-User"},{"path":"/record/beyond-imitation-learning","visits":4,"bots":"ChatGPT-User"},{"path":"/record/pi05-libero-benchmark-first-run","visits":2,"bots":"ChatGPT-User"},{"path":"/record/video-patterns-and-try-it","visits":1,"bots":"ChatGPT-User"},{"path":"/files/LOG383/18_Assets_ServiceSim_Editor_BuildHeadless.cs.txt","visits":1,"bots":"ChatGPT-User"},{"path":"/record/hakobu-4koma-english-without-redrawing","visits":1,"bots":"ChatGPT-User"},{"path":"/llms.txt","visits":1,"bots":"ChatGPT-User"},{"path":"/record/retrained-pi05-still-needs-human-corrections","visits":1,"bots":"ChatGPT-User"},{"path":"/record/serving-robot-jam-detection-without-path-lines","visits":1,"bots":"ChatGPT-User"},{"path":"/record/rewind-and-correct-pi05","visits":1,"bots":"ChatGPT-User"},{"path":"/record/decisions-api-grasp-check","visits":1,"bots":"ChatGPT-User"},{"path":"/record/serving-robot-observation-sheet","visits":1,"bots":"ChatGPT-User"},{"path":"/record/ai-chaos-control-systems-before-robots","visits":1,"bots":"ChatGPT-User"},{"path":"/record/gemini-api-4koma","visits":1,"bots":"ChatGPT-User"},{"path":"/record/world-model-adoption-criteria-robot-arm","visits":1,"bots":"ChatGPT-User"},{"path":"/record/openpi-remote-inference-first-run","visits":1,"bots":"ChatGPT-User"},{"path":"/record/physical-ai-defined-by-how-it-is-built","visits":1,"bots":"ChatGPT-User"},{"path":"/record/deep-dive-article-to-dialogue-video","visits":1,"bots":"ChatGPT-User"},{"path":"/files/LOG383/06_20261025_1545_v11_project_split.txt","visits":1,"bots":"ChatGPT-User"},{"path":"/record/ai-aruaru-youtube-shorts","visits":1,"bots":"ChatGPT-User"},{"path":"/record/full-text-pages-and-read-with-ai-button","visits":1,"bots":"ChatGPT-User"},{"path":"/issues/sources","visits":1,"bots":"ChatGPT-User"}],"byVia":[{"via":"gemini","visits":352,"records":321,"bots":"Amazonbot 308、その他 44","last":"2026-11-06"},{"via":"copy","visits":342,"records":320,"bots":"Amazonbot 309、その他 33","last":"2026-11-06"},{"via":"chatgpt","visits":67,"records":37,"bots":"Googlebot 61、その他 3、Amazonbot 2、ChatGPT-User 1","last":"2026-11-06"},{"via":"claude","visits":4,"records":1,"bots":"その他 2、Claude-User 1、Amazonbot 1","last":"2026-11-06"}],"byViaWeek":[{"week":"2026-11-02","total":749,"via":"gemini 348、copy 337、chatgpt 60、claude 4"},{"week":"2026-10-26","total":16,"via":"chatgpt 7、copy 5、gemini 4"}],"errors":[{"path":"/record/x.md","status":"404","visits":6,"bots":"その他、Amazonbot","last":"2026-11-04"},{"path":"/record/","status":"404","visits":4,"bots":"bingbot、Amazonbot、GPTBot、ClaudeBot","last":"2026-11-06"},{"path":"/files/LOG427/%7BLOGO%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG429/%7BLOGO%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-06"},{"path":"/files/LOG425/%7BEI%5Bpose%5D%5B0%5D%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Bc%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Bo%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_f(","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Bm%5Bl%5D%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_f(A4)%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_f(B4)%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_c%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7B_o%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Be%5B1%5D%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG425/%7Be%5B0%5D%7D","status":"404","visits":4,"bots":"GPTBot、ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/files/LOG431/%7BLOGO%7D","status":"404","visits":3,"bots":"ClaudeBot、Amazonbot","last":"2026-11-05"},{"path":"/ai-agent","status":"404","visits":2,"bots":"meta-externalagent、Amazonbot","last":"2026-11-01"},{"path":"/record/%7B%60/%24%7BseriesPage%5B0%5D%7D%60%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-01"},{"path":"/files/LOG421/%7B%60/%24%7BseriesPage%5B0%5D%7D%60%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-01"},{"path":"/files/LOG413/%7Bmedia(p)%7D","status":"404","visits":2,"bots":"Amazonbot","last":"2026-11-03"},{"path":"/record/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Be%5B1%5D%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Be%5B0%5D%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_f(","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7BEI%5Bpose%5D%5B0%5D%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_f(B4)%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_f(A4)%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Bc%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Bo%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_o%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7B_c%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7Bm%5Bl%5D%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/record/%7BLOGO%7D","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/files/LOG425/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/files/LOG429/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/files/LOG427/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-02"},{"path":"/files/LOG432/%7BLOGO%7D","status":"404","visits":2,"bots":"ClaudeBot、Amazonbot","last":"2026-11-04"},{"path":"/files/LOG445/","status":"404","visits":2,"bots":"GPTBot、ClaudeBot","last":"2026-11-06"},{"path":"/files/LOG395/%7Be%5B1%5D%7D","status":"404","visits":1,"bots":"Amazonbot","last":"2026-11-01"},{"path":"/files/LOG395/%7BEI%5Bp%5D%5B0%5D%7D","status":"404","visits":1,"bots":"Amazonbot","last":"2026-11-01"},{"path":"/files/LOG395/%7B_c%7D","status":"404","visits":1,"bots":"Amazonbot","last":"2026-11-01"},{"path":"/files/LOG395/%7B_o%7D","status":"404","visits":1,"bots":"Amazonbot","last":"2026-11-01"},{"path":"/files/LOG395/%7Be%5B0%5D%7D","status":"404","visits":1,"bots":"Amazonbot","last":"2026-11-01"},{"path":"/files/LOG361/12_1_%E2%80%94via-stride.txt","status":"404","visits":1,"bots":"Googlebot","last":"2026-11-01"},{"path":"/files/LOG361/01_camera_align.py_%E2%80%94episode.txt","status":"404","visits":1,"bots":"Googlebot","last":"2026-11-01"},{"path":"/files/LOG361/11_1_%E2%80%94via-stride.txt","status":"404","visits":1,"bots":"Applebot","last":"2026-11-01"},{"path":"/manga/ep8","status":"404","visits":1,"bots":"Amazonbot","last":"2026-11-02"},{"path":"/files/LOG399/%7BCTA%7D","status":"404","visits":1,"bots":"Amazonbot","last":"2026-11-02"},{"path":"/files/LOG371/%7B%60","status":"404","visits":1,"bots":"Amazonbot","last":"2026-11-02"},{"path":"/record/'%7Bp%7D'","status":"404","visits":1,"bots":"GPTBot","last":"2026-11-02"},{"path":"/files/LOG427/'%7Bp%7D'","status":"404","visits":1,"bots":"GPTBot","last":"2026-11-02"},{"path":"/files/LOG432/'%20%2B%20LOGO%20%2B%20'","status":"404","visits":1,"bots":"ClaudeBot","last":"2026-11-02"},{"path":"/record/x","status":"404","visits":1,"bots":"Amazonbot","last":"2026-11-03"},{"path":"/files/LOG437/%24%7BSITE%7D/llms.txt","status":"404","visits":1,"bots":"ClaudeBot","last":"2026-11-04"},{"path":"/record/%24%7BSITE%7D/llms.txt","status":"404","visits":1,"bots":"ClaudeBot","last":"2026-11-04"},{"path":"/manga/%E7%AC%AC1%E8%A9%B1","status":"404","visits":1,"bots":"Googlebot","last":"2026-11-04"},{"path":"/%24p","status":"404","visits":1,"bots":"Googlebot","last":"2026-11-05"},{"path":"/record/read-by","status":"404","visits":1,"bots":"Baiduspider","last":"2026-11-05"}]}
```


### ev_since1026_human.json（/api/ev-stats?since=2026-10-26&who=human の出力・全量）

```json
{"total":3737,"counted":275,"truncated":false,"since":"2026-10-26","week":null,"who":"human","byWeek":[{"week":"2026-11-02","label":"2026-11-02 〜 11-08","views":112,"medianSeconds":16,"read75Pct":30,"spPct":23,"backViews":1,"outClicks":1,"deadClicks":17,"rageClicks":0,"messageViews":5,"formStarts":0,"formSubmits":0,"formSubmitsValid":0,"messagesReceived":0,"humanViews":112,"botViews":1374,"unknownViews":34,"unmarkedViews":0},{"week":"2026-10-26","label":"2026-10-26 〜 11-01","views":163,"medianSeconds":15,"read75Pct":26,"spPct":50,"backViews":4,"outClicks":8,"deadClicks":13,"rageClicks":1,"messageViews":2,"formStarts":0,"formSubmits":0,"formSubmitsValid":0,"messagesReceived":0,"humanViews":163,"botViews":1987,"unknownViews":67,"unmarkedViews":0}],"byPage":[{"path":"/","views":33,"medianSeconds":18,"read25Pct":73,"read50Pct":48,"read75Pct":30,"read100Pct":18,"deadClicks":0,"rageClicks":0,"copies":1,"videoPlays":1,"outClicks":0},{"path":"/gpu-buy-or-rent","views":19,"medianSeconds":11,"read25Pct":53,"read50Pct":53,"read75Pct":11,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":2,"outClicks":0},{"path":"/issues","views":15,"medianSeconds":10,"read25Pct":7,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":1,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/manga-archive","views":9,"medianSeconds":6,"read25Pct":11,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":1},{"path":"/series8","views":8,"medianSeconds":16,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day18","views":7,"medianSeconds":58,"read25Pct":86,"read50Pct":43,"read75Pct":29,"read100Pct":0,"deadClicks":1,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/message","views":7,"medianSeconds":9,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":14,"deadClicks":0,"rageClicks":0,"copies":1,"videoPlays":0,"outClicks":0},{"path":"/record/service-robot-last-mile","views":7,"medianSeconds":15,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":3},{"path":"/series6","views":5,"medianSeconds":20,"read25Pct":80,"read50Pct":40,"read75Pct":40,"read100Pct":20,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/series4","views":5,"medianSeconds":9,"read25Pct":100,"read50Pct":40,"read75Pct":40,"read100Pct":40,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/check-serving-robot-sim-with-phone","views":5,"medianSeconds":39,"read25Pct":20,"read50Pct":20,"read75Pct":20,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day17","views":4,"medianSeconds":36,"read25Pct":100,"read50Pct":100,"read75Pct":75,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/building-a-physical-ai-lab-at-home","views":4,"medianSeconds":14,"read25Pct":25,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/so101-imitation-learning-papers","views":4,"medianSeconds":15,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/beyond-imitation-learning","views":4,"medianSeconds":16,"read25Pct":50,"read50Pct":50,"read75Pct":50,"read100Pct":0,"deadClicks":1,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/serving-robot-video-ledger","views":4,"medianSeconds":12,"read25Pct":50,"read50Pct":50,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day145","views":3,"medianSeconds":111,"read25Pct":67,"read50Pct":33,"read75Pct":33,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/from-sim-series-to-lp","views":3,"medianSeconds":140,"read25Pct":67,"read50Pct":67,"read75Pct":33,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/video-patterns-and-try-it","views":3,"medianSeconds":12,"read25Pct":33,"read50Pct":33,"read75Pct":33,"read100Pct":33,"deadClicks":2,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/alphanist-binary-reward-assembly","views":3,"medianSeconds":16,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":67,"deadClicks":2,"rageClicks":1,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/one-year-lp-charts","views":3,"medianSeconds":14,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/serving-robot-hidden-waits","views":3,"medianSeconds":15,"read25Pct":33,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":2,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day12","views":3,"medianSeconds":12,"read25Pct":100,"read50Pct":67,"read75Pct":67,"read100Pct":33,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/road-marking-job-post-and-physical-ai","views":3,"medianSeconds":56,"read25Pct":67,"read50Pct":67,"read75Pct":67,"read100Pct":0,"deadClicks":1,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/manga/ep133","views":3,"medianSeconds":9,"read25Pct":100,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/pi05-first-block-in-box","views":2,"medianSeconds":11,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/rewrite-research-report","views":2,"medianSeconds":6,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/four-layers-of-robot-softness","views":2,"medianSeconds":43,"read25Pct":100,"read50Pct":50,"read75Pct":50,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/serving-robot-cost-subsidy","views":2,"medianSeconds":81,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/microfactory-fairino-fr3","views":2,"medianSeconds":1055,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":1},{"path":"/record/pi05-mecharm-demo-to-inference","views":2,"medianSeconds":17,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":1,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/pi05-mecharm-first-real-run","views":2,"medianSeconds":8,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/pi05-all-three-positions","views":2,"medianSeconds":11,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day21","views":2,"medianSeconds":39,"read25Pct":50,"read50Pct":50,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day20","views":2,"medianSeconds":13,"read25Pct":50,"read50Pct":50,"read75Pct":50,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/consult","views":2,"medianSeconds":54,"read25Pct":100,"read50Pct":50,"read75Pct":0,"read100Pct":0,"deadClicks":2,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":1},{"path":"/one-year","views":2,"medianSeconds":77,"read25Pct":100,"read50Pct":50,"read75Pct":50,"read100Pct":50,"deadClicks":1,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/serving-robot-one-less-staff","views":2,"medianSeconds":22,"read25Pct":50,"read50Pct":50,"read75Pct":50,"read100Pct":50,"deadClicks":1,"rageClicks":0,"copies":1,"videoPlays":12,"outClicks":0},{"path":"/record/japan-robot-leader-physical-ai-gap","views":2,"medianSeconds":449,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/rewind-and-correct-pi05","views":2,"medianSeconds":106,"read25Pct":50,"read50Pct":50,"read75Pct":50,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":1},{"path":"/record/vertical-4koma-for-shorts","views":2,"medianSeconds":113,"read25Pct":50,"read50Pct":50,"read75Pct":50,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/serving-robot-video-part2","views":2,"medianSeconds":15,"read25Pct":50,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/manga/ep132","views":2,"medianSeconds":8,"read25Pct":100,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day46","views":2,"medianSeconds":14,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/robot-research-data-index-and-provenance","views":2,"medianSeconds":149,"read25Pct":50,"read50Pct":50,"read75Pct":50,"read100Pct":50,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/robot-ai-divides-like-brain","views":2,"medianSeconds":85,"read25Pct":50,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/six-deep-dives-to-dialogue-videos","views":2,"medianSeconds":37,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day120","views":2,"medianSeconds":106,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":2,"videoPlays":0,"outClicks":0},{"path":"/record/serving-robot-night-runs","views":2,"medianSeconds":10,"read25Pct":50,"read50Pct":50,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day126","views":2,"medianSeconds":1131,"read25Pct":100,"read50Pct":100,"read75Pct":50,"read100Pct":50,"deadClicks":6,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/english-4-koma/ep22","views":1,"medianSeconds":10,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/youtube-script-curation","views":1,"medianSeconds":60,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day72","views":1,"medianSeconds":14,"read25Pct":100,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/issues/sim2real-gap","views":1,"medianSeconds":5,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/linkedin-analytics-research-posts","views":1,"medianSeconds":59,"read25Pct":100,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":1,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/preview/deep-dive-thumbs","views":1,"medianSeconds":24,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/robot-ideas-from-pain-not-robots","views":1,"medianSeconds":57,"read25Pct":100,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/mecharm-not-done-yet","views":1,"medianSeconds":4,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/teach-replay-19-demos","views":1,"medianSeconds":12,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":1},{"path":"/record/youtube-views-to-right-viewers","views":1,"medianSeconds":159,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/cobot-deployment-law-and-coordination","views":1,"medianSeconds":21,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":1,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/small-store-second-robot-wait","views":1,"medianSeconds":77,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day34","views":1,"medianSeconds":4,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/dev-mac-free-space","views":1,"medianSeconds":351,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/ai-readable-openings","views":1,"medianSeconds":174,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":100,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day78","views":1,"medianSeconds":16,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/issues/updates","views":1,"medianSeconds":11,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":2,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/six-stores-fix-the-rules","views":1,"medianSeconds":99,"read25Pct":100,"read50Pct":100,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/pi05-libero-benchmark-first-run","views":1,"medianSeconds":8,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day28","views":1,"medianSeconds":66,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/gemini-api-4koma","views":1,"medianSeconds":15,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":100,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/video-progress-board","views":1,"medianSeconds":11,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/english-4-koma/ep133","views":1,"medianSeconds":12,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/manga-archive-en","views":1,"medianSeconds":21,"read25Pct":100,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/manga/ep43","views":1,"medianSeconds":5,"read25Pct":100,"read50Pct":100,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/series1","views":1,"medianSeconds":34,"read25Pct":100,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/retrained-pi05-still-needs-human-corrections","views":1,"medianSeconds":79,"read25Pct":100,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/maker-voice-in-explainer-video","views":1,"medianSeconds":86,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/serving-robot-one-per-narrow-restaurant","views":1,"medianSeconds":3,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day57","views":1,"medianSeconds":76,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/hakobu-4koma-english-without-redrawing","views":1,"medianSeconds":59,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/hd-map-how-thin","views":1,"medianSeconds":364,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":100,"deadClicks":2,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/ai-reads-more-than-people","views":1,"medianSeconds":328,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/deep-dive-video-serving-robot-modding","views":1,"medianSeconds":18,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/gamepad-moves-mecharm-270-pymycobot-version","views":1,"medianSeconds":38,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/decisions-api-grasp-check","views":1,"medianSeconds":16,"read25Pct":100,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/world-model-adoption-criteria-robot-arm","views":1,"medianSeconds":162,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day122","views":1,"medianSeconds":80,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day113","views":1,"medianSeconds":6,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day114","views":1,"medianSeconds":15,"read25Pct":100,"read50Pct":100,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/serving-robot-faceoff-staff-resolves","views":1,"medianSeconds":100,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":1,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day54","views":1,"medianSeconds":9,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/manga/ep131","views":1,"medianSeconds":6,"read25Pct":100,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/find-tasks-where-nobody-comes","views":1,"medianSeconds":111,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/claude-project-linked-folders","views":1,"medianSeconds":195,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/day97","views":1,"medianSeconds":49,"read25Pct":100,"read50Pct":100,"read75Pct":100,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/series5","views":1,"medianSeconds":13,"read25Pct":100,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/record/pi05-sock-garbage-lora-yolo-so101","views":1,"medianSeconds":71,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/manga/ep130","views":1,"medianSeconds":5,"read25Pct":100,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0},{"path":"/issues/motion-portability","views":1,"medianSeconds":7,"read25Pct":0,"read50Pct":0,"read75Pct":0,"read100Pct":0,"deadClicks":0,"rageClicks":0,"copies":0,"videoPlays":0,"outClicks":0}],"moves":[{"move":"/record/day46 → /","count":4},{"move":"/ → /series4","count":2},{"move":"/series6 → /record/pi05-mecharm-first-real-run","count":2},{"move":"/serving-robot-one-less-staff → /","count":2},{"move":"/ → /series6","count":2},{"move":"/ → /","count":2},{"move":"/record/pi05-first-block-in-box → /series6","count":1},{"move":"/series6 → /gpu-buy-or-rent","count":1},{"move":"(戻る) → /record/rewrite-research-report","count":1},{"move":"/record/rewrite-research-report → /series4","count":1},{"move":"/ → /message","count":1},{"move":"/message → /","count":1},{"move":"/record/service-robot-last-mile → /record/service-robot-last-mile","count":1},{"move":"/record/from-sim-series-to-lp → /series4","count":1},{"move":"(戻る) → /record/from-sim-series-to-lp","count":1},{"move":"/record/beyond-imitation-learning → /record/beyond-imitation-learning","count":1},{"move":"/series6 → /record/teach-replay-19-demos","count":1},{"move":"/series6 → /record/pi05-mecharm-demo-to-inference","count":1},{"move":"(戻る) → /record/pi05-mecharm-demo-to-inference","count":1},{"move":"/record/youtube-views-to-right-viewers → /","count":1},{"move":"/consult → /one-year","count":1},{"move":"/record/from-sim-series-to-lp → /serving-robot-one-less-staff","count":1},{"move":"/record/serving-robot-cost-subsidy → /","count":1},{"move":"/record/serving-robot-hidden-waits → /issues","count":1},{"move":"/issues → /issues/updates","count":1},{"move":"/issues/updates → /manga-archive","count":1},{"move":"/record/rewind-and-correct-pi05 → /","count":1},{"move":"/manga-archive → /manga/ep133","count":1},{"move":"/manga/ep133 → /manga/ep132","count":1},{"move":"/manga/ep132 → /","count":1},{"move":"(戻る) → /","count":1},{"move":"/ → /record/gemini-api-4koma","count":1},{"move":"/record/check-serving-robot-sim-with-phone → /record/check-serving-robot-sim-with-phone","count":1},{"move":"/english-4-koma/ep133 → /manga-archive-en","count":1},{"move":"/ → /series1","count":1},{"move":"/ → /record/robot-research-data-index-and-provenance","count":1},{"move":"/record/robot-ai-divides-like-brain → /record/robot-ai-divides-like-brain","count":1},{"move":"/record/serving-robot-one-per-narrow-restaurant → /series8","count":1},{"move":"/record/pi05-all-three-positions → /","count":1},{"move":"/ → /issues","count":1},{"move":"/record/day122 → /record/day120","count":1},{"move":"/record/day120 → /record/day113","count":1},{"move":"/record/day113 → /record/day114","count":1},{"move":"/record/day114 → /record/day120","count":1},{"move":"/issues/motion-portability → /record/robotics-review-cards-by-category","count":1},{"move":"/record/day126 → /issues","count":1},{"move":"(戻る) → /record/day126","count":1},{"move":"/consult → /series7","count":1},{"move":"/series7 → /manga-archive","count":1},{"move":"/manga-archive → /issues","count":1}],"referrers":[{"from":"（直接・不明）","count":122},{"from":"www.google.com","count":61},{"from":"（サイト内）","count":59},{"from":"search.yahoo.co.jp","count":9},{"from":"www.linkedin.com","count":7},{"from":"teams.public.onecdn.static.microsoft","count":3},{"from":"t.co","count":3},{"from":"www.city.oga.akita.jp","count":2},{"from":"chatgpt.com（リンクの印）","count":2},{"from":"www.bing.com","count":2},{"from":"studio.design","count":2},{"from":"com.google.android.googlequicksearchbox","count":1},{"from":"com.linkedin.android","count":1},{"from":"www.youtube.com","count":1}],"utmSources":[{"source":"chatgpt.com","count":2}],"clicks":[{"target":"/｜ヘッダー","count":8},{"target":"btn:シリーズ｜ヘッダー","count":5},{"target":"/series4｜ページの中身","count":3},{"target":"#about｜フッター","count":3},{"target":"x.com｜本文","count":3},{"target":"/issues｜ヘッダー","count":3},{"target":"btn:次のコマ｜ページの中身","count":3},{"target":"btn:メニュー｜ヘッダー","count":3},{"target":"/｜現在地","count":2},{"target":"/｜フッター","count":2},{"target":"www.youtube.com｜本文","count":2},{"target":"iframe:/embeds/top-video.html｜ページの中身","count":2},{"target":"iframe:/sim/serving-robot.html｜sim","count":2},{"target":"/manga-archive｜ヘッダー","count":2},{"target":"/series6｜ページの中身","count":2},{"target":"iframe:/embeds/day126-F4igYhgG.html｜本文","count":2},{"target":"/series6｜現在地","count":1},{"target":"/gpu-buy-or-rent｜ページの中身","count":1},{"target":"/message｜フッター","count":1},{"target":"/record/service-robot-last-mile｜その他","count":1},{"target":"/series4｜現在地","count":1},{"target":"/record/beyond-imitation-learning｜その他","count":1},{"target":"iframe:/embeds/LOG392_frozen_vla_ports.html｜本文","count":1},{"target":"/files/LOG392/01_research_human_wearable_data_20261027.md｜本文","count":1},{"target":"/files/LOG392/LOG392_files.zip｜本文","count":1},{"target":"/series5｜現在地","count":1},{"target":"www.pi.website｜本文","count":1},{"target":"/files/LOG337/LOG337_full.md｜本文","count":1},{"target":"/files/LOG337/index.json｜本文","count":1},{"target":"iframe:/embeds/LOG399_research_to_work.html｜本文","count":1},{"target":"根拠：1年の記録 /one-year｜ページの中身","count":1},{"target":"/consult｜フッター","count":1},{"target":"#alphanistのコードは未公開で土台のomniresetは公開済みだった｜目次","count":1},{"target":"iframe:/embeds/LOG379_where_it_jams.html｜本文","count":1},{"target":"/issues/updates｜ページの中身","count":1},{"target":"www.youtube.com｜ヘッダー","count":1},{"target":"iframe:/embeds/LOG408_tate_4koma.html｜本文","count":1},{"target":"/manga/ep133｜その他","count":1},{"target":"/manga/ep132｜前後の記事","count":1},{"target":"/record/lighting-breaks-picking｜ページの中身","count":1},{"target":"/record/gemini-api-4koma｜ページの中身","count":1},{"target":"/record/check-serving-robot-sim-with-phone｜その他","count":1},{"target":"iframe:/embeds/LOG414_sheet_to_assumptions.html｜本文","count":1},{"target":"/manga-archive-en｜ヘッダー","count":1},{"target":"/series1｜ページの中身","count":1},{"target":"iframe:embed.figma.com｜ページの中身","count":1},{"target":"/record/robot-research-data-index-and-provenance｜ページの中身","count":1},{"target":"#about｜ヘッダー","count":1},{"target":"iframe:/embeds/LOG420_link_by_text.html｜本文","count":1},{"target":"/record/robot-ai-divides-like-brain｜その他","count":1},{"target":"btn:AIで読む:開く｜ai","count":1},{"target":"iframe:/embeds/LOG424_brain_robot_layers.html｜本文","count":1},{"target":"/series8｜現在地","count":1},{"target":"iframe:/embeds/hd-map-how-thin-LBeozryN.html｜本文","count":1},{"target":"iframe:/embeds/LOG430_ai_vs_people.html｜本文","count":1},{"target":"iframe:/embeds/LOG429_six_picks.html｜本文","count":1},{"target":"#作業ログ--考察記事を選んでから2本目を書き出し直すまで｜目次","count":1},{"target":"iframe:/embeds/LOG438_world_model_levels.html｜本文","count":1},{"target":"/issues｜フッター","count":1},{"target":"/record/day120｜関連記事","count":1}],"areas":[{"area":"本文","count":47},{"area":"ページの中身","count":26},{"area":"ヘッダー","count":26},{"area":"フッター","count":9},{"area":"sim","count":8},{"area":"その他","count":7},{"area":"現在地","count":6},{"area":"目次","count":5},{"area":"前後の記事","count":3},{"area":"関連記事","count":2},{"area":"ai","count":1}],"deadClicks":[{"where":"/record/day126 (リンクなし):p","count":6},{"where":"/issues/updates (リンクなし):th","count":2},{"where":"/record/hd-map-how-thin (リンクなし):p","count":2},{"where":"/record/day99 (リンクなし):p","count":2},{"where":"/consult (リンクなし):div","count":2},{"where":"/record/linkedin-analytics-research-posts (リンクなし):p","count":1},{"where":"/record/beyond-imitation-learning (リンクなし):div","count":1},{"where":"/record/pi05-mecharm-demo-to-inference (リンクなし):code","count":1},{"where":"/record/cobot-deployment-law-and-coordination (リンクなし):p","count":1},{"where":"/one-year (リンクなし):rect","count":1},{"where":"/record/alphanist-binary-reward-assembly (リンクなし):li","count":1},{"where":"/record/alphanist-binary-reward-assembly (リンクなし):td","count":1},{"where":"/serving-robot-one-less-staff (リンクなし):div","count":1},{"where":"/record/serving-robot-hidden-waits (リンクなし):h1","count":1},{"where":"/record/serving-robot-hidden-waits (リンクなし):div","count":1},{"where":"/record/road-marking-job-post-and-physical-ai (リンクなし):p","count":1},{"where":"/record/video-patterns-and-try-it (リンクなし):div","count":1},{"where":"/record/video-patterns-and-try-it (リンクなし):p","count":1},{"where":"/record/serving-robot-faceoff-staff-resolves (リンクなし):img","count":1},{"where":"/record/day18 (リンクなし):p","count":1},{"where":"/issues (リンクなし):nav","count":1}]}
```


## 次は、11/16 の分析で3つの数字を週ごとに並べる

11月16日の分析では、Claude が MCP の `how_to_read` と `kpi` から始め、Search Console を見て11月2日の週と11月9日の週のサイト名の検索を記録します。そこで、AI の依頼読みが増えているか、AI のリンクから来た人が週に2回を超えるか、サイト名の検索が0を抜けるかを見ます。あわせて、分析にかかった時間を、前回の約10分と並べて測ります。
