Sometimes when you are working with snippets you'll encounter a scenario where you have a value in JavaScript that you want to pass back to a PHP function.

One possible solution to this issue is to make use of AJAX. This article is intended to be a basic example of how you might use AJAX within a snippet, though of course it's up to you whether AJAX is the best solution for your use case or not.

Handler function

The first step is to define our PHP function that we want to run when we receive the AJAX request. Here's an example:

const ACTION_NAME = 'shea_ajax_example';

$handler = function () {
	check_ajax_referer( ACTION_NAME );
	
	// do something with the $_POST data here

	wp_send_json_success( 'it works!' );
};

add_action( 'wp_ajax_' . ACTION_NAME, $handler );
add_action( 'wp_ajax_nopriv_' . ACTION_NAME, $handler );

As you can see, on the first line I am making a constant called ACTION_NAME and setting it to a string:

const ACTION_NAME = 'shea_ajax_example';

This is the name we're giving to our AJAX action, and we'll be reusing this constant throughout the example. You don't need a constant here – you can always just use a variable or manually repeat your chosen action name whenever you need it, but I am using a constant here for clarity's sake. It doesn't really matter what you name your AJAX action, just try to ensure it is unique to your current use case.

Next, we define the handler function. We're saving it to the $handler variable as it's the sort of function that doesn't need a name to be called by. Within the function, the first thing we do is check the AJAX referer, to make sure that this is actually a valid request:

check_ajax_referer( ACTION_NAME );

Once we have verified the request is valid, we can do whatever we need with the data stored in $_POST, or perform some other action. In this example, I am just jumping straight to the end where we use wp_send_json_success() to send some data back to the JavaScript code:

wp_send_json_success( 'it works!' );

This data can be whatever you want: some text, a number, even an object.

After defining the handler function, we finish up by attaching it to the relevant action hooks. This ensures that WordPress knows to call our function in response to our AJAX action.

add_action( 'wp_ajax_' . ACTION_NAME, $handler );
add_action( 'wp_ajax_nopriv_' . ACTION_NAME, $handler );

Adding a button

This next part is the simplest: we're just going to add a shortcode which displays a basic button. We're going to use this button to know when to send off the AJAX request in the next part. Here's the code:

add_shortcode( 'shea_ajax_button', function () {
	return '<button id="shea-ajax-button">Click me for AJAX</button>';
} );

The most important thing here is that our button has an id attribute. We'll use this value later to find the button on the page.

Once you've added this part, you'll need to go to a page or post and add in the [shea_ajax_button] shortcode where you want the button to display.

Sending the AJAX request

This part can be a little complicated. There'll be a lot of code at first, but we'll break it apart and explain each bit.

Essentially, we now need some JavaScript code which can respond to button presses and send off an AJAX request to our AJAX handler. Here's what that full code looks like:


add_action( 'wp_footer', function () {
	$data = [
		'ajaxurl' => admin_url( 'admin-ajax.php' ),
		'action'  => ACTION_NAME,
		'nonce'   => wp_create_nonce( ACTION_NAME ),
	];

	?>
	<script>
		const data = <?php echo wp_json_encode( $data ); ?>;
		const ajaxButton = document.getElementById('shea-ajax-button');

		ajaxButton.addEventListener('click', () => {
			const request = new XMLHttpRequest();
			request.open('POST', data.ajaxurl, true);
			request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

			request.onload = () => {				
				if (200 > request.status || 400 <= request.status) {
					alert('AJAX failure :( We received error code ' + request.status);
					return;
				}
				
				const response = JSON.parse(request.responseText)

				alert('AJAX success! Message: ' + response.data);
			};

			request.send(`action=${data.action}&_ajax_nonce=${data.nonce}`);
		});

	</script>

<?php } );

The code begins by adding an action hook to the `wp_footer` hook. This allows us to add some JavaScript code to the page footer, once everything else (including our button) has loaded.

Inside the hook and before we've output any JavaScript, we first define a $data variable. This variable contains everything we'll need in the JavaScript code, including the AJAX URL, a nonce value for security, and the name of our AJAX action.

$data = [
	'ajaxurl' => admin_url( 'admin-ajax.php' ),
	'action'  => ACTION_NAME,
	'nonce'   => wp_create_nonce( ACTION_NAME ),
];

Next, we start writing JavaScript code inside the <script> section. First, we turn our $data variable into actual JavaScript code:

const data = <?php echo wp_json_encode( $data ); ?>;

Next, we use the `shea-ajax-button` ID we used before to find our button on the page:

const ajaxButton = document.getElementById('shea-ajax-button');

Now can can use that ajaxButton variable to add an event listener so that we can perform an action when the button is clicked on:

ajaxButton.addEventListener('click', () => {
	// code goes here	
});

Within this, we're going to start writing our AJAX code. First, we just have some basic boilerplate setup:

const request = new XMLHttpRequest();
request.open('POST', data.ajaxurl, true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');

And then we define the function to run when we get a response back from the PHP code:

request.onload = () => {				
	// this code will run when we get a response back from PHP.
};

In this function, first we'll check whether our AJAX request succeded or not. You might have some proper error handling here, but for this example we're just going to have an alert window come up explaining what went wrong:

if (200 > request.status || 400 <= request.status) {
	alert('AJAX failure :( We received error code ' + request.status);
	return;
}

The return on the end there is important. It's what tells the function to stop there, seeing as there was an error, and not go on any further.

Otherwise, everything worked fine and we can go and do something with the response we got back. In this case, we're just displaying an alert window with the message we received from the PHP handler function:

const response = JSON.parse(request.responseText);
alert('AJAX success! Message: ' + response.data);

The only thing left to do now is actually send off the AJAX request. As the last thing in our button-click function we will call request.send, making sure to include both our AJAX action value and the nonce value, for security:

request.send(`action=${data.action}&_ajax_nonce=${data.nonce}`);

Conclusion

And there we have it! All together, the code should allow you to click on a button, sending an AJAX request to a PHP function, and then receive a response and do something with it.

You can also find the full snippet code on GitHub if you prefer a complete reference.