How to Create a Custom ACF Option Module in WordPress
If you work with Advanced Custom Fields (ACF), you know how powerful it is for managing custom data in WordPress. But sometimes you need even more control, especially when working with options pages.
Learn how to create a custom ACF (Advanced Custom Fields) option module in WordPress to easily manage settings for your theme or plugin. This guide covers the step-by-step process of adding an options page using ACF and how to store and retrieve custom field values. Whether you’re building a theme or a plugin, integrating ACF options gives you a flexible and powerful way to manage your WordPress settings programmatically.
In this tutorial, you’ll learn how to create a custom Option module for ACF.
We’ll register a custom location and handle saving and retrieving options cleanly, avoiding common issues like unwanted slashes in HTML!
Let’s dive in. 🚀
Step 1: Add Code to functions.php
First, we need to tell ACF to add a new Options page and register our custom meta handler.
Paste the following into your theme’s functions.php
file:
<?php
if (function_exists('acf_add_options_page')) {
acf_add_options_page(array(
'page_title' => __('Header Optionen', 'text-domain'),
'menu_title' => __('Header Optionen', 'text-domain'),
'menu_slug' => 'header-optionen',
'capability' => 'edit_posts',
'redirect' => false
));
}
// Load our ACF Meta Option class manually
require_once get_stylesheet_directory() . '/acf-meta-option.php';
add_action('acf/init', function() {
// Register the 'option' meta type with ACF
$meta_locations = acf_get_store('acf-meta-locations');
if ( $meta_locations ) {
$meta_locations->set( 'option', 'ACF\\Meta\\Option' );
}
});
This code does two things:
- It creates a new Options Page titled “Header Optionen.”
- It registers a new custom “meta” location for ACF to handle options differently.
Step 2: Create acf-meta-option.php
in Your Theme
Now create a new file in your active theme folder:
👉 acf-meta-option.php
Paste this code inside:
<?php
namespace ACF\Meta;
use function wp_unslash;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
class Option {
public $location_type = 'option';
public $reference_prefix = '_';
public function __construct() {}
public function get_value( $field_name, $field_key ) {
return get_option($field_key['name']);
}
public function update_value( $field, $post_id, $value ) {
if ( is_string( $value ) ) {
$value = wp_unslash( $value ); // Remove added slashes
$value = stripslashes( $value ); // Remove additional escape
}
return update_option( $post_id['name'], $value );
}
public function delete_value( $name ) {
return delete_option( $name );
}
public function update_reference( $post_id, $field_name, $field_key ) {
$reference = $this->reference_prefix . $field_name;
// Update the reference field (e.g., _your_field_name = field_abc123)
update_option( $reference, $field_key );
// Fetch the latest value
$actual_value = get_field( $field_key, $post_id );
if ( is_string( $actual_value ) ) {
$actual_value = wp_unslash( $actual_value ); // Remove added slashes
$actual_value = stripslashes( $actual_value ); // Remove additional escape
}
// Clean old value if exists
delete_option( $field_key );
// Save cleaned value
return update_option( $field_key, $actual_value );
}
public function get_reference( $field_name ) {
$reference = $this->reference_prefix . $field_name;
return get_option( $reference );
}
public function delete_reference( $field_name ) {
$reference = $this->reference_prefix . $field_name;
return delete_option( $reference );
}
/*
public function get_metadata( $post_id, $name ) {
return $this->get_value( $name );
}
public function update_metadata( $post_id, $name, $value ) {
return $this->update_value( $name, $value );
}
public function delete_metadata( $post_id, $name ) {
return $this->delete_value( $name );
}
*/
}
This custom Option
class does the following:
- Saves your ACF fields without extra slashes (important for clean HTML output!).
- Links fields to their keys properly.
- Handles saving, updating, and deleting option values cleanly.
Why This Approach?
When working with ACF and options pages:
- WordPress sometimes adds extra backslashes (like
\"
) when saving HTML or JavaScript. - ACF’s internal save mechanism wasn’t designed for deeply customized handling of Options.
- By writing a custom handler, you have full control over how the data is stored — ensuring safe, clean, and accurate storage.
This is extremely useful for:
- Saving custom HTML, JS snippets, banner embeds, etc.
- Handling serialized fields properly.
- Making the Options Page behave like normal post meta, but for the site settings.
Final Result
After following these steps:
- You’ll have a clean Options page inside WordPress Admin (
Header Optionen
). - Your fields will save exactly as you input them — no corrupted HTML, no extra slashes.
- You can access your saved fields easily using:
$value = get_field('your_field_name', 'option');
echo $value;
and it will output pure, unescaped HTML like:
<div class="content-header" id="newcontainer"></div>
Conclusion
By creating a custom ACF Option Meta module, you bring more control, stability, and cleanliness to your WordPress project.
Especially when working with HTML-based settings or embedding rich content, this approach saves tons of frustration!
Have any questions?
Feel free to ask in the comments — or if you want a ready-to-use downloadable ZIP for this setup, just let me know! 🚀