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強制の手順で解決します。

お気軽にご相談ください

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