Block Hooks API

In this lesson

WordPress describes the Block Hooks API as a way to automatically insert dynamic blocks into a template, pattern, or part by placing it in relation to another block.

The feature was introduced in WordPress 6.4 and extended in 6.5. The API lets plugin developers insert custom blocks without user interaction.

For example, a plugin can place a shopping cart button inside or after a navigation block in your site header. When a user deactivates the plugin, the block is removed. Two plugins that have already implemented the feature are JetPack and WooCommerce.

All block themes support the Block Hooks API, and it works automatically, no action is needed by the theme developer.

Level: ,

Estimated reading time: 3 minutes

Last updated

How to add a block hook

Block hooks should only be added by plugins: They are activated upon plugin activation and deactivated upon plugin deactivation.

There are two ways to add block hooks:

  • In block.json, when creating a custom block
  • Using PHP filters

I will only show the PHP filter since this lesson is not about building custom blocks.

The filter is called hooked_block_types, and it accepts the following parameters:

  • hooked_block_types: an array of strings, where the string is the block type (prefix/block-name).
  • relative_position: string. One of: before, after, first_child, last_child.
  • anchor_block: string, the anchor block type (prefix/block-name).

The final parameter is context. The context can be the block template, template part, wp_navigation post type, post object or pattern that the anchor block belongs to.

In the first code example, I am placing the site tagline after the site title block. Because the context is not used, it adds the tagline to all site title blocks.

Note: If there is no tagline content saved, the block only shows in the editors.

<?php
/**
 * Plugin Name: Block hook example
 * Version: 0.1.0
 */

function prefix_block_hook_example( $hooked_block_types, $relative_position, $anchor_block_type, $context ) {

	if ( 'after' === $relative_position && 'core/site-title' === $anchor_block_type ) {
		$hooked_block_types[] = 'core/site-tagline';
	}

	return $hooked_block_types;
}
add_filter( 'hooked_block_types', 'prefix_block_hook_example', 10, 4 );

Now lets limit the tagline to the header template part.

$context can be an object or an array. For the template part, we want to check that:

  • $context is an array; not an object
  • the slug property is set
  • the slug contains “/header”

I’m checking if the slug contains header, not if the slug is header, because if the header is provided by the theme, then the slug is themename/header: twentytwentyfive/header.

<?php
/**
 * Plugin Name: Block hook example
 * Version: 0.1.0
 */

function block_hook_example( $hooked_block_types, $relative_position, $anchor_block_type, $context ) {
    $is_header_template_part = is_array( $context ) 
        && isset( $context['slug'] ) 
        && false !== strpos( $context['slug'], '/header' );

    if ( $is_header_template_part && 'after' === $relative_position && 'core/site-title' === $anchor_block_type ) {
        $hooked_block_types[] = 'core/site-tagline';
    }

    return $hooked_block_types;
}
add_filter( 'hooked_block_types', 'block_hook_example', 10, 4 );

How to remove block hooks

You can remove block hooks by using the same filter as above and
prevent them from being returned.

If you want to remove a single block hook, another option is to filter the block. In this PHP example I am filtering the WooCommerce mini-cart block.
The filter is called hooked_block_{block type}. Where block type is the prefix/block-name: woocommerce/mini-cart.

function themeslug_remove_hooks( $parsed_hooked_block, $hooked_block_type, $relative_position, $parsed_anchor_block, $context  ) {
	
	// Has the hooked block been suppressed by a previous filter?
	if ( is_null( $parsed_hooked_block ) ) {
		return $parsed_hooked_block;
	}
	return null;
}
add_filter( 'hooked_block_woocommerce/mini-cart', 'themeslug_remove_hooks', 9, 5 );

The priority may vary depending on how the block is registered.

Credits to Nick Diego & Bernie Reiter for the original code examples.

The block hook interface

When a block is automatically placed, it can be edited, styled, moved or removed by a user. The hooked block is not locked to the anchor block.

When you select the anchor block however, the hooked block is displayed in a new panel called Plugins:

The block settings sidebar of the Site Title block shows the Plugins panel with a single option to toggle the Site Tagline block on or off.

Toggling the block off removes the hooked block.

  • If you have previously deleted the block, you can re-add it using this toggle.
  • If you copy or duplicate a the block, both copies will be hooked to the anchor.

Resources