Since version 5.8 of Advanced Custom Fields (ACF) Pro you can use ACF to create custom Gutenberg blocks. All you need to handle are the PHP templates. This makes it very easy for developers who are not yet experienced in the modern Javascript required to create custom blocks for Gutenberg with any of the field types ACF has to offer. Keep in mind that this functionality is only available in the paid version (Pro) of Advanced Custom Fields. It’s not available in the free version so you’ll need to purchase a license.

If you are a WordPress editor or a webmaster who don’t want to dive deep into coding, this post is definitely for you. However if you want to be a WordPress theme or plugin developer I recommend taking the step to learn how to create your own custom blocks. However using Advanced Custom Fields for creating blocks can provide a nice introduction into handling custom blocks in Gutenberg.

Create a Gutenberg block with ACF

There’s basically three simple steps in creating a custom Gutenberg block with Advanced Custom Fields. The first is easy and probably familiar; setting up the fields (settings) you wish to have in your block. The second step is using ACF’s function to register a Gutenberg block. And the third step is writing the PHP template for the block. You simply write the HTML and handle the settings just like you would do with ACF fields otherwise. And that’s it! (Okay, maybe there’s a fourth step; styling your block. But I won’t go into that in this post).

Create your settings / fields

If you have used Advanced Custom Fields before you probably know how to set up fields. You can use Advanced Custom Field’s admin UI to make this. Or if you want the block settings to be embedded in your plugin or theme write out the settings with PHP. I have a complete reference post in how to add ACF settings with PHP.

The critical thing you need to do with your group is setting the location to “Block”. But because we haven’t registered our block yet, it will default til “All”. Leave it at that, save your fields and let’s proceed to registering our block.

Register a Gutenberg block

In your theme’s functions.php or plugin code you need to write a function hooked to acf/init, and call acf_register_block() to register a block. As this function is pretty new in ACF and depends on a plugin to be activated I recommend that you wrap your code inside an if-check to ensure that your theme or plugin won’t crash your WordPress.

add_action('acf/init', function() {
	if (function_exists('acf_register_block')) {
		acf_register_block([
			'name' => 'yourblock',
			'title' => __('Name of your block', 'txtdomain'),
			'description' => __('Optional description', 'txtdomain'),
			'category' => 'formatting',
			'icon' => 'admin-comments',
			'render_callback' => 'my_acf_block_render_callback',
		]);
	}
});

Registering a block with ACF is actually similar to how we would register a custom Gutenberg block manually. With ACF you need to provide an unique slugified name for you block in name. I recommend using a self-explanatory name, e.g. cta for a Call to action block, or author-card for a block showing authors or similar. If you are somewhat familiar with Gutenberg you might be aware that all blocks must be registered with a namespace, a /, and then their slug-name. For example WordPress’ namespace is core, so for instance the paragraph block in WordPress is called core/paragraph. With ACF the namespace will be acf, so for example the above block will be registered within Gutenberg as acf/yourblock. If you are registering your fields with PHP, as you’ll see later on, we need to remember this.

In category you define which Gutenberg category you want your block to appear in. As of the moment possible values are common, formatting, layout, widgets, or embed. If you create custom Gutenberg categories you can add them to those if you wish. As for icon provide any icon name from WordPress Dashicons (minus the “dashicons-“).

For informing ACF how to render this block you have two choices: either provide a function name to the key render_callback (like above), or provide a template name in your theme to the key render_template. So if you’d rather refer directly to a template, e.g. template-parts/block-yourblock.php in your theme, simply do it like this and remove the render_callback:

'render_template' => 'template-parts/block-yourblock.php',

Connect your field group to your registered block

When you’re satisfied with your block registering code, it’s time to connect your block to the settings you made earlier. If you created the fields in admin, simply go back and choose your block in Location. And if you added the field group with PHP, in location provide the value ‘acf/yourblock‘ where yourblock is what you provided as name above.

Write the template

The final step, and the most fun, is writing the template for the block output!

The location of your block render output depends on what you decided to use in your block registering, render_callback or render_template.

If you provided a function name in render_callback you need to define this function in your theme’s functions.php or plugin code. You get four parameters to your function, as you’ll see below:

function my_acf_block_render_callback($block, $content = '', $is_preview = false, $post_id = 0) {
	$className = 'your_block';
	if (!empty($block['className'])) {
		$className .= ' ' . $block['className'];
	}

	// Example of fetching a field value:
	$my_text = get_field('my_textfield');

	?><div class="<?php echo $className; ?>">
		<?php // echo your output here ?>		
	</div><?php
}

The first parameter, $block, contains certain information from Gutenberg. For example each Gutenberg block will almost always have className, which you should set as class on your outermost wrapper. $block['align'] for alignment could also be set and something you want to add as well. The second parameter, $content, will always be empty with ACF (this would be populated if you added nested blocks, but that’s not possible with ACF). The boolean $is_preview will be true if we are currently looking at the block render in preview mode in Gutenberg editor. And finally $post_id is the post that this block is added in.

As for the fields you fetch fields as you’d normally do, with get_field(). The HTML output is completely up to you and how you want to output your fields.

If you provided a template file in render_template instead, simply create the file at the specified location in your theme. Inside it you have access to the exact same global variables as with the function above (for example $block). For instance:

template-parts/block-yourblock.php
$className = 'your_block';
if (!empty($block['className'])) {
	$className .= ' ' . $block['className'];
}

// Example of fetching a field value:
$my_text = get_field('my_textfield');

?><div class="<?php echo $className; ?>">
	<?php // echo your output here ?>		
</div><?php

And that’s all there’s to it. This is how simple it is to create your custom Gutenberg blocks with ACF.

Conclusion

As easy this was, relying on a plugin – particularly a paid one – is no good end solution if you want to develop themes or plugins. Keep in mind that your blocks will stop working if you move your theme code into another WordPress without ACF Pro. Or where your field settings have not been set up (unless you embedded them into your code with PHP or make sure to export and import them). As a theme (or plugin) developer who distributes code you can’t expect every user to purchase their own license of ACF Pro in order to make your theme work! But this is a good temporary solution for those who can’t or won’t need to code.

If you are convinced you need to take the step and learn Javascript and Gutenberg, check out my introduction to Gutenberg post or the Gutenberg category on this site to learn more.