For most cases ACF (Advanced custom fields plugin for WordPress) free version is enough to meet you and your users’ requirements. For most themes, a custom site settings page is a necessary feature that gives the user a bit more control over the theme.
In ACF pro version, a custom options page can be created easily, as shown in the link. While the option is not available in the free version, a page can be created with the existing features by using a workaround.
Here are the steps to create a custom settings page using the free version of ACF. If you don’t have the plugin yet, first install it from the plugins page
Creating the “page”
For creating the settings page, we will be using a normal “page”. First, go to the Pages section and select “Add new”, you will see a page as shown below.

Now enter only the title and try to make it something simple. In my case, it was “Site settings”, so my permalink was “site-settings”.

That’s all the content that’s needed, for now.
Adding the fields.
Next, select the “Custom Fields” options from the menu to go to the ACF management page.
Select “Add New” to add a new field group.
Give the field group a title, and then add the necessary fields, then go to the “Location” part and add the rule so that the fields appear only for the “site-settings” page.

Next, scroll down to the “Settings” part, and in the “Hide on screen” section, tick the Content Editor checkbox and any other feature that you don’t need. But keep the Permalink and Slug option unchecked so, you can see your site settings slug which will be used later.

Publish the field group so that the changes are applied.
If you go to the pages and select the “Site Settings” page, you will see that the content editor and other features that were chosen to be hidden in the previous step are still visible (If you are using Gutenberg). In order to hide the selected features, we will have to manually hide Gutenberg for this specific page.
Hiding Gutenberg
If you are using a plugin that hides Gutenberg, you can skip this section.
Open your themes functions.php
and paste the below code.
add_filter('use_block_editor_for_post', 'disable_gutenberg_on_settings_page', 5, 2);
function disable_gutenberg_on_settings_page($can, $post){
if($post){
// Replace "site-settings" with the slug of your site settings page.
if($post->post_name === "site-settings"){
return false;
}
}
return $can;
}
The above code will disable Gutenberg on the “site-settings” page.
Now, if you go to the site settings page, you will see that only the custom fields and title bar appear.
By now we will have a basic working settings page.
Hide settings page in pages section
We would probably want the “site settings” page to be independent, mostly accessible via the admin menu. So the next step is to remove the page from pages listing.
In order to do this, copy the below code into your theme’s functions.php file
function hide_settings_page($query) {
if ( !is_admin() && !is_main_query() ) {
return;
}
global $typenow;
if ($typenow === "page") {
// Replace "site-settings" with the slug of your site settings page.
$settings_page = get_page_by_path("site-settings",NULL,"page")->ID;
$query->set( 'post__not_in', array($settings_page) );
}
return;
}
add_action('pre_get_posts', 'hide_settings_page');
This will remove our settings page from the query.
Adding the settings page to the admin menu
To make our custom page a part of the admin menu, paste the below code into your theme’s functions.php
// Add the page to admin menu
function add_site_settings_to_menu(){
add_menu_page( 'Site Settings', 'Site Setttings', 'manage_options', 'post.php?post='.get_page_by_path("site-settings",NULL,"page")->ID.'&action=edit', '', 'dashicons-admin-tools', 20);
}
add_action( 'admin_menu', 'add_site_settings_to_menu' );
// Change the active menu item
add_filter('parent_file', 'higlight_custom_settings_page');
function higlight_custom_settings_page($file) {
global $parent_file;
global $pagenow;
global $typenow, $self;
$settings_page = get_page_by_path("site-settings",NULL,"page")->ID;
$post = (int)$_GET["post"];
if ($pagenow === "post.php" && $post === $settings_page) {
$file = "post.php?post=$settings_page&action=edit";
}
return $file;
}
The above code has two parts,
- Add the page to the menu. To add a custom icon to the item, check the list of available icons here.
- Highlighting the menu when the custom settings page is visited.
By now the important parts of our custom settings page are finished.
The only remaining step is to add a custom title to the settings page. To do so, paste the below code to the functions.php file
function edit_site_settings_title() {
global $post, $title, $action, $current_screen;
if( isset( $current_screen->post_type ) && $current_screen->post_type === 'page' && $action == 'edit' && $post->post_name === "site-settings") {
$title = $post->post_title.' - '.get_bloginfo('name');
}
return $title;
}
add_action( 'admin_title', 'edit_site_settings_title' );
That’s it, now you have a custom settings page.
Querying the data
To query the details you can use the slug of the settings page, ie “site-settings”.
Or find the id of the page from the admin section, for example

