TechEarl

Using ACF Options Pages for Global Site Settings

ACF Options Pages are the right home for site-wide settings: header CTAs, footer links, social profiles, contact info, global announcements. Registration, reading patterns, parent/child structure, and the cache-busting trick for high-traffic sites.

Ishan Karunaratne⏱️ 5 min readUpdated
Share thisCopied
ACF Options Pages for site-wide settings: header CTAs, footer links, social profiles. Registration, reading patterns, parent/child structure, cache strategy.

ACF Options Pages are the right home for site-wide settings: header CTAs, footer disclaimers, social profile URLs, contact info, global announcements, anything that is "one value per site" rather than "one value per post." On directory sites I have shipped, Options Pages typically hold 30-50 fields organized into a parent + sub-pages structure. Reading from them is get_field( 'name', 'option' ), and on high-traffic sites a tiny cache wrapper saves real query time. Here is the canonical setup.

Jump to:

When to use an Options Page vs a per-post field

The decision rule is simple: if the value is "one per site" rather than "one per post," use an Options Page. Examples:

Belongs on an Options PageBelongs on a per-post field
Header CTA text and URLPage hero heading
Footer disclaimerPost excerpt
Social media profile URLsAuthor bio
Default OG imagePer-post OG image override
Site-wide announcement bannerPer-post announcement
Contact email and phonePer-listing contact info
Newsletter signup headingPer-page CTA copy
Schema.org Organization dataPer-post Article schema

The boundary is usually clear. The gray cases (per-section overrides, per-template defaults) usually still belong on the Options Page with conditional logic, not duplicated as per-post fields.

Basic registration

A single Options Page in functions.php or mu-plugins/:

php
add_action( 'acf/init', function () {
    if ( ! function_exists( 'acf_add_options_page' ) ) return;

    acf_add_options_page( [
        'page_title' => 'Site Settings',
        'menu_title' => 'Site Settings',
        'menu_slug'  => 'site-settings',
        'capability' => 'edit_posts', // or 'manage_options' for admin-only
        'redirect'   => false,
        'icon_url'   => 'dashicons-admin-generic',
        'position'   => 80, // position in the admin sidebar
    ] );
} );

The function_exists check matters: it guards against ACF being deactivated and the site fataling. Covered in detail in ACF Options Page Not Showing Up? Check These Things.

Then create a field group with a Location rule of "Options Page is equal to Site Settings" and add your fields.

Parent + sub-pages structure for many settings

For sites with many settings (which is typical on directory sites), the parent + sub-pages structure keeps the admin sidebar tidy:

php
add_action( 'acf/init', function () {
    if ( ! function_exists( 'acf_add_options_page' ) ) return;

    // Top-level parent (renders as a menu item with sub-items below)
    $parent = acf_add_options_page( [
        'page_title' => 'Site Options',
        'menu_title' => 'Site Options',
        'menu_slug'  => 'site-options',
        'capability' => 'edit_posts',
        'redirect'   => true, // skip the parent page, go straight to first child
        'icon_url'   => 'dashicons-admin-settings',
    ] );

    acf_add_options_sub_page( [
        'page_title'  => 'Header',
        'menu_title'  => 'Header',
        'parent_slug' => 'site-options',
    ] );

    acf_add_options_sub_page( [
        'page_title'  => 'Footer',
        'menu_title'  => 'Footer',
        'parent_slug' => 'site-options',
    ] );

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

    acf_add_options_sub_page( [
        'page_title'  => 'Contact Info',
        'menu_title'  => 'Contact Info',
        'parent_slug' => 'site-options',
    ] );

    acf_add_options_sub_page( [
        'page_title'  => 'Schema and SEO',
        'menu_title'  => 'Schema and SEO',
        'parent_slug' => 'site-options',
    ] );
} );

Each sub-page has its own field group with the appropriate fields. The editor sees a clean "Site Options" menu with five sub-items. The value reads are identical regardless of which sub-page contains the field: get_field( 'name', 'option' ).

Reading values from an Options Page

The read pattern is get_field( 'field_name', 'option' ):

