How Do I Create a Custom WordPress Plugin From Scratch?

If you’re new to WordPress development, creating your own plugin can feel intimidating. It sounds like something only “real developers” do.

The truth is much simpler.

A WordPress plugin is just organized PHP code with a purpose. And if you’ve ever added code to functions.php, you’re already closer than you think.

In this article, I’ll show you how to create a custom WordPress plugin from scratch, using a very small, front-end-focused utility plugin. No frameworks, no complex tooling, no unnecessary abstractions.

This is Part 1 of a mini-series aimed at absolute beginners.

Why I Started Creating Custom WordPress Plugins

I didn’t start building plugins because I wanted to.

I started because existing plugins couldn’t solve my problem.

At first, I did what most beginners do:

  • Installed multiple plugins that almost worked
  • Added snippets to functions.php
  • Tweaked themes to force things to fit

Eventually, it became clear that my site’s behavior depended on fragile, scattered code.

That moment led me down the path of building custom plugins — a path that later resulted in premium plugins like LocalBusiness Schema Pro, WooPress License Hub, and Easy DragDrop Uploader Pro.

But every one of those plugins started the same way:

As a small, focused utility plugin.

That’s exactly what we’re building here.

What a WordPress Plugin Really Is (Beginner Mental Model)

Let’s remove the mystery.

A WordPress plugin is:

  • A folder
  • With at least one PHP file
  • That contains a special comment header

That’s it.

There’s no requirement to:

  • Use object-oriented PHP
  • Create admin pages
  • Add settings screens
  • Write thousands of lines of code

In fact, the best plugins usually start small.

When You Should Create a Custom Plugin

You should consider creating a plugin when:

  • The functionality is not purely visual
  • The behavior should survive theme changes
  • The code is reused across pages or sites
  • functions.php starts feeling risky

Here’s the mindset shift that changed everything for me:

Themes control appearance. Plugins control behavior.

Once you understand that, plugin development becomes obvious — not scary.

Step 1: Create the Plugin Folder

Go to your WordPress installation and navigate to:

wp-content/plugins/

Create a new folder:

frontend-utility-plugin

Naming matters.
Renaming a plugin later affects updates, branding, and user trust. I learned that lesson the hard way.

Step 2: Create the Main Plugin File

Inside the folder, create a file named:

frontend-utility-plugin.php

Add the following code:

<?php
/**
 * Plugin Name: Frontend Utility Plugin
 * Description: A small front-end focused utility plugin.
 * Version: 1.0.0
 * Author: Rey C
 */

defined( 'ABSPATH' ) || exit;

Now go to WordPress Admin → Plugins.

You’ll see your plugin listed.

Activate it.

Congratulations — you just created a WordPress plugin.

Why This File Is So Important

That comment block at the top is how WordPress:

  • Identifies your plugin
  • Displays it in the admin area
  • Tracks versions

Even professional plugins rely on this exact same mechanism.

There’s nothing “basic” about it — it’s foundational.

Step 3: What This Plugin Will Do (On Purpose)

For this tutorial, we are building a front-end utility plugin that:

  • Has no admin UI
  • Uses actions and filters
  • Modifies front-end behavior only

Why?

Because most real plugins don’t start as big systems. They start as useful behavior changes.

This approach also keeps things beginner-friendly and performance-aware.

Step 4: Add an /includes Folder (Future-You Will Thank You)

Inside your plugin folder, create:

includes/

Inside that folder, create:

frontend-hooks.php

Now go back to frontend-utility-plugin.php and load it:

require_once plugin_dir_path( __FILE__ ) . 'includes/frontend-hooks.php';

This separation might feel unnecessary now.

It isn’t.

This single habit is one of the reasons my premium plugins stayed maintainable over time.

Step 5: Add Your First Front-End Behavior

Open frontend-hooks.php and add:

<?php
defined( 'ABSPATH' ) || exit;

/**
 * Add a custom class to the body tag
 */
