2026年5月20日

2026年5月20日

WordPressのリンク切れを一括修正する方法

はじめに

リンク切れが検出されたら、次は修正です。修正方法は「内部リンクを直す」「リダイレクトで転送する」「404ページを改善する」の3アプローチがあります。リンク数が多い場合はWP-CLIやSQLで一括処理が効率的です。

症状・原因

  • 削除・移動したページへの内部リンクが大量にある
  • 旧URLへのアクセスが404のまま新URLに転送されていない
  • 外部からのリンクが古いURLに向いている(変更前のパーマリンク)
  • カスタム404ページがなく、ユーザーが迷子になっている

解決手順

ステップ1:WP-CLIで内部リンクを一括置換する

# パーマリンク変更後の内部リンクを一括修正
# ドライランで影響範囲を確認(--dry-run)
wp search-replace \
    'https://example.com/old-category/' \
    'https://example.com/new-category/' \
    --dry-run \
    --report-changed-only \
    --log

# 確認後に実際に置換
wp search-replace \
    'https://example.com/old-category/' \
    'https://example.com/new-category/' \
    --skip-columns=guid \
    --report-changed-only

# 特定テーブルだけを対象にする
wp search-replace \
    '/old-slug/' \
    '/new-slug/' \
    wp_posts wp_postmeta \
    --skip-columns=guid

# 置換後はキャッシュをクリア
wp cache flush
wp rewrite flush

ステップ2:301リダイレクトを設定する

# .htaccess: 特定URLのリダイレクト(Apache)

# 単一URL
Redirect 301 /old-page/ https://example.com/new-page/

# パターンマッチで一括リダイレクト
RedirectMatch 301 ^/old-category/(.*)$ https://example.com/new-category/$1

# 旧パーマリンク構造から新構造へ
# 例: /?p=123 → /post-slug/
RewriteCond %{QUERY_STRING} ^p=([0-9]+)$
RewriteRule ^/?$ https://example.com/?p=%1 [R=301,QSA,L]
# nginx.conf または site設定ファイル

server {
    # 単一URL
    location = /old-page/ {
        return 301 https://example.com/new-page/;
    }

    # パターン
    location ~ ^/old-category/(.*)$ {
        return 301 https://example.com/new-category/$1;
    }
}

ステップ3:Redirectionプラグインで管理画面からリダイレクトを設定する

【Redirectionプラグインの設定】
管理画面 → ツール → Redirection → リダイレクトを追加

Source URL: /old-page/
Target URL: /new-page/
HTTP code: 301(恒久移転)

CSVインポートで一括登録:
source_url,target_url,http_code
/old-page-1/,/new-page-1/,301
/old-page-2/,/new-page-2/,301
/old-category/post-1/,/new-category/post-1/,301
// functions.php: WordPress の template_redirect でリダイレクト
// Redirectionプラグイン不要の軽量実装

add_action('template_redirect', function(): void {
    $redirects = [
        '/old-page/'         => '/new-page/',
        '/old-category/'     => '/new-category/',
        '/contact-old/'      => '/contact/',
    ];

    $request = $_SERVER['REQUEST_URI'] ?? '';
    // クエリストリングを除去
    $path = strtok($request, '?');

    if (isset($redirects[$path])) {
        wp_redirect(home_url($redirects[$path]), 301);
        exit;
    }
});

ステップ4:データベースのリンクをSQLで一括修正する

-- wp_posts の本文内のURLを修正
UPDATE wp_posts
SET post_content = REPLACE(
    post_content,
    'https://example.com/old-category/',
    'https://example.com/new-category/'
)
WHERE post_content LIKE '%/old-category/%'
  AND post_status = 'publish';

-- wp_postmeta のカスタムフィールドURLを修正
UPDATE wp_postmeta
SET meta_value = REPLACE(
    meta_value,
    'https://example.com/old-category/',
    'https://example.com/new-category/'
)
WHERE meta_value LIKE '%/old-category/%';

-- wp_options のウィジェット設定内URLを修正
UPDATE wp_options
SET option_value = REPLACE(
    option_value,
    'https://example.com/old-domain.com',
    'https://example.com/new-domain.com'
)
WHERE option_name LIKE 'widget_%'
   OR option_name = 'sidebars_widgets';

ステップ5:カスタム404ページを作成してユーザーを誘導する

// テーマの 404.php をカスタマイズ

// テーマディレクトリに 404.php を作成
get_header();
?>
<main class="error-404">
    <h1>ページが見つかりません</h1>
    <p>お探しのページは移動または削除された可能性があります。</p>

    <?php
    // 検索フォームを表示
    get_search_form();

    // 人気記事を表示
    $popular = new WP_Query([
        'post_type'      => 'post',
        'posts_per_page' => 5,
        'meta_key'       => 'post_views_count',
        'orderby'        => 'meta_value_num',
        'order'          => 'DESC',
    ]);
    if ($popular->have_posts()) {
        echo '<h2>人気の記事</h2><ul>';
        while ($popular->have_posts()) {
            $popular->the_post();
            echo '<li><a href="' . get_permalink() . '">' . get_the_title() . '</a></li>';
        }
        echo '</ul>';
        wp_reset_postdata();
    }
    ?>

    <a href="<?php echo home_url('/'); ?>" class="button">トップページへ戻る</a>
</main>
<?php
get_footer();
// functions.php: 404ページへのアクセスをGAに送信
add_action('wp_head', function(): void {
    if (!is_404()) return;
    ?>
    <script>
    // GA4 で 404 イベントを送信
    gtag('event', 'page_not_found', {
        'page_location': window.location.href,
        'page_referrer': document.referrer
    });
    </script>
    <?php
});

注意事項

  • wp search-replace は必ず --dry-run で影響範囲を確認してから実行してください。実行前のデータベースバックアップも必須です
  • 301リダイレクトは恒久的な移転を意味します。一時的な転送には302を使用しますが、SEO的には301が推奨されます。リダイレクトチェーン(A→B→C)はSEO評価の希薄化につながるため避けてください
  • シリアライズされたデータ(PHPのserialize形式)がある場合、単純なSQL REPLACE ではデータが壊れます。WP-CLIのwp search-replaceはこれを自動で処理します

まとめ

内部リンクの一括修正はwp search-replace --dry-runで確認後に実行します。旧URLへのアクセスは.htaccessRedirect 301またはRedirectionプラグインで新URLに転送します。データベースのURLはUPDATE ... SET ... REPLACE(...)で一括更新できます。カスタム404.phpで検索フォームと人気記事を表示してユーザーを誘導し、GA4でイベント計測することで継続的な改善につなげます。

お気軽にご相談ください

お見積りへ お問い合わせへ