php
$cta_text = get_field( 'header_cta_text', 'option' );
$cta_url = get_field( 'header_cta_url', 'option' );
$social = get_field( 'social_profiles', 'option' ); // Repeater
$company_address = get_field( 'company_address', 'option' );

For Repeater and Flexible Content fields on Options Pages, the same have_rows / the_row pattern applies with 'option' as the second argument:

php
if ( have_rows( 'social_profiles', 'option' ) ) {
    while ( have_rows( 'social_profiles', 'option' ) ) {
        the_row();
        $platform = get_sub_field( 'platform' );
        $url = get_sub_field( 'url' );
        printf( '<a href="%s">%s</a>', esc_url( $url ), esc_html( $platform ) );
    }
}

Updating Options Page values programmatically

Use update_field with 'option' as the third argument:

php
update_field( 'site_announcement', 'Holiday hours in effect through Jan 5', 'option' );
update_field( 'announcement_active', true, 'option' );
update_field( 'announcement_dismissable', false, 'option' );

For setting an entire Repeater:

php
$social = [
    ['platform' => 'twitter', 'url' => 'https://twitter.com/example'],
    ['platform' => 'linkedin', 'url' => 'https://www.linkedin.com/company/example'],
    ['platform' => 'github', 'url' => 'https://github.com/example'],
];
update_field( 'social_profiles', $social, 'option' );

For the full programmatic-update reference, see How to Update ACF Fields Programmatically.

Cache strategy for high-traffic sites

Options Page values are stored in wp_options under keys like options_field_name (and the _options_field_name field key reference). On every request, WordPress loads autoloaded options into memory as part of the standard request lifecycle, so reading an Options Page field is in-memory after the first lookup.

For high-traffic sites where every microsecond counts, a thin cache wrapper around the read avoids ACF's hydration overhead:

php
function te_get_option( $name, $default = null ) {
    static $cache = [];
    if ( isset( $cache[ $name ] ) ) {
        return $cache[ $name ];
    }
    $value = get_field( $name, 'option' );
    $cache[ $name ] = $value !== null ? $value : $default;
    return $cache[ $name ];
}

The static array dedupes calls within a single request. With persistent object cache (Redis), the underlying wp_options table is cached across requests too, so the per-request cache only saves the ACF hydration cost.

For Options Page fields that update frequently (a counter, a last-seen timestamp), be aware that updating an autoloaded option requires deleting and re-creating it from cache to ensure consistency.

Field group location rules for Options Pages

In the field group's Location section, the rule is:

  • Show this field group if: Options Page is equal to Site Settings (or your menu_slug).

For sub-pages, the rule targets the sub-page's slug rather than the parent's slug. Each field group attaches to exactly one Options Page (parent or sub-page), keeping the editing UI focused.

If a field group is not appearing on the Options Page you expect, the diagnostic is in ACF Options Page Not Showing Up? Check These Things.

Multilingual considerations

Options Page values are NOT automatically multilingual. WPML and Polylang have ACF integration that makes Options Page fields translatable, but the configuration is per-field.

The canonical pattern with WPML:

  1. Install WPML String Translation.
  2. In the ACF field, enable "Translate" in the WPML pane.
  3. The value becomes translatable in the WPML String Translation admin.

For agency builds, decide on multilingual support during the architecture phase. Retrofitting it onto an existing single-language Options Page system is harder than starting with it from the beginning.

For the broader agency-stack context, see The Exact Stack I would Use to Run a Small WordPress Agency Today. For the WP-CLI patterns for bulk-updating Options Page values, see Using AI with WP-CLI for Faster WordPress Operations.

Sources

Authoritative references this article was fact-checked against.

TagsWordPressACFOptions PagesArchitecture

Found this useful? Pass it on.

Copied

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts

Using AI with WP-CLI for Faster WordPress Operations

The WP-CLI patterns that compose well with AI assistants: multi-step plans with checkpoint approval, generated one-off scripts, database surgery, content migrations at scale, and what to never delegate.

Using Claude CLI to Manage WordPress Sites

How I use Claude CLI to run WordPress and ACF work end-to-end: ACF field group generation, WP-CLI orchestration, log triage, plugin debugging, bulk content ops. Concrete prompts, what it gets wrong, and where it fits in an agency workflow.