2026年5月17日

2026年5月17日

WordPress管理画面ダッシュボードにカスタムウィジェットを追加する方法

はじめに

WordPressの管理画面ダッシュボードに独自のウィジェットを追加することで、サイトの重要な情報を一目で把握できる管理ポータルを作成できます。投稿数・コメント数・最近のアクティビティ、外部APIのステータスなど、運営に必要な情報をカスタマイズして表示できます。本記事ではwp_add_dashboard_widget()の使い方から、デフォルトウィジェットの整理まで解説します。

症状・原因

  • クライアントのWordPressサイトで、よく使う機能へのショートカットやサイト統計を管理トップページに表示したい
  • デフォルトのダッシュボードウィジェット(WordPress News等)が不要で、整理したい
  • 管理者向けと編集者向けで表示するウィジェットを分けたい

解決手順

ステップ1:wp_add_dashboard_widget()でウィジェットを登録する

<?php
/**
 * ダッシュボードウィジェットの登録
 * wp_dashboard_setup フックで実行する
 */
add_action( 'wp_dashboard_setup', 'my_register_dashboard_widgets' );

function my_register_dashboard_widgets() {
    wp_add_dashboard_widget(
        'my_site_overview',           // ウィジェットID(一意の文字列)
        'サイト概要',                  // ウィジェットタイトル
        'my_site_overview_widget',    // コンテンツを出力するコールバック
        null,                         // 設定フォームのコールバック(なければnull)
        null,                         // コールバックに渡す引数(なければnull)
        'normal',                     // 表示位置: normal / side / column3 / column4
        'high'                        // 優先度: high / core / default / low
    );

    // 管理者のみに表示するウィジェット
    if ( current_user_can( 'manage_options' ) ) {
        wp_add_dashboard_widget(
            'my_admin_stats',
            '管理者統計',
            'my_admin_stats_widget',
            'my_admin_stats_widget_control' // 設定コントロールのコールバック
        );
    }

    // サイドバー(右カラム)にウィジェットを追加
    wp_add_dashboard_widget(
        'my_quick_links',
        'クイックリンク',
        'my_quick_links_widget',
        null,
        null,
        'side', // 右カラムに配置
        'high'
    );
}

ステップ2:サイト統計(投稿数・コメント数・最新アクティビティ)を表示する

<?php
/**
 * サイト概要ウィジェットの出力コールバック
 */
function my_site_overview_widget() {
    // 投稿数の取得(ステータス別)
    $post_counts    = wp_count_posts( 'post' );
    $page_counts    = wp_count_posts( 'page' );
    $comment_counts = wp_count_comments();

    // ユーザー数の取得
    $user_count = count_users();
    $total_users = $user_count['total_users'];

    echo '<div class="my-dashboard-stats">';

    // 統計テーブルの出力
    echo '<table class="my-stats-table" style="width:100%; border-collapse:collapse;">';
    echo '<thead><tr>
        <th style="text-align:left; padding:8px; border-bottom:1px solid #ddd;">項目</th>
        <th style="text-align:right; padding:8px; border-bottom:1px solid #ddd;">数</th>
    </tr></thead>';
    echo '<tbody>';

    $stats = array(
        array(
            'label' => '公開中の投稿',
            'count' => $post_counts->publish,
            'url'   => admin_url( 'edit.php?post_status=publish' ),
        ),
        array(
            'label' => '下書きの投稿',
            'count' => $post_counts->draft,
            'url'   => admin_url( 'edit.php?post_status=draft' ),
        ),
        array(
            'label' => '公開中の固定ページ',
            'count' => $page_counts->publish,
            'url'   => admin_url( 'edit.php?post_type=page&post_status=publish' ),
        ),
        array(
            'label' => '承認済みコメント',
            'count' => $comment_counts->approved,
            'url'   => admin_url( 'edit-comments.php?comment_status=approved' ),
        ),
        array(
            'label' => '承認待ちコメント',
            'count' => $comment_counts->moderated,
            'url'   => admin_url( 'edit-comments.php?comment_status=moderated' ),
        ),
        array(
            'label' => '登録ユーザー数',
            'count' => $total_users,
            'url'   => admin_url( 'users.php' ),
        ),
    );

    foreach ( $stats as $stat ) {
        printf(
            '<tr>
                <td style="padding:6px 8px;">%s</td>
                <td style="padding:6px 8px; text-align:right; font-weight:bold;">
                    <a href="%s">%s</a>
                </td>
            </tr>',
            esc_html( $stat['label'] ),
            esc_url( $stat['url'] ),
            number_format_i18n( (int) $stat['count'] )
        );
    }

    echo '</tbody></table>';
    echo '</div>';

    // 最新の投稿5件を表示
    echo '<h4 style="margin-top:15px;">最新の投稿</h4>';
    $recent_posts = get_posts( array(
        'numberposts' => 5,
        'post_status' => 'publish',
    ) );

    if ( $recent_posts ) {
        echo '<ul style="margin:0; padding-left:1.5em;">';
        foreach ( $recent_posts as $post ) {
            printf(
                '<li><a href="%s">%s</a> <span style="color:#666; font-size:0.9em;">%s</span></li>',
                esc_url( get_edit_post_link( $post->ID ) ),
                esc_html( get_the_title( $post ) ),
                esc_html( get_the_date( 'Y/m/d', $post ) )
            );
        }
        echo '</ul>';
    }
}

