TRYZM
← ブログ一覧

運営記録

404を直したら、行き先を間違えた|旧サイト移行で、自分の最大の流入ページを失っていた話

2026-08-04

TRYZMは、もともとWordPressで書いていた技術メモのサイトを、Next.jsで作り直したものです。その移行のときに、このサイトで一番読まれているページを、自分の手で殺していました。

今日それに気づいて直したので、何が起きていたのか、どう直したのかをそのまま書きます。効果がどうだったかは、まだ書けません(理由は最後に書きます)。

何をやっていたか

next.config.ts に、こういうリダイレクト設定が入っていました。

const oldPaths = [
  "/7zip_cmd",
  "/cmd-copy",
  "/cmd-dir-folderlist",
  "/mklink_for_dropboxuser",
  "/send-pdf-to-kindle",
  "/category/kindle",
];
return oldPaths.map((source) => ({
  source,
  destination: "/", // ← すべてトップページへ
  permanent: true,
}));

旧サイトの記事URLを、全部トップページへ301リダイレクトしていました。

そしてTRYZMのトップページは、格安SIMの比較コンテンツです。つまり 「7za.exe コマンド」で検索した人が、格安SIM比較のページに着地していた。 そのまま戻るボタンを押すに決まっています。

実測値:一番読まれているページが、そこにあった

Search Consoleの直近6週間の数字です。

URL表示平均掲載順位
/7zip_cmd/12211.5
/mklink_for_dropboxuser/46.2

