How to create Child Theme?

  • Child Theme directory structure

    Create a directory in your themes directory to hold the child theme. The theme directory is wp-content/themes. You should name the directory without any space as part of the name, and it is common practice to use the name of the parent theme folder with “-child” appended to it. For example, if you are making a child of the twentyfourteen theme, your folder name would be twentyfourteen-child.

  • In the child theme directory, create a file called style.css. This is the only file required to make a child theme. The style sheet must start with the following lines:
 Theme Name:   Twenty Fourteen Child
 Theme URI:
 Description:  Twenty Fourteen Child Theme
 Author:       John Doe
 Author URI:
 Template:     twentyfourteen
 Version:      1.0.0
 Tags:         light, dark, two-columns, right-sidebar, responsive-layout, accessibility-ready
 Text Domain:  twenty-fourteen-child

For older themes, and themes that do not use wp_enqueue_style() to enqueue their stylesheet, use the following line where twentyfourteen is the name of the directory where the theme resides:

@import url("../twentyfourteen/style.css");

/* =Theme customization starts here
-------------------------------------------------------------- */

You can change each of these lines to suit your theme. The only required lines are the Theme Name, the Template.

The Template is the directory name of the parent theme. In this case, the parent theme is the Twenty Fourteen theme, so the Template is twentyfourteen, which is the name of the directory where the Twenty Fourteen theme resides. If you want to make a child of a theme with the directory name example-theme-name, then you would use Template: example-theme-name.

Likewise, in the @import url line, twentyfourteen should be replaced with the name of your parent theme if you wish to import the parent’s stylesheet, and you’re using a theme that does not use wp_enqueue_style() in its functions.php file.

Note: The child theme’s stylesheet is included after the parent theme’s and styles will therefore override those in the parent theme’s stylesheet.

(If your wordpress is running in multi-site mode, you may need to switch to the network admin dashboard, then themes, then click network enable. Then you switch to regular admin dashboard and the above step to activate your child theme should be present)

Template Files

If you want to change more than just the stylesheet, your child theme can override any file in the parent theme: simply include a file of the same name in the child theme directory, and it will override the equivalent file in the parent theme directory when your site loads. For instance, if you want to change the PHP code for the site header, you can include a header.php in your child theme’s directory, and that file will be used instead of the parent theme’s header.php.

You can also include files in the child theme that are not included in the parent theme. For instance, you might want to create a more specific template than is found in your parent theme, such as a template for a specific page or category archive. See the Template Hierarchy for more information about how WordPress decides what template to use.

Using functions.php

Unlike style.css, the functions.php of a child theme does not override its counterpart from the parent. Instead, it is loaded in addition to the parent’s functions.php. (Specifically, it is loaded right before the parent’s file.)

In that way, the functions.php of a child theme provides a smart, trouble-free method of modifying the functionality of a parent theme. Say that you want to add a PHP function to your theme. The fastest way would be to open its functions.php file and put the function there. But that’s not smart: The next time your theme is updated, your function will disappear. But there is an alternative way which is the smart way: you can create a child theme, add a functions.php file in it, and add your function to that file. The function will do the exact same job from there too, with the advantage that it will not be affected by future updates of the parent theme. Do not copy the full content of functions.php of the parent theme into functions.php in the child theme.

The structure of functions.php is simple: An opening PHP tag at the top, a closing PHP tag at the bottom, and, between them, your bits of PHP. In it you can put as many or as few functions as you wish. The example below shows an elementary functions.php file that does one simple thing: Adds a favicon link to the head element of HTML pages.

<?php //Opening PHP tag

