Category: Dev Tips & Snippets

  • Dev Tip #4: Handling AJAX in WordPress (The Clean Way)

    Using AJAX in your plugin can make it feel fast and modern — but if you don’t structure it right, it can become messy and insecure fast.

    Here’s how I handle AJAX calls the clean and secure way in WordPress.

    1. Enqueue Your Script with ajaxurl

    When enqueuing your JavaScript, always localize it with the ajaxurl.

    add_action( 'admin_enqueue_scripts', function() {
        wp_enqueue_script( 'my-plugin-admin', plugin_dir_url( __FILE__ ) . 'admin.js', [ 'jquery' ], '1.0', true );
        
        wp_localize_script( 'my-plugin-admin', 'myPlugin', [
            'ajax_url' => admin_url( 'admin-ajax.php' ),
            'nonce'    => wp_create_nonce( 'my_plugin_nonce' ),
        ] );
    });

    2. The JS Side (Calling AJAX)

    jQuery(document).ready(function($) {
        $('#my-button').on('click', function() {
            $.post(myPlugin.ajax_url, {
                action: 'my_plugin_do_something',
                nonce: myPlugin.nonce,
                data: 'SomeValue'
            }, function(response) {
                console.log('Server says:', response);
            });
        });
    });

    3. The PHP Side (Handling AJAX)

    add_action( 'wp_ajax_my_plugin_do_something', 'my_plugin_do_something_callback' );
    
    function my_plugin_do_something_callback() {
        check_ajax_referer( 'my_plugin_nonce', 'nonce' );
    
        // Capability check if needed
        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( 'Not allowed' );
        }
    
        $value = sanitize_text_field( $_POST['data'] ?? '' );
    
        // Do something here...
    
        wp_send_json_success( 'Success! You sent: ' . $value );
    }

    Bonus: For Frontend Users

    If you want AJAX support on the frontend too:

    add_action( 'wp_ajax_nopriv_my_plugin_do_something', 'my_plugin_do_something_callback' );

    This lets non-logged-in users run the same AJAX handler — great for forms, voting, tracking, etc.

    Final Thought

    Keep your AJAX code:

    • Localized with nonces
    • Protected with check_ajax_referer()
    • Cleanly separated in JS and PHP
    • Always sanitized and validated

    Done right, it makes your plugins feel snappy and pro.

  • Dev Tip #3: Plugin Security Basics I Never Skip

    Security isn’t the flashiest part of plugin development — but it’s the part that breaks trust the fastest when ignored.

    These are the basics I always keep in mind while building plugins. They’re simple, but missing even one of them can open up real problems.

    1. Escape Output, Always

    Whenever I print something to the screen, especially user-generated content or dynamic settings, I escape it properly:

    echo esc_html( $setting_value );

    Use the right escaping function for the context:

    • esc_html() for regular text
    • esc_attr() for input values
    • esc_url() for links
    • wp_kses_post() if allowing some HTML

    If you forget this, it opens doors to XSS attacks.


    2. Sanitize Input Before Saving

    Before saving anything to the database — whether it’s from a form or a setting screen — I sanitize it.

    $sanitized = sanitize_text_field( $_POST['your_field'] );

    Other useful sanitizers:

    • sanitize_email()
    • sanitize_textarea_field()
    • absint()
    • esc_url_raw()

    Even if it “looks safe,” I sanitize it anyway.


    3. Always Use Nonces for Forms & AJAX

    A nonce protects your forms and AJAX requests from being abused by external scripts or bad actors.

    For forms:

    wp_nonce_field( 'my_plugin_action', 'my_plugin_nonce' );

    On submit:

    if ( ! isset( $_POST['my_plugin_nonce'] ) || 
         ! wp_verify_nonce( $_POST['my_plugin_nonce'], 'my_plugin_action' ) ) {
        return; // Invalid request
    }

    For AJAX: Same logic applies — pass and verify a nonce.

    4. Capability Checks Matter

    Before saving data or doing anything admin-related, I make sure the current user has permission to do so.

    if ( ! current_user_can( 'manage_options' ) ) {
        return;
    }

    I don’t rely only on menu access. I protect everything behind capability checks too.


    5. Never Trust $_POST or $_GET Blindly

    I treat all global inputs ($_POST, $_GET, $_REQUEST, etc.) as untrusted by default.
    Even if it’s a simple text field, I treat it with caution.

    Trust your logic, not the input.


    Final Thought

    You don’t need to be a security expert to write secure plugins.
    Just follow these simple habits every time, and you’ll avoid 90% of common issues.

    It’s not about fear — it’s about respect.
    For your users, their data, and the trust they place in your work.

  • Dev Tip #2: How to Load Scripts Only on a Specific Admin Page

    When building a plugin, loading your scripts and styles everywhere in the WordPress admin isn’t ideal.
    It adds unnecessary bloat and slows things down.

    Here’s how I load my JS or CSS files only on the plugin settings page (or any specific admin page).

    The Snippet

    add_action( 'admin_enqueue_scripts', function( $hook ) {
        if ( $hook !== 'settings_page_my-plugin-slug' ) {
            return;
        }
    
        wp_enqueue_script(
            'my-plugin-script',
            plugin_dir_url( __FILE__ ) . 'assets/admin.js',
            [ 'jquery' ],
            '1.0',
            true
        );
    
        wp_enqueue_style(
            'my-plugin-style',
            plugin_dir_url( __FILE__ ) . 'assets/admin.css',
            [],
            '1.0'
        );
    });
    

    How It Works

    • $hook is passed by WordPress to tell you what admin page is currently being loaded.
    • settings_page_my-plugin-slug is the ID of your plugin settings page (you get this from the slug used in add_options_page() or add_menu_page()).
    • If you return early, your scripts won’t load anywhere else.

    Bonus Tip

    You can error_log( $hook ); on any admin page to quickly find the correct page slug during development. Super handy.


    Why This Matters

    This keeps your plugin lightweight, improves performance, and avoids accidentally breaking unrelated parts of the admin area with your scripts.

  • The Best WordPress Advice I Ever Got

    I’ve been working with WordPress for over a decade now.
    I’ve built plugins, worked with agencies, shipped products, burned out, restarted, and kept going.

    But looking back, there’s one piece of advice that stuck with me more than anything else.

    It wasn’t from a blog post.
    It wasn’t from a course or a conference talk.
    It was something simple that a senior dev told me during my early days:

    “If you’re building for WordPress, build like you’re part of WordPress.”

    At the time, I didn’t fully get it.
    I was busy trying to make things look custom, unique, “better” than WordPress core.
    I wanted to change everything — custom UIs, new dashboard layouts, fancy JS behavior that ignored WordPress conventions.

    But that advice started making more sense the longer I stuck around.

    What they meant was:
    If you’re building something for WordPress users, don’t fight the platform.
    Blend into it. Use its patterns. Speak its design language.
    Make your plugin feel like it belongs there.

    Because users already know how WordPress works.
    They don’t want to learn a new UI just to enable one feature.
    They don’t want your plugin to break every time WordPress updates.
    They want something that feels native — something they trust.

    And that shifted how I build.

    I started focusing more on:

    • Clean, native UI using WordPress components
    • Logical settings that match how WordPress core does things
    • Avoiding unnecessary custom code when WordPress already solves it well
    • Writing code that respects hooks, filters, roles, and capabilities

    That one mindset saved me hours of future maintenance, made support easier, and helped users feel at home using my tools.

    It also helped me enjoy building more — because I wasn’t reinventing the wheel. I was working with the system, not against it.

    It sounds simple. But it’s easy to forget, especially when you’re trying to build something cool or different.

    So if you’re working on a plugin, a theme, or even just a small tweak, remember this:

    Don’t try to make WordPress look like your plugin.
    Make your plugin feel like part of WordPress.

    That’s the best advice I ever got — and I’m still following it today.

  • Dev Tip #1: How to Add a Custom Admin Notice in WordPress

    Sometimes your plugin or theme needs to show a message in the WordPress admin area — maybe a success message after saving settings, or a warning if something is missing.

    Here’s how I usually do it:
    Keep it simple, clean, and native.

    The Snippet

    add_action( 'admin_notices', function() {
        if ( ! current_user_can( 'manage_options' ) ) {
            return;
        }
    
        echo '<div class="notice notice-success is-dismissible">';
        echo '<p>Your custom admin notice goes here.</p>';
        echo '</div>';
    });

    How It Works

    • Hooks into admin_notices, which is used by WordPress to display messages at the top of admin screens.
    • notice-success gives it a green success style. You can also use:
      • notice-error (red)
      • notice-warning (yellow)
      • notice-info (blue)
    • is-dismissible makes it closable.
    • Always wrap with a capability check like manage_options to avoid showing notices to users who don’t need to see them.

    Bonus: Show it only on specific pages

    You can limit where the notice appears like this:

    if ( get_current_screen()->id === 'settings_page_my-plugin' ) {
        // show notice
    }

    I use this pattern in almost every plugin I write.
    Clean admin messages go a long way in making your tools feel more polished and professional.