5
is the id of my settings page and to fetch all the acf fields for this page, we can use either get_option
or get_options
depending on the use case
$allOptions = get_fields(5);
$specificOption = get_field('option_field_name', 5);
Feel free to comment if you have any suggestions/improvements or you’re having any difficulties.
Comments
JRiver
almost 5 years ago
DKasper
over 4 years ago
akzhy
over 4 years ago
DKasper
over 4 years ago
akzhy
over 4 years ago
DKasper
over 4 years ago
DKasper
over 4 years ago
akzhy
over 4 years ago
Dazza
about 2 years ago
hi, just wanted to say that i'm looking forward to setup this solution on my new boilerplate wp. Great tutorial, I however have the same problem related to this piece:
$post = (int)$_GET["post"];
and even though I tried to add the code (below) that Gökay suggested I'm getting an error in the dashboard: key "post" in [...]/bricks-child/functions.php on line 205
I tried adding the code but the error is still there, and the 2nd line breaks the function.php Sorry I'm not a dev hence problems. please can you help? thank you.
================================== function op($slug) { $page_url_id = get_page_by_path( $slug ); return $page_url_id->ID; } the_field('my_title', op('site-settings'));
Dazza
about 2 years ago
should be: Undefined array key "post" in [...]/bricks-child/functions.php on line 205
Dazza
about 2 years ago
ok, in case anybody have had this problem i have managed to fix it by amending the code to:
$settings_page = get_page_by_path("site-settings",NULL,"page")->ID; $post = isset($_GET["post"]) ? (int)$_GET["post"] : null;
Gökay Mozakoğlu
over 4 years ago
Elton
over 4 years ago
akzhy
over 4 years ago
Elton
over 4 years ago
Muhibul Haque
over 3 years ago
The options only works in same page, I mean in "Settings Page", do not work in other pages. So, how can I display in all pages.
akzhy
over 3 years ago
Muhibul Haque
over 3 years ago
Excellent Boss! Working absolutely fine :)
omran
over 3 years ago
hi man this is really good , it works in the same page altho im not that good at coding . how I did not understand how to apply the custom fields for another page ? I saw your reply
$query = new WP_Query( array( 'name' => 'site-settings, 'post_type' => 'page', ) );
but I did not understand it .
else how can I apply the custom fields for a header or a footer ?
akzhy
over 3 years ago
get_fields
function provided by acf. To get the id of the page, open the page from admin side and you will find something like this in the address barpost.php?post=5&action=edit
here 5 is the id of the page. Now open the file you wish to edit (header.php/footer.php) and then use the below code This will display all the options, to fetch a specific option you can get it by$customOptions['option_name'];
or if you only need to fetch a specific option you can useget_field('option_name', 5);
Aman
over 3 years ago
This page is visible on search results on google. It's means this page rank by default. Any Suggestion??
akzhy
over 3 years ago
Poldro
over 3 years ago
That's an awesome piece of code! I was wondering... How can we give access to this page to a specific role?
Poldro
over 3 years ago
My current workaround has been using Advanced Access Manager. I created a new role and duplicated the admin, then limited its access to only this page and some other custom post types I needed. This seems to work but I'm sure there is a cleaner way to achieve it
akzhy
over 3 years ago
Additionally you can conditionally show the menu bar item using the
user_can_view_custom_options_page
function. You can edit the function to match the roles you want, refer this for available capabilities and tolesNICKYG
over 3 years ago
All clear, all perfect except for this small (extra) piece of code that I didn't understand what it is for and where I see the changes it makes.
A custom title to the settings page, I see as the title what I entered in the page name.
function edit_site_settings_title() { global $post, $title, $action, $current_screen; if( isset( $current_screen->post_type ) && $current_screen->post_type === 'page' && $action == 'edit' && $post->post_name === "site-settings") { $title = $post->post_title.' - '.get_bloginfo('name');
} return $title;
}
add_action( 'admin_title', 'edit_site_settings_title' );
NICKYG
over 3 years ago
What if you want to create 2 different pages by placing them in the main bar? (page A, Page B)
Should I duplicate all of this code or can it be simplified by merging the functions?
akzhy
over 3 years ago
hide_settings_page
will have to include both the ids, so it should look likeakzhy
over 3 years ago
NICKYG
over 3 years ago
I understand function edit_site_settings_title () how it works!
Tell me how to set which roles can access the settings page ... I try to change editor, contributor, author etc. But only as an administrator I see the page.
akzhy
over 3 years ago
add_site_settings_to_menu
the user capability is set tomanage_options
. This means that only those users with the manage_options capability will have the Page added to the sidebar. In order to show this to other roles, you can replace the manage_options with a different capability according to the role you need. Refer this page for the full list of roles and capabilities. In your case, you can useedit_private_posts
as only editor and admin roles have that capability.NICKYG
over 3 years ago
I had found this script to Bypass ACF Free's lack of entering Galleries. https://github.com/demirdoven/image-gallery-for-cpt-or-post-in-wordpress
The script works but I would like to make some changes (which I can't) and the comunity on Git seems dead. I don't know if you succeed as you are very good at programming (maybe it's a script that you can also use)
these were my requests:
I have some questions since I don't understand how to do:
Replacing the name given to the "house" example with the name? or the slag? of my personal CPT or "post or page" I can show the multiple gallery where I need it. But what if I would like to apply the gallery to multiple CPTs? CPT example: portfolio, products, machines, tools, posts, pages ... How should i do? is there a way to apply the "function property_gallery_add_metabox () - (GALLERY)" directly to multiple CPTs? post, page .. without having to create a new function with the same data?
How should you separate the part of function.php from that of the CSS and JS file? Example create separate files:
Script Gallery CSS Style JAVASCRIPT script Since the CSS / JS files are unique, I could have a core file of the gallery with multiple galleries (galleries 1, 2, 3) applied to multiple CPTs (post, page, CPT etc.) and the absolute reference to the css files unique / js.
I need to understand better how to get the url, size, caption, alt, title ... from the inserted image ...
I have noticed that many times it does not load the preview image in the post
And if we make a simple plug-in from these files to always keep it ready when needed?
This morning I noticed another problem: I am using the classic editor (both as a plug-in and using the script in function.php) When I activate the GALLERY script, the text field (classic editor) no longer works, everything I write when saving the page is not displayed in visual but works in the text editor and in the front-end. There are no problems with gutemberg blocks how is it resolved? (removing the gallery script, everything works normally)
akzhy
over 3 years ago
For the first part, you can use an array to show the gallery in multiple post types, eg:
["portfolio", "products", "machines", "tools", "posts"]
.For the script/css part, I don't fully understand what you want, but I am guessing that you are looking to move the scripts and styles from functions.php into their respective files. If that's the case then you can create separate files, and then use the admin_enqueue_scripts to load the js and css files.
To get the metadata of an image you can use the wp_get_attachment_image function.
As for the classic editor issue, I am not sure why it happens as I couldn't find any conflicting code, try disabling all other plugins and check.
Thijs
about 3 years ago
How can I make this work on a PHP 8 Wordpress Website? I'm getting a few warnings inside the dashboard.
james v
about 2 years ago
thank you tremendously! very helpful.
here's a full snippet of this working in my footer.php for others to reference
<?php // the query $the_query = new WP_Query( array( 'p' => '401', /used post ID here / 'post_type' => 'page', ) ); ?>
<?php if ( $the_query->have_posts() ) : ?>
<?php else : ?> <p><?php _e( 'Sorry, no posts matched your criteria.' ); ?></p> <?php endif; ?>
james v
about 2 years ago
<?php // the query $the_query = new WP_Query( array( 'p' => '401', 'post_type' => 'page', ) ); ?>
(didn't like my stars for php comment. used post ID versus page name)
lauren
almost 2 years ago
I have read your blog on Theme Options Page in WordPress.It was very interesting and helpful but I can add some extra points in your article. Here some extra points: 1.Create a new Menu for WordPress Theme Options. 2.Add Blank Page for new Menu. 3.Add and display custom sections to new Page. 4.Add Settings Field to Section. 5.Retrieve the Settings Field value. These are some extra points to add to your article. Readers if you are confused about your web and App development , you can get a free consultation at Alakmalak technologies.Visit our site for more information.