// Custom Function to Include
function favicon_link() {
    echo '<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />' . "\n";
add_action( 'wp_head', 'favicon_link' );

?> //Closing PHP tag

TIP FOR THEME DEVELOPERS. The fact that a child theme’s functions.php is loaded first means that you can make the user functions of your theme pluggable —that is, replaceable by a child theme— by declaring them conditionally. E.g.:

if ( ! function_exists( 'theme_special_nav' ) ) {
    function theme_special_nav() {
        //  Do something.

In that way, a child theme can replace a PHP function of the parent by simply declaring it beforehand.

Referencing / Including Files in Your Child Theme

When you need to include files that reside within your child theme’s directory structure, you will use get_stylesheet_directory(). Because the parent template’s style.css is replaced by your child theme’s style.css, and your style.css resides in the root of your child theme’s subdirectory, get_stylesheet_directory() points to your child theme’s directory (not the parent theme’s directory).

Here’s an example, using require_once, that shows how you can use get_stylesheet_directory when referencing a file stored within your child theme’s directory structure.

require_once( get_stylesheet_directory() . '/my_included_file.php' );

Other Useful Information

Using Post Formats

A child theme inherits post formats as defined by the parent theme. When creating child themes, be aware that using add_theme_support(‘post-formats’) will override the formats defined by the parent theme, not add to it.

RTL support

To support RTL languages, add rtl.css file to your child theme, containing:

Theme Name: Twenty Fourteen Child
Template: twentyfourteen

@import url("../twentyfourteen/rtl.css");

rtl.css is only loaded by WordPress if is_rtl() returns true.

It’s recommended to add the rtl.css file to your child theme even if the parent theme has no rtl.css file.


Child themes, much like other extensions, may be translated into other languages by using gettext functions. For an overview, please see Translating WordPress & I18n for WordPress Developers.

To internationalize a child theme follow these steps:

  • Add a languages directory.
    • Something like my-theme/languages/.
  • Add language files.
    • Your filenames have to be he_IL.po & (depending on your language), unlike plugin files which are domain-he_IL.xx.
  • Load a textdomain.
    • Use load_child_theme_textdomain() in functions.php during the after_setup_theme action.
    • The text domain defined in load_child_theme_textdomain() should be used to translate all strings in the child theme.
  • Use GetText functions to add i18n support for your strings.

Example: textdomain

 * Setup My Child Theme's textdomain.
 * Declare textdomain for this child theme.
 * Translations can be filed in the /languages/ directory.
function my_child_theme_setup() {
	load_child_theme_textdomain( 'my-child-theme', get_stylesheet_directory() . '/languages' );
add_action( 'after_setup_theme', 'my_child_theme_setup' );

Example: gettext functions

_e( 'Code is Poetry', 'my-child-theme' );

To sum up, all strings that use “my-child-theme” textdomain will be translatable. The translation files must reside in “/languages/” directory.

How to Use Gravatars on your Site

Using Gravatars on your Site

To start using Gravatars on your site:

  1. Log in as an administrator to your site
  2. Navigate to Settings > Discussion and scroll down to the “Avatar” Section
  3. The “Avatar” section presents you with several options:
    • Avatar Display: Toggle Gravatars on and off for your site.
    • Maximum Rating: When users create a profile on Gravatar, they are given the opportunity to rate their Gravatar image as G, PG, R, X based on its appropriateness. Select the radio button for the maximum rating you would like displayed on your site.
    • Default Avatar: WordPress allows for you to select what image you would like to display when a commenter does not have a Gravatar account. Selecting one of the “generated” icons gives you and your users some of the benefits of a Gravatar without requiring them to have a Gravatar account. The icons that say “generated” next to them take the email of the commenter and link it to an auto-generated image. Now, every time that commenter posts to your site, they will have the same unique image next to their name.

For Developers

Starting with WordPress 2.7, when you retrieve the comments on a post or page using wp_list_comments, WordPress will automatically retrieve your users’ Gravatars. If you would like to retrieve a user’s Gravatar without retrieving comments, you can use get_avatar.

Customizing how Gravatars are displayed

Using wp_list_comments allows you to customize how WordPress outputs your comments in your theme. It also controls the size of the Gravatar attached to the comments. By default, Gravatars are displayed at 32px x 32px. To change the size of the Gravatar, you can use the ‘avatar_size’ argument with wp_list_comments.

For example, to return a 50px x 50px Gravatar, you would call wp_list_comments like this:

<?php wp_list_comments( array( 'avatar_size' => '50' ) ); ?>

get_avatar works slightly different. The first argument you pass it must be a user’s ID, email address or the comment object. You can then specify the size of the returned Gravatar, the URL for the default image you want to display if a user does not have a Gravatar, and the alternate text for the Gravatar image.

This will return a 50px x 50px Gravatar:

<?php echo get_avatar( '', 50 ); ?>

Customizing Gravatars with CSS

Because you can retrieve Gravatars with or without comments, you need to be specific with your CSS classes when styling Gravatars. When WordPress returns Gravatars, it assigns them the .avatar class. However, you don’t want to only target the class .avatar because it is generated in different contexts. For example, when you hover over the Gravatar in the WordPress admin bar, the Gravatar that appears has the .avatar class. If you were to change the CSS for the .avatar class, you would alter the style of both the Gravatar in your theme’s comments and admin bar.

As the Twenty Eleven theme demonstrates, you can simply use an additional class to target a specific instance of a Gravatar.

This will change the display of Gravatars only in the Twenty Eleven theme’s comments:

.commentlist .avatar {
	Here */

Create a Custom Default Avatar

If you don’t want to use any of the default images for users not registered with Gravatar, you can easily add your own by adding a filter to the avatar_defaults hook.

After uploading the new image to your theme files, add this to your theme’s function.php file:

add_filter( 'avatar_defaults', 'new_default_avatar' );

function new_default_avatar ( $avatar_defaults ) {
		//Set the URL where the image file for your avatar is located
		$new_avatar_url = get_bloginfo( 'template_directory' ) . '/images/new_default_avatar.png';
		//Set the text that will appear to the right of your avatar in Settings>>Discussion
		$avatar_defaults[$new_avatar_url] = 'Your New Default Avatar';
		return $avatar_defaults;

Now, go to Settings > Discussion and select your new avatar from the list.

Select Your New Default Avatar

From now on, all your users that don’t use Gravatar will have this avatar next to their comments.

Custom Default Avatar in Use

Using Gravatar’s Hovercards

If you want to use Gravatar’s Hovercard feature, like on, you can install the Jetpack Plugin.

An example of a Hovercard

Fun Character Entities


Character Entities or Extended Characters

In many WordPress sites, you will see odd symbols that will pop up from time to time. Often these symbols appear in navigation links. For instance, look at the the double left angle quotes («) and the double right angle quotes (») in this example:

These symbols are called HTML character entities or extended characters. They are generated by strange looking code on the web page that the web browser interprets as symbols.

The code that generated the above example looks like this:

<?php previous_post('&laquo; &laquo; %', '', 'yes'); ?>
| <?php next_post('% &raquo; &raquo; ', '', 'yes'); ?>

Some of the most popular HTML character entities are:

&raquo;     »     double right angle quote
&laquo;     «      double left angle quote
&lt;     <      single left arrow (left angle bracket)
&gt;     >      single right arrow (right angle bracket)
&bull;     •      bullet
     or     &hearts;      ♥      black heart
   or   &diams;     ♦    black diamond
   or   &clubs;   ♣    black clubs (shamrock)
   or   &spades;     ♠      black spade
    ∞      infinity symbol
&mdash;    —      long dash

Using Character Entities in WordPress

Using character entities can be a fun part of your design! You can use these special accents with template tags such as the the_category() tag. Note: the_category() template tag lists, in post meta data section, the various categories assigned to a post.

In this example, the special character entity, the heart () symbol, separates the categories of WordPress, Computers, and Internet News:

<?php the_category(' &hearts; ') ?>
WordPress ♥ Computers ♥ Internet News

In this example you see the use of an accent in your post’s title:

<?php the_title('∞ ', ' ∞'); ?> 
∞ WordPress Makes Me Smile ∞

If you want to highlight the post’s author, you don’t have to use a character entity inside of a WordPress template tag. You can use it in the text.

<div id="author">&diams; <?php the_author(); ?></div>
♦ Harriet Smith

As you have seen, there are a many uses for character entities within your site. With this information you can experiment and find creative ways to use these symbols in your design!

Note: Not all template tags can use character entities, especially those tags that use boolean parameters. Test a template tag thoroughly to be sure that it will accept the symbols.

Custom Login Form

The Login Form

At the top of login page is the WordPress logo and link, followed by the login form, with:

WordPress login form page screenshot
  • Input fields for “Username” and “Password.”
  • A “Remember Me” checkbox. If checked your browser keeps you logged in for 14 days. (If unchecked you’re logged out when you quit the browser, or after two days.)
  • The “Log In” button for submitting the form data.

Below the form are two links: One is for registered users who’ve forgotten their password. The other goes to the front page of your WordPress site.

This one login form can do three things:

  1. Log into a site (by filling in a valid Username and Password).
  2. Email a password to a registered user (by clicking the Lost your password? (link: wp-login.php?action=lostpassword).
  3. Register new users (who’ve arrived at this form by clicking a Register (link: wp-login.php?action=register).

Customizing the WordPress Login

Much of WordPress login page can be easily changed with WordPress Plugins (search for “login”). It can also be changed by manually adding code to the WordPress Theme’s functions.php file.

Change the Login Logo

To change the WordPress logo to your own, you will need to change the CSS styles associated with this heading:

<h1><a href="" title="Powered by WordPress">Your Site Name</a></h1>

WordPress uses CSS to display a background image — the WordPress logo — in the link (<a>) inside the heading tag (<h1>). You can use the login_enqueue_scripts hook to insert CSS into the head of the login page so your logo loads instead. To use the code below, replace the file named site-login-logo.png with the file-name of your logo, and store your logo with your active Theme files in a directory named /images:

function my_login_logo() { ?>
    <style type="text/css">
        body.login div#login h1 a {
            background-image: url(<?php echo get_stylesheet_directory_uri(); ?>/images/site-login-logo.png);
            padding-bottom: 30px;
<?php }
add_action( 'login_enqueue_scripts', 'my_login_logo' );

The size of your logo should be no bigger than 80 x 80 pixels (though even this can change with custom CSS). Adjust the above padding-bottom value to the spacing you want between your logo and the login form.

To change the link values so the logo links to your WordPress site, use the following WordPress hooks example; edit it and paste it below the previous in the functions.php:

function my_login_logo_url() {
    return home_url();
add_filter( 'login_headerurl', 'my_login_logo_url' );

function my_login_logo_url_title() {
    return 'Your Site Name and Info';
add_filter( 'login_headertitle', 'my_login_logo_url_title' );

Styling Your Login

You can style every HTML element on the WordPress login page with CSS. To add styles to the <head> of your login page, use a function like the above my_login_logo. Styles declared within the head element of a page are called an “embedded style sheet” and take precedence over styles in linked external style sheets.

If you have a lot of login page styles, you may want to make your own custom login style sheet. This code, added to your functions.php file, would load a CSS file named style-login.css, stored with your active Theme files:

function my_login_stylesheet() {
    wp_enqueue_style( 'custom-login', get_template_directory_uri() . '/style-login.css' );
    wp_enqueue_script( 'custom-login', get_template_directory_uri() . '/style-login.js' );
add_action( 'login_enqueue_scripts', 'my_login_stylesheet' );

WordPress links two of its own external style sheets to the login page: wp-admin/css/colors.css and wp-admin/css/wp-admin.css (since Version 3.8, previous versions used wp-admin/css/color/color-fresh.css, wp-admin/css/login.css). You can override the WordPress default styles by making your style declaration more “specific” — when two styles apply to the same element, CSS gives precedence to the more specific selector.

Here’s some helpful, highly specifc CSS selectors for the login page:

body.login {}
body.login div#login {}
body.login div#login h1 {}
body.login div#login h1 a {}
body.login div#login form#loginform {}
body.login div#login form#loginform p {}
body.login div#login form#loginform p label {}
body.login div#login form#loginform input {}
body.login div#login form#loginform input#user_login {}
body.login div#login form#loginform input#user_pass {}
body.login div#login form#loginform p.forgetmenot {}
body.login div#login form#loginform p.forgetmenot input#rememberme {}
body.login div#login form#loginform p.submit {}
body.login div#login form#loginform p.submit input#wp-submit {}
body.login div#login p#nav {}
body.login div#login p#nav a {}
body.login div#login p#backtoblog {}
body.login div#login p#backtoblog a {}

WordPress uses the CSS style sheet wp-admin.css to insert the logo and to hide the heading text with text-indent:-9999px;:

.login h1 a {
	background-image: url('../images/w-logo-blue.png?ver=20131202');
	background-image: none, url('../images/wordpress-logo.svg?ver=20131107');
	background-size: 80px 80px;
	background-position: center top;
	background-repeat: no-repeat;
	color: #999;
	height: 80px;
	font-size: 20px;
	font-weight: normal;
	line-height: 1.3em;
	margin: 0 auto 25px;
	padding: 0;
	text-decoration: none;
	width: 80px;
	text-indent: -9999px;
	outline: none;
	overflow: hidden;
	display: block;

Using a more specific selector in your custom style sheet overrides the above background-image value, inserting your logo instead:

body.login div#login h1 a {
    background-image: url("images/site-logo.png");

The default login page style in colors.css sets the text color of the links below the form:

.login #nav a,
.login #backtoblog a {
	text-decoration: none;
	color: #999;

To override that, increase the specificity and include !important:

body.login div#login p#nav a,
body.login div#login p#backtoblog a {
    color: #0c0 !important; /* Your link color. */

Login Hooks

Login form screenshot demonstrating content added via hooks

You can customize your WordPress login page with action hooks and filter hooks, including:

  • Actions in the <head> of the document: login_enqueue_scripts, login_head.
  • Filters in the <body>: login_headerurl, login_headertitle, login_message, login_errors.
  • Actions at the bottom of and below the form: login_form, login_footer.

The image to the right shows where several of the hooks can add content.

The above hooks run when using the form to login. Others are meant for registration, password retrieval, and WordPress Plugins.

The WordPress file wp-login.php generates the HTML, containing the location and sequence of all the login page hooks.

Make a Custom Login Page

So far you’ve seen how to customize WordPress’ built-in login page. You can also create your own custom login Page by using the wp_login_form function in one of your WordPress Theme’s Page Templates:

<?php wp_login_form(); ?>

The function has several parameters to change the default settings. For instance, you can specify: the ID names of the form and its elements (for CSS styling), whether to print the “Remember Me” checkbox, and the URL a user is redirected to after a successful login (default is to stay on the same Page):

if ( ! is_user_logged_in() ) { // Display WordPress login form:
    $args = array(
        'redirect' => admin_url(), 
        'form_id' => 'loginform-custom',
        'label_username' => __( 'Username custom text' ),
        'label_password' => __( 'Password custom text' ),
        'label_remember' => __( 'Remember Me custom text' ),
        'label_log_in' => __( 'Log In custom text' ),
        'remember' => true
    wp_login_form( $args );
} else { // If logged in:
    wp_loginout( home_url() ); // Display "Log Out" link.
    echo " | ";
    wp_register('', ''); // Display "Site Admin" link.
Screenshot of wp_login_form display, with filters adding text

The above function parameters:

  • Redirect the user to the Administration Dashboard Screen after login.
  • Set the ID name for the form: id="loginform-custom".
  • Change the text labels for the form elements (e.g., from the default “Username” to, in this example, “Username custom text”).
  • Print the “Rememeber Me” checkbox.

If the user is already logged in, the form does not print; instead they see two links: Log Out | Site Admin.

This login form has the filters: login_form_top, login_form_middle, and login_form_bottom. Each can print text in the form, as shown in the image on the right.

The form itself is generated by code in the WordPress wp-includes/general-template.php file. Because your custom login Page is different than the built-in WordPress login page (wp-login.php), the same CSS stylesheets do not apply. But your active Theme’s stylesheet (style.css) does apply, so use that to style this form.

Other template tags related to login functionality include wp_login_url, wp_logout_url, wp_loginout, wp_lostpassword_url, login_redirect, and wp_register.

Add Navigation Menu On Theme

Register Menus

Firstly, in your theme’s functions.php, you need to write a function to register the names of your menus. (This is how they will appear in the Appearance -> Menus admin screen.) As an example, this menu would appear in the “Theme Locations” box as “Header Menu”.

function register_my_menu() {
  register_nav_menu('header-menu',__( 'Header Menu' ));
add_action( 'init', 'register_my_menu' );

And this would make two menu options appear, header menu and extra menu –

function register_my_menus() {
      'header-menu' => __( 'Header Menu' ),
      'extra-menu' => __( 'Extra Menu' )
add_action( 'init', 'register_my_menus' );

Display Menus on Theme

Once you’ve done that, your theme will be almost ready. The last preparation step is to tell the theme where you want the menus to show up. You do this in the relevant theme file. So, for example, we might want our header menu to be in header.php. So open up that file in the theme editor, and decide where you want to put your menu. The code to use here is wp_nav_menu which we will need once for each menu location. So, add this code –

<?php wp_nav_menu( array( 'theme_location' => 'header-menu' ) ); ?>

All you need to ensure is that the theme_location points to the name you provided for your menu in the functions.php code above. (Note that it’s the header-menu being used here rather than Header Menu without a hyphen. header-menu is the name that the code understands, Header Menu is the human-readable version that you see in the admin page.)

To complete the code, you can put your extra menu someplace else. Maybe you want a menu on one of your pages, for example, and you might even want it to be jazzed up a little with a containing DIV of a certain class –

wp_nav_menu( array( 'theme_location' => 'extra-menu', 'container_class' => 'my_extra_menu_class' ) );

So you’d put the above into your Page template, and not only would the menu show up wherever you put it, it’d be styled as my_extra_menu_class so that you can work with that in CSS.

Menus Panel

That’s all the background work. To finish, you would simply visit the Appearance -> Menus panel in your site admin. Now, instead of seeing some text suggesting that your theme doesn’t natively support menus, you’ll see some Theme Location options.

You can now use the GUI menu creator on this admin panel to put your menu(s) together. Give them each a name, and then assign a menu to a location with the pull-down options.

(You will see your new navigation choices when you Add a New Menu.


Create a Plugins

Creating a Plugin

This section of the article goes through the steps you need to follow, and things to consider when creating a well-structured WordPress Plugin.

Names, Files, and Locations

Plugin Name

The first task in creating a WordPress Plugin is to think about what the Plugin will do, and make a (hopefully unique) name for your Plugin. Check out Plugins and the other repositories it refers to, to verify that your name is unique; you might also do a Google search on your proposed name. Most Plugin developers choose to use names that somewhat describe what the Plugin does; for instance, a weather-related Plugin would probably have the word “weather” in the name. The name can be multiple words.

Plugin Files

The next step is to create a PHP file with a name derived from your chosen Plugin name. For instance, if your Plugin will be called “Fabulous Functionality”, you might call your PHP file fabulous-functionality.php. Again, try to choose a unique name. People who install your Plugin will be putting this PHP file into the WordPress Plugins directory in their installation (usually wp-content/plugins/), so no two Plugins they are using can have the same PHP file name.

Another option is to split your Plugin into multiple files. Your WordPress Plugin must have at least one PHP file; it could also contain JavaScript files, CSS files, image files, language files, etc. If there are multiple files, pick a unique name for a directory and a name of your choice (usually the same) for the main PHP file of your Plugin, such as fabulous-functionality and fabulous-functionality.php, respectively, put all your Plugin’s files into that directory, and tell your Plugin users to install the whole directory under wp-content/plugins/. Notice that WordPress installation can be configured for wp-content/plugins/ directory to be moved, so you must use plugin_dir_path() and plugins_url() for absolute paths and URLs. See: for more details.

In the rest of this article, “the Plugin PHP file” refers to the main Plugin PHP file, whether in wp-content/plugins/ or a sub-directory.

Security Note: Consider blocking direct access to your plugin PHP files by adding the following line at the top of each of them, or be sure to refrain from executing sensitive standalone PHP code before calling any WordPress functions.

defined('ABSPATH') or die("No script kiddies please!");

Readme File

If you want to host your Plugin on, you also need to create a readme.txt file in a standard format, and include it with your Plugin. See for a description of the format or use the automatic plugin ‘readme.txt’ generator.

Note that the WordPress plugin repository takes the “Requires” and “Tested up to” versions from the readme.txt in the stable tag.

Home Page

It is also very useful to create a web page to act as the home page for your WordPress Plugin. This page should describe how to install the Plugin, what it does, what versions of WordPress it is compatible with, what has changed from version to version of your Plugin, and how to use the Plugin.

File Headers

Now it’s time to put some information into your main Plugin PHP file.

Standard Plugin Information

The top of your Plugin’s main PHP file must contain a standard Plugin information header. This header lets WordPress recognize that your Plugin exists, add it to the Plugin management screen so it can be activated, load it, and run its functions; without the header, your Plugin will never be activated and will never run. Here is the header format:

 * Plugin Name: Name Of The Plugin
 * Plugin URI: http://URI_Of_Page_Describing_Plugin_and_Updates
 * Description: A brief description of the Plugin.
 * Version: The Plugin's Version Number, e.g.: 1.0
 * Author: Name Of The Plugin Author
 * Author URI: http://URI_Of_The_Plugin_Author
 * License: A "Slug" license name e.g. GPL2

The minimum information WordPress needs to recognize your Plugin is the Plugin Name line. The rest of the information (if present) will be used to create the table of Plugins on the Plugin management screen. The order of the lines is not important.

So that the upgrade mechanism can correctly read the version of your plugin it is recommended that you pick a format for the version number and stick to it between the different releases. For example, x.x or x.x.x or

The License slug should be a short common identifier for the license the plugin is under and is meant to be a simple way of being explicit about the license of the code.

Important: file must be in UTF-8 encoding.


It is customary to follow the standard header with information about licensing for the Plugin. Most Plugins use the GPL2 license used by WordPress or a license compatible with the GPL2. To indicate a GPL2 license, include the following lines in your Plugin:


    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License, version 2, as 
    published by the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

Programming Your Plugin

Now, it’s time to make your Plugin actually do something. This section contains some general ideas about Plugin development, and describes how to accomplish several tasks your Plugin will need to do.

WordPress Plugin Hooks

Many WordPress Plugins accomplish their goals by connecting to one or more WordPress Plugin “hooks”. The way Plugin hooks work is that at various times while WordPress is running, WordPress checks to see if any Plugins have registered functions to run at that time, and if so, the functions are run. These functions modify the default behavior of WordPress.

For instance, before WordPress adds the title of a post to browser output, it first checks to see if any Plugin has registered a function for the “filter” hook called “the_title”. If so, the title text is passed in turn through each registered function, and the final result is what is printed. So, if your Plugin needs to add some information to the printed title, it can register a “the_title” filter function.

Another example is the “action” hook called “wp_footer”. Just before the end of the HTML page WordPress is generating, it checks to see whether any Plugins have registered functions for the “wp_footer” action hook, and runs them in turn.

You can learn more about how to register functions for both filter and action hooks, and what Plugin hooks are available in WordPress, in the Plugin API. If you find a spot in the WordPress code where you’d like to have an action or filter, but WordPress doesn’t have one, you can also suggest new hooks (suggestions will generally be taken); see Reporting Bugs to find out how.

Template Tags

Another way for a WordPress Plugin to add functionality to WordPress is by creating custom Template Tags. Someone who wants to use your Plugin can add these “tags” to their theme, in the sidebar, post content section, or wherever it is appropriate. For instance, a Plugin that adds geographical tags to posts might define a template tag function called geotag_list_states() for the sidebar, which lists all the states posts are tagged with, with links to the state-based archive pages the Plugin enables.

To define a custom template tag, simply write a PHP function and document it for Plugin users on your Plugin’s home page and/or in the Plugin’s main PHP file. It’s a good idea when documenting the function to give an example of exactly what needs to be added to the theme file to use the function, including the <?php and ?>.

Saving Plugin Data to the Database

Most WordPress Plugins will need to get some input from the site owner or blog users and save it between sessions, for use in its filter functions, action functions, and template functions. This information has to be saved in the WordPress database, in order to be persistent between sessions. There are four (4) methods for saving Plugin data in the database:

  1. Use the WordPress “option” mechanism (described below). This method is appropriate for storing relatively small amounts of relatively static, named pieces of data — the type of data you’d expect the site owner to enter when first setting up the Plugin, and rarely change thereafter.
  2. Post Meta (a.k.a. Custom Fields). Appropriate for data associated with individual posts, pages, or attachments. See post_meta Function Examples, add_post_meta(), and related functions.
  3. Custom Taxonomy. For classifying posts or other objects like users and comments and/or for a user-editable name/value list of data consider using a Custom Taxonomy, especially when you want to access all posts/objects associated with a given taxonomy term. See Custom Taxonomies.
  4. Create a new, custom database table. This method is appropriate for data not associated with individual posts, pages, attachments, or comments — the type of data that will grow as time goes on, and that doesn’t have individual names. See Creating Tables with Plugins for information on how to do this.

WordPress Options Mechanism

See Creating Options Pages for info on how to create a page that will automatically save your options for you.

WordPress has a mechanism for saving, updating, and retrieving individual, named pieces of data (“options”) in the WordPress database. Option values can be strings, arrays, or PHP objects (they will be “serialized”, or converted to a string, before storage, and unserialized when retrieved). Option names are strings, and they must be unique, so that they do not conflict with either WordPress or other Plugins.

It’s also generally considered a good idea to minimize the number of options you use for your plugin. For example, instead of storing 10 different named options consider storing a serialized array of 10 elements as a single named option.

Here are the main functions your Plugin can use to access WordPress options.

add_option($name, $value, $deprecated, $autoload);
Creates a new option; does nothing if option already exists.
Required (string). Name of the option to be added.
Optional (mixed), defaults to empty string. The option value to be stored.
Optional (string), no longer used by WordPress, You may pass an empty string or null to this argument if you wish to use the following $autoload parameter.
Optional, defaults to ‘yes’ (enum: ‘yes’ or ‘no’). If set to ‘yes’ the setting is automatically retrieved by the wp_load_alloptions function.
Retrieves an option value from the database.
Required (string). Name of the option whose value you want returned. You can find a list of the default options that are installed with WordPress at the Option Reference.
update_option($option_name, $newvalue);
Updates or creates an option value in the database (note that add_option does not have to be called if you do not want to use the $deprecated or $autoload parameters).
Required (string). Name of the option to update.
Required. (string|array|object) The new value for the option.

Administration Panels

Assuming that your Plugin has some options stored in the WordPress database (see section above), you will probably want it to have an administration panel that will enable your Plugin users to view and edit option values. The methods for doing this are described in Adding Administration Menus.

Internationalizing Your Plugin

Once you have the programming for your Plugin done, another consideration (assuming you are planning on distributing your Plugin) is internationalization. Internationalization is the process of setting up software so that it can be localized; localization is the process of translating text displayed by the software into different languages. WordPress is used all around the world, so it has internationalization and localization built into its structure, including localization of Plugins.

Please note that language files for Plugins ARE NOT automatically loaded. Add this to the Plugin code to make sure the language file(s) are loaded:

	load_plugin_textdomain('your-unique-name', false, basename( dirname( __FILE__ ) ) . '/languages' );

To fetch a string simply use __(‘String name’,’your-unique-name’); to return the translation or _e(‘String name’,’your-unique-name’); to echo the translation. Translations will then go into your plugin’s /languages folder.

It is highly recommended that you internationalize your Plugin, so that users from different countries can localize it. There is a comprehensive reference on internationalization, including a section describing how to internationalize your plugin, at I18n for WordPress Developers.

Updating Your Plugin

This section describes the necessary steps to update your Plugin when you host it on, including details about using Subversion (SVN) with

Assuming you have already submitted your Plugin to the WordPress Plugin Repository, over time you will probably find the need, and hopefully the time, to add features to your Plugin or fix bugs. Work on these changes and commit the changes to the trunk of your plugin as often as you want. The changes will be publicly visible, but only to the technically-minded people checking out your Plugin via SVN. What other users download through the website or their WordPress Plugin administration will not change.

When you’re ready to release a new version of the Plugin:

  • Make sure everything is committed and the new version actually works. Pay attention to all WordPress versions your Plugin supports and try to test it with all of them. Don’t just test the new features; also make sure you didn’t accidentally break some older functionality of the Plugin.
  • Change the version number in the header comment of the main PHP file to the new version number (in the trunk folder).
  • Change the version number in the ‘Stable tag’ field of the readme.txt file (in the trunk folder).
  • Add a new sub-section in the ‘changelog’ section of the readme.txt file, briefly describing what changed compared to the last release. This will be listed on the ‘Changelog’ tab of the Plugin page.
  • Commit these changes.
  • Create a new SVN tag as a copy of trunk, following this guide.

Give the system a couple of minutes to work, and then check the Plugin page and a WordPress installation with your Plugin to see if everything updated correctly and the WordPress installation shows an update for your Plugin (the update checks might be cached, so this could take some time — try visiting the ‘available updates’ page in your WordPress installation).


  • The Plugin’s page on still lists the old version. Have you updated the ‘stable tag’ field in the trunk folder? Just creating a tag and updating the readme.txt in the tag folder is not enough!
  • The Plugin’s page offers a zip file with the new version, but the button still lists the old version number and no update notification happens in your WordPress installations. Have you remembered to update the ‘Version’ comment in the main PHP file?
  • For other problems check Otto’s good write-up of common problems: The Plugins directory and readme.txt files

Plugin Development Suggestions

This last section contains some random suggestions regarding Plugin development.

  • The code of a WordPress Plugin should follow the WordPress Coding Standards. Please consider the Inline Documentation Standards as well.
  • All the functions in your Plugin need to have unique names that are different from functions in the WordPress core, other Plugins, and themes. For that reason, it is a good idea to use a unique function name prefix on all of your Plugin’s functions. A far superior possibility is to define your Plugin functions inside a class (which also needs to have a unique name).
  • Do not hardcode the WordPress database table prefix (usually “wp_”) into your Plugins. Be sure to use the $wpdb->prefix variable instead.
  • Database reading is cheap, but writing is expensive. Databases are exceptionally good at fetching data and giving it to you, and these operations are (usually) lightning quick. Making changes to the database, though, is a more complex process, and computationally more expensive. As a result, try to minimize the amount of writing you do to the database. Get everything prepared in your code first, so that you can make only those write operations that you need.
  • Use WordPress’ APIs instead of using direct SQL where possible. For example, use get_posts() or new WP_Query() instead of SELECT * FROM {$wpdb->prefix}_posts.
  • Use the existing database tables instead of creating new custom tables if possible. Most use-cases can be accomplished with custom post types and meta data, custom taxonomy and/or one of the other standard tables and using the standard tables provides a lot of UI and other functionality “for free.” Think very carefully before adding a table because it adds complexity to your plugin that many users and site builders prefer to avoid.
  • SELECT only what you need. Even though databases fetch data blindingly fast, you should still try to reduce the load on the database by only selecting that data which you need to use. If you need to count the number of rows in a table don’t SELECT * FROM, because all the data in all the rows will be pulled, wasting memory. Likewise, if you only need the post_id and the post_author in your Plugin, then just SELECT those specific fields, to minimize database load. Remember: hundreds of other processes may be hitting the database at the same time. The database and server each have only so many resources to spread around amongst all those processes. Learning how to minimize your Plugin’s hit against the database will ensure that your Plugin isn’t the one that is blamed for abuse of resources.
  • Eliminate PHP errors in your plugin. Add define('WP_DEBUG', true); to your wp-config.php file, try all of your plugin functionality, and check to see if there are any errors or warnings. Fix any that occur, and continue in debug mode until they have all been eliminated.
  • Try not to echo <script> and <style> tags directly – instead use the recommended wp_enqueue_style() and wp_enqueue_script() functions. They help eliminate including duplicate scripts and styles as well as introduce dependency support. See posts by the following people for more info: Ozh Richard, Artem Russakovskii, and Vladimir Prelovac.