Block Usage Report Under Tools
Adds a Tools > Block Usage screen counting how many posts and pages use each block, with a link to the content using it, so you know which blocks and plugins are safe to remove.
Opens WPIDE on
Code
add_action( 'admin_menu', function () {
add_management_page( 'Block Usage', 'Block Usage', 'manage_options', 'wpide-block-usage', function () {
global $wpdb;
if ( isset( $_GET['rescan'] ) && check_admin_referer( 'wpide_block_rescan' ) ) {
delete_transient( 'wpide_block_usage' );
}
$usage = get_transient( 'wpide_block_usage' );
if ( false === $usage ) {
$usage = array();
$rows = $wpdb->get_results(
"SELECT ID, post_content FROM {$wpdb->posts} WHERE post_status IN ('publish','draft','private','future','pending')
AND post_type NOT IN ('revision','attachment','nav_menu_item','customize_changeset') AND post_content LIKE '%<!-- wp:%' ORDER BY ID DESC LIMIT 2000"
);
foreach ( $rows as $row ) {
preg_match_all( '/<!--\s+wp:([a-z0-9-]+\/)?([a-z0-9-]+)[\s\/]/', $row->post_content, $matches, PREG_SET_ORDER );
$seen = array();
foreach ( $matches as $match ) {
$name = ( $match[1] ? $match[1] : 'core/' ) . $match[2];
$usage[ $name ]['uses'] = ( $usage[ $name ]['uses'] ?? 0 ) + 1;
if ( ! isset( $seen[ $name ] ) ) {
$usage[ $name ]['posts'] = ( $usage[ $name ]['posts'] ?? 0 ) + 1;
$usage[ $name ]['example'] = $usage[ $name ]['example'] ?? (int) $row->ID;
$seen[ $name ] = true;
}
}
}
uasort( $usage, function ( $a, $b ) {
return $b['posts'] <=> $a['posts'];
} );
set_transient( 'wpide_block_usage', $usage, HOUR_IN_SECONDS );
}
echo '<div class="wrap"><h1>Block Usage</h1>';
printf( '<p><a class="button" href="%s">Rescan</a></p>', esc_url( wp_nonce_url( admin_url( 'tools.php?page=wpide-block-usage&rescan=1' ), 'wpide_block_rescan' ) ) );
echo '<table class="widefat striped"><thead><tr><th>Block</th><th>Posts using it</th><th>Total uses</th><th>Example</th></tr></thead><tbody>';
foreach ( $usage as $name => $data ) {
$registered = WP_Block_Type_Registry::get_instance()->is_registered( $name );
printf(
'<tr><td><code>%s</code>%s</td><td>%d</td><td>%d</td><td><a href="%s">%s</a></td></tr>',
esc_html( $name ),
$registered ? '' : ' <span style="color:#b32d2e">(not registered)</span>',
(int) $data['posts'],
(int) $data['uses'],
esc_url( get_edit_post_link( $data['example'] ) ),
esc_html( get_the_title( $data['example'] ) ? get_the_title( $data['example'] ) : '#' . $data['example'] )
);
}
echo '</tbody></table></div>';
} );
} );
Notes
Scans up to 2,000 published and draft items and caches the result for an hour; click "Rescan" to refresh.
How to add this snippet
- Install WPIDE on your WordPress site (it is free) and open Code Snippets.
- Use snippet above adds it from the library in one click. Or copy the code into a new snippet with the same code type.
- It is added inactive: review the code and settings, then switch it on.