Getting your WordPress plugin approved on wp.org isn't just about submitting code and waiting. The review process is thorough—plugin reviewers examine security, code quality, compatibility, licensing, and adherence to WordPress standards. Understanding what reviewers look for and preparing your plugin accordingly dramatically increases your chances of first-time approval.
WordPress plugin review requirements exist to protect the WordPress community. With millions of WordPress sites and countless users relying on plugins from wp.org, the review team maintains high standards. Plugins that fail review often have preventable issues—incorrect readme.txt formatting, missing security checks, incompatible code, or licensing problems. This guide walks through every requirement, provides a complete checklist, and shows you how to prepare your plugin for successful approval.
The wp.org plugin directory serves as a distribution channel for hundreds of thousands of WordPress plugins. Site administrators rely on the directory as a trusted source for extending WordPress functionality. This trust depends on the review team maintaining high security and quality standards. A single widely-installed vulnerable plugin can compromise millions of sites. This enormous potential impact justifies the thorough review process and the strict standards the team maintains.
The review process is also an investment in the WordPress ecosystem as a whole. Plugins that follow best practices are more maintainable, more compatible, and more secure. By requiring plugins to meet standards, the review team improves the entire ecosystem's quality. As a plugin developer, the review process isn't a barrier to overcome—it's an investment in building a better plugin that serves users well.
Table of Contents
- Understanding the WordPress Plugin Review Process
- Security Requirements and Best Practices
- README.txt Format and Requirements
- Licensing and Copyright Compliance
- Prohibited Practices and Rejected Patterns
- Code Quality and WordPress Standards
- Compatibility and Testing Requirements
- Complete Pre-Submission Checklist
- Frequently Asked Questions
Understanding the WordPress Plugin Review Process
The WordPress plugin review team uses automated tools and manual human review to assess each plugin submission. Understanding their workflow helps you prepare more effectively.
When you submit a plugin to wp.org, an automated system first checks for common issues: readme.txt format, basic security problems, and obvious violations. Then, human reviewers examine your code for security vulnerabilities, WordPress compliance, user experience, and standards adherence.
The review process typically takes 5-10 business days, though it can be faster or slower depending on queue times and the complexity of your plugin. If your plugin receives feedback, you have 30 days to address it before it's rejected. If rejected, you can resubmit after making corrections.
Common reasons for rejection include:
- Insufficient security measures (missing nonce verification, lack of capability checks, SQL injection vulnerabilities)
- Improper readme.txt formatting
- Licensing conflicts (GPL compatibility issues)
- Code quality problems (deprecated functions, outdated patterns)
- Using unslashed data (accessing $_POST directly without wp_unslash)
- Prohibited practices (adding admin menus without proper structure, external network requests without user consent)
- Insufficient documentation or vague descriptions
Security Requirements and Best Practices
Security is the primary focus of plugin review. Your plugin will be thoroughly examined for common WordPress vulnerabilities.
Nonce Verification: Every form submission and AJAX request must include nonce verification:
// In your form or AJAX request
wp_nonce_field( 'my_plugin_nonce_action', 'my_plugin_nonce' );
// In your handler
check_admin_referer( 'my_plugin_nonce_action', 'my_plugin_nonce' );
Capability Checks: Always verify that the current user has permission to perform the action:
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( 'Insufficient permissions' );
}
// For different user roles
if ( ! current_user_can( 'edit_posts' ) ) {
wp_die( 'You cannot perform this action' );
}
Data Sanitization: Sanitize all input before processing or storing:
$user_input = sanitize_text_field( $_POST['user_input'] );
$email = sanitize_email( $_POST['email'] );
$post_id = absint( $_GET['post_id'] );
// For HTML content
$content = wp_kses_post( $_POST['content'] );
Escaping Output: Always escape data before displaying:
// For HTML content
echo wp_kses_post( $content );
// For HTML attributes
echo 'value="' . esc_attr( $value ) . '"';
// For URLs
echo 'href="' . esc_url( $url ) . '"';
// For JavaScript
echo 'data-id="' . intval( $id ) . '"';
Use wp_unslash() for slashed data:
// WordPress automatically adds slashes to $_POST, $_GET, etc.
// Remove them before processing
$unslashed_data = wp_unslash( $_POST['data'] );
$clean_data = sanitize_text_field( $unslashed_data );
Avoid accessing super globals directly: Use proper WordPress functions:
// Wrong
$post_data = $_POST['key'];
// Right
$post_data = isset( $_POST['key'] ) ? wp_unslash( $_POST['key'] ) : '';
$clean_data = sanitize_text_field( $post_data );
Database queries must use prepared statements:
global $wpdb;
// Wrong: Vulnerable to SQL injection
$user_data = $wpdb->get_results( "SELECT * FROM {$wpdb->users} WHERE user_login = '{$_POST['login']}'" );
// Right: Using prepared statements
$user_data = $wpdb->get_results( $wpdb->prepare(
"SELECT * FROM {$wpdb->users} WHERE user_login = %s",
sanitize_text_field( $_POST['login'] )
) );
Use proper REST API authentication:
register_rest_route(
'my-plugin/v1',
'/action',
array(
'methods' => 'POST',
'callback' => 'my_callback',
'permission_callback' => function() {
return current_user_can( 'manage_options' );
},
)
);
README.txt Format and Requirements
Your plugin's readme.txt file is critical for wp.org approval. It must follow a strict format or your plugin will be rejected without human review.
The readme.txt file uses a specific structure. Here's a template:
=== Plugin Name ===
Contributors: username1, username2
Tags: tag1, tag2, tag3, tag4, tag5
Requires at least: 5.0
Tested up to: 6.4
Stable tag: 1.0.0
License: GPL v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Short description of what your plugin does in 1-2 sentences.
== Description ==
Longer description of your plugin. Explain what it does, how to use it, and why users would want it. This can be 2-3 paragraphs.
Key features:
* Feature one
* Feature two
* Feature three
== Installation ==
1. Upload the plugin files to the `/wp-content/plugins/plugin-name/` directory, or install the plugin through the WordPress plugins screen directly.
2. Activate the plugin through the 'Plugins' screen in WordPress.
3. Use the Settings > Plugin Name screen to configure the plugin.
== Frequently Asked Questions ==
= How do I use this plugin? =
Explain how to use your plugin.
= What are the system requirements? =
List your system requirements.
== Screenshots ==
1. Dashboard overview - Shows the main settings screen
2. Results view - Displays processed data
== Changelog ==
= 1.0.0 =
* Initial release
== Upgrade Notice ==
= 1.0.0 =
Initial plugin release.
Critical formatting rules:
- Section headers must be exact (== Section Name ==)
- The first line is === Plugin Name === (three equal signs)
- Contributors line uses WordPress.org usernames
- Tags should be lowercase and comma-separated (max 5 tags)
- Tested up to should be the latest WordPress version you've tested with
- License must be GPL v2 or later (or compatible)
- Screenshots are optional but recommended
- Changelog is required
Example of proper header:
=== My Awesome Plugin ===
Contributors: myusername, coauthor
Tags: security, optimization, utilities, admin-tools, monitoring
Requires at least: 5.7
Requires PHP: 7.4
Tested up to: 6.4
Stable tag: 2.1.3
License: GPL v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
My plugin does amazing things for WordPress site owners.
Licensing and Copyright Compliance
WordPress.org requires all plugins to use GPL-compatible licenses. GPL v2 or later is the standard choice for WordPress plugins.
GPL-compatible licenses include:
- GPL v2 or later
- GPL v3 or later
- AGPL v3 or later
- MIT License
- Apache 2.0
Incompatible licenses (will be rejected):
- Proprietary/Closed source
- Commercial licenses
- Licenses that restrict modification or redistribution
Include a license header in your main plugin file:
<?php
/**
* Plugin Name: My Awesome Plugin
* Plugin URI: https://example.com/my-plugin
* Description: Brief description of what the plugin does
* Version: 1.0.0
* Author: Your Name
* Author URI: https://example.com
* License: GPL v2 or later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: my-awesome-plugin
* Domain Path: /languages
* Requires at least: 5.7
* Requires PHP: 7.4
*/
If you include third-party code or libraries, include their licenses in a LICENSES folder or note them in your main file. Ensure all dependencies are GPL-compatible.
Prohibited Practices and Rejected Patterns
Certain practices automatically result in rejection. Understanding these prevents wasted effort.
Phone Home: Your plugin must not send data to external servers without user consent and clear documentation:
// Wrong: Silently calling external API
function my_plugin_check_for_updates() {
wp_remote_post( 'https://example.com/check', array() );
}
add_action( 'admin_init', 'my_plugin_check_for_updates' );
// Right: Only with explicit user action
if ( isset( $_POST['check_updates'] ) ) {
check_admin_referer( 'my_nonce' );
wp_remote_post( 'https://example.com/check', array() );
}
Hiding Functionality: Don't obfuscate code or hide what your plugin does:
// Wrong: Obfuscated code
eval( base64_decode( 'some_encoded_string' ) );
// Right: Clear, readable code
// Include necessary functionality with clear variable names
Deceptive Practices: Don't claim features you don't have or misrepresent functionality.
Admin Menu Structure: Follow WordPress conventions:
// Wrong: Creating menus in unexpected places
add_menu_page( 'My Plugin', 'My Plugin', 'manage_options', 'my-plugin', 'render_page' );
// Right: Proper menu structure with icons and correct positioning
add_menu_page(
'My Plugin Settings',
'My Plugin',
'manage_options',
'my-plugin',
'render_page',
'dashicons-admin-tools',
65
);
No Auto-Updates: Don't install your own update mechanism if your plugin is on wp.org. WordPress handles updates automatically.
No Tracking: Don't collect user data without explicit consent.
No Cryptocurrency/NFT: Plugins for mining, buying, selling, or managing cryptocurrency/NFTs are not permitted.
No Reserved Names: Don't use names that conflict with WordPress core functions or widely-used plugins.
Code Quality and WordPress Standards
Plugin reviewers check for code quality and adherence to WordPress coding standards.
Use WordPress coding standards: WordPress has official coding standards for PHP, HTML, and JavaScript.
Avoid deprecated functions: Check that you're not using functions marked as deprecated:
// Wrong: Using deprecated function
global $wp_version;
if ( $wp_version < '5.0' ) {
// Old code
}
// Right: Using is_wp_version_compatible()
if ( is_wp_version_compatible( '5.0' ) ) {
// Modern code
}
Use proper hooks: Leverage WordPress actions and filters rather than modifying core behavior:
// Right: Using hooks for customization
add_action( 'the_content', 'my_plugin_modify_content' );
add_filter( 'post_type_labels_post', 'my_plugin_change_label' );
Translation readiness: Make your plugin translatable:
// Wrong: Hardcoded strings
echo 'Welcome to my plugin';
// Right: Using translation functions
echo __( 'Welcome to my plugin', 'my-plugin-textdomain' );
// In README.txt
Text Domain: my-plugin-textdomain
Domain Path: /languages
Use proper hooks for admin pages:
// Wrong: Creating options without proper structure
add_menu_page( 'Settings', 'Settings', 'manage_options', 'my-plugin' );
// Right: Proper settings page with sections and fields
add_settings_section();
add_settings_field();
register_setting();
Compatibility and Testing Requirements
Your plugin must be tested and compatible with current WordPress versions.
Test with current WordPress: The "Tested up to" field in readme.txt should match the latest WordPress release you've tested with. You should regularly test your plugin with new WordPress releases.
PHP version compatibility: Specify your minimum PHP version in the readme.txt:
Requires PHP: 7.4
Check for conflicts: Test your plugin with popular plugins to ensure no conflicts:
- WooCommerce (if relevant)
- Yoast SEO
- Jetpack
- Contact Form 7
- Elementor (if relevant)
Test on multiple themes: Ensure your plugin works with various themes, especially:
- Twenty Twenty-Four (latest default theme)
- Popular commercial themes
- Your own theme
Performance considerations:
- Use proper caching for expensive operations
- Avoid running heavy code on every page load
- Use scheduled actions (wp-cron) for background tasks
// Wrong: Heavy processing on every page
add_action( 'wp_footer', 'process_all_posts' );
// Right: Using wp-cron for background tasks
register_activation_hook( __FILE__, function() {
wp_schedule_event( time(), 'hourly', 'my_plugin_hourly_task' );
} );
add_action( 'my_plugin_hourly_task', 'process_all_posts' );
Complete Pre-Submission Checklist
Before submitting to wp.org, systematically verify every item:
Security (CRITICAL)
- All user input sanitized (text, email, URLs, numbers)
- All output properly escaped (HTML, attributes, URLs, JavaScript)
- Nonce verification on all forms and AJAX requests
- Capability checks before performing actions
- Database queries use prepared statements
- No direct access to $_POST, $_GET without wp_unslash()
- No hardcoded credentials or API keys
- CSRF protection implemented
- XSS prevention implemented
- SQL injection prevention implemented
Code Quality
- Follow WordPress coding standards
- No deprecated functions used
- Comments explain complex logic
- Proper error handling and logging
- No obfuscated or encoded code
- Proper use of hooks and filters
Functionality
- Plugin performs as described
- No unintended side effects
- Proper error messages for users
- Documentation for features
README.txt
- Proper section headers (==, ===)
- Description clearly explains functionality
- Installation instructions included
- FAQ section with common questions
- Proper tags (5 or fewer, relevant)
- License set to GPL v2 or later
- Contributors listed correctly
- Screenshots included (recommended)
- Changelog with version history
Plugin File Header
- Plugin Name clearly specified
- Description provided
- Version number included
- Author/Author URI included
- License and License URI proper
- Text Domain matches plugin slug
- Domain Path for translations
- Requires at least specified
- Requires PHP specified
Licensing
- All code is GPL v2 or compatible
- Third-party libraries are GPL-compatible
- Copyright notices included
- No proprietary or restricted licenses
Compatibility
- Tested with latest WordPress version
- Tested with PHP versions back to your minimum
- Tested with popular plugins
- Tested with default themes
- No conflicts with WordPress core
- Mobile responsive if applicable
Performance
- No unnecessary database queries
- Appropriate use of caching
- Background tasks use wp-cron
- Load times acceptable
Use WP HealthKit for automated verification: WP HealthKit scans plugins for hundreds of security issues, deprecated patterns, and quality problems that plugin reviewers check. Upload your plugin before submitting to wp.org to catch issues early.
Frequently Asked Questions
How long does plugin review typically take?
The WordPress plugin review team aims to review submissions within 5-10 business days. However, during periods of high volume or with complex plugins, it can take longer. Simple, well-prepared plugins often receive faster review.
Can I resubmit immediately after rejection?
You can resubmit after addressing the feedback. You have 30 days to respond to reviewer comments. After 30 days without response, your submission expires and you must resubmit.
What if I disagree with reviewer feedback?
You can reply to the reviewer's comments with your reasoning. However, the final decision rests with the review team. Focus on meeting their requirements rather than arguing.
Do I need to use a specific plugin boilerplate or starter template?
No. WordPress doesn't require any particular template. Use whatever structure works for you—just ensure it follows coding standards and security requirements.
Can I include ads or promotional content in my plugin?
You can link to your website and mention your services, but intrusive ads or aggressive promotional content will be rejected. Keep it professional and minimal.
What about pre-release or beta versions?
You can submit beta versions, but they must be stable enough for general use. Mark them clearly in your version numbering (e.g., 1.0.0-beta) and ensure they meet all approval requirements.
Can I sell versions of my plugin separately if it's free on wp.org?
No. If your plugin is on wp.org (free), you can't sell premium versions of the same plugin. You can offer premium add-ons or extensions, but not the base plugin.
How do I know if my plugin will pass security review?
Use WP HealthKit to scan your plugin before submission. It checks the same security patterns and vulnerabilities that plugin reviewers examine manually.
Can I use external JavaScript/CSS libraries?
Yes, but they must be properly enqueued and GPL-compatible. Load them with wp_enqueue_script() and wp_enqueue_style() to ensure proper version management.
What's the best way to handle plugin updates after approval?
Use the standard WordPress plugin update mechanism. When you update your plugin, increment the version number in both the main file and readme.txt, then commit to wp.org. The update will be automatically available to users.
Conclusion
Preparing your plugin for wp.org approval requires attention to detail and understanding WordPress standards. The most critical requirements are security (nonces, capability checks, sanitization), proper readme.txt formatting, GPL-compatible licensing, and adherence to WordPress coding standards.
The best strategy is comprehensive pre-submission verification. Use this checklist systematically. Better yet, use WP HealthKit to audit your plugin automatically before submitting. Upload your plugin to WP HealthKit to catch security vulnerabilities, deprecated patterns, and quality issues that plugin reviewers will examine. This dramatically increases your chances of first-time approval.
For detailed guidance, consult the WordPress Plugin Review Guidelines and the WordPress Plugin Handbook. You might also find our guides on PHPCS WordPress Coding Standards and other security resources in WP HealthKit's plugin directory and ecosystem helpful.
Good luck with your plugin submission! Following these requirements ensures you build plugins the WordPress community can trust.