How and Why to Create a Site Specific Plugin

Image for How and Why to Create a Site Specific Plugin

If you’ve spent anytime as a WordPress theme developer, you’ll be intimintaly familiar with the functions.php file. It’s included in every theme, and is the main file for defining the functions which affect the behavior of your site/theme.

However, in many cases, your themes functions.php is not the best place to place your snippets! Themes are all about presentation. That is, they define how your site looks and feels. It defines where to place things, and how to display them. That means enqueuing stylesheets or scripts, enabling theme support, defining widget areas, image sizes, etc, are all the responsibility of the theme.

When you need a plugin

When you start getting into defining logic, as oppose to presentation, you’ve reached plugin territorry. While many plugins do include CSS, and JS that are required for reasonable out-of-the-box default presentation, plugins aren’t really concerned with how your site looks. The primary purpose is to do something, rather than display it. Some of the things that would be included in a site-specific plugin:

  • Registering custom post types
  • Registering custom taxonomies
  • Creating / saving metaboxes
  • Creating custom functionality, like custom widgets
  • Defining custom shortcodes

These are all things that should be theme agnostic. By that I mean, all of this type of functionality should operate independently of the theme. More than a few times we’ve cloned a clients existing site to begin a new project, and we’re left with a mess of un-renderable shortcodes and post types that now have to be found, and cleaned up from the old theme.

But what if I’m not going to change my theme?

If you truly aren’t ever going to change your theme, than you have nothing to worry about. Go ahead and stuff all of that functionality inside your theme’s functions.php file, but… You’re creating an unecessary limitation if/when you do decide that it’s time for a facelift. And if you’re doing any type of client work where you are handing off the product to someone else, you’ve created that same limitation for them!

Creating a site-specific plugin

Luckily, it’s not actually any more difficult to create a site specific plugin than it is to add code to your theme’s functions.php file. Granted, if you want to build something more complex than a few site-specific snippits, you’re probably going to want to use something more sophisticated, such as the popular WordPress Plugin Boilerplate. Let’s take a look at a plugin that registers a post type of “Testimonials”: View the code on Gist. As you can see, creating a plugin isn’t significantly different than creating a theme’s functions.php file. In this example, we are doing one thing: registering a custom post type. In the future, when it comes time to rebuild the website using this plugin, we can retain the testimonial functionality without an additional effort on our part.


 * Plugin Name: Site Specific Plugin File 
 * Plugin URI:
 * Description: Site Specific Plugin for [project_name]
 * Version:     1.0.0
 * Author:      WP Code Labs
 * Author URI:
 * License:     GPL-2.0+ 
 * License URI:
 * Text Domain: plugin_text_domain

 * Abort if this file is called directly
if ( !defined( 'WPINC' ) ) {
	die( 'Bugger Off Script Kiddies!' );

 * Define and register the custom post type
function my_plugin_prefix_register_posttype() {     
	$labels = array(         
		'name'                  => _x( 'Testimonials', 'Post Type General Name', 'text_domain' ),
       	'singular_name'         => _x( 'Testimonial', 'Post Type Singular Name', 'text_domain' ),
       	'menu_name'             => __( 'Testimonials', 'text_domain' ),
       	'name_admin_bar'        => __( 'Testimonial', 'text_domain' ),
       	'archives'              => __( 'Testimonial Archives', 'text_domain' ),
       	'parent_item_colon'     => __( 'Parent Testimonial:', 'text_domain' ),
       	'all_items'             => __( 'All Testimonials', 'text_domain' ),
       	'add_new_item'          => __( 'Add New Testimonial', 'text_domain' ),
       	'add_new'               => __( 'Add New', 'text_domain' ),
       	'new_item'              => __( 'New Testimonial', 'text_domain' ),
       	'edit_item'             => __( 'Edit Testimonial', 'text_domain' ),
       	'update_item'           => __( 'Update Testimonial', 'text_domain' ),
       	'view_item'             => __( 'View Testimonial', 'text_domain' ),
       	'search_items'          => __( 'Search Testimonial', 'text_domain' ),
       	'not_found'             => __( 'Not found', 'text_domain' ),
       	'not_found_in_trash'    => __( 'Not found in Trash', 'text_domain' ),
       	'featured_image'        => __( 'Featured Image', 'text_domain' ),
       	'set_featured_image'    => __( 'Set featured image', 'text_domain' ),
       	'remove_featured_image' => __( 'Remove featured image', 'text_domain' ),
       	'use_featured_image'    => __( 'Use as featured image', 'text_domain' ),
       	'insert_into_item'      => __( 'Insert into testimonial', 'text_domain' ),
       	'uploaded_to_this_item' => __( 'Uploaded to this testimonial', 'text_domain' ),
       	'items_list'            => __( 'Testimonials list', 'text_domain' ),
       	'items_list_navigation' => __( 'Testimonials list navigation', 'text_domain' ),
       	'filter_items_list'     => __( 'Filter testimonial list', 'text_domain' ),

   	$args = array(
   		'label'                 => __( 'Testimonial', 'text_domain' ),
        'description'           => __( 'Client Testimonials', 'text_domain' ),
        'labels'                => $labels,
        'supports'              => array( 'title', 'editor', 'excerpt', 'thumbnail', 'custom-fields' ),
        'taxonomies'            => array( 'category', ' post_tag' ),
        'hierarchical'          => false,
        'public'                => true,
        'show_ui'               => true,
        'show_in_menu'          => true,
        'menu_position'         => 5,
        'menu_icon'             => 'dashicons-thumbs-up',
        'show_in_admin_bar'     => true,
        'show_in_nav_menus'     => true,
        'can_export'            => true,
        'has_archive'           => true,
        'exclude_from_search'   => false,
        'publicly_queryable'    => true,
        'capability_type'       => 'page',
   	register_post_type( 'testimonials', $args );
add_action( 'init', 'my_plugin_prefix_register_posttype', 0 );

Leave a Reply

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