Advanced Custom Fields (ACF) Guide for Beginners: How to Use ACF with WordPress

Updated on
9 min read

In today’s digital landscape, mastering Advanced Custom Fields (ACF) in WordPress is essential for developers who want to provide structured, editor-friendly content without excessive manual effort. This comprehensive guide is tailored for WordPress theme builders and site developers aiming to enhance their projects with ACF. You will learn how to set up ACF, output fields in your theme, and incorporate best practices for performance and security.

What is Advanced Custom Fields (ACF)?

ACF is a powerful WordPress plugin that streamlines the management of custom fields (post meta) and seamlessly maps them to posts, pages, taxonomies, users, and options. Originally introduced as a free plugin, it later evolved into a paid “Pro” version with enhanced features.

Editions: Free vs ACF Pro (Short Summary)

FeatureACF (Free)ACF Pro
Basic fields (text, image, textarea, WYSIWYG)
Repeater field
Flexible Content
Options pages
Gallery enhancements & clone fields

ACF Pro provides advanced tools such as Repeater and Flexible Content fields, as well as the ACF Blocks API for creating Gutenberg blocks. Choose ACF for structured content without the need for a full-fledged plugin or when server-rendered templates are preferred over complex client-side block development.

For a complete list of functions and field types, refer to the official ACF documentation: ACF Resources.

Installation and Basic Setup

Follow these steps to install ACF from your WordPress admin:

  1. Navigate to Plugins > Add New and search for “Advanced Custom Fields”.
  2. Click Install Now and then Activate (for the free version).
  3. For ACF Pro, upload the ZIP file through Plugins > Add New > Upload Plugin, then click Activate.

Creating Your First Field Group

  1. In the WordPress admin, go to Custom Fields > Add New.
  2. Enter a Field Group name (e.g., “Page Hero”).
  3. Click Add Field, then select a field type (text, image, link, etc.).
  4. Set a field name (machine name) such as hero_title, and give it an intuitive label like “Hero Title”.
  5. Define location rules (e.g., Show if Post Type is Page OR Page Template is About).
  6. Save the Field Group.

Location rules dictate where field groups appear: based on post type, specific page templates, taxonomy terms, user profiles, or options pages (Options pages require ACF Pro).

Tip: Enable Local JSON to version field group definitions by storing JSON files in your theme, which is beneficial for collaboration and repository workflows.

Common Field Types and When to Use Them

Here are some common ACF field types along with brief usage notes:

  • Text: Short single-line strings (e.g., subtitle).
  • Textarea: Multi-line text (intro or summary).
  • WYSIWYG: HTML content for rich blocks (long descriptions).
  • Number: Numeric values for sorting or calculations.
  • Image: Single image (hero background).
  • Gallery: Multiple images (product gallery) — Pro adds improved features.
  • File: Attachments or downloadable PDFs.
  • Select/Checkbox/Radio: Controlled options for editors.
  • Link: URL + text target (CTA links).
  • Relationship/Post Object/Taxonomy: Link to other posts or terms (related posts, products).
  • Repeater (ACF Pro): Repeatable row sets (team members, FAQs).
  • Flexible Content (ACF Pro): Block-like, multi-layout areas suited for page-builder needs.

Naming and Field Key Conventions:

  • Use descriptive, snake_case field names (e.g., team_member_title).
  • Avoid collisions with native meta keys or plugin keys.
  • Field keys (e.g., field_123abc) are generated by ACF and useful during migrations.

Performance Note: Be cautious with repeaters and large relationships to prevent issues with postmeta.

Displaying Field Values in Themes (PHP)

ACF provides helper functions for fetching and displaying field values:

  • get_field('field_name', $post_id) – retrieves the value.
  • the_field('field_name', $post_id) – directly echoes the value.
  • get_post_meta($post_id, 'meta_key', true) – utilizes a native WP function.

Basic Examples

Text Field Example (in single.php or page template):

<?php
$hero_title = get_field('hero_title');
if ( $hero_title ) {
    echo '<h1>' . esc_html( $hero_title ) . '</h1>';
}
?>

Image Field Example:

<?php
$hero_image = get_field('hero_image');
if ( $hero_image ) {
    $url = esc_url( $hero_image['url'] );
    $alt = esc_attr( $hero_image['alt'] );
    echo '<div class="hero" style="background-image:url(' . $url . ');" role="img" aria-label="' . $alt . '"></div>';
}
?>

Repeater Loop Pattern:

<?php
if ( have_rows('team_members') ) {
    echo '<ul class="team">';
    while ( have_rows('team_members') ) {
        the_row();
        $name = get_sub_field('name');
        $role = get_sub_field('role');
        echo '<li><strong>' . esc_html($name) . '</strong><span>' . esc_html($role) . '</span></li>';
    }
    echo '</ul>';
}
?>

Escaping and Sanitization: Always sanitize output — use esc_html() for plain text, esc_url() for URLs, wp_kses_post() for trusted HTML blocks, and esc_attr() for attributes.

Using ACF with Gutenberg and Blocks

ACF Pro simplifies the creation of custom Gutenberg blocks via acf_register_block_type.

When to Use ACF Blocks vs Dynamic Templates

  • Use ACF Blocks for block UI in Gutenberg while favoring server-side rendering.
  • For interactive blocks with rich client-side functionality, consider building native JS/React blocks.

Registering a Simple ACF Block

add_action('acf/init', 'my_acf_init_block_types');
function my_acf_init_block_types() {
    if( function_exists('acf_register_block_type') ) {
        acf_register_block_type(array(
            'name'              => 'hero-block',
            'title'             => __('Hero'),
            'render_template'   => 'template-parts/blocks/hero/hero.php',
            'category'          => 'layout',
            'icon'              => 'cover-image',
            'keywords'          => array('hero','banner'),
        ));
    }
}

