3 May

How to Build a Business Listing Using ACF Blocks and the Query Loop Block in a Block Theme

By Liam Gladdy

Full Site Editing in WordPress is here, and it’s going to change the way you build themes. In this tutorial, I’ll show you how block themes work, how to use ACF Blocks in a block theme, and provide some real world examples. By the time we get to the end, you’ll know how to give your clients a more complete site editing experience, and how to use ACF Blocks to give yourself a head start in switching to block theme development.

Full Site Editing (FSE) involves changes to WordPress core that extend the Block Editor to the whole page, from the header to the footer, making it editable with blocks. If you’re already familiar with the Block Editor, this allows you to modify things like header logos or footer social media icons in a similar interface. Even widgets have been replaced by blocks.

However, it’s not just a case of flicking a switch. Enabling FSE on your WordPress site requires a block-based theme. This new style of theme requires significant changes to how you build your WordPress themes.

How Block Themes Work

Block themes came to WordPress with the release of the block-based version of Twenty Twenty-One, the TT1 Blocks theme. This is an experimental theme built to show WordPress users the new features of FSE. There are now a number of new themes that take advantage of the new WordPress FSE features, such as Blockbase and Frost.

There have been a lot of changes “under the hood” to bring Full Site Editing features into WordPress, but from the user experience point of view, the key point is that it turns everything on your WordPress website into an editable block as long as you’re using a block theme. This extends to the entire site, not just obvious items like post content and post titles. A block theme gives you the power to edit just about everything, from the site title right down to the footer.

WordPress 5.9 ships with a block theme called Twenty Twenty-Two, the first default block theme. We’ll use this for the examples in this article.

In a block theme, your templates become HTML files that contain block markup. Using Twenty Twenty-Two’s home page template as an example, you can see the block markup that builds the frontend output, including reusable template-part blocks. These contain reusable aspects of the site, like the header and footer. You can learn more about template parts and template editing in the WordPress developer documentation.

Template view with template parts.