add_filter( 'body_class', function( $classes ) {
    $classes[] = 'frontend-utility-plugin-active';
    return $classes;
});

Refresh your site and inspect the <body> tag.

You’ll see the new class.

You just:

  • Modified front-end behavior
  • Without touching the theme
  • Using a plugin

This is the core power of WordPress plugins.

Why I Default to Actions and Filters

In my real-world work, actions and filters are my first choice because they:

  • Are update-safe
  • Respect WordPress core
  • Avoid theme lock-in
  • Scale cleanly

You’re not changing WordPress — you’re extending it.

That distinction matters.

The Most Important Lesson: Plugins Are Products

Here’s the mindset that changed how I build plugins:

Every plugin is a product — even the small ones.

That means:

  • Clean structure
  • Thoughtful naming
  • Versioning from day one
  • Respect for users and performance

This mindset is what separates fragile snippets from reliable tools.

What’s Next in This Mini-Series

In Part 2, we’ll cover:

  • Why functions.php becomes dangerous
  • How to move front-end logic into a plugin
  • When code belongs in a plugin vs a theme

That’s where most beginners get stuck — and where things start to click.

How to Create a Custom Testimonial Shortcode for ElegantThemes in WordPress

While customizing my WordPress template, I came across an interesting new feature called the “Testimonial Shortcode” that comes with themes developed by ElegantThemes.
I was fascinated by this feature, but I noticed one limitation — it lacks flexibility. Every time you want to add a new testimonial, you have to manually edit the page or post that contains the shortcode.

This tutorial is intended for WordPress developers and intermediate users who are using an ElegantThemes template and have some knowledge of PHP and WordPress programming.

What Are Shortcodes and Custom Post Types?

Before we dive into coding, let’s review what shortcodes and custom post types are.

What Is a Shortcode?

A shortcode is a WordPress-specific tag that lets you perform powerful functions with minimal code.
Shortcodes can embed files or create objects that would otherwise require complex programming — all in one line of code.

Example:
<code>[shortcode_name]</code>

In short: shortcode = shortcut.

What Is a Custom Post Type?

A custom post type allows you to add new kinds of content to your WordPress site beyond the default “posts” and “pages.”
For instance, you might create custom post types for “Testimonials,” “Portfolio Items,” or “Events.”

In this tutorial, we’ll create a custom post type called “Testimony.”

Step 1: Register a Custom Post Type

First, we’ll create the custom post type.
You can place the following code in your functions.php file inside your theme directory.

/**
 * Register Custom Post Type: Testimony
 */
function register_testimony_post_type() {
	$labels = array(
		'name'                  => __( 'Testimony', 'yourtheme' ),
		'singular_name'         => __( 'Testimony', 'yourtheme' ),
		'add_new'               => __( 'Add Testimony', 'yourtheme' ),
		'add_new_item'          => __( 'Add New Testimony', 'yourtheme' ),
		'edit_item'             => __( 'Edit Testimony', 'yourtheme' ),
		'new_item'              => __( 'New Testimony', 'yourtheme' ),
		'view_item'             => __( 'View Testimony', 'yourtheme' ),
		'search_items'          => __( 'Search Testimony', 'yourtheme' ),
		'not_found'             => __( 'No testimony created', 'yourtheme' ),
		'not_found_in_trash'    => __( 'No testimony found in trash', 'yourtheme' ),
	);

	$args = array(
		'labels'                => $labels,
		'public'                => true,
		'show_ui'               => true,
		'can_export'            => true,
		'_builtin'              => false,
		'_edit_link'            => 'post.php?post=%d',
		'capability_type'       => 'post',
		'hierarchical'          => true,
		'rewrite'               => array(
			'slug' => 'testimony',
		),
		'query_var'             => 'testimony',
		'supports'              => array(
			'title',
			'editor',
			'author',
			'excerpt',
			'thumbnail',
			'comments',
			'trackbacks',
			'revisions',
			'page-attributes',
		),
		'menu_position'         => 7,
		'show_in_nav_menus'     => true,
	);
	register_post_type( 'testimony', $args );
}
add_action( 'init', 'register_testimony_post_type' );

