Get ACF field values in WordPress templates and functions

Advanced Custom Fields is one of the most installed WordPress plugins for a reason: it bridges the gap between WordPress as a blogging platform and WordPress as a structured content management system without requiring developers to write custom meta box code from scratch. Instead of building registration arrays, sanitization callbacks, and rendering functions for every piece of custom data your theme needs, ACF gives you a visual interface to define fields, groups, and conditional logic, then exposes a clean PHP API to retrieve those values anywhere in your templates or functions. The difference between building a theme with ACF and building one without it is roughly the difference between two days of meta box boilerplate for a modest project and ten minutes of point-and-click field group setup followed by straightforward template code. ACF stores all field values as standard WordPress post meta under the hood, which means the data is always accessible through get_post_meta() as a fallback, but ACF’s own functions add significant convenience on top: automatic value formatting, relationship field resolution, image field array expansion, repeater row iteration, and type-appropriate return values without manual casting or unserialization. The primary function is get_field(), which accepts a field name and an optional post ID, returning the value in the format configured for that field type. A text field returns a string, an image field returns an array of attachment data or just the ID or URL depending on the return format setting, a repeater field returns an array of row arrays, and a relationship field returns an array of WP_Post objects. The companion function the_field() echoes the value directly, saving a line in template contexts where escaping is handled by the field type. For options page fields registered via acf_add_options_page(), pass 'options' as the second argument to target the global options post ID. ACF is particularly powerful when combined with custom post types, where each CPT entry carries a consistent set of structured fields — exactly the use case covered in our guide to registering a custom post type in WordPress. The snippets below cover the most common access patterns you will use in every ACF-powered theme.

Problem: You have defined ACF fields on a post type or options page and need to retrieve their values in PHP templates or functions.

Solution: Use ACF’s built-in functions in your theme template files:

<?php
// Get a text or textarea field for the current post (inside The Loop)
$tagline = get_field( 'project_tagline' );
if ( $tagline ) {
    echo '<p>' . esc_html( $tagline ) . '</p>';
}

// Get a field for a specific post by ID (outside The Loop)
$price = get_field( 'property_price', 42 );

// Get an image field (returns array by default)
$image = get_field( 'team_photo' );
if ( $image ) {
    echo '<img src="' . esc_url( $image['url'] ) . '" alt="' . esc_attr( $image['alt'] ) . '">';
}

// Loop through a Repeater field
$features = get_field( 'feature_list' );
if ( $features ) {
    echo '<ul>';
    foreach ( $features as $row ) {
        echo '<li>' . esc_html( $row['feature_name'] ) . '</li>';
    }
    echo '</ul>';
}

// Get a field from the ACF Options Page
$company_email = get_field( 'company_email', 'options' );

// Check if field has a value before using it
if ( have_rows( 'gallery_images' ) ) {
    while ( have_rows( 'gallery_images' ) ) {
        the_row();
        $img = get_sub_field( 'image' );
        echo '<img src="' . esc_url( $img['url'] ) . '">';
    }
}

NOTE: Always check the return value of get_field() before using it — it returns false when the field has no value, not an empty string or zero, so a simple if ( $value ) check works correctly for all field types. When outputting field values in HTML, always escape appropriately: esc_html() for text content, esc_url() for URLs, and esc_attr() for HTML attributes. If ACF is not active, calls to get_field() will cause a fatal error — wrap ACF-dependent code in if ( function_exists( 'get_field' ) ) checks when writing code that might run on sites without the plugin.