Site Health Check in 5.2

WordPress 5.2 will include two new pages in the admin interface to help end users to self-service their site through common configuration issues and other elements that go along with having a healthy online presence. It also provides a standardized location for developers to add debugging information.

The new pages can be found under the Tools menu, as Site Health, and presents the user with a fresh new admin interface. As we hope users will regularly ensure their site is up to standards, focus has been put on creating an interface you want to return to in the future.

Site Health Status

Screenshot of the WordPress Site Health Status page

The first page runs a series of tests on the user’s site, and will be categorized as critical, recommended, or good responses. These outcomes also affect the percentage of completion you have (where critical is weighted more heavily than recommended).

Each test result can be expanded to get an explanation of what you as a user should be paying attention to, and which problems are there if any, that need addressing.

Most of the bundled tests will also have actionable items, and provide links directly to the appropriate areas of your dashboard where you can improve upon the relevant settings.

Filtering the Tests

The tests are filterable via site_status_tests, meaning plugins or themes may add their own tests, or remove existing ones. We’ve also split these into two different types of tests: direct  and async. This was done as some tests may require more time to run, so to avoid potential timeouts within admin pages, any tests added to the async section will be run in succession via AJAX calls after the page is loaded.

Specifically of interest to server admins is the companion filter site_status_test_php_modules, which is based off the WordPress Hosting Team list of recommended and required PHP extensions.

Removing a Test

An example of a filter use would be a hosting provider that does automated updates. They may wish to remove the test for background updates being enabled or disabled as follows:

function myhost_remove_update_check( $tests ) {
	unset( $tests['async']['background_updates'] );
	return $tests;
add_filter( 'site_status_tests', 'myhost_remove_update_check' );

Adding a Test

This is an example of how a caching plugin might check to ensure that it’s cache setting is enabled.

function myplugin_add_caching_test( $tests ) {
	$tests['direct']['caching_plugin'] = array(
		'label' => __( 'My Caching Test' ),
		'test'  => 'myplugin_caching_test',
	return $tests;
add_filter( 'site_status_tests', 'myplugin_add_caching_test' );

function myplugin_caching_test() {
	$result = array(
		'label'       => __( 'Caching is enabled' ),
		'status'      => 'good',
		'badge'       => array(
			'label' => __( 'Performance' ),
			'color' => 'orange',
		'description' => sprintf(
			__( 'Caching can help load your site more quickly for visitors.' )
		'actions'     => '',
		'test'        => 'caching_plugin',

	if ( ! myplugin_caching_is_enabled() ) {
		$result['status'] = 'recommended';
		$result['label'] = __( 'Caching is not enabled' );
		$result['description'] = sprintf(
			__( 'Caching is not currently enabled on your site. Caching can help load your site more quickly for visitors.' )
		$result['actions'] .= sprintf(
			'<p><a href="%s">%s</a></p>',
			esc_url( admin_url( 'admin.php?page=cachingplugin&action=enable-caching' ) ),
			__( 'Enable Caching' )

	return $result;

myplugin_add_caching_test() is hooked to the site_status_tests filter. It adds a new test called caching_plugin to the direct tests list. The value of test in this array is the function that will be called when the tests run on the Site Health Status page.

Note: If you add a test to the async test list, then you will also need to register the test function as an AJAX action using the wp_ajax_{$action} hook.

The test function should return an array with data about the result of the test. This array includes:

  • label: What the header of the section should say.
  • status: Section the result should be displayed in. Possible values are good, recommended, or critical.
  • badge: Array containing:
    • label: What the badge should say.
    • color: Applies a CSS class with this value to the badge. Core styles support blue, green, red, orange, purple and gray.
  • description: Additional details about the results of the test.
  • actions: A link or button to allow the end user to take action on the result.
  • test: The name of the test.

In the above example, the test function, myplugin_caching_test() sets an initial baseline value for the result, and then overrides portions as needed if the call to its internal function myplugin_caching_is_enabled() returns false.

Site Health Info

Screenshot of the WordPress Site Health Information page

The Information tab is meant for debug purposes. It provides a plethora of information about the website and server setup for sharing when looking for support in various locations, alongside a button to quickly copy any non-private information so you can easily paste this to others.

The page is split up into sections. Plugins and themes may introduce their own entries to this page using the debug_information filter, either by adding entries to existing sections, or by creating their own sections.

As mentioned, the copied information only includes non-private information, this can of course be subjective, and is therefore also included in the filter. Marking either a full section, or just individual entries as private can be done by setting the corresponding $private value to true.

For example, the database prefix is shown under the Database section, and is marked as private, so when I go to copy all the information, it’s not there:

Example of the database section of the Site Health Information page

The content that gets added to the clipboard for the entire Database section is shown below:

### Database ###

Extension: mysqli
Server version: 5.5.5-10.1.38-MariaDB-1~jessie
Client version: mysqlnd 5.0.12-dev - 20150407 - $Id: 7cc7cc96e675f6d72e5cf0f267f48e167c2abb23 $

A security plugin may for example think that any database information is always seen as private, and would filter this in the following way:

function secplugin_remove_database_info( $debug_info ) {
	$debug_info['wp-database']['private'] = true;
	return $debug_info;
add_filter( 'debug_information', 'secplugin_remove_database_info' );

Adding a new section may also be of interest. The example below adds your own plugin and its license key, but marks it as private, to the list:

function myplugin_add_debug_info( $debug_info ) {
	$debug_info['my-plugin-slug'] = array(
		'label'    => __( 'My Plugin', 'my-plugin-slug' ),
		'fields'   => array(
			'license' => array(
				'label'    => __( 'License', 'my-plugin-slug' ),
				'value'   => get_option( 'my-plugin-license', __( 'No license found', 'my-plugin-slug' ) ),
				'private' => true,

	return $debug_info;
add_filter( 'debug_information', 'myplugin_add_debug_info' );

Each new section that’s added should use your plugin or theme slug to avoid name collisions. All core entries are prefixed with wp-.

All debug information is added in an unescaped manner, the Information page will run all data through wp_kses, and only allows a, strong, em and span tags (used for emphasis or linking to documentation).
Debug information is expected to be plain text, and is escaped before showing on the page. The displayed data is ran through esc_html(), and data that can be copied is ran through esc_attr().

#5-2, #dev-notes