Step 2: Customize the Admin Columns

To make the “Testimony” post type easier to manage in the WordPress admin panel, add this code to modify the columns.

add_filter( 'manage_edit-testimony_columns', 'custom_edit_testimony_columns' );
function custom_edit_testimony_columns( $columns ) {
	$columns = array(
		'cb'      => '',
		'title'   => 'Author Name',
		'content' => 'Testimony',
	);

	return $columns;
}

add_action( 'manage_testimony_posts_custom_column', 'custom_manage_testimony_columns', 10, 2 );
function custom_manage_testimony_columns( $column, $post_id ) {
	global $post;

	switch ( $column ) {
		case 'content':
			$content = et_content_helper( $post->post_content );
			echo esc_html( $content );
			break;

		default:
			break;
	}
}

add_filter( 'manage_edit_testimony_sortable_columns', 'custom_testimony_sortable_columns' );

function custom_testimony_sortable_columns( $columns ) {
	$columns['content'] = 'Testimony';
	return $columns;
}

Step 3: Create the Shortcode

Now, we’ll create a shortcode called “custom_testimonial” that dynamically retrieves all “Testimony” posts and outputs them using ElegantThemes’ built-in testimonial shortcode.

Add the following code to your functions.php file:

<?php
/**
 * Generate custom testimonials shortcode output
 */
function custom_testimonial_generator() {
	$testimonial_query = new WP_Query(
		array(
			'post_type'      => 'testimony',
			'posts_per_page' => -1, // optional: get all testimonials
		)
	);

	if ( $testimonial_query->have_posts() ) {
		while ( $testimonial_query->have_posts() ) {
			$testimonial_query->the_post();

			$content = et_content_helper( get_the_content() );
			$author  = get_the_title();
			$company = get_post_meta( get_the_ID(), 't_company', true );

			$thumbnail_id = get_post_thumbnail_id( get_the_ID() );
			$image_url    = wp_get_attachment_image_src( $thumbnail_id, 'thumbnail' );
			$image        = ! empty( $image_url[0] ) ? $image_url[0] : '';

			echo do_shortcode(
				sprintf(
					'[tstimonial author="%s" company="%s" image="%s"]%s[/tstimonial]',
					esc_attr( $author ),
					esc_attr( $company ),
					esc_url( $image ),
					$content
				)
			);
		}
	}

	wp_reset_postdata();
}

Step 4: Use the Shortcode in a Page or Post

Finally, you can display all your testimonials on any page or post by inserting the following shortcode:

<code>[custom_testimonial]</code>

That’s it!
This shortcode will automatically display all your custom testimonials using ElegantThemes’ testimonial format.

Conclusion

By creating a custom post type and a custom shortcode, you can easily manage and display testimonials without manually editing each page.
This approach gives you more flexibility, organization, and control over your website’s testimonial section.

Hope you find this tutorial helpful and that it helps you make better use of ElegantThemes’ testimonial shortcode feature.

Remove “via” information from emails – WordPress

If you’ve ever sent an email from your WordPress website and noticed the extra “via” information (for example, “sent via yourserver.com”) in the sender details, you’re not alone. This often happens when your website uses the default PHP mail function instead of a verified SMTP connection.

In this article, you’ll learn how to remove the “via” information from WordPress emails by setting up your own SMTP server.

Why Use Your Own SMTP Server?

By default, WordPress uses PHP mail to send emails, which may cause authentication issues or display “via” information. Using an SMTP server ensures:

  • Better email deliverability
  • Professional-looking “From” details
  • Compatibility with your domain’s SPF and DKIM records
  • Elimination of the “via” tag in outgoing emails

