All posts
Gutenberg and Blocks

WordPress ACF: Master Custom Fields and Blocks

Elevate your WordPress development with Advanced Custom Fields (ACF). This guide dives deep into mastering custom fields and leveraging ACF to create dynamic, reusable Gutenberg blocks that transform your content creation workflow.

mb3techs Team Sep 12, 2025 5 min read

WordPress is an incredibly powerful Content Management System (CMS), but sometimes its default fields don’t quite cut it for the unique content needs of a project. Whether you’re building a real estate listing site, a portfolio for artists, or a directory of events, you’ll likely need to add specific data points that aren’t covered by the standard ‘Title’ and ‘Content’ fields. This is where the magic of Advanced Custom Fields (ACF) comes in.

ACF is a free, open-source WordPress plugin that allows you to easily add fields to your posts, pages, users, taxonomies, or even theme options. Think of it as an extension to WordPress’s core content capabilities, empowering you to create custom data structures that perfectly suit your project’s requirements. It’s an indispensable tool for developers and site builders looking to elevate their WordPress websites beyond the ordinary.

Why Use ACF for Custom Fields?

Before ACF, adding custom fields often involved diving deep into WordPress’s code, creating custom meta boxes, and managing data storage yourself. This was not only time-consuming but also prone to errors for those less experienced with PHP and WordPress development. ACF simplifies this entire process, offering a user-friendly interface to define, manage, and display custom data.

  • Intuitive Interface: ACF provides a drag-and-drop interface for creating and arranging fields, making it accessible even to non-developers.
  • Vast Field Types: It offers a comprehensive library of field types, including text, textarea, image, file, select, checkbox, radio button, date picker, color picker, and even relationship fields to link between different pieces of content.
  • Conditional Logic: Show or hide fields based on the value of other fields, creating dynamic forms and content entry experiences.
  • Repeaters and Flexible Content: Build complex data structures with repeatable field groups (Repeaters) or create flexible content layouts with different field configurations (Flexible Content). Both are ACF Pro features.
  • Scalability: ACF scales with your project, from simple additions to intricate custom post type structures.
  • Theme and Plugin Development: It’s a favorite among developers for its robustness and integration capabilities, making it easy to build custom themes and plugins.

Getting Started with ACF

To begin using ACF, you first need to install and activate the plugin. You can find it in the official WordPress plugin repository. Once activated, you’ll see a new ‘Custom Fields’ menu in your WordPress dashboard.

Creating a Field Group

The core of ACF is the ‘Field Group.’ A field group is a collection of custom fields that you want to assign to a specific location or set of locations. To create one:

  • Navigate to Custom Fields > Add New.
  • Give your field group a descriptive title (e.g., “Book Details”).
  • Under the ‘Location’ rules, define where this field group should appear. For instance, you might set it to appear if ‘Post Type’ is equal to ‘Post’ or ‘Book’ (if you have a custom post type for books).
  • Click the ‘Add Field’ button to start adding your custom fields.

Adding Custom Fields

When adding a field, you’ll encounter several key settings:

  • Field Label: The human-readable name of the field (e.g., “Author Name”).
  • Field Name: A unique identifier for the field used in code (e.g., author_name). ACF typically auto-generates this from the label, but you can customize it. Stick to lowercase and underscores.
  • Field Type: Select the type of input you want (Text, Textarea, Image, etc.).
  • Instructions: Provide helpful text for the user entering data.
  • Required?: Mark if the field is mandatory.
  • Default Value: Pre-fill the field with a value.
  • Conditional Logic: Set rules for when this field should be displayed.

Let’s imagine we’re creating a simple field group for a ‘Book Review’ custom post type. We’ll add fields for the author’s name, publication date, and a star rating.

A Practical Example: Book Reviews

First, ensure you have a ‘Book Review’ custom post type set up (you can do this with plugins like CPT UI or by coding it yourself). Then, create a new ACF Field Group.

Field Group Setup

  • Field Group Title: Book Details
  • Location Rules: Show this field group if ‘Post Type’ is equal to ‘Book Review’.

