You are planning to write a brilliant plugin. Its’ got a form from which you collect data from the user and register them to your website

In your plugin, to generate the form, you are probably using a shortcode. When the user hits that submit button you’ve to submit that data to the server and register him. There are multiple ways to do this.

We will look at two of these methods, their merits and demerits.

Handling POST/GET data in WP Shortcode:

We can handle the submitted data in the shortcode’s callback function.
Example :
There is a shortcode for a registration page. The page has a form with its method attribute set to “POST”. It has an email and password field.
On submission, the form data is sent to the server. The same shortcode hook will be triggered because by default the form is submitted to the same page.
In the callback hook / method we can check if the post data ($_POST) is set and then process the data.

add_shortcode(‘printRegistrationForm’, ‘handleRegistrationForm’);

function handleRegistrationForm() {
 // Handling POST data, register button
 // is the name of the button in the form.
 if(isset($_POST[‘registerBtn’])) {
 $email = $_POST[‘email’];
 $pwd = $_POST[‘pwd’];
 // Do some very basic validation
 if(empty($email) || empty($pwd)) {
 $responseHtml = ‘Please provide the proper email and password’;
 $responseHtml = ‘Your ’.$email.’ Has been registered successfully’;
 return $html;
 $html = renderView('register-form.php');
 return $html;

function renderView($file) {
 return ob_get_clean();

We will render the form from the above function. The form will be present in our register-form.php. Think of it as a view / template file.

<form action="””" method="”POST”"><input name="”email”" type="”text”" />
<input name="”pwd’" type="”password”" />
<input name="”registerBtn”" type="submit" value="Submit" /></form>

In the above example the shortcode is handling the POST requests and sending the response.

Advantages in the above method:

• Displaying error messages in the form is easy in case of a validation error.
• Relatively easier to setup and develop.

Drawbacks in above method:

• We can’t redirect from the shortcode since by the time the shortcodes run, headers have already been sent to the browser.
• We can’t log the user in after they register, since that requires sending of Cookies which have to be sent along with the header.
• If there are many forms in the page, we need to check which form’s request was submitted.
• We can’t show response in another page (the only way is by echoing JavaScript to redirect to another page).

The admin_post and admin_ajax hooks

The admin_post hook

This hook allows you to create custom handlers for your own GET and POST form submissions and requests. The admin_post hook follows the format “admin_post_$youraction“, where $youraction is your GET or POST request’s ‘action’ parameter.

If you needed to create a request or form handler for an “my_plugin_register_user” action request, you would create a hook like this:

add_action('admin_post_my_plugin_register_user', 'handle_register_user');
 function handle_register_user() {
 // Handle request then generate response
 // by echoing PHP and using HTML.

The above hook will be triggered when we submit this registration form. Notice that we keep the action attribute in a hidden field, which will help WordPress route this function to our hook.

NOTE : The action of the form should be always admin-post.php. To echo the path of this file, we will admin_url() function. The path will be – http://{{your-website}}/wp-admin/admin-post.php

<form action="<?php echo admin_url('admin-post.php') ?>" method="post">
<input type="hidden" name="action" value="my_plugin_register_user">
<input type="text" name="email" value="">
<input type="password" name="pwd" value="password">
<?php echo wp_nonce_field('register-user', ‘_mynonce’); ?>
<input type="submit" value="Submit">

The email, password values can be accessed in the hook from $_GET, $_POST or $_REQUEST. If you want to redirect to login page on successful submission, we can do that in that in the hook.

In the above code we’ve also used something called nonce. WordPress nonces can help strengthen the security of the website.

The process is a fairly simple two-step affair:
1. Generate a nonce at the origin of an action (placing it in a link or as a hidden field in a form)
2. Validate it at the target.

To generate a nonce field we use wp_nonce_field. This will generate 2 hidden fields.

<input type="hidden" id="_mynonce" name="_mynonce" value="b29b766cf0">
<input type="hidden" name="_wp_http_referer" value="/register/">

The value of the 1st field will be generated using 1st parameter of the function. Here the 1st parameter is ‘register-user’. 2nd parameter will be the name of the hidden field.

function handle_register_user() {
 $email = $_POST[‘email’];
 $pwd = $_POST[‘pwd’];

// Verify if the nonce is valid
 if ( !isset($_POST['_mynonce']) || !wp_verify_nonce($_POST['_mynonce'], 'register-user’)) {
 // Do something if the nonce does not verify

// Store them in database.
 // If data inserted in db
 // If there is an error while inserting data to db

The nonce can be verified by wp_verify_nonce(). If the nonce is not valid, that means the action is not intended. We can handle it according to the context.

Handling logged in/non logged in users :

Using admin-post hook we can implement separate functionality for logged in and non-logged in user. We can register two different functions to trigger when the user is either logged in or not logged in. WordPress will determine at runtime whether the user is logged in and trigger the appropriate function.

add_action('admin_post_my_plugin_register_user', 'handle_register_user');
 // this next action version allows users
 // not logged in to submit requests
 add_action('admin_post_nopriv_my_plugin_register_user', 'handle_register_user');

If we did this in a shortcode we’d have to have a is_user_logged_in() check, but here WordPress takes care of it for us.

The admin_ajax hook

This hook allows you to create custom handlers for your own custom AJAX requests. It is similar in usage with the admin_post hooks. The wp_ajax hook follows the format “wp_ajax_$youraction“, where $youraction is your AJAX request’s ‘action’ property.

If you need to add an AJAX based handler for a “my_plugin_register_user” request, you would create a hook like this:

add_action('wp_ajax_my_plugin_register_user', 'handle_register_user');
 add_action('wp_ajax_nopriv_my_plugin_register_user', ‘handle_register_user');
 $params = array(
 'ajaxurl' => admin_url('admin-ajax.php'),
 'ajax_nonce' => wp_create_nonce('registerUser'),
 wp_localize_script('my_local_script', 'ajax_object', $params);

function handle_register_user() {
 // Check if nonce is valid
 check_ajax_referer('registerUser', 'security');

// Handle request then generate
 // response using WP_Ajax_Response

To make the AJAX call secure, we are using something called ajax_nonce. This will create a nonce for the AJAX call. We are localizing those values to use those in our script using wp_localize_script.

In the above function we used check_ajax_referer function to check if nonce is valid.
If the nonce is not set or incorrect, then check_ajax_referrer() will cause the AJAX call to die, protecting the AJAX call from invalid requests.

Using the above example, any time an AJAX request is sent to WordPress, and the request’s ‘action’ property is set to ‘register_user’, this hook will be automatically executed. For example, the following code would execute the above hook.
 'action': 'my_plugin_register_user',
 'email': '',
 ‘security’ : ajax_object.ajax_nonce,
 'pwd': 'password'
 alert('The server responded: ' + response);

The AJAX request can be handled by admin-ajax.php. The URL where the data should be submitted – http://{{your-website}}/wp-admin/admin-ajax.php

Advantages in the above method(s):

• Redirection to another page is possible.
• Can login the user in this hook, since headers have not yet been sent.
• Using individual actions for individual forms, it is easier to have a single page containing multiple forms.
• Comparatively faster since less processing happens and inputs are processed earlier in the WP page life cycle.
• Better separation of code.

Disadvantages in the above methods(s):

• Displaying error messages in case of validation errors is trickier than it is for shortcodes.

So, when to use what?

Although the two approaches can be used interchangeably, admin-post hooks were built by WordPress to handle form submissions. Shortcodes make sense when your plugin is small but if you intend to provide user login, perform redirections, set cookie’s then admin hooks are the way to go.

Our recommendation would be to use both, use the shortcodes to handle loading of the view, based on attributes passed by the user, whereas use the wp_action hooks to handle the data submitted by the user. This also introduces a nice separation of code, where the core business logic stays in the admin_post hook, whereas the view and view related logic is taken care by the shortcode.

Since your business logic is in the admin_hook, the view is in the shortcode and they both trigger as part of a different request, you’ll have to find a way to send errors with user submitted data from the admin_hook to the shortcode so that you can tell the user about them in the view. WordPress’ transients provide a way to handle this problem.

About the author:

Prasanna works at Osmosys as a PHP developer. She is a Computer Science Graduate from JNTU Vijayanagaram, with over 2 years of PHP and wordpress experience. You can find her on facebook @pulukurthi.prasanna