2026年5月20日
2026年5月20日
WordPressの外部リンクをSEOに最適化する方法
はじめに
外部リンクは適切に設定しないとSEO評価の漏洩やセキュリティリスクにつながります。rel="nofollow"・rel="sponsored"・rel="ugc"の使い分け、target="_blank"時のrel="noopener noreferrer"設定、アフィリエイトリンクの正しい扱いを理解することが重要です。
症状・原因
- 外部リンクを貼るたびに手動でrel属性を設定するのが面倒
- アフィリエイトリンクにnofollow/sponsoredを付けていなかった
target="_blank"なのにnoopenerがなくセキュリティリスクがある- コメント欄の外部リンクがすべてフォロードリンクになっている
解決手順
ステップ1:rel属性の種類と使い分けを理解する
【rel属性の種類】
rel="nofollow"
→ Googleにリンク先へのPageRank評価を渡さない
→ 信頼できない外部リンク全般に使用
rel="sponsored"
→ 広告・アフィリエイトなど有料で設置したリンク
→ Googleのガイドライン上、アフィリエイトは必須
rel="ugc"
→ User Generated Content(コメント・フォーラム投稿)
→ ユーザーが投稿したリンクに使用
rel="noopener noreferrer"
→ target="_blank"時のセキュリティ対策
→ noopener: 開いた先から window.opener へのアクセスを防ぐ
→ noreferrer: リファラー情報を送信しない
→ SEOとは別の設定(nofollow と併用可)
【Googleの方針】
・nofollowはヒント扱い(無視される場合あり)
・sponsoredは比較的厳格に扱われる
・ugcはコメントスパム対策として評価される
ステップ2:外部リンクに自動でrel属性を追加する
// functions.php: 外部リンクに自動で rel と target を追加
add_filter('the_content', 'add_external_link_attributes');
add_filter('the_excerpt', 'add_external_link_attributes');
function add_external_link_attributes(string $content): string {
$home = home_url();
return preg_replace_callback(
'/<a\s([^>]*)href=["\']((https?:)?\/\/[^"\']+)["\']([^>]*)>/i',
function(array $matches) use ($home): string {
$attrs = $matches[1] . $matches[4];
$url = $matches[2];
// 内部リンクはスキップ
if (str_starts_with($url, $home) || str_starts_with($url, '/')) {
return $matches[0];
}
// 既存のrel属性を取得
preg_match('/rel=["\']([^"\']*)["\']/', $attrs, $rel_match);
$existing_rel = $rel_match[1] ?? '';
// noopener と noreferrer を追加
$rel_values = array_filter(explode(' ', $existing_rel));
foreach (['noopener', 'noreferrer'] as $val) {
if (!in_array($val, $rel_values, true)) {
$rel_values[] = $val;
}
}
// target="_blank" が未設定なら追加
$has_target = str_contains($attrs, 'target=');
$target_attr = $has_target ? '' : ' target="_blank"';
// rel属性を更新
$new_rel = 'rel="' . implode(' ', $rel_values) . '"';
if ($rel_match) {
$attrs = preg_replace('/rel=["\'][^"\']*["\']/', $new_rel, $attrs);
} else {
$attrs .= ' ' . $new_rel;
}
return '<a ' . trim($attrs) . ' href="' . esc_url($url) . '"' . $target_attr . '>';
},
$content
);
}
ステップ3:アフィリエイトリンクに sponsored を設定する
// functions.php: アフィリエイトドメインに自動でsponsored付与
add_filter('the_content', function(string $content): string {
// アフィリエイトドメインリスト
$affiliate_domains = [
'amzn.to',
'amazon.co.jp',
'a8.net',
'af.moshimo.com',
'click.linksynergy.com',
];
return preg_replace_callback(
'/<a\s([^>]*)href=["\']([^"\']+)["\']([^>]*)>/i',
function(array $matches) use ($affiliate_domains): string {
$url = $matches[2];
// ドメインを取得
$parsed = parse_url($url);
$host = $parsed['host'] ?? '';
$is_affiliate = false;
foreach ($affiliate_domains as $domain) {
if (str_contains($host, $domain)) {
$is_affiliate = true;
break;
}
}
if (!$is_affiliate) {
return $matches[0];
}
// rel="sponsored noopener noreferrer" を付与
$attrs = $matches[1] . $matches[3];
preg_match('/rel=["\']([^"\']*)["\']/', $attrs, $rel_match);
$rel_values = $rel_match ? explode(' ', $rel_match[1]) : [];
foreach (['sponsored', 'noopener', 'noreferrer'] as $val) {
if (!in_array($val, $rel_values, true)) {
$rel_values[] = $val;
}
}
$new_rel = 'rel="' . implode(' ', array_filter($rel_values)) . '"';
if ($rel_match) {
$attrs = preg_replace('/rel=["\'][^"\']*["\']/', $new_rel, $attrs);
} else {
$attrs .= ' ' . $new_rel;
}
return '<a ' . trim($attrs) . ' href="' . esc_url($url) . '">';
},
$content
);
});
ステップ4:コメント欄のリンクに ugc を設定する
// functions.php: コメント内リンクに rel="ugc nofollow" を追加
add_filter('comment_text', function(string $comment_text): string {
return preg_replace_callback(
'/<a\s([^>]*)href=["\']([^"\']+)["\']([^>]*)>/i',
function(array $matches): string {
$attrs = $matches[1] . $matches[3];
preg_match('/rel=["\']([^"\']*)["\']/', $attrs, $rel_match);
$rel_values = $rel_match ? explode(' ', $rel_match[1]) : [];
foreach (['ugc', 'nofollow', 'noopener'] as $val) {
if (!in_array($val, $rel_values, true)) {
$rel_values[] = $val;
}
}
$new_rel = 'rel="' . implode(' ', array_filter($rel_values)) . '"';
if ($rel_match) {
$attrs = preg_replace('/rel=["\'][^"\']*["\']/', $new_rel, $attrs);
} else {
$attrs .= ' ' . $new_rel;
}
return '<a ' . trim($attrs) . ' href="' . esc_url($matches[2]) . '">';
},
$comment_text
);
});
ステップ5:Yoast SEOプラグインで外部リンク設定を管理する
【Yoast SEO での外部リンク設定】
Yoast SEO → 設定 → サイトの表示 → リンク
・外部リンクにrel="noopener"を追加: 有効
・外部リンクを新しいウィンドウで開く: サイトポリシーに応じて設定
【All in One SEO での設定】
All in One SEO → 一般設定 → リンク
・外部リンクにnofollow: 有効にするとすべての外部リンクにnofollow
(アフィリエイトサイトでは全部nofollowは不自然なため注意)
・UGCリンクにnofollow: 有効
# 既存記事の外部リンクを一括チェック
wp post list --post_status=publish --format=ids | \
xargs -I{} sh -c '
content=$(wp post get {} --field=post_content 2>/dev/null)
echo "$content" | grep -oP "href=\"https?://[^\"]+\"" | \
grep -v "example\.com"
' | sort -u | head -50
注意事項
- アフィリエイトリンクに
rel="sponsored"を付けることはGoogleのウェブマスターガイドラインで要求されています。付けない場合はリンクスキームとして手動ペナルティの対象になる可能性があります nofollowをすべての外部リンクに機械的に付けるのは推奨されません。信頼できる権威あるサイトへのリンクはnofollowなしでも問題ありませんtarget="_blank"のリンクには必ずrel="noopener"を付けてください。付けないと開いた先のページからwindow.openerを通じて元ページを操作される脆弱性(Reverse Tabnapping)があります
まとめ
外部リンクのrel属性は、アフィリエイト・広告はsponsored、ユーザー投稿はugc、その他信頼できない外部リンクはnofollowを使い分けます。target="_blank"には必ずnoopener noreferrerを付けます。the_contentフィルターとPHPの正規表現で既存コンテンツへの一括適用が可能です。Yoast SEOプラグインの設定で自動化することで手動設定の手間を削減できます。