Adding Fields to the Group

  1. Author Name: field name author_name, type Text, required.
  2. Publication Date: field name publication_date, type Date Picker, optional, return format Y-m-d (this keeps date handling consistent).
  3. Star Rating: field name star_rating, type Select, required, default value 3. Enter the choices one per line as value : label, for example 1 : 1 Star through 5 : 5 Stars.

After saving this field group, when you create or edit a ‘Book Review’ post, you’ll see these new fields neatly organized under the content editor. You can then input the author’s name, select a publication date, and choose a star rating for each review.

Displaying ACF Data on the Frontend

Adding the fields is only half the battle; you also need to display this data on your website’s frontend. This is where you’ll typically modify your theme’s template files.

Template File Modifications

For custom post types, you’ll usually be working within the single-{post_type}.php file or within template parts that are included in your single post template. For standard posts or pages, you might edit single.php or page.php.

ACF provides helpful PHP functions to retrieve the values of your custom fields. The most common ones are get_field() and the_field().

Using the_field()

the_field() directly echoes the value of a field. It’s the simplest way to display data. Here’s how you might display the book details in your single-book_review.php template:

<?php // Inside your single-book_review.php template file ?>

<?php if ( get_field( 'author_name' ) ) : ?>
    <p><strong>Author:</strong> <?php the_field( 'author_name' ); ?></p>
<?php endif; ?>

<?php if ( get_field( 'publication_date' ) ) : ?>
    <p><strong>Published on:</strong> <?php the_field( 'publication_date' ); ?></p>
<?php endif; ?>

<?php if ( get_field( 'star_rating' ) ) : ?>
    <p><strong>Rating:</strong> <?php
        $rating = (int) get_field( 'star_rating' );
        echo str_repeat( '★', $rating ); // Star character
    ?></p>
<?php endif; ?>

In this example, we use get_field('field_name') within an if statement to ensure we only display the field if it has a value. For the star rating, we fetch the value and repeat the star character that many times. This is a common pattern for displaying custom data.

Using get_field()

get_field() retrieves the field’s value without echoing it. This is useful when you need to manipulate the data before displaying it, pass it to a function, or store it in a variable. For instance, if you wanted to display the star rating as a simple number:

<?php
$rating = get_field( 'star_rating' ); // Get the rating value
if ( $rating ) {
    echo '<p><strong>Rating:</strong> ' . esc_html( $rating ) . ' out of 5 stars</p>';
}
?>

This snippet retrieves the ‘star_rating’ value into the $rating variable and then displays it within a paragraph. This approach offers more control over how the data is presented.

Handling Different Field Types

Some field types return structured data rather than a plain string, so check the field’s ‘Return Format’ setting (Array, URL or ID for images and files) before you write the template.

Images. With the return format set to Array, get_field() returns the image url, width, height and alt text:

<?php $image = get_field( 'your_image_field' ); if ( $image ) : ?>
    <img src="<?php echo esc_url( $image['url'] ); ?>" alt="<?php echo esc_attr( $image['alt'] ); ?>" />
<?php endif; ?>

Files. A file field set to Array works the same way, so you can build a download link from its URL:

<?php $file = get_field( 'your_file_field' ); if ( $file ) : ?>
    <a href="<?php echo esc_url( $file['url'] ); ?>">Download Brochure</a>
<?php endif; ?>

Relationship fields. These link to other posts and return an array of post objects (or IDs, depending on the setting), which you loop through:

<?php $related_posts = get_field( 'related_books' ); if ( $related_posts ) : ?>
    <h3>Related Books</h3>
    <ul>
    <?php foreach ( $related_posts as $post_object ) : ?>
        <li>
            <a href="<?php echo esc_url( get_permalink( $post_object->ID ) ); ?>"><?php echo esc_html( get_the_title( $post_object->ID ) ); ?></a>
        </li>
    <?php endforeach; ?>
    </ul>
<?php endif; ?>

True/False fields. These return true or false, so you can use them directly in an if statement.

Advanced Features: Repeaters and Flexible Content

ACF’s power truly shines with its Repeater and Flexible Content fields. These allow for complex, user-defined content structures.

Repeater Fields