A block theme also contains a theme.json file which contains a list of all the custom templates your theme is using, as well as all the default configuration for typography, fonts, and global styles that will apply across all your templates. The full documentation for theme.json has more information on this.

    "version": 2,
    "customTemplates": [
            "name": "blank",
            "title": "Blank",
            "postTypes": [
    "settings": {+
        "appearanceTools": true,
        "color": {
            "palette": [
                    "slug": "foreground",
                    "color": "#000000",
                    "name": "Foreground"
        "layout": {
            "contentSize": "650px",
            "wideSize": "1000px"
    "styles": {
        "color": {
            "background": "var(--wp--preset--color--background)",
            "text": "var(--wp--preset--color--foreground)"
    "templateParts": [
            "name": "header",
            "title": "Header",
            "area": "header"

Another core aspect of a block theme is the Query Loop block, which displays posts based on specified parameters. It’s like a WordPress Loop without the code. This block handles configuration of the WordPress Loop, and lets you use your other blocks in the context of a loop.

We’ve worked hard across our recent releases of Advanced Custom Fields PRO to let you use ACF Blocks to bridge the gap between the old style of theme building and the new block theme style of development.

How ACF Blocks Work

ACF Blocks were introduced in ACF PRO’s 5.8 release. Unlike a native WordPress block, an ACF Block lets you write your blocks purely in PHP, without the need to write any JavaScript or React code, and use ACF to define which fields the block uses.

Because ACF Blocks load a PHP template for their output, you can continue writing code and templates the same way you always have, using ACF as a bridge between the old way and the new way. Let’s say you created a testimonial block; you’d create an ACF Field Group containing the fields required for that block to function, such as the text, author, and date, then assign that to the block. These fields would then be shown on the page when a testimonial has been added to the page.

The introduction of the Query Loop block gives us another use case for ACF Blocks: using an ACF Block and its templating system to display fields assigned to a post type rather than assigned to the block itself.

ACF PRO 5.12 introduced compatibility with WordPress 5.9 and the Full Site Editor. As part of those changes, ACF now makes sure the post ID is set correctly where the block is being displayed. This means if you’re inside a Query Loop block and you call get_the_ID(), you’ll now correctly get the ID of the post the loop is showing, rather than the ID of the post or page hosting the Query Loop block. This allows you to access fields on that post directly.

Example: Using ACF Blocks Inside a Block Theme

Let’s say you’re producing a WordPress site listing your favorite local cafes. You’re likely to have a bunch of metadata for each shop, such as opening hours or a map showing its location. This metadata is stored as fields defined with ACF on a cafe custom post type, but displayed in a Block Theme template inside a Query Loop block.

For our examples below, we’ll create an “Opening Hours” block. We’ll use this to display a cafe’s opening hours across the site. The site itself is using a custom child theme based on the Twenty Twenty-Two block theme.


First, we need to create the custom fields on our cafe post type to store the opening hours for each location. We’ll do this using a repeater field type in ACF PRO so we can support different opening times for different days. The repeater contains a time_period, opening_time, and closing_time for each row, as shown in the screenshot.

A screenshot showing the field group settings for the cafe custom post type.

Creating the Block

Creating the block requires the use of ACF’s acf_register_block_type function. We do this in our theme’s functions.php with the following code:

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

    if ( function_exists( 'acf_register_block_type' ) ) {
                'name'            => 'opening-hours',
                'title'           => 'Café Opening Hours',
                'description'     => 'Display opening hours for a café',
                'render_template' => 'block-templates/opening-hours.php',
                'category'        => 'text',
                'icon'            => 'admin-comments',
                'api_version'     => 2,
                'keywords'        => array( 'opening hours', 'hours' ),
                'mode'            => 'preview',
                'supports'        => array(
                    'jsx'        => true,
                    'color'      => array(
                        'text'       => true,
                        'background' => false,
                    'align_text' => true,

ACF PRO blocks can use the majority of supports options that WordPress provides in the Block Editor, so we can enable support for text-align and color for our block. The values selected for these in the Block Editor are passed into our template code via the $block variable.

You can also see in the example code that we provide a path to our render_template. This is the PHP file that is used to render the output for our block. Inside this file, you can use any WordPress functions you could normally use in a template file.

You may recall that we assigned our field group to the cafe post type, instead of to the block itself. This means we enter the field values when creating a new cafe page, instead of in the block directly. It also means that we’ll need to pass the post ID (via get_the_ID() or similar) to any calls to get_field() or the_field() in our block render template. For example, get_field('opening_times', get_the_ID()).

Here’s the content of our template code:

$align     = isset( $block['align_text'] ) ? $block['align_text'] : 'left';
$textcolor = isset( $block['textColor'] ) ? $block['textColor'] : 'inherit';

if ( substr( $textcolor, 0, 1 ) !== '#' && substr( $textcolor, 0, 4 ) !== 'rgb(' ) {
    $textcolor = 'var(--wp--preset--color--' . $textcolor . ')';
<aside class="opening-times" style="color: <?php echo $textcolor; ?>; text-align: <?php echo $align; ?>">
    <h5 style="margin-top: 0; margin-bottom: 0.5rem;">Opening Hours</h5>
    <?php $opening_times = get_field( 'opening_times', get_the_ID() ); ?>
    <?php if ( ! empty( $opening_times ) ) { ?>
        <?php foreach ( $opening_times as $period ) { ?>
            <strong><?php echo $period['time_period']; ?></strong>:
            <?php echo $period['opening_time']; ?>
            <?php if ( ! empty( $period['closing_time'] ) ) { ?>
                - <?php echo $period['closing_time']; ?>
            <?php } ?>
            <br />
        <?php } ?>
    <?php } ?>

Because the template receives the raw values from the Block Editor for any supports options, we have to manually translate those values into valid CSS properties. In the case of color values, they could be passed to us as hex, RGB, or CSS variables. For the CSS variables, we need to apply the WordPress prefix of --wp--preset--color-- to the variable name. In a future version of ACF PRO, we intend to automatically handle the conversion of these variables to valid CSS for you.

Outputting the Block

Now our block is ready to be displayed on the page. We can output our block anywhere a cafe post type is displayed, so we’ll add this in two places: once in the template for a single post, and once on a page where we’ll highlight our favorite cafes from all the options available using the new Query Loop block.

Single Post Template

Let’s start with the single post template. We can do this by selecting the template from the sidebar, and clicking the Edit button. This will launch the template editor, showing the template currently being used for our cafe post type.

A screenshot showing the custom post type meta edit screen.

Once we’re in the template editor, we can modify the default template to add a column layout block. This allows us to move the content to one side, and add our “Café Opening Hours” block to the right-hand side.

A screenshot showing the template editor and the custom block.

Now we just need to save the template, and it will be used for any of our cafes.

Adding a Query Loop Block

Next, we want to create a page highlighting our favorite cafes. To do this, we create a page as normal, use the Block Editor to set the title, and add any content we want to show on the page.

To bring the cafe post types onto the page, we need to add a Query Loop block to the page. Once we’ve added this, we can configure it to show the cafe post type by selecting the post type from the sidebar. We can also set any parameters we want here, such as filtering by keyword or category. In an upcoming version of WordPress, we’ll also be able to use custom taxonomies to filter the Query Loop block too. You can use this feature now by installing the Gutenberg plugin, which offers an advanced preview of Gutenberg releases before they’re merged into WordPress core.

A screenshot showing the Query Loop block configuration.

Now we can configure the Query Loop block to display content how we like. I’ve decided to use a column layout, showing a split for the featured image block, the title and excerpt blocks, then our opening hours block, all nested inside our Query Loop block. This is easier to configure using the left-hand sidebar (“List view”), as it makes it easier to see what blocks are nested under each other, and lets you drag items around to change things. We’ll also customize the text color used for our “Café Opening Hours” block, and align the text to the right using the default WordPress editor toolbar, enabled by our block supports.

A screenshot showing the Query Loop block with our custom block inside.


Block themes are a significant change to the development workflow of building WordPress themes. However, you can grant your users a significantly more complete site editing experience, and reduce the amount of support you’ll need to provide them to update things like logos, headers, and footers. For more on how you can do this, see our case study with Sam Kent of Zoo Studios.

There are also many more usability features, like block patterns. You can use these to save a group of blocks as a reusable one-click addition to your content.

That said, giving that much control to your users might be detrimental. If you’ve got a beautifully designed theme, the user could break it by adding a huge banner in the middle of the homepage or changing the column percentages on a whim. WordPress is starting to cater for this situation with template and block level locking. You can use this to prevent users editing areas of the site which should be fixed, such as column widths, while still letting them edit the content inside using the Block Editor.

No matter which method of theme building you decide to use, block themes or traditional theme development, both will be supported for the foreseeable future, and both work well with ACF Blocks.

Using ACF Blocks also gives you a head start if the time comes for you to switch to block theme development. Your existing blocks will be portable across projects and themes and you will also keep a consistent development experience by giving you a templating system that you already know from developing traditional themes.

Are you using ACF Blocks already? Do you have any feature requests for us for how we can make your development experience even easier? Let us know in the comments below! We’d love to hear from you.

About the Author