How to Register Blocks with ACF and block.json

Let's set the ground work and scaffold our first ACF block.

Steps in this guide:

  1. Register our blocks with block.json
  2. Handle our block data
  3. Create the block render template
  4. Using the block

Register the block

Since WP 6.0, the recommended way of registering blocks is via block.json. This is a big deal, because keeping our ACF blocks as close to Core as possible allows us to take advantage of many native block features.

You can register blocks from a plugin or your theme. For simplicity, and to make this guide more accessible to beginners, I’ll be doing this directly in my theme. Go ahead and stub out the following structure:


└─── /blocks
│ │ register-blocks.php
│ │
│ └─── /my-first-block
│ │ block.json
│ │ block.php
│ │ template.php

In /blocks/my-first/block.json, we'll configure our block. The JSON example below is just about the bare minimum you need to register a block.

"name": "my-first-block",
"title": "My First Block",
"description": "Displays my very first ACF block.",
"category": "theme",
"apiVersion": 2,
"acf": {
"mode": "preview",
"renderTemplate": "blocks/my-first-block/block.php"
"supports": {
"anchor": true

Inside of /blocks/register-blocks.php, we’ll include the path to our block’s json file. This is where we’ll register all future blocks:

register_block_type( get_template_directory() . '/blocks/my-first-block/block.json' );

In your functions.php you can include the path to /blocks/register-blocks.php..

* Register ACF Blocks

require get_template_directory() . '/blocks/register-blocks.php';

Just to recap what's going on:

Our function.php file includes our /blocks/register-blocks.php file. /blocks/register-blocks.php will be where we register all of our future blocks by pointing to each block's block.json.

Handle our block data

/blocks/my-first-block/block.php will serve as the model / controller for our block. It’s where we’ll handle all of the data that gets passed into the render template. This helps keep things clean and organized so our logic is in one place (block.php) and our front-end template (template.php) is in another.

* My First Block

// $data is what we're going to expose to our render template
$data = array(
'example_field' => get_field( 'example_field' ),
'another_field' => get_field( 'another_field' )

// Dynamic block ID
$block_id = 'my-first-block-' . $block['id'];

// Check if a custom ID is set in the block editor
if( !empty($block['anchor']) ) {
$block_id = $block['anchor'];

// Block classes
$class_name = 'my-first-block';
if( !empty($block['class_name']) ) {
$class_name .= ' ' . $block['class_name'];

* Pass the block data into the template part

'block' => $block,
'is_preview' => $is_preview,
'post_id' => $post_id,

'data' => $data,
'class_name' => $class_name,
'block_id' => $block_id,

$block, $is_preview, and $post_id are variables given to us by the block registration API.

Contains all of the attributes of our block from the block API. We have access to the block's name, description, ID, class names, and many other attributes that come from the block editor.

Either true or false – it tells us whether the block is currently being viewed in the block editor (true) or the front-end (false).

The ID of the post or page that the block is being viewed on.

The other three variables, $data, $class_name, and $block_id are variables that we have defined ourselves.

Create the block render template

Now we can create the block’s render template: /blocks/my-first-block/template.php.

* Block Name: My First Block
* Description: Displays my very first block.

// The block attributes
$block = $args['block'];

// The block data
$data = $args['data'];

// The block ID
$block_id = $args['block_id'];

// The block class names
$class_name = $args['class_name'];

<!-- Our front-end template -->
<div id="<?php echo $block_id; ?>" class="<?php echo $class_name; ?>">
if ( $data['example_field']) {
echo "<p>" . $data['example_field'] . "</p>";

if ( $data['another_field']) {
echo "<p>" . $data['another_field'] . "</p>";


All of the data exposed to our block's render template is found in the $args variable.

Get The Free ACF Blocks Mini Course

    Checkout the lesson outline