Repeaters let users add multiple instances of a set of fields. Imagine a ‘Team Members’ section where each member has a photo, name, title, and bio. With a Repeater field, you can easily add new team members one by one.

<?php
if( have_rows('team_members') ): // Loop through rows of the repeater
    while( have_rows('team_members') ): the_row(); // Get the current row

        // Get field values from the current row
        $member_name = get_sub_field('member_name');
        $member_title = get_sub_field('member_title');
        $member_photo = get_sub_field('member_photo'); // Assuming this returns an image array

        ?>
        <div class="team-member">
            <?php if( $member_photo ): ?>
                <img src="<?php echo esc_url($member_photo['url']); ?>" alt="<?php echo esc_attr($member_photo['alt']); ?>" />
            <?php endif; ?>
            <h4><?php echo esc_html($member_name); ?></h4>
            <p><?php echo esc_html($member_title); ?></p>
        </div>
        <?php
    endwhile;
else:
    // No rows found
endif;
?>

Notice the use of have_rows(), the_row(), and get_sub_field(). This structure is fundamental for working with Repeater fields. get_sub_field() is used to retrieve values from fields within the current repeater row.

Flexible Content Fields

Flexible Content fields allow you to define multiple ‘layouts’ or templates, and the user can choose which layout to add for each content block. This is incredibly powerful for building modular page content. For example, you could have layouts for a ‘Text Block’, an ‘Image Gallery’, a ‘Call to Action’, and a ‘Video Embed’.

<?php
if( have_rows('flexible_content') ):
    while( have_rows('flexible_content') ): the_row();

        if( get_row_layout() == 'text_block' ):
            // Display content for Text Block layout
            $text = get_sub_field('text_content');
            ?>
            <div class="text-block"><?php echo wp_kses_post( $text ); ?></div>
            <?php

        elseif( get_row_layout() == 'image_gallery' ):
            // Display content for Image Gallery layout
            $images = get_sub_field('gallery_images'); // Assuming this returns an array of image arrays
            ?>
            <div class="image-gallery">
                <?php if( $images ): ?>
                    <?php foreach( $images as $image ): ?>
                        <img src="<?php echo esc_url($image['url']); ?>" alt="<?php echo esc_attr($image['alt']); ?>" />
                    <?php endforeach; ?>
                <?php endif; ?>
            </div>
            <?php

        // Add more elseif blocks for other layouts

        endif;
    endwhile;
else:
    // No layouts found
endif;
?>

Here, get_row_layout() determines which of your defined layouts the current row is, allowing you to conditionally display content based on the chosen layout. This opens up immense possibilities for creating dynamic page builders within the WordPress admin.

Best Practices and Tips

  • Naming Conventions: Use consistent and descriptive naming for your field groups and field names. This makes your code cleaner and easier to manage.
  • Return Formats: Pay attention to the ‘Return Format’ setting for fields like images and files. Choose the format that best suits how you intend to use the data in your templates.
  • Sanitization and Escaping: Always escape data when displaying it on the frontend to prevent security vulnerabilities. WordPress provides functions like esc_html(), esc_attr(), esc_url() and wp_kses_post() for this purpose.
  • Conditional Logic Wisely: Use conditional logic to create a streamlined user experience in the admin area, only showing relevant fields.
  • Code Comments: When modifying theme files, add comments explaining where ACF fields are being displayed. This helps future maintainers.
  • Performance: For very complex setups with many fields, consider the performance impact. ACF is generally efficient, but always test your site’s speed.
  • ACF Pro Features: While the free version is powerful, ACF Pro offers additional field types (like Repeater, Flexible Content, Gallery, Clone, and Options Pages) and features that are invaluable for more advanced projects.

Advanced Custom Fields is more than just a plugin; it’s a fundamental tool for building robust, data-driven WordPress websites. By mastering its capabilities, you can transform standard WordPress content into rich, dynamic, and highly customized experiences that meet any project’s unique demands.

Need This Built for a Client?

Knowing how it works is one thing; shipping it on a deadline, under your agency’s brand, is another. That is what we do. See our white label WordPress development services, our dedicated developer plans if you need ongoing capacity, or our maintenance plans to keep client sites healthy after launch. Tell us about the project.