Building Your First Custom Functionality Plugin

WordPress Custom Functionality A custom functionality plugin allows you to separate your WordPress code between the presentation and functionality layers. It is a best practice often overlooked yet important to help future-proof your WordPress website.

Creating a plugin like this is easy to do and fast. It won’t slow down your workflow and once you have a good base coded you can easily reuse code in additional projects. In fact, a custom functionality plugin may actually speed your development process up. There are many reasons to separate you presentation code from your functionality code.

Why Create a Separate Functionality Plugin?

Many theme authors add a lot of mission critical functionality code like registering post types within a theme’s functions.php file. This isn’t thinking long term. What if in a few years the user wants to change themes? All that content is now hidden from the users’ view and unless they know how to re-register that CPT they are lost.

Site-Specific WordPress plugin is a specific place to add snippets that you find on the web that performs functions that are not theme related.

– wpbeginner

Beware of Application Themes…

Beware of Ball and Chain Themes

Many application themes do not separate theme code from plugin code. Suppose you or someone else developed an entire website using a popular directory theme (like you find within many themes on some of the larger theme marketplaces). The client decides they no longer like that theme and wants a change. Now what? You’re stuck trying to figure out how to move that data. That’s a big headache.

If you’re the developer you could get a call from that client that you haven’t heard from in years. So make sure before you buy that next theme that they separate plugin (application) logic from theme (presentation) logic and can verify the data the theme uses is portable from theme to theme.

Examples of What Goes in a Site-Specific WordPress Plugin

A good rule of thumb when thinking about what to place into a functionality plugin would be to ask yourself, if I change themes will it break? For instance, if you add a post redirect in your theme’s functions.php and switch themes the redirect is gone. This is an example of something that needs to go into a plugin. Here are a few more:

  • Shortcodes
  • Thumbnail support and sizes
  • Redirects (301, 302, etc)
  • Custom rewrite rules
  • Custom post types and taxonomies
  • Custom metaboxes and fields

What CAN you put in functions.php?

Don’t get the idea that the functions.php file is totally off limits. This is the place for theme-specific functions like navigation menus, sidebars and enqueuing scripts.

Registering navigation and sidebars belong in the theme because they rely on it for their placement. If you were to put these within a separate plugin and switch themes the theme would not contain the code to output them appropriately.

Enqueuing scripts gets a little into a gray area. If a script is solely used for a theme function it can go within the theme. But, if it’s purpose is outside the realms of a theme then put it in a separate plugin. For instance, if you have a script to filter posts like isotope this can go in the theme. This is because if you switch themes down the line this script will be still present in your source but rendered useless which increases load time. If a script is used to modify things like the WP login screen or admin area then this can go in a plugin because most likely you want this to carry over regardless of the theme.

Building a Custom Functionality Plugin

If you thought developing a separate plugin for functionality was difficult I’m here to prove to you it’s not. In fact, it’s actually quite easy. Here’s what our custom functionality plugin will do:

  1. Customize the WP login
  2. Add a simple dashboard widget with developer information
  3. Move some admin menu items
  4. Add a favicon for the admin area

Please note that all the following code is up on GitHub. Please feel free to fork and use for your needs. Let’s get started:

1. Create the plugin directory structure

I like to structure functionality plugins with the following structure. Feel free to modify this to your liking. This is just my preference:

  • company-name-plugin
    • includes
    • assets
      • js
      • css
      • img


My rationale with this structure is that it you can easily place your assets within their specific subdirectory. Includes is reserved for helper classes for registering post types or custom metaboxes and fields.

2. Create the main plugin file

Within the base directory create a file called company-name-plugin.php and add the following code customized to suit your needs:

Plugin Name: WordImpress Custom Functions
Plugin URI:
Description: Custom functions for the ::client name:: website
Author: Devin Walker
Version: 1.0
Requires at least: 3.8.1
Author URI:

Congrats, you have created a plugin. Now go and activate it:


Got it activated? Good. Now let’s add some functionality.

3. Customize the WP Login Screen

Customizing the admin login is a nice touch to add for your clients. It’s simple to do and our plugin here is the perfect place to put the code.  First, create a new css file under assets/css called admin.css. Next, add the following code to our main php file:

//* custom CSS for admin logo and layout
function wordimpress_custom_styles() {

	echo '<link rel="shortcut icon" type="image/png" href="' . plugins_url( 'assets/img/favicon.ico', __FILE__) . '" />';
    echo '<link rel="stylesheet" href="' . plugins_url( 'assets/css/admin.css', __FILE__) . '" type="text/css" media="screen" />';


add_action('login_head', 'wordimpress_custom_styles');
add_action('admin_head', 'wordimpress_custom_styles');

This code is essentially adding our CSS file to the admin head and also placing a favicon. The following is some CSS to customize the login screen which you can add to our previous created admin.css file:

/* Login Screen */
body.login {
	background: url('') no-repeat center center fixed;
	-webkit-background-size: cover;
	-moz-background-size: cover;
	-o-background-size: cover;
	background-size: cover;
	background-color: #EEE;
	padding-top: 0;

#login {
	margin: 0 auto;
	padding-top: 30px;

#login h1 {
	margin-top: 60px;
	padding: 20px 0 0;

#login h1 a {
	background: url('') no-repeat top left !important;
	height: 70px;
	width: 190px !important;
	margin: 0 auto 30px;

#login form {
	box-shadow: 0 4px 18px #1D2736;
	-moz-box-shadow: 0 4px 18px #1D2736;

.login #nav a, .login #backtoblog a {
	text-shadow: none;

Refresh your admin screen and you should now see a WordImpress branded login. You can easily swap out the images here for your own background and logo.


Don’t forget to add a favicon. You can either use a PNG or ICO file for your favicon. Simply place it in the image directory and you should see it display on your admin pages.

 4. Create a Better Dashboard Experience

The WordPress Admin dashboard likes to include a few widgets I find unnecessary. I like to remove some of these widgets and also include my own helper widget that includes information about the site and how to get support. Here’s the code I use to do that:

// Add and remove dashboard widgets
function wordimpress_dashboard_cleanup() {

	//* remove meta boxes
	remove_meta_box( 'dashboard_right_now', 'dashboard', 'normal' );
	remove_meta_box( 'dashboard_plugins', 'dashboard', 'normal' );
	remove_meta_box( 'dashboard_secondary', 'dashboard', 'side' );
	remove_meta_box( 'dashboard_primary', 'dashboard', 'side' );
	remove_meta_box( 'dashboard_recent_drafts', 'dashboard', 'side' );
	remove_meta_box( 'dashboard_incoming_links', 'dashboard', 'normal' );
	remove_meta_box( 'dashboard_recent_comments', 'dashboard', 'normal' );
	remove_meta_box( 'dashboard_quick_press', 'dashboard', 'side' );

	//* add call to include a custom widget
	wp_add_dashboard_widget('wordimpress_help_text', 'Website Help and Support', 'wordimpress_help_links'); // add a new custom widget for help and support

add_action('wp_dashboard_setup', 'wordimpress_dashboard_cleanup');

//* add custom help links
function wordimpress_help_links() { ?>

    <img src="<?php echo plugins_url( 'assets/img/wordimpress-logo.png', __FILE__) ?>" />

		<p>We're here to help. If you have any questions please don't hesitate to reach out to us.</p>

    <li>Site Developer: <a href="" title="Visit WordImpress">Devin Walker @ WordImpress</a></li>

<?php }

Now when a users visits the dashboard they are met with a much cleaner interface and also have our helpful widget. This widget can be extended to show videos, latest posts, tweets, and even forms to submit bug reports or support requests.


 5. Remove and/or Rearrange Admin Menu Links

Depending on the site you are building you may not want to display admin menu links such as “Posts” or “Comments”. These can easily be hidden from view with just a few lines of code. You may also rearrange them in an order that may make more sense for your use case. Here’s how we do it:

//* re-order admin panel
function wordimpress_reorder_menu( $__return_true ) {
	return array(
		'index.php', // this represents the dashboard link
		'edit.php?post_type=page', // this is the default page menu
		'edit.php?post_type=post', // this is the default page menu
		'edit.php', // this is the default POST admin menu

add_filter( 'custom_menu_order', 'wordimpress_reorder_menu' );
add_filter( 'menu_order', 'wordimpress_reorder_menu' );

Now suppose we aren’t using posts? Using remove_menu_page we can easily get rid of the items we don’t want:

//* Remove Menu Links
function wordimpress_remove_menus() {

//  remove_menu_page( 'index.php' );                  //Dashboard
		remove_menu_page( 'edit.php' ); 									//Posts
//  remove_menu_page( 'upload.php' );                 //Media
//  remove_menu_page( 'edit.php?post_type=page' );    //Pages
//  remove_menu_page( 'edit-comments.php' );          //Comments
//  remove_menu_page( 'themes.php' );                 //Appearance
//  remove_menu_page( 'plugins.php' );                //Plugins
//  remove_menu_page( 'users.php' );                  //Users
//  remove_menu_page( 'tools.php' );                  //Tools
//  remove_menu_page( 'options-general.php' );        //Settings


add_action( 'admin_menu', 'wordimpress_remove_menus' );

Now when you refresh the admin screen you should see posts are removed. Simply uncomment some of the other functions to remove other links. As you can see it’s really easy to remove them.

6. Columns Clean Up

There are a number of columns that display which I don’t like to see such as author and comments. Removing default columns only takes a few lines of code as well:

//* remove unwanted columns 
function wordimpress_edit_post_columns($defaults) {
    return $defaults;

add_filter('manage_edit-page_columns', 'wordimpress_edit_post_columns'); // will affect all non-hierarchical post types

 7. Tame WordPress SEO’s Metabox

WordPress SEO is an excellent plugin. However, I don’t like how it sets it’s own metabox priority at the highest level. This means it displays above all others in the edit page view. Let’s put a wrangle on this and knock it down a few pegs:

function yoast_dont_boast() {
     return 'low';
add_filter( 'wpseo_metabox_prio', 'yoast_dont_boast');

Special thanks to Chris over at Revelation Concept for this snippet.

8. Registering Post Types and Taxonomies

As previously mentioned, it is very important to register post types and taxonomies within a custom functionality plugin. I like to include two classes that make this extremely easy: WordPress Custom Post Types and WordPress Custom Taxonomies. Within the GitHub repo I have included these as submodules.

9. Custom Metaboxes and Fields

I tend to sway between using Custom Metaboxes and Fields and Advanced Custom Fields. They both have their pluses and minuses. CMB is lightweight yet less powerful. ACF is heavier but oh so powerful. It depends on the project but it’s always good to have CMB at your disposal. That’s why I’ve also included it as a submodule.

Check it Out on GitHub

You can find the code above all packed and ready to go for your use on GitHub.


Please feel free to fork, submit pull request and use at your disposal. Have any questions or comments? Be sure to leave them below!


6 thoughts on “Building Your First Custom Functionality Plugin

  1. Got this sucker bookmarked. Going to work on it this weekend. I honestly never even thought about creating a reusable plugin for materials I use on a constant basis. I’ve known that it was good practice to separate things into theme specific and plugin specific but I would always just turn to another plugin for the plugin portion. I never actually thought of just reusing my own. Sounds goofy but it just never crossed my mind until now. Thanks Devin.

    1. Hey Timonthy – Glad you found in useful. Hopefully this will serve as a good base for you. I plan on adding some example code to register post types, taxomies and metaboxes to make it that much faster to setup those things.

  2. Devin I have gone through most of your tutorial and it would be nice to extend each section (as in extra tricks/tips). For instance adding a widget into the Dashboard area section. What about changing the full Dashboard to include a background image, adding shadow behind widgets, curved corners. Etc. Make changes to the Welcome widget etc. Next the reorder and remove side menu sections. Moving a section like pages, posts etc into a new sidebar item called content etc or moving it into for instance the Settings area. Juggling items around. Here it would be interesting to also change some of the CSS used. Or to force the user to use one of the color schemes (which is likely another separate area). Kinda like doing a WordPress mini makeover..:) Btw I look forward to part 2. With even more tricks to make additional changes!

    1. I’m debating whether to keep this very clean and limited. Most of the changes you mention to the dashboard could be done with CSS. You can also add other really awesome additional features like contact forms, RSS feeds, etc. I like the idea to force a certain color scheme. That would be useful to include. Most likely there will be a part 2. Stay tuned.

      1. The article could be clean and simple. Additional and fuller examples and be added to Github in a readme etc. Showing how to extend examples used here as well as additional examples not used in the article. It is a good way for people to also check github knowing that even more information is added there as well. People could also post their own examples in the issues or another section. Sharing code examples with each other. It is a good way to learn.

Leave a Reply

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