Gutenberg, WordPress’s block editor, simplifies the process of visually creating and managing content. By using Advanced Custom Fields (ACF), you can easily build custom blocks for Gutenberg without extensive knowledge of JavaScript.
Since WordPress 5.8, it is recommended to register blocks using the block.json
file instead of PHP functions. In this guide, you’ll learn how to create a custom Call to Action (CTA) block using ACF and the block.json
method. Let’s get started!
Step 1: Create the Block Configuration (block.json)
In your theme directory, navigate to /template-parts/blocks/custom-cta/
and create a file named block.json
. This file defines the block’s properties and settings:
{
"apiVersion": 2,
"name": "acf/custom-cta",
"title": "Custom CTA Block",
"description": "A custom call to action block with an image, title, description, and button.",
"category": "common",
"icon": "megaphone",
"keywords": ["cta", "call to action", "button"],
"supports": {
"align": ["wide", "full"],
"html": false
},
"acf": {
"mode": "preview",
"renderTemplate": "custom-cta.php"
},
"enqueueStyle": "template-parts/blocks/custom-cta.css"
}
Note: The
enqueueStyle
property allows you to define a CSS file that will be automatically loaded when the block is used in the editor and on the frontend. This ensures your styles are applied consistently without additional enqueue functions in PHP.
Explanation of Key Properties:
name
: The block’s unique identifier.title
: The block’s display name.description
: A brief explanation of the block.category
: Defines where the block appears in Gutenberg.icon
: The WordPress Dashicon representing the block.supports
: Controls block settings like alignment.acf.renderTemplate
: Specifies the PHP file used to render the block.enqueueStyle
: Links to the CSS file for styling.
Step 2: Register the Block in functions.php
Although block.json
eliminates the need for manual registration, you must ensure WordPress recognizes it. Add this snippet to your functions.php
file:
function register_acf_blocks() {
register_block_type(get_template_directory() . '/template-parts/blocks/custom-cta/block.json');
}
add_action('init', 'register_acf_blocks');
Step 3: Create the ACF Field Group for the Block
1. In your WordPress dashboard, go to ACF > Field Groups.
2. Click Add New to create a new field group.
3. Name the field group Custom CTA Block Fields.
Add the following fields:
- Title: Add a
Text
field for the CTA title. - Description: Add a
Text Area
field for the CTA description. - Image: Add an
Image
field for the CTA image. - Button Text: Add a
Text
field for the button label. - Button URL: Add a
URL
field for the button link. - Background Color: Add a
Color Picker
field for setting the block’s background color.
It looks like this:
When you’ve finished adding the fields, go to the “Location Rules” settings in the ACF field group editor. Set the rule to Block is equal to Custom CTA Block.

Step 4: Create the Block Template
In your theme directory, navigate to template-parts/blocks/custom-cta/
and create a file named custom-cta.php
.
<?php
$title = get_field('title');
$description = get_field('description');
$image = get_field('image');
$button_text = get_field('button_text');
$button_url = get_field('button_url');
$background_color = get_field('background_color');
?>
<div class="custom-cta-block" style="background-color: <?php echo esc_attr($background_color); ?>">
<?php if ($image): ?>
<img src="<?php echo esc_url($image['url']); ?>" alt="<?php echo esc_attr($image['alt']); ?>" class="cta-image" />
<?php endif; ?>
<div class="cta-content">
<?php if ($title): ?>
<h3 class="cta-title"><?php echo esc_html($title); ?></h3>
<?php endif; ?>
<?php if ($description): ?>
<p class="cta-description"><?php echo esc_html($description); ?></p>
<?php endif; ?>
<?php if ($button_text && $button_url): ?>
<a href="<?php echo esc_url($button_url); ?>" class="cta-button">
<?php echo esc_html($button_text); ?>
</a>
<?php endif; ?>
</div>
</div>
Step 5: Add Custom CSS
Create a file at template-parts/blocks/custom-cta.css
and add styles:
.custom-cta-block {
padding: 40px;
border-radius: 15px;
text-align: center;
color: #fff;
max-width: 700px;
margin: 30px auto;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}
.custom-cta-block:hover {
transform: translateY(-5px);
}
.cta-image {
max-width: 120px;
margin-bottom: 20px;
border-radius: 50%;
border: 4px solid #fff;
}
.cta-title {
font-size: 28px;
margin: 15px 0;
font-weight: 700;
}
.cta-description {
font-size: 18px;
margin-bottom: 20px;
line-height: 1.5;
}
.cta-button {
display: inline-block;
padding: 12px 25px;
background-color: #ff6b6b;
color: #fff;
text-decoration: none;
border-radius: 25px;
font-weight: bold;
}
.cta-button:hover {
background-color: #e05656;
}
Final Thoughts
Using block.json
simplifies block registration and ensures future compatibility with WordPress updates. By following these steps, you’ve built a fully functional custom Gutenberg block using ACF!
If you encounter any issues or have questions, feel free to leave a comment below!
Great tutorial, thank you!
The only thing I would have expected is that you would have written it with `Blocks.json` support in mind:
> Since WordPress 5.8, WordPress has supported – and recommended – that blocks are registered through a JSON configuration file.
Source: https://www.advancedcustomfields.com/resources/whats-new-with-acf-blocks-in-acf-6/#blockjson-support
Maybe an idea for a follow-up post?
Cheers,
Pieter
Hi Pieter,
I appreciate the comment…
You are correct, i’ve modified the post to reflect the update. Thanks again! 🙂
Hi Roee,
Amazing how quick you have adapted your post following my suggestion! Many thanks, truly surprised!
Pieter