放置していた8年前の技術メモが、サイト内で最も上位にいました。同じ期間、力を入れて書いた格安SIM記事は15〜23位、一般的なキーワードでは80位台です。勝てていた唯一の場所を、自分の手で潰していたことになります。(公開時この一文は「リダイレクトで潰していた」と書いていました。実際の死因は404です → 訂正

サイト全体のCTRは 0.7% でした。掲載順位が11位で表示122なら、本来もう少しクリックされてよいはずの数字です。

なぜこうなったか:「404を消す」が目的になっていた

該当のコミットメッセージが残っていました。

旧URL /7zip_cmd の301リダイレクト追加(唯一の漏れ・GSC最上位URLが404だった)

404は正しく検知していたし、正しく消していました。 GSCで「最上位URLが404だ」と気づいて、その日のうちに直している。ここまでは悪くありません。

抜けていたのは、そのあとです。「どこに送るか」を考えていない。 「404を出さないこと」がタスクになった瞬間に、「その読者は何を求めて来たのか」という問いが消えました。行き先がトップページなのは、それが一番手近だったからです。

これは技術の問題ではなく、問題の立て方の問題でした。「404を消す」ではなく「7za.exeを調べに来た人に7za.exeの話を返す」と立てていれば、トップページという選択肢は最初から出てこなかったはずです。

Googleも明示的に止めている

あとから確認したら、Google Search Centralのサイト移行のドキュメントに、そのままの注意書きがありました。

Don't redirect many old URLs to one irrelevant single URL destination

— Google Search Central「Site moves with URL changes

「新サイトのホームページのような、内容の対応しない1つのURLへ大量の旧URLを集約するな。ユーザーを混乱させるし、ソフト404として扱われる可能性がある」という趣旨です。ソフト404扱いになると、そのURLは検索結果から落ちていきます。

書いてある通りのことを、書いてある通りにやってしまっていました。

直し方:リダイレクトをやめて、元のURLで記事を返す

方針はシンプルで、リダイレクトを全部やめて、旧URLでそのまま記事を配信することにしました。順位はすでにあるので、URLを変える理由がありません。

ここで問題になったのが、記事の中身が手元に無いことです。旧サイトのWordPressはとっくに畳んでいて、エクスポートも残っていませんでした。

まずWayback Machineを見る → ほぼ無かった

archive.orgに残っていないか確認しました。1本ずつ調べる公式APIがあります。

curl "http://archive.org/wayback/available?url=tryzm.com/7zip_cmd"

返ってきたのは archived_snapshots: {}一番助けてほしい /7zip_cmd のスナップショットが、1枚も無い。 7本の記事のうち、個別ページが保全されていたのは1本だけでした。

ここで諦めると、「復元不能だから、内容の近いページへ301するしかない」という結論になります。実際そう書きかけました。

諦める前に、ドメイン全体を棚卸しする

available が返すのはそのURL単体の有無でしかありません。ドメイン単位で「何が保全されているか」を一覧できるCDX APIがあります。

curl "https://web.archive.org/cdx/search/cdx?url=tryzm.com&matchType=domain\
&fl=original,timestamp,statuscode&collapse=urlkey&limit=300"

これを見たら、記事ページは無いのに sitemap-posttype-post.2018.xml/feed/ が保全されていることが分かりました。ここから道が開けます。

① sitemapで「そもそも何本あったか」を確定させる

まずsitemapのスナップショットを取ります。URLに id_ を挟むと、Waybackのツールバー等が付かない素のオリジナルが落ちてきます。

curl -sSL "https://web.archive.org/web/20250714102157id_/https://tryzm.com/sitemap-posttype-post.2018.xml"

ここで想定外のことが分かりました。旧サイトの記事は7本あり、そのうち2本(/xcopy_directory_copy/findstr-cmd)は、リダイレクトのリストにすら入っていなかった。 つまりトップに飛ばされてすらおらず、素の404を返し続けていました。自分が把握していた「移行した記事の一覧」自体が間違っていたわけです。

移行の点検は、記憶や設定ファイルではなく、旧サイトのsitemapから始めるべきでした。

② RSSフィードから本文を回収する

そして本命がこれです。WordPressの /feed/ は、既定で直近記事の全文を <content:encoded> に入れて配信します。1つのURLに複数記事の本文がまとまって入るので、記事ページより保全されている確率が高い。

curl -sSL "https://web.archive.org/web/20250714082311id_/https://tryzm.com/feed/" -o feed.xml

65KBのXMLが落ちてきました。中身を開いたら、7本すべての本文が丸ごと入っていました。

import xml.etree.ElementTree as ET

ns = {"content": "http://purl.org/rss/1.0/modules/content/"}
root = ET.parse("feed.xml").getroot()

for item in root.find("channel").findall("item"):
    link = item.findtext("link")
    slug = link.rstrip("/").split("/")[-1]
    body = item.find("content:encoded", ns).text
    open(f"{slug}.html", "w").write(body or "")

個別ページのスナップショットがゼロだった /7zip_cmd も、これで本文が戻りました。

消えたサイトを復元するときの探索順

今回の教訓をそのまま手順にすると、こうなります。

  1. CDX APIでドメイン全体を棚卸しmatchType=domain)— 何が残っているかを先に把握する
  2. sitemap*.xml のスナップショット — 旧サイトの全URLを確定させる。「何本あったか」の記憶は当てにしない
  3. /feed//feed/atom/content:encoded から本文を一括回収する
  4. 個別記事ページのスナップショット — 最後。無いことのほうが多い
  5. カテゴリ一覧・検索結果ページ — 抜粋だけでも手がかりになる

取得はどれも https://web.archive.org/web/<timestamp>id_/<URL> の形で、id_ を忘れないこと。

復元しただけでは、誤情報になった

本文が戻ったので、そのまま公開しようとして止めました。8年前・5年前の記事です。当時正しかったことが、今は間違いになっている。

実際に2件ありました。

7-Zip:記事にあったダウンロード先 sevenzip.osdn.jp が消滅していました。今の配布元は 7-zip.org(実体はGitHubのリリース)です。ついでに、記事の主役である 7za.exe が現行版にも同梱されているかを確認するため、Extraパッケージ(26.02)を実際にダウンロードして中身を見ました7za.exe は今も入っていて、x64とarm64も同梱されています。

