How to Create a Custom WordPress Plugin: A Practical Tutorial

A custom plugin is the right place for WordPress functionality that should remain available when the site’s theme changes. Instead of modifying theme files or WordPress core, you can keep a feature in its own portable, maintainable package.

In this tutorial, you will build a small plugin that adds a business notice shortcode. The example is intentionally simple, but it introduces the same building blocks used in larger plugins: a plugin header, hooks, shortcode attributes, sanitization, and escaped output.

Why Put Custom Functionality in a Plugin?

Adding code to a theme’s functions.php file can be convenient for a quick experiment, but that code is tied to the active theme. Change the theme and the feature may disappear.

A plugin separates functionality from presentation. You can activate or deactivate it independently, move it to another site, and continue using it after a redesign. WordPress plugins connect to the platform through hooks:

  • Actions run your code at a particular point in WordPress’s execution.
  • Filters let you modify a value before WordPress uses or displays it.

This hook-based approach also avoids editing WordPress core files, which may be replaced during updates.

For larger projects, see our guide to WordPress plugin development and why it matters.

What You Need Before You Start

A small plugin does not require a complex development setup. Prepare the following:

  • A WordPress installation, ideally on a local or staging site.
  • Access to the wp-content/plugins directory.
  • A code editor such as Visual Studio Code, Notepad++, or another PHP editor.
  • Basic familiarity with PHP, HTML, and WordPress functions.

Do not test unfamiliar PHP directly on a busy production site. Create a backup and use staging or a local installation first. A syntax error can make the dashboard or front end unavailable until the faulty code is removed.

Step 1: Create the Plugin Folder

Open your WordPress installation and go to:

wp-content/plugins/

Create a folder with a distinctive name:

business-notice

Inside it, create the main plugin file:

business-notice.php

Choosing a reasonably unique folder and file name reduces the chance of conflicts with another plugin.

Step 2: Add a WordPress Plugin Header

Open business-notice.php and add the following header:

<?php
/**
 * Plugin Name: Business Notice
 * Plugin URI: https://example.com/
 * Description: Adds a simple business notice shortcode to WordPress.
 * Version: 1.0.0
 * Author: Your Name
 * License: GPL-2.0-or-later
 */

WordPress reads this comment to identify the plugin on the Plugins screen. The file must include a valid Plugin Name, and the PHP opening tag should be the first content in the file.

Replace the example URL and author name with details appropriate to your project. If you distribute the plugin, also review the license requirements for any third-party code it includes.

Step 3: Block Direct File Access

Add this check below the header:

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

WordPress defines ABSPATH while loading the application. If someone tries to request the plugin file directly instead, the script exits without running its code.

Step 4: Build a Shortcode

Next, create a function that returns a notice. This version accepts a message and a background color as shortcode attributes:

function bn_business_notice( $atts ) {
    $atts = shortcode_atts(
        array(
            'message' => 'Thank you for visiting our website.',
            'color'   => '#eef6ff',
        ),
        $atts,
        'business_notice'
    );

    $message = sanitize_text_field( $atts['message'] );
    $color   = sanitize_hex_color( $atts['color'] );

    if ( ! $color ) {
        $color = '#eef6ff';
    }

    return '<div style="background:' . esc_attr( $color ) . ';padding:15px;margin:15px 0;">'
        . esc_html( $message )
        . '</div>';
}

add_shortcode( 'business_notice', 'bn_business_notice' );

shortcode_atts() supplies defaults when an attribute is missing. The code then sanitizes the incoming values and escapes them in the returned HTML. Sanitization prepares data for use; escaping protects the output in its display context.

The bn_ prefix is intentional. Prefixing functions, options, and hooks helps reduce naming collisions with WordPress core and other plugins.

Step 5: Add the Shortcode to a Page

Save the file, then activate the plugin from Plugins > Installed Plugins. Add the shortcode to a post, page, widget, or compatible block:

[business_notice]

To provide a custom message and color, use:

[business_notice message="Book a free consultation today." color="#fff4cc"]

Shortcodes work well for small, reusable features. A custom block may be a better choice when editors need a richer interface, live previews, or structured content controls.

Step 6: Add Activation and Deactivation Hooks

Activation and deactivation hooks are useful when a plugin needs to create default options, register rewrite rules, or remove temporary data.

function bn_activate_plugin() {
    add_option( 'bn_default_message', 'Thank you for visiting our website.' );
}
register_activation_hook( __FILE__, 'bn_activate_plugin' );

function bn_deactivate_plugin() {
    // Remove temporary data here if your plugin creates any.
}
register_deactivation_hook( __FILE__, 'bn_deactivate_plugin' );

Deactivation does not necessarily mean the site owner wants all plugin data deleted. Keep durable settings unless removal is explicitly intended. For permanent cleanup, add an uninstall routine and document what it removes.

Security Practices for Custom Plugins

Security decisions belong in the first version of a plugin, not only after it grows.

  • Check capabilities: Use functions such as current_user_can() before processing administrative actions.
  • Use nonces: Nonces help verify that requests came through an expected WordPress form or workflow. They do not replace permission checks.
  • Sanitize input: Choose a function suited to the value, such as sanitize_text_field(), sanitize_email(), or sanitize_key().
  • Escape output: Use esc_html(), esc_attr(), esc_url(), or another context-appropriate escaping function.
  • Prefer WordPress APIs: When a custom database query is necessary, prepare it with $wpdb->prepare().

For broader site-hardening ideas, read our guide to securing WordPress without using plugins.

When to Add a Settings Page

A settings page makes sense when site owners need to change values such as email addresses, API keys, display preferences, or automation rules. Use the WordPress Settings API to register options, fields, validation, and permissions within the normal administration system.

Not every plugin needs a settings screen. If a feature has one stable value or only a single shortcode attribute, adding an administration interface may create more maintenance work than it solves.

Testing and Troubleshooting

Test the plugin before relying on it for a live site. Check ordinary and edge-case inputs, including empty values, unusual characters, invalid colors, and long messages. Also test the feature with different user roles and alongside the other active plugins.

Verify that activation, deactivation, updates, and removal behave as intended. If the site reports a critical error, use a safe environment and inspect the PHP error log. Our guide to solving WordPress fatal errors covers common troubleshooting steps.

As the plugin expands, separate responsibilities into files and folders such as includes, admin, public, and assets. Keep names consistently prefixed, and document hooks, settings, and setup requirements so another developer can maintain the project.

Frequently Asked Questions

Can I create a WordPress plugin without coding experience?

You can assemble a very small plugin by following an example, but basic PHP and WordPress knowledge will help you adapt it safely and diagnose errors. Avoid copying code you cannot review when the plugin handles important site data.

Should custom functionality go in a plugin or the theme?

Use a plugin for functionality that should survive a theme change. Keep visual presentation and design-specific behavior in the theme when those features have no value outside that design.

Can I install a custom plugin on multiple websites?

Yes. You can package the plugin folder as a ZIP file and upload it through Plugins > Add New > Upload Plugin. Confirm that the plugin and any bundled libraries are properly licensed before distributing it.

When should I hire a developer?

Professional help is sensible when the plugin handles payments, personal or customer data, external APIs, scheduled tasks, complex database operations, or business-critical automation.

Conclusion

A basic WordPress plugin can start with one folder, one PHP file, and a focused feature. From there, hooks, shortcodes, settings, and WordPress APIs provide a path toward more capable functionality.

Build incrementally, validate incoming data, escape output, test away from production, and keep the plugin separate from the theme. Those habits make custom code easier to maintain as the site develops.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top