Once created, add a field group and set the location rule to “Block is equal to Hero” to display its fields in the editor. The render_template file will handle ACF fields using get_field() as usual.

ACF and the REST API / Headless WordPress

Post meta isn’t automatically included in REST API responses. For headless setups, consider:

  • Using the ACF to REST API plugin to add fields cleanly to REST responses.
  • Registering ACF fields with show_in_rest for inclusion in REST responses.

Example for exposing fields via register_post_meta:

register_post_meta('post', 'hero_title', array(
    'show_in_rest' => true,
    'single' => true,
    'type' => 'string',
));

Best Practices for Structured JSON:

  • Return arrays/objects instead of serialized strings.
  • Use dedicated endpoints for consistent structures.
  • Cache responses for improved performance.

Performance and Security Best Practices

Avoid Expensive Meta Queries

  • Use meta_query cautiously; large meta queries can slow down performance.
  • Preload data and minimize repeated calls to get_field() in loops.

Caching

Cache expensive ACF reads with transients:

$cache_key = 'home_hero_data';
$hero = get_transient($cache_key);
if ( false === $hero ) {
    $hero = get_field('hero_settings', 'option');
    set_transient($cache_key, $hero, HOUR_IN_SECONDS);
}

Sanitization and Validation

Utilize ACF field validation and sanitize on save when allowing HTML, ensuring output is escaped properly.

Caution with Relationships and Repeater Fields

Heavy use of these fields can increase postmeta entries and degrade performance; consider custom tables if dealing with significant data.

Common Pitfalls and Troubleshooting

Field Name Collisions

  • Ensure field names match the field group’s machine name and correspond to the correct post type.

Scope/Post ID Issues

  • When working outside the loop or during AJAX callbacks, pass the post ID explicitly to get_field('name', $post_id).

Migration and Environment Changes

  • Use ACF Local JSON and Export/Import tools to synchronize field group definitions across environments.

Serialized Meta Risks

  • Avoid direct editing of serialized data; always use ACF functions or PHP to update fields.

ACF Pro License/Updates

  • Keep ACF Pro updated to access ongoing support and features.

Practical Examples / Mini Tutorials

  1. Hero Block (Simple): Field Group: “Hero”
  • hero_title (Text)
  • hero_subtitle (Textarea)
  • hero_background (Image)
  • hero_cta (Link)

Template Snippet (template-parts/sections/hero.php):

<?php
$title = get_field('hero_title');
$subtitle = get_field('hero_subtitle');
$image = get_field('hero_background');
$cta = get_field('hero_cta');
?>
<section class="hero" style="background-image:url(<?php echo esc_url($image['url']); ?>);">
  <div class="container">
    <h1><?php echo esc_html($title); ?></h1>
    <p><?php echo esc_html($subtitle); ?></p>
    <?php if ( $cta ) : ?>
      <a class="btn" href="<?php echo esc_url($cta['url']); ?>"><?php echo esc_html($cta['title']); ?></a>
    <?php endif; ?>
  </div>
</section>
  1. Portfolio Item with Gallery and Related Posts: Fields: gallery (Gallery), related_projects (Relationship) Display example: use get_field('related_projects') to loop through related posts and display them using setup_postdata() or WP_Query.

  2. FAQ Page with Repeater: Fields: faqs (Repeater)

  • question (Text)
  • answer (WYSIWYG)

Accessible markup example:

<?php if ( have_rows('faqs') ) : ?>
  <div class="faqs">
  <?php while ( have_rows('faqs') ) : the_row(); ?>
    <details>
      <summary><?php echo esc_html(get_sub_field('question')); ?></summary>
      <div><?php echo wp_kses_post(get_sub_field('answer')); ?></div>
    </details>
  <?php endwhile; ?>
  </div>
<?php endif; ?>
  1. Exporting ACF Data and Migrating Field Groups: Use the Export feature in ACF admin or enable Local JSON (acf-json directory in your theme) to version field groups, ideal for repository strategies. For more on organizing code, read about Organizing code for larger projects.

Plugins and Add-ons Worth Knowing

  • ACF Extended: Enhances the ACF admin UI with additional features (conditional logic, UI helpers).
  • ACF to REST API: Clearly exposes ACF fields in REST responses, ideal for headless setups.
  • Query builders/UI helpers: Various community plugins simplify building WP_Query queries with ACF fields.

When to Consider Custom Tables

For large datasets with frequent complex queries, a custom table may be a better fit than relying on postmeta. Check out Designing maintainable theme/plugin architecture for more on data isolation strategies.

Resources and Next Steps

Official Documentation and Tutorials:

Suggested Follow-up Projects:

  • Create a reusable field group (Hero + CTA) and implement Local JSON in your theme.
  • Build a simple ACF Block and render it server-side in Gutenberg.
  • Expose selected ACF fields via the REST API to construct a headless demo using a JavaScript front end.

Community and Help:

Consider sharing advanced examples or case studies; learn how to contribute ACF tutorials or examples.

Conclusion

ACF is an essential tool for WordPress developers seeking a simple way to manage structured content. Start small by creating a basic field group, incorporate it into your templates with proper output sanitization, and use Local JSON for version control. As your projects grow, explore ACF Pro features like Repeater, Flexible Content, and Blocks while focusing on performance and security. Happy building with ACF to enhance and streamline content delivery!

TBO Editorial

About the Author

TBO Editorial writes about the latest updates about products and services related to Technology, Business, Finance & Lifestyle. Do get in touch if you want to share any useful article with our community.