Close Menu
GeekBlog

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    What's Hot

    Miami Will Let Rockstar Turn Downtown Into Vice City. The Fine Print Runs to Six Banners and a Deadline.

    September 24, 2026

    Apple Watch Series 12 Takes Aim at WHOOP and Oura With Always-On Heart Tracking

    September 24, 2026

    DoorDash Owes 264,000 Dashers $131.5 Million. Most of It Is an Argument About Waiting Around.

    September 24, 2026
    Facebook X (Twitter) Instagram Threads
    GeekBlog
    • Home
    • Mobile
    • Tech News
    • Blog
    • Gaming
    • Smartwatch
    • How-To Guides
    • AI & Software
    Facebook
    GeekBlog
    Home»Blog»How to Create a WordPress Plugin: Beginner Tutorial
    Blog

    How to Create a WordPress Plugin: Beginner Tutorial

    Ethan CaldwellBy Ethan CaldwellSeptember 4, 202611 Mins Read
    Share Facebook Twitter Pinterest LinkedIn Tumblr Email Copy Link
    Share
    Facebook Twitter LinkedIn Pinterest Email Copy Link

    Creating a WordPress plugin takes one folder, one PHP file, and a comment block at the top of that file. WordPress reads the comment block, lists your plugin on the Plugins screen, and once you activate it your code runs on every request. Everything after that is a question of choosing the right hook and writing code that cannot be abused.

    Quick answer: Make a folder inside wp-content/plugins/, add a PHP file with the same name, paste a plugin header comment into it containing at least a Plugin Name: line, then activate it under Plugins in the admin. Add behavior with add_action() and add_filter(), block direct file access with a defined( 'ABSPATH' ) check, and verify every form submission with a nonce before you save anything.

    This tutorial builds a tiny but complete plugin called GB Notice Bar. It stores one setting, prints a message in the site footer, cleans up after itself, and does all of that with the security checks that reviewers and security scanners expect. The current release line is WordPress 7.1, and everything below works on WordPress 6.5 and later. If you do not have a test site yet, set one up locally first using our guide to installing WordPress on a local host, because you do not want your first plugin experiments touching a live site.

    What a plugin really is

    A plugin is a folder of PHP that WordPress loads on every page request, after the core files and before the theme. It has no special powers a theme lacks. What it has is a lifecycle: it can be activated, deactivated, and deleted independently of the design, and it survives theme changes. That is why anything that is behavior rather than presentation belongs in a plugin.

    Plugins hook into WordPress rather than editing it. WordPress fires named events (actions) and passes values through named filters, and your plugin attaches callbacks to those names. You never modify a core file. Here are the hooks a first plugin usually needs.

    HookTypeFires whenTypical use
    initActionWordPress is loaded, user is knownRegister post types, taxonomies, shortcodes
    admin_menuActionAdmin menu is being builtAdd a settings screen
    admin_initActionAny admin request startsRegister settings, run admin only checks
    wp_enqueue_scriptsActionFront end assets are queuedLoad your CSS and JavaScript
    the_contentFilterPost body is about to printAppend or modify post output
    wp_footerActionJust before </body>Inject markup at the end of the page

    Create the folder and the plugin header

    Every plugin lives in its own directory, and the convention is that the main file matches the directory name. Create wp-content/plugins/gb-notice-bar/gb-notice-bar.php. Pick a slug that nobody else is likely to use, because the slug becomes your namespace on WordPress.org later.

    <?php
    /**
     * Plugin Name:       GB Notice Bar
     * Plugin URI:        https://example.com/gb-notice-bar
     * Description:       Prints a short site wide notice in the footer.
     * Version:           1.0.0
     * Requires at least: 6.5
     * Requires PHP:      7.4
     * Author:            Ethan Caldwell
     * License:           GPL-2.0-or-later
     * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
     * Text Domain:       gb-notice-bar
     */
    
    if ( ! defined( 'ABSPATH' ) ) {
        exit;
    }
    
    define( 'GBNB_VERSION', '1.0.0' );
    define( 'GBNB_FILE', __FILE__ );

    Only Plugin Name: is strictly required. The rest is metadata WordPress shows in the Plugins list or uses to block activation on an unsupported PHP version. The ABSPATH guard matters: without it, anyone who requests your file directly over HTTP executes it outside WordPress, which is a classic source of fatal errors and worse. Save the file, open Plugins in the admin, and GB Notice Bar appears in the list. Activate it. Nothing happens yet, which is correct.

    Tip: Prefix every function, class, constant, and option name with something short and unique, such as gbnb_. WordPress loads all active plugins into one global namespace, so an unprefixed function called get_settings() will eventually collide with somebody else’s and take the whole site down.

    Add your first hook

    Recommended for you:

    Can You Use Movie Clips in YouTube Videos? What the Law Actually Says
    Blog·Sep 3, 2026

    Can You Use Movie Clips in YouTube Videos? What the Law Actually Says

    Now make the plugin do something. The pattern is always the same: write a function, then attach it to a hook with add_action() for events or add_filter() for values.

    add_action( 'wp_footer', 'gbnb_render_bar' );
    
    function gbnb_render_bar() {
        $message = get_option( 'gbnb_message', '' );
    
        if ( '' === trim( $message ) ) {
            return;
        }
    
        printf(
            '<div class="gbnb-bar" role="status">%s</div>',
            esc_html( $message )
        );
    }

    Two details are doing real work here. get_option() reads a row from the wp_options table, which is where small settings belong because WordPress caches the autoloaded ones in a single query. And esc_html() escapes the value on the way out, so a stored message containing markup prints as text instead of executing.

    Activation and deactivation hooks

    Activation hooks run exactly once, at the moment the user clicks Activate. Use them for one time setup: seeding default options, creating a custom table, scheduling a cron event. Deactivation hooks run when the plugin is switched off and should undo anything that would keep running without the plugin, such as scheduled events.

    register_activation_hook( GBNB_FILE, 'gbnb_activate' );
    register_deactivation_hook( GBNB_FILE, 'gbnb_deactivate' );
    
    function gbnb_activate() {
        add_option( 'gbnb_message', '' );
        add_option( 'gbnb_version', GBNB_VERSION );
    
        if ( ! wp_next_scheduled( 'gbnb_daily_cleanup' ) ) {
            wp_schedule_event( time(), 'daily', 'gbnb_daily_cleanup' );
        }
    }
    
    function gbnb_deactivate() {
        wp_clear_scheduled_hook( 'gbnb_daily_cleanup' );
    }
    Warning: Do not delete user data in the deactivation hook. People deactivate plugins to test a conflict and expect their settings to survive. Permanent removal belongs in an uninstall.php file, which only runs when the plugin is deleted.

    Use add_option() rather than update_option() when seeding defaults. add_option() does nothing if the row already exists, so reactivating the plugin will not wipe a value the site owner already set. The official reference for this behavior is in the WordPress Plugin Handbook.

    Build a small settings page

    The Settings API handles the form rendering, saving, nonce, and capability plumbing for you. Register the screen on admin_menu and the setting itself on admin_init.

    add_action( 'admin_menu', 'gbnb_menu' );
    add_action( 'admin_init', 'gbnb_register_settings' );
    
    function gbnb_menu() {
        add_options_page(
            __( 'Notice Bar', 'gb-notice-bar' ),
            __( 'Notice Bar', 'gb-notice-bar' ),
            'manage_options',
            'gb-notice-bar',
            'gbnb_settings_page'
        );
    }
    
    function gbnb_register_settings() {
        register_setting(
            'gbnb_group',
            'gbnb_message',
            array(
                'type'              => 'string',
                'sanitize_callback' => 'sanitize_text_field',
                'default'           => '',
            )
        );
    }
    
    function gbnb_settings_page() {
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_die( esc_html__( 'You do not have permission to do this.', 'gb-notice-bar' ) );
        }
        ?>
        <div class="wrap">
            <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
            <form method="post" action="options.php">
                <?php settings_fields( 'gbnb_group' ); ?>
                <input type="text" class="regular-text" name="gbnb_message"
                       value="<?php echo esc_attr( get_option( 'gbnb_message', '' ) ); ?>">
                <?php submit_button(); ?>
            </form>
        </div>
        <?php
    }

    settings_fields() prints the nonce and the option group hidden fields, and options.php checks both before writing. That is why the Settings API is worth learning before you hand roll a form.

    Security basics you cannot skip

    Three rules cover most of what plugin reviewers reject. Check capability, verify intent, and sanitize on the way in while escaping on the way out.

    add_action( 'admin_post_gbnb_reset', 'gbnb_handle_reset' );
    
    function gbnb_handle_reset() {
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_die( 'Forbidden', 403 );
        }
    
        check_admin_referer( 'gbnb_reset_action' );
    
        $note = isset( $_POST['note'] )
            ? sanitize_text_field( wp_unslash( $_POST['note'] ) )
            : '';
    
        update_option( 'gbnb_message', $note );
    
        wp_safe_redirect( admin_url( 'options-general.php?page=gb-notice-bar' ) );
        exit;
    }

    Note wp_unslash() before sanitizing, because WordPress adds slashes to superglobals. Note also that escaping is chosen by context: esc_html() inside an element, esc_attr() inside an attribute, esc_url() for a link, and wp_kses_post() when you genuinely want to allow a limited set of tags. Never trust a value just because you wrote it to the database yourself.

    Note: If a query touches the database directly, always run it through $wpdb->prepare() with placeholders such as %d and %s. Interpolating a variable straight into SQL is the single most common way a plugin fails a security review.

    Where this tutorial ends and the next two begin

    This piece is the on ramp: structure, hooks, one setting, safe output. Two companion articles pick up from here in different directions. If you want to see a single plugin built all the way through, including a shortcode, a block with block.json, translation loading, and an uninstall routine, read how to make a WordPress plugin that does something useful, which is one complete project rather than a set of concepts.

    If you already write plugins and the question is how to structure a large one, building a WordPress plugin from scratch covers Composer autoloading, dependency injection instead of singletons, custom tables with dbDelta(), REST routes, and continuous integration. And when your plugin is ready for other people, submitting a plugin to the WordPress repository walks through readme.txt, the review queue, and the Subversion workflow.

    Troubleshooting

    The plugin does not appear in the Plugins list. WordPress only scans one level deep. The main PHP file has to sit at wp-content/plugins/your-plugin/your-plugin.php or directly in the plugins folder. If it is buried a second level down, or the header comment is missing the Plugin Name: line, or the file uses Windows line endings that broke the comment block, the plugin is invisible.

    Activating gives a white screen or a fatal error. Turn on debugging in wp-config.php with define( 'WP_DEBUG', true ); and define( 'WP_DEBUG_LOG', true );, then read wp-content/debug.log. The usual causes are a PHP syntax error, a function name that collides with another plugin, or calling a WordPress function that is not loaded yet.

    You are locked out and cannot deactivate from the admin. Rename the plugin folder over SFTP or in the file manager and WordPress deactivates it on the next request. Our guide to disabling a WordPress plugin from cPanel covers the steps if you only have hosting panel access.

    The settings form saves nothing. The option name in register_setting() must match the name attribute on the input exactly, and the group passed to settings_fields() must match the first argument of register_setting(). A mismatch fails silently.

    Recommended for you:

    Why Is Jack the Black Cat Squishmallow So Rare?
    Blog·Sep 3, 2026

    Why Is Jack the Black Cat Squishmallow So Rare?

    Your change does not show on the front end. Page caching, object caching, or a CDN is serving an old copy. Flush the site cache and hard reload, and confirm you are not viewing a static cached HTML file.

    Frequently asked questions

    Do I need to know object oriented PHP to write a plugin?

    No. A single file of prefixed functions is perfectly valid and thousands of published plugins work that way. Classes become worthwhile once you have several features sharing state, or once you want autoloading and unit tests. Start procedural, then refactor when the file passes a few hundred lines.

    What is the difference between an action and a filter?

    An action is an event: WordPress announces that something is happening and your callback does work, returning nothing. A filter passes a value through your callback and expects the value back, changed or unchanged. Forgetting to return a value from a filter callback is the single most common beginner bug.

    Where should I put my CSS and JavaScript?

    Never inline them in the footer. Register them with wp_enqueue_style() and wp_enqueue_script() on the wp_enqueue_scripts hook, passing your plugin version as the version argument so browsers pick up changes. That lets WordPress deduplicate dependencies and lets caching plugins combine files correctly.

    Can I edit plugin files in the WordPress admin?

    You can, through the built in plugin editor, but you should not. There is no syntax check and no undo, so one typo produces a fatal error on a live site. Edit locally, use version control, and deploy. Many hosts disable the editor with DISALLOW_FILE_EDIT for exactly this reason.

    How do I make my plugin translatable?

    Wrap user facing strings in __() or esc_html__() with your text domain as the second argument, and keep the text domain identical to your plugin slug. Since WordPress 4.6, plugins hosted on WordPress.org get translations loaded automatically, so you usually do not need load_plugin_textdomain() at all.

    The bottom line

    A working plugin is a folder, a header comment, and a handful of hooks. The skill is not in the boilerplate; it is in knowing which hook fires at the right moment, prefixing everything so you do not collide with the rest of the site, and escaping output every single time you print it.

    Build GB Notice Bar on a local install, break it deliberately, read the debug log, and fix it. Once that loop feels routine, move on to a complete project build or to the architecture patterns that keep a large plugin maintainable. If your goal is eventually to publish or sell what you build, the packaging and licensing decisions come later, and none of them are harder than the first fatal error you fix on your own.

    Share. Facebook Twitter Pinterest LinkedIn Tumblr Telegram Email Copy Link
    Previous ArticleHow to Trade With the Money Flow Index (MFI)
    Next Article How Keltner Channels Are Calculated and Used
    Ethan Caldwell

      Ethan Caldwell is GeekBlog's resident Apple specialist, covering the entire Apple ecosystem - iPhone, iPad, Mac, Apple Watch, AirPods and the software that ties them together. A longtime iOS user and gadget collector, Ethan tracks Cupertino's every move, breaking down Apple keynotes, A- and M-series chip benchmarks, iOS feature updates and the rumor mill into clear, practical takes that help readers decide whether the latest Apple hardware is worth the upgrade.

      Related Posts

      10 Mins Read

      Google Ads Keyword Planner: How It Shows the Most Relevant Keywords

      11 Mins Read

      How to Use Remarketing Techniques for Better Conversions

      11 Mins Read

      How to Conduct A/B Testing for Marketing Campaigns

      10 Mins Read

      AMP for WP Plugin Vulnerability: What Was Fixed and What to Do

      11 Mins Read

      How to Create a Facebook Business Page in 2026

      11 Mins Read

      How to Convert GMT Time to Other Time Zones in C++

      Top Posts

      How to Fix PS5 Controller Stick Drift (2026): 7 Working Methods

      July 10, 20262 Views

      Best Free Online Music Apps in 2026

      July 7, 20262 Views

      COD Mobile Best Loadouts and Meta Guns (2026 Guide)

      July 2, 20262 Views
      Stay In Touch
      • Facebook

      Subscribe to Updates

      Get the latest tech news from FooBar about tech, design and biz.

      Most Popular

      How to Convert HEIC to JPG on iPhone, Mac, Android and Windows

      September 3, 20266 Views

      Gal Gadot’s Lawyers Spent Six Months on One AI Clause. Then SAG Called Them for Pointers.

      September 2, 20265 Views

      The Mesh Router Placement Strategy That Finally Gave Me Full Home Coverage

      September 9, 20263 Views
      Our Picks

      Miami Will Let Rockstar Turn Downtown Into Vice City. The Fine Print Runs to Six Banners and a Deadline.

      September 24, 2026

      Apple Watch Series 12 Takes Aim at WHOOP and Oura With Always-On Heart Tracking

      September 24, 2026

      DoorDash Owes 264,000 Dashers $131.5 Million. Most of It Is an Argument About Waiting Around.

      September 24, 2026

      Subscribe to Updates

      Get the latest creative news from FooBar about art, design and business.

      HEICJPG.online - Convert HEIC to JPG online
      Facebook
      • About Us
      • Contact us
      • Privacy Policy
      • Disclaimer
      • Terms and Conditions
      • Editorial Policy
      • Cookie Policy
      © 2026 GeekBlog

      Type above and press Enter to search. Press Esc to cancel.