Skip to main content

October 30th, 2022

A Guide to Registering a Custom ACF Block with Block.json

With the release of ACF 6.0 in late September, the recommended route to registering ACF custom blocks shifted. In earlier versions, custom blocks were registered using an ACF function called acf_register_block_type. In ACF 6.0, registering ACF blocks is done with the native WordPress register_block_type function. This function is part of the WordPress block API, which is the official way to create custom blocks in WordPress.

How to Register an ACF Block with block.json

Block registration consists of 3 pieces:

  • The block.json file (each block you register will have its own)
  • The location where the register_block_type function is called, referencing your block.json file(s)
  • The code that actually renders the block

Let’s take a look at each of these pieces separately.

The Block.json File

With the old route of registering a custom ACF block, something like the following may have been present in your theme’s functions file:

add_action('acf/init', 'wpfieldwork_acf_blocks_init');
function wpfieldwork_acf_blocks_init() {

    // Check function exists.
    if( function_exists('acf_register_block_type') ) {

        // Register a sample ACF block.
        acf_register_block_type(array(
            'name'              => 'sample-block',
            'title'             => __('Sample Block'),
            'description'       => __('An example custom ACF block.'),
            'render_template'   => 'blocks/sample-block/sample-block.php',
            'category'          => 'formatting',
        ));
    }
}

You can see key data being provided to the acf_register_block_type function like the unique block name, title, description, where to find the code that actually displays the block, and what category the block appears under in the Gutenberg editor’s list of blocks. This isn’t a comprehensive example of all items supported by the acf_register_block_type function, but just a small example to show how a lot of these same attributes get carried over to the new recommended way of block registration in ACF.

When registering a custom ACF block via JSON, each block will have a corresponding block.json file with comparable data to what you were using in the acf_register_block_type function. So a block.json file for this same block would work out to:

{
    "name": "sample-block",
    "title": "Sample Block",
    "description": "An example custom ACF block.",
    "category": "formatting",
    "acf": {
        "mode": "preview",
        "renderTemplate": "blocks/sample-block/sample-block.php"
    }
}

This is a very minimal block.json file example, but your block.json can be built out to support block metadata options outlined in the Block Editor Handbook. WordPress uses a camelCase format inside JSON files, and ACF does, as well. Configuration that you used in acf_register_block_type with underscores such as render_template become renderTemplate in the block.json file.

You’ll notice that the block.json file for custom ACF blocks require ACF-specific configuration keys, which you can highlighted below, from the above example.

{
    "name": "sample-block",
    "title": "Sample Block",
    "description": "An example custom ACF block.",
    "category": "formatting",
    "acf": {
        "mode": "preview",
        "renderTemplate": "blocks/sample-block/sample-block.php"
    }
}

This supports:

  • mode: Controls how the block appears in the editor, defaults to “Preview” (the visual appearance of the block vs. the fields.) Options are: (1) auto: Preview is shown by default but changes to edit (field view) when block is selected. (2) preview: Preview/visual is always shown. The edit form will appear in the sidebar when the block is selected. (3) edit: Edit form containing the block’s fields is always shown.
  • renderTemplate: The path to the file containing the code for the block. This can either be a relative path to the file based on where the block.json file is located, or an absolute path. You would be using this or renderCallback, not both.
  • renderCallback: Instead of providing a renderTemplate, a callback function can be specified to render the block.
  • postTypes: if you want to limit your block to certain content types like only allowing it on a custom post type or just posts, you can create an array listing those allowed types here.
  • blockVersion: Blocks registered via block.json will default to version 2, blocks registered with acf_register_block_type default to 1. For an overview of the differences between the two block versions, you should read the section on block versioning in the ACF 6.0 announcement post.

Registering the Block with the Register_block_type function

Now that the block.json file exists, the file needs to actually be referenced somewhere. It won’t be automatically detected. The block.json file gets passed to the register_block_type function, which makes this new block available to be used in the WordPress block editor. This could be in your theme functions file or in a custom plugin depending on how you’re approaching custom blocks in your set up, but it would look something comparable to:

function wpfieldwork_register_acf_blocks() {
  // Check availability of block editor
  if ( ! function_exists( 'register_block_type' ) ) {
    return;
  }

  // adjust location(s) as needed for block.json
  register_block_type( get_template_directory() . '/blocks/sample-block/block.json' );
}
add_action( 'init', 'wpfieldwork_register_acf_blocks' );

You should now see your new custom ACF block available for use within the block editor. However, if you go to add it anywhere, nothing will display because the block display code has yet to be added in the noted location from the block.json file.

The Actual Code to Display the Block

In the block.json, WordPress was told to find the code for this block at this highlighted location.

{
    "name": "sample-block",
    "title": "Sample Block",
    "description": "An example custom ACF block.",
    "category": "formatting",
    "acf": {
        "mode": "preview",
        "renderTemplate": "blocks/sample-block/sample-block.php"
    }
}

What that PHP file looks like will vary based on your preferred approach for theme development. ACF provides a full block example in their official blocks documentation that supports anchors and custom class names, as well as sets default field values. However, you’re not locked into their approach for displaying block data. For example, Joey Farruggio outlines a great approach for separating logic from front-end display when it comes to your ACF block code. You also may prefer grabbing all fields at once with one get_fields call and then hitting that array. There are a multitude of ways you can approach the actual block display, but it’s important it does exist at the location noted in your block.json file.

There are a couple variables you can use within your ACF block to get certain data.

  • $block: This contains the block settings and attributes. You can pull attributes like the anchor, alignment (align), and custom class names from the block settings via the $block variable.
  • $is_preview: This returns true if displaying on the backend. You can use this to isolate behavior to the front or backend.
  • $post_id: The post ID the block is rendering content for. Inside of a query loop, this will be the looped post ID, outside of it, it would be the post/page that the block is assigned to.
  • $context: Any context that is provided to the block by the post or parent blocks would be available here.

Once you’ve set up this file, it should be the final piece missing to register a custom ACF block. The block should be able to be selected in your editor so once it’s styled to your liking, you’re good to go.

Additional Insight

Here is a roundup of links from around the web that contain great insight to build on this topic:

  • 10up made their Gutenberg Best Practices public and there’s a wealth of information in there including a super helpful & detailed breakdown of different block supports options that can be utilized in block.json.
  • Full Stack Digital dives into an efficient development workflow that supports custom ACF blocks, custom native Gutenberg blocks, and compiles everything through @wordpress/scripts with live reload.
  • Bill Erickson offers some great Advanced Usage options for registering blocks, like a function that automates block registration of block.json files found in a blocks theme subfolder and other helpful tips.

Get the latest in your inbox