2026年8月18日
2026年8月18日
WordPressのGravatar・アバター表示エラーを解決する方法
はじめに
WordPressのコメント欄でGravatarのアバター画像が表示されずに壊れたアイコンが表示される・Gravatarの読み込みが遅くページ全体の表示速度に影響している・GDPRの観点からGravatarをGoogleやGravatar外部サービスに問い合わせたくない・会員制サイトでユーザーが自分のアバターをWordPress内でアップロード・変更できるようにしたいといった問題は、外部サービスへの接続設定・キャッシュ設定・カスタムアバター機能の未実装が原因です。
症状・原因
- コメントのアバター欄に壊れた画像アイコンが表示される
- サイトのページ読み込みが遅く、ネットワーク分析ツールで
gravatar.comへの多数のリクエストが確認できる - ヨーロッパのユーザーからGDPR違反の指摘を受けた(外部サービスへのIPアドレス送信)
- ユーザーが管理画面でプロフィール写真を変更できない(Gravatarのみ対応)
解決手順
ステップ1:Gravatar設定を診断する
# WP-CLIでアバター設定を確認
wp option get show_avatars
wp option get avatar_default
wp option get avatar_rating
# GravatarのURLを確認
wp eval "
\$email = 'test@example.com';
\$hash = md5(strtolower(trim(\$email)));
echo 'Gravatar URL: https://www.gravatar.com/avatar/' . \$hash . '?s=96&d=mm&r=g' . PHP_EOL;
echo 'get_avatar_url: ' . get_avatar_url(\$email) . PHP_EOL;
"
# アバター表示のフィルターを確認
wp eval "
global \$wp_filter;
if (isset(\$wp_filter['get_avatar'])) {
echo 'get_avatar filters: ' . count(\$wp_filter['get_avatar']->callbacks) . PHP_EOL;
}
if (isset(\$wp_filter['pre_get_avatar_data'])) {
echo 'pre_get_avatar_data filters: ' . count(\$wp_filter['pre_get_avatar_data']->callbacks) . PHP_EOL;
}
"
ステップ2:Gravatarをローカルにキャッシュする
// functions.php: GravatarをWordPressサーバーでキャッシュ
// ① Gravatar画像をローカルにダウンロードしてキャッシュ
add_filter('pre_get_avatar_data', function(array $args, mixed $id_or_email): array {
$email = '';
if (is_string($id_or_email) && str_contains($id_or_email, '@')) {
$email = $id_or_email;
} elseif ($id_or_email instanceof WP_User) {
$email = $id_or_email->user_email;
} elseif (is_numeric($id_or_email)) {
$user = get_user_by('id', (int) $id_or_email);
$email = $user ? $user->user_email : '';
}
if (empty($email)) {
return $args;
}
$hash = md5(strtolower(trim($email)));
$size = (int) ($args['size'] ?? 96);
$cache_key = 'gravatar_' . $hash . '_' . $size;
// キャッシュ済みのローカルURLがあればそれを使用
$local_url = get_transient($cache_key);
if ($local_url) {
$args['url'] = $local_url;
return $args;
}
// GravatarをダウンロードしてWordPressメディアとして保存
$gravatar_url = "https://www.gravatar.com/avatar/{$hash}?s={$size}&d=404&r=g";
$response = wp_remote_get($gravatar_url);
if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) === 200) {
$upload = wp_upload_bits("avatar-{$hash}-{$size}.jpg", null, wp_remote_retrieve_body($response));
if (!$upload['error']) {
set_transient($cache_key, $upload['url'], WEEK_IN_SECONDS);
$args['url'] = $upload['url'];
}
}
return $args;
}, 10, 2);
ステップ3:カスタムアバターをアップロードできるようにする
// functions.php: ユーザーがWordPress内でアバターをアップロード
// ① プロフィールページにアバターアップロードフィールドを追加
add_action('show_user_profile', 'add_avatar_upload_field');
add_action('edit_user_profile', 'add_avatar_upload_field');
function add_avatar_upload_field(WP_User $user): void {
$avatar_id = get_user_meta($user->ID, 'custom_avatar_id', true);
?>
<h3>カスタムアバター</h3>
<table class="form-table">
<tr>
<th><label for="custom_avatar">プロフィール写真</label></th>
<td>
<?php if ($avatar_id): ?>
<img src="<?php echo esc_url(wp_get_attachment_url((int) $avatar_id)); ?>"
width="96" height="96" style="border-radius:50%">
<?php endif; ?>
<input type="file" id="custom_avatar" name="custom_avatar" accept="image/*">
<p class="description">JPG・PNG・WebP形式、最大2MB</p>
</td>
</tr>
</table>
<?php
}
// ② アバター画像を保存
add_action('personal_options_update', 'save_custom_avatar');
add_action('edit_user_profile_update', 'save_custom_avatar');
function save_custom_avatar(int $user_id): void {
if (!current_user_can('edit_user', $user_id)) {
return;
}
if (empty($_FILES['custom_avatar']['name'])) {
return;
}
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/image.php';
require_once ABSPATH . 'wp-admin/includes/media.php';
$attachment_id = media_handle_upload('custom_avatar', 0);
if (!is_wp_error($attachment_id)) {
update_user_meta($user_id, 'custom_avatar_id', $attachment_id);
}
}
// ③ カスタムアバターをget_avatar()で使用
add_filter('pre_get_avatar_data', function(array $args, mixed $id_or_email): array {
$user_id = 0;
if (is_numeric($id_or_email)) {
$user_id = (int) $id_or_email;
} elseif ($id_or_email instanceof WP_User) {
$user_id = $id_or_email->ID;
} elseif (is_object($id_or_email) && isset($id_or_email->user_id)) {
$user_id = (int) $id_or_email->user_id;
}
if ($user_id) {
$avatar_id = get_user_meta($user_id, 'custom_avatar_id', true);
if ($avatar_id) {
$args['url'] = wp_get_attachment_url((int) $avatar_id);
}
}
return $args;
}, 10, 2);
ステップ4:GDPRに対応したGravatar設定
// functions.php: GDPR対応のGravatar設定
// ① ユーザーの同意がある場合のみGravatarを読み込む
add_filter('pre_get_avatar_data', function(array $args, mixed $id_or_email): array {
// セッションやクッキーで同意状態を確認
$consented = isset($_COOKIE['gravatar_consent']) && $_COOKIE['gravatar_consent'] === '1';
if (!$consented) {
// デフォルトアバターを使用(外部接続なし)
$args['url'] = get_avatar_url('', ['default' => 'mystery', 'force_default' => true]);
return $args;
}
return $args;
}, 5, 2);
// ② GravatarをデフォルトのローカルSVGに置き換え
add_filter('avatar_defaults', function(array $avatar_defaults): array {
$custom_avatar = get_theme_file_uri('assets/images/default-avatar.svg');
$avatar_defaults[$custom_avatar] = 'カスタムデフォルトアバター';
return $avatar_defaults;
});
// ③ Gravatarを完全に無効化してローカルデフォルトを使用
add_filter('pre_get_avatar', function(?string $avatar, mixed $id_or_email, array $args): ?string {
if (get_option('gravatar_disabled')) {
$size = (int) ($args['size'] ?? 96);
return sprintf(
'<img src="%s" width="%d" height="%d" class="avatar avatar-%d photo" alt="%s">',
esc_url(get_theme_file_uri('assets/images/default-avatar.svg')),
$size, $size, $size,
esc_attr($args['alt'] ?? 'アバター')
);
}
return $avatar;
}, 10, 3);
ステップ5:アバター表示を最適化する
// functions.php: アバターパフォーマンス最適化
// ① アバター画像にlazy loadを追加
add_filter('get_avatar', function(string $avatar): string {
return str_replace('<img ', '<img loading="lazy" ', $avatar);
});
// ② アバターサイズを適切に設定(Retinaディスプレイ対応)
add_filter('pre_get_avatar_data', function(array $args): array {
// 要求サイズの2倍を取得してRetinaに対応
if (isset($args['size']) && $args['size'] < 200) {
$args['size'] = $args['size'] * 2;
}
return $args;
}, 20);
// ③ アバターURLをHTTPSに強制
add_filter('get_avatar_url', function(string $url): string {
return str_replace('http://', 'https://', $url);
});
注意事項
- Gravatarをローカルにキャッシュする場合、
wp-content/uploads/に保存された画像はメディアライブラリに表示されます。定期的に古いキャッシュファイルを削除するクリーンアップ処理を実装することをお勧めします - カスタムアバターのアップロード機能を実装する際は、アップロードされたファイルのサイズと形式を必ず検証してください。悪意のあるファイルがアップロードされないよう
wp_check_filetype()でMIMEタイプを確認してください - GDPRの観点では、Gravatarはユーザーのメールアドレスのハッシュ値をGravatar社のサーバーに送信します。EU圏のユーザーがいる場合はプライバシーポリシーへの記載とユーザーの同意取得が必要です
まとめ
WordPressのGravatar・アバターエラーの解決は①wp option get show_avatarsでアバター設定確認・get_avatar_url()でGravatarURL検証・フィルター登録状況の確認、②pre_get_avatar_dataでGravatar画像をローカルダウンロード・wp_upload_bitsで保存・set_transientで1週間キャッシュ、③プロフィールページにshow_user_profileフックでアップロードフィールド追加・media_handle_uploadでWordPressメディア保存・custom_avatar_idユーザーメタで管理、④クッキーで同意確認してGravatarを条件的に無効化・avatar_defaultsでローカルデフォルトアバター追加・pre_get_avatarで完全ローカル化、⑤get_avatarフィルターでloading="lazy"追加・Retinaディスプレイ対応・get_avatar_urlでHTTPS強制の手順で解決します。