Introducing Block Hooks for dynamic blocks

WordPress 6.4 introduces BlockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. HooksHooks In WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same. (#53987), a feature that provides an extensibility mechanism for Block Themes. This is the first step in emulating WordPress’ Hooks concept that allows developers to extend Classic Themes using filters and actions.

Specifically, the Block Hooks APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways. allows a block to automatically insert itself relative to instances of other block types. For example, a “Like” button block can ask to be inserted before the Post Content block, or an eCommerce shopping cart block can ask to be inserted after the Navigation block.

Tenets and current limitations

There are two coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. tenets of Block Hooks:

  1. Front-end insertion should happen as soon as the pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party containing a hooked block is activated. In other words, the user isn’t required to insert the block in the Editor manually. Similarly, disabling the plugin should remove the hooked block from the front end.
  2. The user has the ultimate control over any automatically inserted blocks. This means that a hooked block is visible in the Editor, and the user’s decision to keep, remove, customize, or move the block will be respected and reflected on the front end.

To account for both tenets, tradeoffs had to be made. Block hooks are limited to templates, template parts, and patterns (i.e., the elements that define the layout of the theme). For patterns, this includes those provided by the theme, from Block Pattern Directory, or from calls to register_block_pattern.

Blocks cannot be hooked into post content or patterns crafted by the user, such as synced patterns or theme templates and template parts that the user has modified.

Furthermore, as of WordPress 6.4, you can’t automatically insert blocks that have a save function, or block validation errors will occur. In colloquial terms, this means that Block Hooks work with Dynamic blocks, not Static blocks. Refer to this article on the difference between the two.

Using Block Hooks

You can implement Block Hooks in two different ways: in a block’s block.json file or using the new hooked_block_types filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output.. While simpler, the block.json method provides a more limited implementation, so let’s review that first.

block.json

The block.json method allows you to hook a third-party block unconditionally, meaning that the block will be inserted relative to all instances of the target (anchor) block provided the abovementioned limitations.

In the block’s block.json file, include the blockHooks property. This property takes an object where the key (string) is the name of the block you want to hook into, and the value (string) specifies its position. Possible positions are:

  • before – inject before the target block.
  • after – inject after the target block.
  • firstChild – inject before the first inner block of the target container block.
  • lastChild – inject after the last inner block of the target container block.
{
    blockHooks: {
        'core/verse': 'before'
        'core/spacer': 'after',
        'core/column': 'firstChild',
        'core/comment-template': 'lastChild',
    }
}

In the example above, the block will be inserted before every Verse block that appears in an unmodified template, template part, or pattern. It will also be inserted after every Spacer block, etc.

When using the block.json method with firstChild or lastChild, a Setting SidebarSidebar A sidebar in WordPress is referred to a widget-ready area used by WordPress themes to display information that is not a part of the main content. It is not always a vertical column on the side. It can be a horizontal rectangle below or above the content area, footer, header, or any where in the theme. panel titled Plugins will be added to the target block in the Editor. This allows the user to toggle on and off the hooked block.

Below is an example of a Like button block that is hooked to the lastChild position in the Comment Template block.

The Like button block is hooked to the 'lastChild' position of the Core Comment Template block.

hooked_block_types

The hooked_block_types filter provides more flexibility. It allows you to hook any Dynamic block unconditionally, like the block.json method, or conditionally based on the template, template part, or pattern where the target (anchor) block is located.

The callback function for the filter accepts four parameters:

  • $hooked_blocks (array) – An array of hooked blocks.
  • $position (string) – The relative position of the hooked block: before, after, first_child, or last_child.
  • $anchor_block (string) – The name of the anchor block.
  • $context (WP_Block_Template|array) – The block template, template part, or pattern the anchor block belongs to.

Below are a few examples using the Like button block plugin (ockham/like-button) built to demonstrate Block Hooks functionality in a third-party block. The pattern example does require the Twenty Twenty-Four theme.

function example_block_hooks( $hooked_blocks, $position, $anchor_block, $context ) {

	// Template/Template Part hooks.
	if ( $context instanceof WP_Block_Template ) {
		
		// Hooks the "Like" button block before the Post Title in the Single template.
		if ( 
			'core/post-title' === $anchor_block &&
			'before' === $position &&
			'single' === $context->slug
		) {
			$hooked_blocks[] = 'ockham/like-button';
		}

		// Hooks the Login/Logout link block after the Navigation block if the context of the template part is a header.
		if ( 
			'core/group' === $anchor_block &&
			'last_child' === $position &&
			'header' === $context->area
		) {
			$hooked_blocks[] = 'core/loginout';
		}
	}

	// Pattern hooks.
	if ( is_array( $context ) && isset( $context['slug'] ) ) {
		
		// Hooks into the Post Meta pattern in the Twenty Twenty-Four theme.
		if ( 
			'core/post-terms' === $anchor_block && 
			'after' === $position && 
			'twentytwentyfour/post-meta' === $context['slug']
		) {
			$hooked_blocks[] = 'ockham/like-button';
		}
	}

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

It’s important to note that $context will be an object of type WP_Block_Template for templates and template parts and an array for patterns. If you want to insert blocks conditionally using this parameter, make sure to check the parameter type before applying hooking blocks.

You will also note that you can only specify the name of the block that is being hooked. There is no way to set the attributes of the hooked block, so only the default instance of the block is inserted. Future improvements to Block Hooks will likely account for this limitation and others, providing a robust way for developers to extend Block Themes.

For more information on what additional features are currently being worked on, stay tuned to the tracking issue for Block Hook improvements.

Props to @bernhard-reiter, @gziolo, @webcommsat, and @bph for reviews.

#6-4, #dev-notes, #dev-notes-6-4