ステップ3:$callback_argsを使ったウィジェット設定の実装

<?php
/**
 * コントロール(設定)コールバックを使ったウィジェット
 * ダッシュボードウィジェットのタイトルバーに「設定」リンクが表示される
 */
function my_admin_stats_widget( $post, $callback_args ) {
    // $callback_args['args'] に保存された設定値が渡される
    $settings = get_option( 'my_admin_stats_settings', array(
        'show_charts' => true,
        'days'        => 7,
    ) );

    $days = absint( $settings['days'] );
    echo '<p><strong>過去 ' . esc_html( $days ) . ' 日間の統計</strong></p>';

    // 統計データの表示(実際は外部APIやカスタムテーブルから取得)
    $page_views = my_get_page_views( $days );
    echo '<p>ページビュー:' . number_format_i18n( $page_views ) . ' 回</p>';
}

/**
 * ウィジェットの設定コントロール(「設定」クリックで表示されるフォーム)
 */
function my_admin_stats_widget_control() {
    $settings = get_option( 'my_admin_stats_settings', array(
        'show_charts' => true,
        'days'        => 7,
    ) );

    // フォームが送信された場合に保存する
    if ( isset( $_POST['my_admin_stats_days'] ) ) {
        $settings['days']        = absint( $_POST['my_admin_stats_days'] );
        $settings['show_charts'] = ! empty( $_POST['my_admin_stats_show_charts'] );
        update_option( 'my_admin_stats_settings', $settings );
    }

    // 設定フォームの出力
    ?>
    <p>
        <label for="my_admin_stats_days">表示日数:</label>
        <select id="my_admin_stats_days" name="my_admin_stats_days">
            <?php foreach ( array( 7, 14, 30, 90 ) as $day ) : ?>
                <option value="<?php echo $day; ?>" <?php selected( $settings['days'], $day ); ?>>
                    <?php echo $day; ?> 日間
                </option>
            <?php endforeach; ?>
        </select>
    </p>
    <p>
        <label>
            <input type="checkbox"
                   name="my_admin_stats_show_charts"
                   value="1"
                   <?php checked( $settings['show_charts'] ); ?>>
            グラフを表示する
        </label>
    </p>
    <?php
}

/**
 * ページビューの集計(サンプル実装)
 */
function my_get_page_views( $days ) {
    // 実際の実装ではカスタムテーブルやキャッシュから取得
    return get_option( 'my_total_page_views', rand( 1000, 9999 ) );
}

ステップ4:remove_meta_box()でデフォルトウィジェットを非表示にする

<?php
/**
 * デフォルトのダッシュボードウィジェットを削除する
 */
add_action( 'wp_dashboard_setup', 'my_remove_dashboard_widgets' );