Send to Kindle:対応ファイル形式が変わっていました。記事に書いてあった MOBI(.MOBI / .AZW)とWord(.DOC / .DOCX)は、現在サポート対象外です。代わりにEPUBが追加され、ブラウザから200MBまで送れるウェブ版が主役になっています。Amazon公式ヘルプで確認しました。

昔の記事をそのまま復活させていたら、「Wordファイルが送れます」と嘘を書いたページが公開されるところでした。復元は、内容の正しさを保証しません。

実装

やったことは3つです。

  1. 旧URLのまま記事を配信する。 content/legacy/*.mdx に本文を置き、ルート直下の動的ルート(src/app/[legacySlug]/page.tsx)で返す。Next.jsの dynamicParams = false を付けて、登録した7本以外のパスは確実に404にしています。ルート直下に動的セグメントを置くと何でも拾いかねないので、ここは閉じておく
  2. トップページへの301は全撤去。 唯一 /category/kindle だけは復元対象の記事が無いので、内容が最も近い記事(KindleでPDFを読む方法)へ送りました。トップには投げません
  3. sitemapと記事一覧に載せる。 内部リンクが1本も通っていない状態だったので、そこも繋ぎました

復元した記事はこの7本です。

訂正:殺したのは301ではなく、その前の404だった

2026年8月6日追記。 この記事を公開したあと、8月18日の計測に備えてSearch ConsoleのAPIから週別の数字を取り直しました。そこで、自分の書いた因果関係が間違っていたことが分かりました。

週別の表示回数(実測)

週(月曜起点)/7zip_cmd//send-pdf-to-kindle/
6/017168
6/0810968
6/157358
6/225762
6/294691
7/06289
7/13076
7/20066
7/27089

そしてコミット履歴を突き合わせると、こうでした。

日付何が起きたか/7zip_cmd/ の状態
6/09新サイトを公開
6/11旧URLの301を設定。このリストに /7zip_cmd が入っていなかった404
〜7/06表示が 109 → 46 → 2 と減衰404
7/130
7/20/7zip_cmd の301を追加(トップページ宛)0のまま
8/04記事を復元

301を入れたのは7月20日。表示がゼロになったのは7月13日の週です。 順序が逆でした。

つまり何が起きていたか

  • 殺したのは404です。 移行時にリダイレクトのリストから /7zip_cmd を取りこぼし、約1か月かけてじわじわ検索結果から消えていった
  • 301はその後に打った、遅れた救命措置でした。すでにゼロになったURLをトップページへ飛ばしても、当然もどりません
  • /xcopy_directory_copy/findstr-cmd に至っては、301すら設定されていませんでした。ずっと404のままです

一方で、6月11日から301でトップへ飛ばされ続けていた /send-pdf-to-kindle/ は、表示が減っていません(毎週60〜90)。ただし掲載順位は43位前後で、クリックはゼロでした。

この2つを並べると、こう言えます。

404はインデックスを殺す。内容の対応しないページへの301は、インデックスは保つが、クリックを捨てる。

/7zip_cmd は404で検索結果から消えました。/send-pdf-to-kindle は301のまま検索結果に残り続けましたが、43位で、誰にもクリックされませんでした。

つまり 301→トップの害は「表示が消えること」ではなく、「着地した人がすぐ戻ること」のほうだったわけです。これは、この記事のもともとの主張、つまり着地したページが、その人の問いに答えていないという見立てを、むしろ裏づけています。凶器は違いましたが、症状の見立ては外していませんでした。

(ただしこれは1サイト・11週間の観測で、母数も小さいです。一般化はできません。もう1つ注意点があって、Search Consoleのデータは2〜3日遅れて入るので、週次で見ると最後の1〜2週が「まだ集計途中」で少なく見えます。そこを減少と読むと間違えます。実際、私も一度そう読みかけました)

自分の記事の何が間違っていたか

もとの本文で「勝てていた唯一の場所を、リダイレクトで潰していた」と書きました。リダイレクトで潰した、という部分が誤りです。 正しくは「移行時にURLを取りこぼして404にし、潰した」。

言い訳をすると、7月20日のコミットメッセージ(「唯一の漏れ・GSC最上位URLが404だった」)を読んだ時点で、順序は分かるはずでした。そこに書いてあったのに、301という分かりやすい犯人が目の前にあったので、それ以上調べなかった

これは、この記事自体が批判している構造と同じです。 「404を消す」がタスクになって行き先を考えなかったのと同じように、「犯人が見つかった」で調査を止めていました。

記事の結論は変わりません

  • 自分の最大の流入ページを、自分の手で失った:変わりません(凶器が404になっただけです)
  • 移行の点検は、記憶ではなく旧サイトのsitemapから始める:むしろ補強されました。取りこぼしこそが直接の死因だったので
  • リダイレクト先は「着地した人の検索意図が満たされるか」で選ぶ:変わりません。/send-pdf-to-kindle が順位43位・クリックゼロで生き続けていたのが、その実例です

そして教訓が1つ増えました

原因が1つ見つかった時点で、調べるのをやめない。 分かりやすい犯人は、たいてい先に目に入るだけで、いちばん手前にいるとは限らない。

効果は、まだ分かりません

ここが一番大事なところです。

この記事を書いている時点で、直した効果は測れていません。 復元したのは今日(2026年8月4日)で、Search Consoleに数字が出るのはこれからです。

なので、「流入が回復しました」「CTRが改善しました」とは書きません。 書けるのは「事故を見つけて、直した。効果はこれから測る」までです。

記録として、直す前の数字だけ置いておきます。

指標復元前(直近6週)
/7zip_cmd/ 表示122
/7zip_cmd/ 平均掲載順位11.5
/mklink_for_dropboxuser/ 平均掲載順位6.2
サイト全体のCTR0.7%

2週間後(8月18日頃)に同じ指標を取って、この記事に追記します。見る順番も決めてあります。

  1. 復元した7つのURLが200を返し、表示を得ているか(ソフト404から抜けたかの確認。これは少ない標本でも判断できる)
  2. サイト全体のCTRの方向
  3. クリック数の絶対値

ただし、もともと6週間で9クリックというサイトです。2週間で統計的に意味のある差は出ない可能性が高い。 数クリックの増減を「改善しました」と言うつもりはありません。改善が見えなかった場合の解釈も、あらかじめ3つ用意しています。再評価に数週間から数か月かかっている/期間が短くて検出できていない/そもそも診断が間違っていた。

「やってみたら3倍になりました」と書けたら記事としては強いのでしょうが、まだ測っていないものを成果として書いた時点で、この記事の主張と矛盾します。

残った教訓

自分に向けて3つ書いておきます。

リダイレクト先は「404にならないか」ではなく「着地した人の検索意図が満たされるか」で選ぶ。 満たせないなら、トップではなく内容が最も近いページへ。それも無いなら、素直に404を返したほうがマシです。内容の対応しない301は、ユーザーにとっても検索エンジンにとっても嘘になります。

移行の点検は、記憶ではなく旧サイトのsitemapから始める。 「移行した記事の一覧」を自分の設定ファイルから作っていたせいで、2本が404のまま何か月も放置されていました。正解を持っているのは自分ではなく、旧サイトが残したデータのほうです。

「無い」という一次情報の範囲を、勝手に広げない。 available APIが返した「無い」は、そのURL1本の話でしかありませんでした。それを「復元不能」と読み替えていたら、一段劣る対処で終わっていました。諦める前に、探索の範囲がまだ狭くないかを疑う。


TRYZMは、こういう失敗と訂正を消さずに残していきます。うまくいった話だけを並べたほうが読み物としては気持ちいいのですが、それは自分が読みたいものではないので。


追記(2026年9月17日):測りました。そして、その後に落ちました

この記事の最後に「8月18日に、この記事の続き(数字)を追記します」と書きました。

その追記が、30日遅れました。 計測自体は8月18日に予定どおり実行されていて、結果もその日のうちに記録されています。止まっていたのは追記の作業のほうでした。計測を実行した側から、記事を書く側への申し送りが、共有ノートに書き置かれたまま誰にも読まれずに残っていました。読む人と読む時刻が決まっていない申し送りは、受け手が存在しないのと同じです。遅れた理由はこれで、忘れていたわけではないぶん、かえって性質が悪いと思っています。

まず約束どおり、判定基準は結果を見る前に決めて公開してありました。その基準に機械的に当てた結果です。

8月18日の結果(4基準中3つ達成)

指標事前に決めた線復元前(7/24〜8/03)復元後(8/05〜8/15)判定
/7zip_cmd 表示10以上で回復の兆し046達成
復元7本 合計クリック3以上03達成(ぎりぎり)
復元7本 合計表示200以上131315達成
サイト全体CTR1.0%以上0.36%0.76%未達

死んでいた6つのURLが、そろってゼロから合計120表示・3クリックになりました。6本が同時に動いたので、偶然の揺れではないと判断しています。

CTRは倍になりましたが、達成とは書きません。比較する期間を1日ずらすと0.7%になります。差より誤差のほうが大きいので、これは判定保留です。

ところが、8月22日に落ちました

この記事の続きは、本来ここで終わるはずでした。今回あらためて直近の数字を取ったところ、別のことが起きていました。

8/18   71表示  平均掲載順位 26.2
8/19   66             23.2
8/20   54             30.6
8/21   55             28.5
8/22    3             ← ここで落ちている
8/23以降  0〜3表示/日・平均掲載順位 70〜92 が今日まで継続

崖のような落ち方です。そして、この状態が24日間続いていました。私は今日まで気づいていませんでした。

クエリ単位で見ると、性質がはっきりします。

8/11〜8/218/23〜9/14
全体の表示71180
平均掲載順位25.972.8
7za の順位8.0位87.0位

検索結果から消えたのではありません。同じクエリで今も出ています。順位だけが、サイト全体で一様に下がりました。 しかも現在の水準は、復元前のベースライン(1日あたり約25表示)よりも低い状態です。「回復したものが元に戻った」ではなく、その下に抜けています。

原因は、まだ分かっていません

調べて潰せたものだけ書きます。

  • 部分窓ではありません。 データの最終日は9月14日で、9月7日〜13日は完全な1週間です
  • サイト側の変更ではありません。 8月18日から25日のあいだ、コミットが1件もありません
  • 技術的な不具合ではありません。 全URLが200を返し、canonicalは正常、noindexは無く、robots.txtは許可、sitemapには81件が載っています(本日実測)

ここで犯人を1つ名指ししたくなりますが、しません。この記事はもともと、分かりやすい犯人を見つけてそれ以上調べなかったせいで、因果を間違えて訂正した記事です。 同じことを2回やるわけにはいきません。

いま最も安い決定的な証拠は、Search Consoleの「手動による対策」と「セキュリティの問題」の確認です。これはAPIでは取得できず、管理画面を開く必要があります。確認できしだい、結果がどちらであってもここに追記します。

この追記で言えること

復元そのものは、2週間の窓では数字に出ていました。ゼロだった6本が同時に表示を得ています。ただしその効果が続いたとは書けません。 1か月後に見たら、復元前より低い場所にいました。

2週間の測定で「効いた」と判定して、そこで観測をやめていたら、私は間違ったことを書いたまま終わっていました。 事前に基準を決めて測るところまではやったのに、測り続ける設計になっていなかった。ここが今回いちばん効いた反省です。

次に測るのは、原因が判明した時点です。判明しない場合も、11月に同じ窓で取り直して追記します。

ナオTRYZM管理人

AIに関わるPMで、夜はAIで作って試す人。囲碁では布石が好き(何もない盤面に構想を描く時間)。 嘘をつくと自分があとで気にして引きずるタチなので、報酬が入らないプランでも一番ならそのまま書きます。 守れるルールは3つ — 盛らない。順位を売らない。試せないことも、徹底的に調べて正確に。