
Intermediate
This post covers WordPress, custom PHP, JavaScript, and HTML. Fundamentals of both JavaScript and PHP/WordPress is recommended.
There comes a time in a WordPress theme’s life where custom PHP is needed. This can be a packaged plugin that’s used across multiple client sites, or a single theme. There are several ways to approach a custom admin button. A common approach is invoking a JavaScript function on click, then using AJAX to send a request to a PHP file. Though this is a nice solution, there are alternative ways to approach it.
In this article, I go over how to utilize ACF to create button(s) on any field group that send POST data. The process is fairly straightforward, here are the steps:
- Decide the best place for the button
- Hook up a JavaScript file with your admin button
- On click, append your inputs with optional data
- In a PHP file, look at the
$_POST
array and perform your logic
From there, it’s up to you to add the logic you or your client wants. Setting it up is a multi-step process, but it’s not too much overhead and shouldn’t require any plugins. You technically don’t even need ACF to do this. However, I’ll use ACF as an example since it’s my favorite plugin. Let’s dig into it!
Where To Put The Admin Button(s)?
Technically, you can add buttons inside any <form>
element. You can even use it outside of a form since we’re using JavaScript to append the <input>
elements. Where you end up placing the button depends on usability. Will this button update a certain part of the site? Will it change how backend admin functionality works?
Let’s use an admin button that refreshes cached API data as an example. You want to refresh all testimonials on your site. I’m willing to bet you have a custom post type for it. If you have a field group for it too, you could add it there. If your button updates a single testimonial, just add it to each CPT field group. If it updates all testimonials, make a global options field under your Testimonials menu item.
If your button invokes general site-wide functionality, stick it in your global options page. At the end of the day, you should make it easier for whoever will actually be using it. It might be a client, and not you. Think about what would be easiest for them.
Introducing the ACF Message Field
If you haven’t heard of the message field already, it’s a great way to add instructions under any field group. While not the prettiest solution, you should be able to add markup to it.
For a simple button, this option provides a lot of flexibility for placement. A simple button will look like this:
<div id="refresh-button-container"> <button type="button" class="button-secondary" id="refresh-cache">Refresh Testimonial Data </button> </div>

Using the message field, you can add this markup under any defined field group. So the button is in place.. now what?
Linking JavaScript to Your Admin Page
In order for the button to do anything.. it needs to perform an action on click. This obviously requires JavaScript, so let’s set that up. Doing so isn’t difficult and is already documented here.
We can use admin_enqueue_scripts
to load a JavaScript file, but we only want to load it for the relevant admin page.
add_action( 'admin_enqueue_scripts', function ($hook) { //only load this script for a certain URL page slug if($hook == 'your-url-page-slug') { $path = asset_path('scripts/admin.js'); wp_enqueue_script( 'textdomain/custom-admin-js', $path, ['jquery']); } } );
Here’s what’s happening: We’re using the admin_enqueue_scripts
parameter $hook
to check which admin page to load the JavaScript. You can get a specific ACF page’s slug by checking the URL. It should be after the &page=
query parameter.
Once the conditional passes, simply enqueue the script like any other. I placed this in a file called admin.php
, but it can be loaded in your functions.php
file. You can also load it from your plugin files if you’re packaging this up into a separate plugin.
From your JS file, test to make sure everything is working.
import $ from 'jquery'; $(document).ready(function($) { console.log('Im working!'); });
Appending Data To Your Form Using JavaScript/jQuery
In the last example, we loaded the JavaScript file with jQuery as a dependency. However, this solution is simple enough to use vanilla JS, if preferred. From here, it’s a two step process.
- Add a click event listener to the admin button
- Attach hidden input fields to the ACF
<form>
element.
Here’s the code to accomplish this:
import $ from 'jquery'; $(document).ready(function($) { Admin.init(); }); let Admin = { init() { this.setEventListeners(); }, setEventListeners() { $('#refresh-cache').click(Admin.refreshCache); }, refreshCache() { //attach hidden input then submit the form Admin.attachData(); $('#post').submit(); }, attachData() { let $buttonContainer = $('#refresh-button-container'); let inputField = '<input type="hidden" name="refresh-cache" value="1" />'; $buttonContainer.append(inputField); }, }
This is a basic example and only attaches a single input. Yours may need multiple pieces of data, so you could simply attach more <input>
fields. Once the button is clicked, the JavaScript code will submit the form automatically. Once the form is submitted, the last step is to check the POST data that is sent through.
Processing POST Data in Your PHP Files
Where you perform PHP logic depends on your theme’s file structure. I’d recommend performing the logic in a separate file outside of functions.php
, or even in its own packaged plugin. However you do it, the process is pretty straightforward.
//Here, we're only checking if the POST data has been sent through //so we can outsource the logic to the refreshCache function if($_POST['refresh-cache'] == 1) { refreshCache(); }
If you’re passing multiple bits of data, you should be able to access it using the $_POST
array.
if($_POST['refresh-cache'] == 1) { $exampleArg1 = $_POST['example_data']; $exampleArg2 = $_POST['more_example_data']; refreshCache($exampleArg1, $exampleArg2); }
From there, what logic you implement is up to you. That’s pretty much it! Have fun, and make something awesome.
Very nicely described, thank you!
You are very welcome!