Tips・WordPress custom fields (ACF / SCF)

Managing site-wide information with an ACF options page

How to build an options page so phone numbers, social links, shared CTAs and other site-wide information can be edited from the admin screen. Covers how to write acf_add_options_page and the 'option' argument you must pass to retrieve values.

Phone number, address, social links, a shared tagline—hard-code site-wide information into your templates and you have to touch code every time it changes. Build an ACF (SCF) options page and it becomes editable from the admin screen.

There are only two steps. Add the page in functions.php, and pass 'option' when you retrieve values—that’s it.

TipsACF or SCF—which one should I install?The difference between ACF and SCF, and how to choose

Step 1: add the options page

function my_acf_options_page() {
  if (!function_exists('acf_add_options_page')) {
    return;   // so the site doesn't break where the plugin isn't installed
  }
  acf_add_options_page([
    'page_title' => 'Site settings',
    'menu_title' => 'Site settings',
    'menu_slug'  => 'site-settings',
    'capability' => 'edit_posts',   // let editors touch it too
    'position'   => 30,             // where it sits in the menu
    'icon_url'   => 'dashicons-admin-generic',
    'redirect'   => false,          // false if you aren't creating sub pages
  ]);
}
add_action('acf/init', 'my_acf_options_page');

“Site settings” is added to the left-hand admin menu. From there, set the field group’s “Location” to “Options Page = Site settings” and your input fields appear on it.

Step 2: pass 'option' when retrieving

This is the big one. Without 'option' as the second argument, you get nothing.

<p class="tel">Phone: <?php echo esc_html(get_field('tel', 'option')); ?></p>
<p class="address"><?php echo esc_html(get_field('address', 'option')); ?></p>

If you’re only printing, the_field() works the same way.

<?php the_field('tel', 'option'); ?>

Repeaters and groups work as usual

For things where you don’t know how many there will be—social links, say—putting a repeater field on the options page is handy. Pass 'option' as the second argument to have_rows() as well.

<?php if (have_rows('sns', 'option')) : ?>
  <ul class="sns">
    <?php while (have_rows('sns', 'option')) : the_row(); ?>
      <li>
        <a href="<?php echo esc_url(get_sub_field('url')); ?>">
          <?php the_sub_field('name'); ?>
        </a>
      </li>
    <?php endwhile; ?>
  </ul>
<?php endif; ?>

For a group, walk the array as always: get_field('company', 'option')['tel'].

TipsHow to output an ACF repeater fieldHow to write repeater fields

Organize with sub pages

Once the number of items grows, laying sub pages out under a parent menu keeps things findable.

acf_add_options_page([
  'page_title' => 'Site settings',
  'menu_slug'  => 'site-settings',
  'redirect'   => true,   // open the parent and jump to the first sub page
]);

acf_add_options_sub_page([
  'page_title'  => 'Company details',
  'menu_title'  => 'Company details',
  'parent_slug' => 'site-settings',
]);

acf_add_options_sub_page([
  'page_title'  => 'Social',
  'menu_title'  => 'Social',
  'parent_slug' => 'site-settings',
]);

When you use sub pages, setting 'redirect' => true on the parent prevents an empty page from showing when someone clicks the parent.

What’s worth putting there?

These are the ones that come up most in real projects.

  • Contact details—phone number, opening hours, address (shared by the footer and the contact page)
  • Social links—a repeater field so they can be added and removed freely
  • A shared notice bar—a one-liner like “Holiday closing dates”
  • Logo and OG image—an image field so they can be swapped out
  • Copyright line—the year from PHP, the company name from the admin screen

“Any wording that appears in two or more places” is a candidate for the options page—apply that rule and hard-coded text keeps shrinking.

An alternative that doesn’t depend on the plugin

Options pages are a plugin feature, so deactivating the plugin means losing the ability to edit them. If you want to stay plugin-independent, a static page can stand in.

<?php
$settings_id = 12;   // ID of the "Site settings" page
echo esc_html(get_field('tel', $settings_id));
?>

You create an unpublished page called “Site settings,” put the fields on it, and read them by naming its ID. If you’d rather not hard-code the ID, get_page_by_path('site-settings') can look it up from the slug.

If you want to stick to core features only, there’s also the theme customizer (customize_register). Building out the input fields, though, is far easier with ACF.

Summary

  1. acf_add_options_page() in functions.php adds a shared-settings page to the admin screen
  2. Retrieve with get_field('name', 'option'). Forget 'option' and you always get nothing
  3. Repeaters and groups work too (have_rows('sns', 'option')). As items grow, organize with sub pages
  4. Wording that appears in two or more places is a candidate. To stay plugin-independent, use a static page instead

The less you hard-code, the less “please change one line of text” turns into development work.

FAQ

How do I retrieve values from an options page?
Pass 'option' as the second argument, like get_field('tel', 'option'). Forget it and WordPress goes looking for a field on the current post instead, so the value comes back empty.
Can I create options pages in the free version of ACF?
With ACF (the WP Engine version) you need the paid ACF PRO. SCF, distributed by WordPress officially, includes it for free, so with SCF you can create them right away.
Can I put a repeater field on an options page?
Yes. Loop with 'option' as the second argument, like have_rows('items', 'option'). It's often used for a list of social links.
Could I use a static page instead?
Yes. Create a "Site settings" page, put the fields on it, and retrieve them by naming that page ID, as in get_field('tel', 12). The advantage is that it doesn't depend on a plugin feature.