2026年11月12日

2026年11月12日

ACF: How to Add Custom Fields to WordPress with Advanced Custom Fields

This article is a localized edition of the Japanese original. Read the Japanese original

Introduction

"I want to add my own data, such as a price, URL or rating, to posts." "I want to manage custom fields through a GUI." Advanced Custom Fields (ACF) is the most widely used custom field plugin for WordPress: you manage fields through a GUI and can easily output them from your templates.

Symptoms and Causes

WordPress's built-in custom fields are too generic, their UI is hard to use and field types are difficult to manage. With ACF, you can manage many field types, such as text, number, image, repeater and relationship, through a GUI.

How to Fix It

Step 1: Install ACF and Create a Field Group

[Install ACF]
Plugins → Add New → "Advanced Custom Fields" → Install and activate

[Create a field group]
ACF → Field Groups → Add New

Field group name: Product Info

Add fields:
  1. Field Label: Price
     Field Name:  price
     Field Type: Number
     Unit: yen
     Minimum Value: 0

  2. Field Label: Product URL
     Field Name:  product_url
     Field Type: URL

  3. Field Label: Features
     Field Name:  features
     Field Type: Text Area

  4. Field Label: Featured image (sub)
     Field Name:  sub_image
     Field Type: Image
     Return Format: Image Array

Location rules:
  Post Type = product (shown on the custom post type "Product")

Step 2: Display the Fields in a Template

<?php
// single-product.php: display ACF fields
get_header();
?>

<main>
    <?php while ( have_posts() ) : the_post(); ?>
        <article>
            <h1><?php the_title(); ?></h1>

            <?php
            // Text, number and URL fields
            $price       = get_field( 'price' );        // number
            $product_url = get_field( 'product_url' );  // URL
            $features    = get_field( 'features' );     // text area
            ?>

            <?php if ( $price ) : ?>
                <p class="price">¥<?php echo esc_html( number_format( $price ) ); ?></p>
            <?php endif; ?>

            <?php if ( $product_url ) : ?>
                <a href="<?php echo esc_url( $product_url ); ?>" target="_blank" rel="noopener">
                    View the product page
                </a>
            <?php endif; ?>

            <?php if ( $features ) : ?>
                <div class="features">
                    <?php echo wp_kses_post( $features ); ?>
                </div>
            <?php endif; ?>

            <?php
            // Image field (when the return format is an array)
            $sub_image = get_field( 'sub_image' );
            if ( $sub_image ) : ?>
                <figure>
                    <img src="<?php echo esc_url( $sub_image['url'] ); ?>"
                         alt="<?php echo esc_attr( $sub_image['alt'] ); ?>"
                         width="<?php echo esc_attr( $sub_image['width'] ); ?>"
                         height="<?php echo esc_attr( $sub_image['height'] ); ?>">
                </figure>
            <?php endif; ?>

            <?php the_content(); ?>
        </article>
    <?php endwhile; ?>
</main>

<?php get_footer(); ?>

Step 3: Use Repeater Fields (ACF Pro)

// Manage repeating data with a repeater field
// Field group: "FAQ" → repeater: faqs
//   Sub fields:
//     question (Text): Question
//     answer (Text Area): Answer
// Display the repeater in a template
<?php if ( have_rows( 'faqs' ) ) : ?>
    <dl class="faq-list">
        <?php while ( have_rows( 'faqs' ) ) : the_row(); ?>
            <dt><?php the_sub_field( 'question' ); ?></dt>
            <dd><?php echo wp_kses_post( get_sub_field( 'answer' ) ); ?></dd>
        <?php endwhile; ?>
    </dl>
<?php endif; ?>
// Display Flexible Content
<?php if ( have_rows( 'page_sections' ) ) : ?>
    <?php while ( have_rows( 'page_sections' ) ) : the_row(); ?>

        <?php if ( is_row_layout( 'hero_section' ) ) : ?>
            <section class="hero">
                <h2><?php the_sub_field( 'headline' ); ?></h2>
                <p><?php the_sub_field( 'subtext' ); ?></p>
            </section>

        <?php elseif ( is_row_layout( 'cta_section' ) ) : ?>
            <section class="cta">
                <a href="<?php the_sub_field( 'cta_url' ); ?>">
                    <?php the_sub_field( 'cta_label' ); ?>
                </a>
            </section>
        <?php endif; ?>

    <?php endwhile; ?>
<?php endif; ?>

Step 4: Version Field Settings with ACF JSON

// functions.php: set the ACF JSON save location inside the theme
// (the default is the /acf-json/ folder in the theme root)
add_filter( 'acf/settings/save_json', function( $path ) {
    return get_stylesheet_directory() . '/acf-json';
} );

add_filter( 'acf/settings/load_json', function( $paths ) {
    $paths[] = get_stylesheet_directory() . '/acf-json';
    return $paths;
} );
[How to use ACF JSON]

1. Create an /acf-json/ directory in the theme folder
2. When you save an ACF field group, a .json file is generated automatically
3. You can version the .json files with git
4. When you deploy the theme to another environment, the field settings are synced automatically

[Benefits]
- Moving field settings from development to production is easy
- You can track the history of field changes in git
- Settings can be shared in team development

Step 5: Register ACF Fields in Code (Without ACF JSON)

// functions.php: register an ACF field group in code
add_action( 'acf/include_fields', function() {
    if ( ! function_exists( 'acf_add_local_field_group' ) ) return;

    acf_add_local_field_group( [
        'key'      => 'group_product_info',
        'title'    => 'Product Info',
        'fields'   => [
            [
                'key'           => 'field_price',
                'label'         => 'Price',
                'name'          => 'price',
                'type'          => 'number',
                'required'      => 0,
                'min'           => 0,
                'append'        => 'yen',
            ],
            [
                'key'           => 'field_product_url',
                'label'         => 'Product URL',
                'name'          => 'product_url',
                'type'          => 'url',
            ],
            [
                'key'           => 'field_sub_image',
                'label'         => 'Sub image',
                'name'          => 'sub_image',
                'type'          => 'image',
                'return_format' => 'array',
                'preview_size'  => 'medium',
            ],
        ],
        'location' => [
            [
                [
                    'param'    => 'post_type',
                    'operator' => '==',
                    'value'    => 'product',
                ],
            ],
        ],
        'position' => 'normal',
        'style'    => 'default',
    ] );
} );

Caveats

  • The free version of ACF does not include advanced features such as repeater fields, flexible content and options pages. If you need them, you need ACF Pro.
  • Once you decide on a field name (name), do not change it. If you change it, previously saved data can no longer be retrieved. Use only alphanumeric characters and underscores in field names.
  • get_field() retrieves a field of the current post. To get a value outside the loop or from a specific post ID, pass the post ID as the second argument: get_field('price', 123).

Summary

Put ACF to work in this order: install the plugin → create field groups in the GUI → display them in templates with get_field()/the_field() → version them with the acf-json folder → turn them into a plugin by registering them in code. Related articles: How to create a custom post type in WordPress, How to create a custom taxonomy in WordPress.

Questions about WordPress? The publisher of this site is based in Japan and replies in Japanese. Contact (Japanese)

お気軽にご相談ください

お見積りへ お問い合わせへ
▲