function my_remove_dashboard_widgets() {
    // WordPressデフォルトのウィジェットIDと画面
    $widgets_to_remove = array(
        // ウィジェットID               => 画面ID
        'dashboard_right_now'         => 'dashboard', // 概要(投稿数・コメント数)
        'dashboard_activity'          => 'dashboard', // アクティビティ
        'dashboard_quick_draft'       => 'dashboard', // クイック下書き
        'dashboard_primary'           => 'dashboard', // WordPress ニュース
        'dashboard_secondary'         => 'dashboard', // 他のWordPressニュース
    );

    foreach ( $widgets_to_remove as $widget_id => $screen ) {
        remove_meta_box( $widget_id, $screen, 'normal' );
        remove_meta_box( $widget_id, $screen, 'side' );   // サイドも確認
        remove_meta_box( $widget_id, $screen, 'column3' );
    }

    // 管理者以外にはすべてのデフォルトウィジェットを非表示
    if ( ! current_user_can( 'manage_options' ) ) {
        remove_meta_box( 'dashboard_right_now', 'dashboard', 'normal' );
    }
}

ステップ5:admin_headでダッシュボードウィジェットをスタイリングする

<?php
/**
 * ダッシュボードページ専用のCSSを追加する
 */
add_action( 'admin_head', 'my_dashboard_widget_styles' );

function my_dashboard_widget_styles() {
    // ダッシュボードページ以外では出力しない
    $screen = get_current_screen();
    if ( ! $screen || 'dashboard' !== $screen->id ) {
        return;
    }
    ?>
    <style>
        /* カスタムダッシュボードウィジェットのスタイル */
        #my_site_overview .inside {
            padding: 0;
        }

        .my-dashboard-stats {
            padding: 12px;
        }

        .my-stats-table {
            width: 100%;
            border-collapse: collapse;
        }

        .my-stats-table th,
        .my-stats-table td {
            padding: 8px 12px;
            border-bottom: 1px solid #f0f0f1;
            font-size: 13px;
        }

        .my-stats-table th {
            background: #f6f7f7;
            font-weight: 600;
            color: #1d2327;
        }

        .my-stats-table tr:last-child td {
            border-bottom: none;
        }

        .my-stats-table td:last-child {
            text-align: right;
        }

        /* クイックリンクウィジェット */
        #my_quick_links .my-quick-link {
            display: block;
            padding: 8px 12px;
            margin: 4px 0;
            background: #0073aa;
            color: #fff;
            text-decoration: none;
            border-radius: 3px;
            font-size: 13px;
            text-align: center;
        }

        #my_quick_links .my-quick-link:hover {
            background: #005d8c;
        }
    </style>
    <?php
}

/**
 * クイックリンクウィジェットの出力
 */
function my_quick_links_widget() {
    $links = array(
        '新規投稿を作成'     => admin_url( 'post-new.php' ),
        'メディアをアップロード' => admin_url( 'media-new.php' ),
        'ユーザーを追加'     => admin_url( 'user-new.php' ),
        'プラグインを管理'    => admin_url( 'plugins.php' ),
        '設定を変更'        => admin_url( 'options-general.php' ),
    );

    echo '<div style="padding:8px;">';
    foreach ( $links as $label => $url ) {
        printf(
            '<a href="%s" class="my-quick-link">%s</a>',
            esc_url( $url ),
            esc_html( $label )
        );
    }
    echo '</div>';
}

注意事項

  • wp_dashboard_setupフックのタイミング: ダッシュボードウィジェットはwp_dashboard_setupフック内でのみ登録・削除できます。admin_initなどの早いタイミングでは機能しません
  • ユーザー権限の確認: current_user_can()で権限を確認し、役割ごとに表示するウィジェットを制御してください
  • パフォーマンス: ダッシュボードは管理者がログインするたびに読み込まれます。重い処理(外部APIコール等)はTransientでキャッシュしてください
  • remove_meta_box()の第3引数: 一部のウィジェットは'normal'または'side'に配置されているため、両方で試す必要があります

まとめ

wp_add_dashboard_widget()wp_dashboard_setupフックを組み合わせることで、管理画面のダッシュボードをクライアントやチームのニーズに合わせてカスタマイズできます。不要なデフォルトウィジェットはremove_meta_box()で整理し、admin_headでスタイルを適用することで、プロフェッショナルな管理ポータルを実現できます。関連記事:WordPress管理画面に通知(admin_notices)を実装する方法

お気軽にご相談ください

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