Table of Contents
- WordPress Site Health Overview
- Registering Custom Health Checks
- Implementing Debug Information Providers
- Status Tests and Pass/Fail Logic
- Troubleshooting Mode Integration
- Testing and Deployment
- Frequently Asked Questions
WordPress Site Health Overview
WordPress Site Health, introduced in WordPress 5.2, is a diagnostic tool that helps site administrators understand and fix issues affecting site performance, security, and functionality. Located at Tools → Site Health in the admin dashboard, Site Health checks various system requirements, configuration settings, and plugin status, providing actionable recommendations when problems are detected.
For plugin developers, integrating with WordPress Site Health through custom health checks provides a professional way to communicate plugin status and requirements to administrators. Rather than relying on admin notices that might be dismissed or ignored, WordPress Site Health integration embeds your plugin's health status directly into the diagnostic dashboard administrators already use when troubleshooting site issues.
WordPress plugin health check integration enables you to register custom status tests, provide debug information, and even integrate with troubleshooting mode. This guide covers the complete WordPress Site Health plugin integration process, from implementing basic health checks to providing comprehensive debug information and enabling the troubleshooting mode—WordPress's experimental safe mode for testing plugin compatibility.
Registering Custom Health Checks
Custom health checks are registered through the site_status_tests filter, which receives an array of test callables. Each test returns an associative array describing the check's result—whether it passed or failed, what it means, and what actions administrators can take.
Create a basic health check with the site_status_tests filter:
<?php
add_filter('site_status_tests', function($tests) {
// Add our custom test
$tests['my_plugin_test_api_connectivity'] = [
'label' => __('My Plugin API Connectivity', 'my-plugin'),
'test' => 'my_plugin_test_api_connectivity',
];
return $tests;
});
// The actual test callback
function my_plugin_test_api_connectivity() {
// Test result structure
$result = [
'label' => __('My Plugin Can Connect to External API', 'my-plugin'),
'status' => 'good', // 'good', 'recommended', or 'critical'
'badge' => [
'label' => __('My Plugin', 'my-plugin'),
'color' => 'blue',
],
'description' => __('My Plugin successfully connected to its required external API.', 'my-plugin'),
'actions' => '',
'test' => 'my_plugin_test_api_connectivity',
];
// Test the API connection
$response = wp_remote_get('https://api.myplugin.com/health');
if (is_wp_error($response)) {
$result['status'] = 'critical';
$result['description'] = sprintf(
__('My Plugin cannot connect to the external API: %s', 'my-plugin'),
esc_html($response->get_error_message())
);
}
return $result;
}
?>
The test function should return an array with these key elements:
- label: What administrators see in the Site Health list
- status: Either "good" (passes), "recommended" (warning), or "critical" (failure)
- badge: Optional label and color identifying your plugin
- description: Explanation of what the test checks and what the result means
- actions: Optional HTML containing action buttons or links
- test: The test identifier (must match the callback name)
Well-designed WordPress Site Health checks provide specific, actionable information. Rather than saying "Connection failed," explain what failed and what administrators should do: "My Plugin requires PHP 7.4+ to function. Your server is running PHP 7.2. Contact your hosting provider to upgrade."
The test callback is executed when Site Health page loads, and also periodically via AJAX as the administrator views the page. Ensure your tests are fast—don't run intensive operations that block the dashboard. Cache external API checks or defer heavy operations:
<?php
function my_plugin_test_dependencies() {
$result = [
'label' => __('My Plugin Dependencies', 'my-plugin'),
'status' => 'good',
'badge' => [
'label' => __('My Plugin', 'my-plugin'),
'color' => 'blue',
],
'description' => __('All My Plugin dependencies are available.', 'my-plugin'),
'actions' => '',
'test' => 'my_plugin_test_dependencies',
];
// Check if we have cached test result (cache for 1 hour)
$cached = get_transient('my_plugin_health_dependencies_cache');
if ($cached !== false) {
return $cached;
}
// Perform the actual check
$dependencies_ok = check_required_dependencies();
if (!$dependencies_ok) {
$result['status'] = 'critical';
$result['description'] = __('My Plugin requires additional dependencies that are not available.', 'my-plugin');
$result['actions'] = '<p><a href="' . esc_url(admin_url('admin.php?page=my-plugin-install-deps')) . '">Install Missing Dependencies</a></p>';
}
// Cache result
set_transient('my_plugin_health_dependencies_cache', $result, HOUR_IN_SECONDS);
return $result;
}
?>
Caching test results prevents your health checks from slowing down the Site Health dashboard. Update cached results when relevant conditions change—when your plugin settings are saved, or when 1 hour has passed.
Implementing Debug Information Providers
The WordPress Site Health debug information section displays technical details about the WordPress environment that site administrators and support personnel use when troubleshooting. Plugin developers can register debug information providers that contribute plugin-specific debugging details to this export.
Debug information is registered through the debug_information filter:
<?php
add_filter('debug_information', function($info) {
// Add our plugin's debug information
$info['my-plugin'] = [
'label' => __('My Plugin', 'my-plugin'),
'description' => __('Debug information about My Plugin.', 'my-plugin'),
'fields' => [
'version' => [
'label' => __('Plugin Version', 'my-plugin'),
'value' => defined('MY_PLUGIN_VERSION') ? MY_PLUGIN_VERSION : 'Unknown',
],
'settings_saved' => [
'label' => __('Settings Saved', 'my-plugin'),
'value' => get_option('my_plugin_settings') ? 'Yes' : 'No',
],
'database_tables' => [
'label' => __('Database Tables Created', 'my-plugin'),
'value' => my_plugin_check_database_tables() ? 'Yes' : 'No',
],
'api_key' => [
'label' => __('API Key Configured', 'my-plugin'),
'value' => get_option('my_plugin_api_key') ? 'Yes' : 'No',
'private' => true, // Don't include in exported reports
],
],
];
return $info;
});
?>
Each field in the debug information array should have:
- label: What the field represents
- value: The actual value to display
- private: (Optional) Set to true for sensitive data that shouldn't be exported
Private fields are excluded from debug exports that administrators might share with support staff. Never include raw API keys, passwords, or other secrets—even in debug information. Instead, indicate whether they're configured without revealing their values:
<?php
'api_credentials' => [
'label' => __('API Credentials', 'my-plugin'),
'value' => function() {
$key = get_option('my_plugin_api_key');
$secret = get_option('my_plugin_api_secret');
if ($key && $secret) {
return 'Configured';
}
return 'Not configured';
},
'private' => true,
],
?>
Debug information values can be static strings, or callable functions that compute values dynamically:
<?php
'database_status' => [
'label' => __('Database Status', 'my-plugin'),
'value' => function() {
global $wpdb;
$table = $wpdb->prefix . 'my_plugin_data';
// Check if table exists
$query = $wpdb->prepare(
"SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = %s AND table_name = %s",
DB_NAME,
$table
);
$exists = $wpdb->get_var($query) ? 'Yes' : 'No';
if ($exists === 'Yes') {
$row_count = $wpdb->get_var($wpdb->prepare("SELECT COUNT(*) FROM {$table}"));
return "Table exists with {$row_count} rows";
}
return 'Table does not exist';
},
],
?>
Callable functions are executed when generating debug information, allowing you to compute values dynamically. This is useful for information that changes—like row counts or file sizes—that shouldn't be cached.
Status Tests and Pass/Fail Logic
Effective WordPress Site Health checks provide clear pass/fail logic that administrators immediately understand. Rather than creating ambiguous status messages, communicate exactly what's being tested, whether it passed, and what it means.
Implement conditional logic in your tests to return different results based on actual conditions:
<?php
function my_plugin_test_configuration() {
$result = [
'label' => __('My Plugin Configuration', 'my-plugin'),
'status' => 'good',
'badge' => [
'label' => __('My Plugin', 'my-plugin'),
'color' => 'blue',
],
'test' => 'my_plugin_test_configuration',
'actions' => '',
];
// Check for required configuration
$license_key = get_option('my_plugin_license_key');
if (empty($license_key)) {
$result['status'] = 'critical';
$result['description'] = __('My Plugin license key is not configured. The plugin will not function without a valid license.', 'my-plugin');
$result['actions'] = sprintf(
'<p><a class="button button-primary" href="%s">%s</a></p>',
esc_url(admin_url('admin.php?page=my-plugin-settings')),
__('Configure License', 'my-plugin')
);
return $result;
}
// Verify license is valid
$is_valid = verify_plugin_license($license_key);
if (!$is_valid) {
$result['status'] = 'critical';
$result['description'] = __('My Plugin license is invalid or expired. Please renew your license.', 'my-plugin');
$result['actions'] = sprintf(
'<p><a class="button button-primary" href="%s">%s</a></p>',
esc_url('https://myplugin.com/renew-license'),
__('Renew License', 'my-plugin')
);
return $result;
}
$result['description'] = __('My Plugin is properly configured and licensed.', 'my-plugin');
return $result;
}
?>
Status levels carry specific meanings:
- "good": Test passed, everything is working correctly. These items appear at the top of Site Health in green.
- "recommended": Test passed but with warnings. This status suggests improvements (like "you're running an older PHP version"). These appear in yellow.
- "critical": Test failed, action is required for the plugin to function correctly. These appear in red and demand administrator attention.
Choose status levels honestly. A test should be "critical" only if the condition genuinely prevents functionality. "Recommended" is appropriate for warnings—things that could be better but don't break the plugin.
Troubleshooting Mode Integration
WordPress 5.7 introduced Troubleshooting Mode (now called Recovery Mode), which temporarily disables all plugins except WordPress core, allowing administrators to diagnose plugin conflicts without losing access to their admin panel. Starting with WordPress 5.9, plugins can integrate with this system to provide custom troubleshooting information.
Provide troubleshooting-specific information through the recovery_mode_clean_up hook:
<?php
add_action('recovery_mode_clean_up', function() {
// This runs when Troubleshooting Mode is active
// You can log information, clear caches, or prepare for diagnosis
// Log that troubleshooting mode was activated
error_log('My Plugin: Troubleshooting mode activated at ' . current_time('mysql'));
// Clear plugin-specific caches that might interfere with diagnosis
wp_cache_delete('my_plugin_cache');
delete_transient('my_plugin_health_check_cache');
});
// Register fatal error handler for Troubleshooting Mode
add_action('wp_php_error_message', function($message) {
// Enhance error messages with plugin-specific context
if (strpos($message, 'my-plugin') !== false) {
// This error is related to our plugin
error_log('My Plugin fatal error: ' . $message);
}
return $message;
});
?>
Additionally, register your plugin to support Troubleshooting Mode by defining the proper headers in your main plugin file:
<?php
/**
* Plugin Name: My Awesome Plugin
* Plugin URI: https://example.com/my-plugin
* Description: A professional WordPress plugin
* Version: 1.0.0
* Author: Example
* Requires at least: 5.9
* Requires PHP: 7.4
* Text Domain: my-plugin
* Domain Path: /languages
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
*/
?>
The Requires at least: 5.9 header indicates your plugin supports Troubleshooting Mode. When administrators enter Troubleshooting Mode, WordPress automatically disables conflicting plugins and provides your plugin the opportunity to clean up and prepare for diagnosis.
Testing and Deployment
Before deploying your WordPress Site Health integration, thoroughly test your health checks and debug information providers. Test that checks execute quickly, return accurate information, and don't cause PHP errors.
Create a testing checklist:
- Verify health checks execute in under 1 second – Slow checks degrade Site Health dashboard performance
- Test all pass/fail scenarios – Ensure your checks handle both success and failure conditions
- Verify debug information displays correctly – Check both in the debug information section and in exported reports
- Test with private debug fields – Ensure sensitive data is excluded from exports
- Verify action links work – Test that any action buttons or links in health checks navigate correctly
- Test on multiple PHP versions – Ensure compatibility across supported versions
Create a test scenario generator to validate health checks work properly:
<?php
// Add a WP-CLI command for testing health checks
if (defined('WP_CLI') && WP_CLI) {
class MyPlugin_Site_Health_Tests {
/**
* Test all My Plugin Site Health checks
*
* @subcommand test-health
*/
public function test_health() {
$tests = apply_filters('site_status_tests', []);
if (!isset($tests['my_plugin_test_configuration'])) {
WP_CLI::error('My Plugin health checks not registered');
}
$test_callback = $tests['my_plugin_test_configuration']['test'];
$result = call_user_func($test_callback);
WP_CLI::log('Health Check Results:');
WP_CLI::log('Status: ' . $result['status']);
WP_CLI::log('Description: ' . $result['description']);
}
}
WP_CLI::add_command('myplugin', 'MyPlugin_Site_Health_Tests');
}
?>
This WP-CLI command lets you test health checks without accessing the WordPress admin interface, useful for automated testing and deployment verification.
Mid-Article Call to Action
Integrating WordPress Site Health checks demonstrates plugin maturity and helps administrators quickly diagnose issues affecting your plugin. However, implementing comprehensive health checks—covering configuration, dependencies, API connectivity, and database integrity—requires careful design and thorough testing.
WP HealthKit's automated security audits verify your WordPress Site Health integration, checking that health checks execute efficiently, display relevant information, and provide actionable recommendations. Upload your WordPress plugin to WP HealthKit to verify your Site Health integration meets current WordPress best practices and provides administrators with clear, accurate diagnostic information.
Additional Resources
For a comprehensive view of how WP HealthKit approaches plugin analysis, explore our 17 verification layers or browse the plugin directory to see real audit scores. Ready to check your own plugin? Run a free audit now.
Broader Context and Best Practices
Step-by-step tutorials for WordPress plugin development serve a critical role in the ecosystem by bridging the gap between documentation and practical implementation. WordPress.org documentation explains what functions are available, but tutorials show how to combine them into working solutions. This practical knowledge is especially valuable for patterns that span multiple WordPress subsystems, such as building a custom REST API endpoint that validates input, checks permissions, queries the database, and returns properly formatted responses. Each step involves different WordPress APIs that must work together correctly.
The most effective WordPress development tutorials teach not just the how but the why behind each decision. Understanding why WordPress uses nonces instead of simpler tokens, why capability checks should test specific capabilities rather than roles, or why prepared statements matter more than escaping for SQL queries gives developers the foundation to make good decisions when they encounter situations that tutorials haven't covered. This deeper understanding is what separates developers who can follow instructions from developers who can architect secure, maintainable solutions.
Testing and validation are often the most overlooked aspects of WordPress plugin tutorials, yet they are arguably the most important. A tutorial that shows how to build a feature without showing how to verify it works correctly and handles edge cases teaches only half the lesson. Modern WordPress development tutorials should include PHPUnit test examples, WP-CLI test commands, and browser testing strategies alongside the implementation code. This testing-first mindset helps developers build confidence in their code and catch regressions before they reach production.
The WordPress developer community's shift toward more professional development practices has elevated the expectations for plugin quality significantly. Practices like dependency management with Composer, automated testing with PHPUnit, continuous integration with GitHub Actions, and static analysis with PHPStan were once considered optional extras. They are now expected baseline practices for serious plugin development. Understanding these tools and how they integrate into the WordPress development workflow is essential knowledge for any developer building plugins that others will rely on.
Broader Context and Best Practices
Step-by-step tutorials for WordPress plugin development serve a critical role in the ecosystem by bridging the gap between documentation and practical implementation. WordPress.org documentation explains what functions are available, but tutorials show how to combine them into working solutions. This practical knowledge is especially valuable for patterns that span multiple WordPress subsystems, such as building a custom REST API endpoint that validates input, checks permissions, queries the database, and returns properly formatted responses. Each step involves different WordPress APIs that must work together correctly.
The most effective WordPress development tutorials teach not just the how but the why behind each decision. Understanding why WordPress uses nonces instead of simpler tokens, why capability checks should test specific capabilities rather than roles, or why prepared statements matter more than escaping for SQL queries gives developers the foundation to make good decisions when they encounter situations that tutorials haven't covered. This deeper understanding is what separates developers who can follow instructions from developers who can architect secure, maintainable solutions.
Frequently Asked Questions
Can I register multiple health checks from the same plugin?
Yes, you can register as many health checks as needed. Use distinct test identifiers and maintain them in the array returned by the site_status_tests filter. However, keep the number reasonable—too many health checks create dashboard clutter. Combine related checks into single tests when appropriate.
What's the difference between status "recommended" and "critical"?
"Critical" status indicates something that prevents your plugin from functioning—missing configuration, incompatible PHP version, failed external API connection. "Recommended" indicates things that could be improved but don't break functionality—outdated PHP versions, non-critical missing features, or performance optimization suggestions.
How do I prevent health checks from slowing down the Site Health dashboard?
Cache check results using transients, and set appropriate cache durations. Quick checks (like checking if options exist) don't need caching. Slower checks (like testing API connectivity) should cache results for 1 hour or longer. Use AJAX endpoints or deferred background jobs for very slow operations rather than executing them during dashboard page load.
Can I hide my plugin's debug information from the exported report?
Individual fields can be marked as private: true to exclude them from exports. However, the entire plugin section appears in the debug information list even if all fields are private. To completely hide your plugin's debug information, don't register it in the debug_information filter.
How does Troubleshooting Mode affect my plugin's health checks?
Troubleshooting Mode disables your plugin entirely, so health checks don't execute. However, your plugin can register a recovery mode clean-up callback that runs before deactivation, allowing you to log information or clear caches. When Troubleshooting Mode is exited, health checks resume running normally.
Should I include plugin update checks in health checks?
You can, but it's not the primary purpose of Site Health. The site_status_tests filter is for system-level diagnostic checks—dependencies, configuration, system compatibility. Update availability is better handled through WordPress's standard plugin update mechanism. Only use health checks to notify administrators of critical issues or missing configuration.
Conclusion
Integrating WordPress Site Health transforms your plugin from a black box into a transparent, diagnostic-friendly component of the WordPress ecosystem. Administrators using Site Health can quickly understand your plugin's status, requirements, and any issues affecting functionality. Debug information providers contribute technical details that support staff and developers use when troubleshooting problems.
The investment in comprehensive WordPress Site Health integration—status tests for critical functionality, debug information providers revealing plugin state, and Troubleshooting Mode compatibility—demonstrates professional plugin development. Administrators appreciate plugins that integrate with WordPress's native diagnostic tools, making it obvious your plugin is well-maintained and security-conscious.
Ensure your WordPress Site Health integration meets current standards and provides accurate diagnostic information by reviewing your plugin with WP HealthKit. Our automated audits verify health checks execute efficiently, debug information displays correctly, and your integration follows WordPress best practices. Take the next step toward professional plugin development today.