When to Build a Custom WordPress Plugin, and How to Do It
When a WordPress site needs behavior that should remain in place after a theme change, a custom plugin is often the right…
A WordPress plugin is code that WordPress loads to add or change site features. WordPress uses PHP, a programming language that runs on the web server. A plugin keeps custom features separate from WordPress core files, so a WordPress update does not overwrite your changes. The WordPress Plugin Handbook recommends plugins for adding functionality.
You can start with one PHP file. The example below creates a shortcode, a short piece of text in brackets that you place in a post or page to display content generated by the plugin. You will create the plugin, connect it to WordPress, activate and test it, then learn how to keep it secure as it grows.
Work on a test WordPress site rather than experimenting on a live site. If you do not have a local installation, WordPress Playground provides a browser-based way to test plugins.
Inside the WordPress installation, create a folder under wp-content/plugins, then add a PHP file:
wp-content/
└── plugins/
└── first-plugin/
└── first-plugin.php
WordPress identifies a plugin through a header comment in its main PHP file. Only one file in the plugin folder should contain that header. The plugin header documentation describes the required Plugin Name field and the optional fields for details such as version and description.
A hook is a named point in WordPress where plugin code can run or change data. An action hook lets a plugin run a function at a particular point. A filter hook lets a plugin modify data and return the changed value. add_action() and add_filter() register functions, called callbacks, for WordPress to run. The Hooks Handbook explains both types.
The shortcode example uses the init action, which runs as WordPress starts up. The callback registers the shortcode, and a second callback returns the content WordPress displays wherever the shortcode appears.
<?php
/*
* Plugin Name: First Plugin
* Description: Adds a simple greeting shortcode.
* Version: 1.0.0
* Text Domain: first-plugin
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
function first_plugin_register_shortcode() {
add_shortcode( 'first_greeting', 'first_plugin_render_greeting' );
}
add_action( 'init', 'first_plugin_register_shortcode' );
function first_plugin_render_greeting() {
return '<p>' . esc_html__( 'Hello from my plugin!', 'first-plugin' ) . '</p>';
}
The ABSPATH check stops someone from running this PHP file directly outside WordPress. The translation function esc_html__() returns translated text escaped for display inside HTML. The function returns a paragraph for WordPress to display. Shortcode callbacks provide content through a return value rather than printing it immediately.
Save the file, then open Plugins in the WordPress admin and activate First Plugin. Add [first_greeting] to a post or page and view that page to check the result.
When displaying data, escape it with a function suited to where it appears. For example, use esc_html() for text inside HTML, esc_attr() for an HTML attribute, and esc_url() for a URL. When you accept input, validate it against the rules your feature needs. If the value needs cleaning into an expected format, sanitize it. WordPress’s security guidance recommends validation when possible and escaping at output.
Before showing a settings screen or allowing another restricted action, check the user’s capabilities, which describe what that user is allowed to do. A nonce, a value used to help verify that a request came from an intended interaction, does not establish a user’s identity or permission. Use a nonce to verify request intent, then check capabilities to control access. WordPress documents that a default nonce is valid for 12 to 24 hours, but that time window does not make it an authorization check. See the wp_verify_nonce() reference.
The shortcode works without saving data. If you later need an administrator to configure its greeting, use WordPress’s Options API to store the setting and the Settings API to build the admin interface. These APIs provide standard ways to store options and handle settings forms.
Add lifecycle hooks when the plugin has setup or data to manage. An activation hook can create defaults or set up rewrite rules. A deactivation hook can clear temporary data, while an uninstall routine handles permanent cleanup when someone deletes the plugin. The lifecycle documentation distinguishes these events; deactivating a plugin should not automatically erase a user’s saved data.
After each change, activate the plugin and check the feature on a page where the shortcode appears. Also check a page without the shortcode and confirm the plugin produces no unwanted output or PHP errors. If the plugin accepts input, test expected values, empty values, and values in the wrong format. For privileged actions, verify that users without the required capability cannot perform them.
A single file suits a small plugin. As the code grows, separate related functions into files or directories. The WordPress plugin best practices recommend keeping the structure proportional to the plugin’s needs; add classes and folders only when they serve a purpose. For command-line work, WP-CLI plugin commands can check plugin status and manage activation.
Publishing to the WordPress.org Plugin Directory adds requirements beyond building a private plugin. Review the directory guidance before submitting; it covers licensing and packaging. A directory readme also has its own format and description rules, separate from the header in the main PHP file.
Give Vroni a GitHub issue, bug report, spec, or rough idea. It reads the repo, plans the change, writes code, runs checks, and works toward a review-ready pull request.
Take a look at vroni.com