Before proceeding, make sure you know your SMTP server details. Most web hosting plans already include an SMTP server or PHPMailer setup. If you’re unsure, contact your web hosting provider (for example, Bluehost, SiteGround, or Hostinger) for the correct SMTP information.

Step 1: Add Your SMTP Credentials

Open your wp-config.php file (found in your website’s root directory) using a text editor, then paste the following code just below the database constants:

define('SMTP_USER',   'your email');          // Username for SMTP authentication
define('SMTP_PASS',   'your password');       // Password for SMTP authentication
define('SMTP_HOST',   'your host');           // Hostname of the mail server (usually your domain)
define('SMTP_FROM',   'from email address');  // SMTP From email address
define('SMTP_NAME',   'from name');           // SMTP From name
define('SMTP_PORT',   '465');                 // SMTP port (25, 465, or 587)
define('SMTP_SECURE', 'ssl');                 // Encryption type: ssl or tls
define('SMTP_AUTH',   true);                  // Enable SMTP authentication (true/false)

Tip: For better security, define your credentials in wp-config.php rather than functions.php.

Step 2: Configure WordPress to Use SMTP

Next, open your functions.php file (located in your active theme directory) and paste this code:

add_action('phpmailer_init', 'custom_send_smtp_email');
function custom_send_smtp_email($mailer) {
    $mailer->isSMTP();
    $mailer->Host       = SMTP_HOST;
    $mailer->SMTPAuth   = SMTP_AUTH;
    $mailer->Port       = SMTP_PORT;
    $mailer->Username   = SMTP_USER;
    $mailer->Password   = SMTP_PASS;
    $mailer->SMTPSecure = SMTP_SECURE;
    $mailer->From       = SMTP_FROM;
    $mailer->FromName   = SMTP_NAME;
}

This tells WordPress to use your SMTP configuration whenever the wp_mail() function is called.

Step 3: Test Your Email

Once everything is set up, send a test email from your website (for example, using a contact form). You should now see your email sent without the “via” information in the sender details.

If you still notice “via” appearing, double-check your SMTP settings or confirm that your domain’s SPF and DKIM records are properly configured.

Conclusion

That’s it! You’ve successfully removed the “via” information from your WordPress emails using your own SMTP setup.

This approach improves both email deliverability and brand professionalism — and it only takes a few minutes to configure.

If you found this article helpful, please share it or leave a comment below.
Happy coding!

How to Remove Query Strings from CSS and JS in WordPress

If you want to improve your WordPress site speed and SEO, one simple optimization is to remove query strings from CSS and JS files. By default, WordPress adds a ?ver= query string to static resources like CSS and JavaScript files. This can prevent caching on proxy servers and CDNs, negatively affecting your site’s SEO performance.

In this guide, we will show you how to remove query strings from your WordPress static files using a simple snippet added to your theme’s functions.php file.

Why Remove Query Strings from CSS and JS?

Query strings like ?ver=5.9 make it harder for some caching systems to store static files efficiently. Removing them can:

  • Improve page load speed
  • Enhance caching for CDNs and proxy servers
  • Boost your SEO performance

For more insights on WordPress performance optimization, check out Google PageSpeed Insights.

How to Remove Query Strings from CSS and JS

Follow these steps:

  1. Open your WordPress theme folder and locate the functions.php file.
  2. Add the following code at the end of the file:
function remove_cssjs_ver( $src ) {
    if( strpos( $src, '?ver=' ) )
        $src = remove_query_arg( 'ver', $src );
    return $src;
}
add_filter( 'style_loader_src', 'remove_cssjs_ver', 10, 2 );
add_filter( 'script_loader_src', 'remove_cssjs_ver', 10, 2 );

This code will remove the version query string from all your CSS and JS files.

Conclusion

Removing query strings from CSS and JS in WordPress is a small tweak that can significantly improve caching, page speed, and SEO. Add the code snippet above, test your site, and pair it with a caching plugin for the best results.

If you found this guide helpful, please share it with your fellow WordPress developers.