Independent Editorial DeskWordPress Releases, Builds, and Operations
Back to Archive
Implementation Notes

WordPress admin_post Example: Handle Custom Form Submission Safely

Use admin-post.php for secure WordPress form handling with nonce checks, capability gates, sanitization, and safe redirects.

Published

April 24, 2026

Reading Time

2 min read

Updated

April 24, 2026

WordPress admin form flowing into a secure admin_post handler.
Build PatternImplementation Notes

Implementation Notes

Extension points, code paths, and implementation choices that should survive contact with production.

Best For

WordPress developers, agencies, and technical teams building custom plugin or theme functionality with cleaner operational defaults.

Primary Topics

Implementation Notes

Editorial Focus

Build Pattern: Extension points, code paths, and implementation choices that should survive contact with production. Updated on April 24, 2026.

Full Report

Last reviewed: April 24, 2026

Not every WordPress form needs AJAX or a custom REST endpoint. For many back-office workflows, a direct request to wp-admin/admin-post.php is the simplest and safest route because WordPress already gives you a handler entry point, authenticated routing, and a predictable redirect pattern.

This guide shows how to build a custom admin form handler with admin_post_{$action}, a nonce, strict capability checks, sanitized input, and a safe redirect back to the UI.

Build the form

<form action=\"<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>\" method=\"post\">
	<input type=\"hidden\" name=\"action\" value=\"vulnwp_save_notice\" />
	<?php wp_nonce_field( 'vulnwp_save_notice_action', 'vulnwp_notice_nonce' ); ?>

	<label for=\"vulnwp-notice-text\">Homepage notice</label>
	<input id=\"vulnwp-notice-text\" type=\"text\" name=\"notice_text\" value=\"\" class=\"regular-text\" />

	<?php submit_button( __( 'Save notice', 'vulnwp' ) ); ?>
</form>

The hidden action value is the router key. WordPress turns that value into the hook name that receives the request.

Register the handler

<?php
add_action( 'admin_post_vulnwp_save_notice', 'vulnwp_handle_notice_form' );

function vulnwp_handle_notice_form() {
	if ( ! current_user_can( 'manage_options' ) ) {
		wp_die( esc_html__( 'You are not allowed to perform this action.', 'vulnwp' ), 403 );
	}

	if ( ! isset( $_POST['vulnwp_notice_nonce'] ) ) {
		wp_die( esc_html__( 'Missing security token.', 'vulnwp' ), 400 );
	}

	if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['vulnwp_notice_nonce'] ) ), 'vulnwp_save_notice_action' ) ) {
		wp_die( esc_html__( 'Invalid security token.', 'vulnwp' ), 403 );
	}

	$notice = isset( $_POST['notice_text'] )
		? sanitize_text_field( wp_unslash( $_POST['notice_text'] ) )
		: '';

	update_option( 'vulnwp_home_notice', $notice, false );

	$redirect = add_query_arg(
		array(
			'page'    => 'vulnwp-settings',
			'updated' => '1',
		),
		admin_url( 'options-general.php' )
	);

	wp_safe_redirect( $redirect );
	exit;
}

The handler exits after the redirect. That matters because WordPress does not stop execution automatically after a redirect header is sent.

Public forms need the non-privileged hook too

If a form should accept requests from users who are not logged in, register both the authenticated and unauthenticated actions. Then apply your own validation model carefully, because there is no user session to rely on.

add_action( 'admin_post_nopriv_vulnwp_capture_signup', 'vulnwp_capture_signup' );
add_action( 'admin_post_vulnwp_capture_signup', 'vulnwp_capture_signup' );

Do not add the nopriv version unless it is truly needed. A public handler expands the attack surface immediately.

When to use admin-post instead of REST or AJAX

  • Use admin-post.php for simple form submissions and redirect-based admin flows.
  • Use REST when the caller expects structured JSON responses.
  • Use admin AJAX when you need legacy asynchronous behavior inside wp-admin.

Production checklist

  1. Keep the action name prefixed. Hook collisions are avoidable.
  2. Check the exact capability needed. Do not over-grant access.
  3. Verify the nonce before reading request data deeply.
  4. Sanitize every field. Each input type needs an explicit rule.
  5. Redirect with wp_safe_redirect() and exit.

Common mistakes

  • Forgetting the hidden action field. The handler will never fire.
  • No nonce. Authenticated forms still need CSRF protection.
  • Using manage_options everywhere. Many handlers need a narrower capability.
  • Returning raw output instead of redirecting the user. Admin flows become inconsistent fast.
  • Adding a public handler accidentally. admin_post_nopriv_* should be a deliberate choice.

Related reading

If the form changes site settings, pair this with the Settings API example. For redirect hygiene after the handler completes, read the wp_safe_redirect guide.

References and further reading

Popular Guides

Popular WordPress guides to read next.

These articles connect recurring production concerns: implementation details, updates, troubleshooting, recovery paths, and operational cleanup.

Continue Reading

More from the archive.

Diagnostic dashboard scene representing a WordPress Site Health review before major updates.
01Build Pattern
Implementation Notes

Build Pattern

Extension points, code paths, and implementation choices that should survive contact with production.

May 21, 2026 · 3 min read

WordPress Site Health Check Before Major Updates: What to Review First

A pre-update WordPress Site Health checklist covering loopbacks, connectivity, debug settings, and environment readiness.

Structured data and route review scene representing permalink validation after a WordPress migration.
02Build Pattern
Implementation Notes

Build Pattern

Extension points, code paths, and implementation choices that should survive contact with production.

May 21, 2026 · 3 min read

WordPress Permalink Checklist After Migration: Catch URL Problems Early

A post-migration WordPress permalink checklist for checking rewrite rules, post URLs, archives, and redirect noise.

Technical media workspace representing image preparation and optimization before upload to WordPress.
03Build Pattern
Implementation Notes

Build Pattern

Extension points, code paths, and implementation choices that should survive contact with production.

May 21, 2026 · 3 min read

WordPress Image Optimization Checklist: What to Fix Before Upload

A practical WordPress image optimization checklist covering dimensions, compression, formats, and Media settings before upload.