Menu Search
Jump to the content X X
Smashing Conf Barcelona

You know, we use ad-blockers as well. We gotta keep those servers running though. Did you know that we publish useful books and run friendly conferences — crafted for pros like yourself? E.g. our upcoming SmashingConf Barcelona, dedicated to smart front-end techniques and design patterns.

WordPress Essentials: How To Create A WordPress Plugin

WordPress plugins are PHP scripts that alter your website. The changes could be anything from the simplest tweak in the header to a more drastic makeover (such as changing how log-ins work, triggering emails to be sent, and much more). This article has been checked and updated on July 5th, 2017.

Whereas themes modify the look of your website, plugins change how it functions. With plugins, you can create custom post types, add new tables to your database to track popular articles, automatically link your contents folder to a “CDN1” server such as Amazon S3… you get the picture.

Further Reading on SmashingMag: Link

Theme Or Plugin? Link

If you’ve ever played around with a theme, you’ll know it has a functions.php file, which gives you a lot of power and enables you to build plugin-like functionality into your theme. So, if we have this functions.php file, what’s the point of a plugin? When should we use one, and when should we create our own?


The line here is blurrier than you might think, and the answer will often depend on your needs. If you just want to modify the default length of your posts’ excerpts, you can safely do it in functions.php. If you want something that lets users message each other and become friends on your website, then a plugin would better suit your needs.

The main difference is that a plugin’s functionality persists regardless of what theme you have enabled, whereas any changes you have made in functions.php will stop working once you switch themes. Also, grouping related functionality into a plugin is often more convenient than leaving a mass of code in functions.php.

Creating Our First PlugIn Link

To create a plugin, all you need to do is create a folder and then create a single file with one line of content. Navigate to the wp-content/plugins folder, and create a new folder named awesomeplugin. Inside this new folder, create a file named awesomeplugin.php. Open the file in a text editor, and paste the following information in it:

   Plugin Name: Awesomeness Creator
   Plugin URI:
   Description: a plugin to create awesomeness and spread joy
   Version: 1.2
   Author: Mr. Awesome
   Author URI:
   License: GPL2

Of all this information, only the plugin’s name is required. But if you intend to distribute your plugin, you should add as much data as possible.

With that out of the way, you can go into the back end to activate your plugin. That’s all there is to it! Of course, this plugin doesn’t do anything; but strictly speaking, it is an active, functioning plugin.

Structuring PlugIns Link

When creating complex functionality, splitting your plugin into multiple files and folders might be easier. The choice is yours, but following a few good tips will make your life easier.

If your plugin focuses on one main class, put that class in the main plugin file, and add one or more separate files for other functionality. If your plugin enhances WordPress’ back end with custom controls, you can create the usual CSS and JavaScript folders to store the appropriate files.

Generally, aim for a balance between layout structure, usability and minimalism. Split your plugin into multiple files as necessary, but don’t go overboard. I find it useful to look at the structure of popular plugins such as WP-PageNavi6 and Akismet7.

Naming Your PlugIn And Its Functions Link

When creating a plugin, exercise caution in naming the functions, classes and plugin itself. If your plugin is for generating awesome excerpts, then calling it “excerpts” and calling its main function “the_excerpt” might seem logical. But these names are far too generic and might clash with other plugins that have similar functionality with similar names.

The most common solution is to use unique prefixes. You could use “acme_excerpt,” for example, or anything else that has a low likelihood of matching someone else’s naming scheme.

Plugin Safety Link

If you plan to distribute your plugin, then security is of utmost importance, because now you are fiddling with other people’s websites, not just your own. All of the security measures you should take merit their own article, so keep an eye out for an upcoming piece on how to secure your plugin. For now, let’s just look at the theory in a nutshell; you can worry about implementation once you grasp that.

The safety of your plugin usually depends on the stability of its two legs. One leg makes sure that the plugin does not help spread naughty data. Guarding against this entails filtering the user’s input, escaping queries to protect against SQL injection attacks and so on. The second leg makes sure that the user has the authority and intention to perform a given action. This basically means that only users with the authority to delete data (such as administrators) should be able to do it. Guarding intention ensures that visitors aren’t misled by a hacker who has managed to place a malicious link on your website.

All of this is much easier to do than you might think, because WordPress gives you many functions to handle it. A number of other issues and best practices are involved, however, so we’ll cover those in a future article. There is plenty to learn and do until then; if you’re just starting out, don’t worry about all that for now.

Cleaning Up After Yourself Link

Many plugins are guilty of leaving a lot of unnecessary data lying around. Data that only your plugin uses (such as meta data for posts or comments, database tables, etc.) can wind up as dead weight if the plugin doesn’t clean up after itself.

WordPress offers three great hooks to help you take care of this:

  • register_activation_hook()8
    This hook allows you to create a function that runs when your plugin is activated. It takes the path to your main plugin file as the first argument, and the function that you want to run as the second argument. You can use this to check the version of your plugin, do some upgrades between versions, check for the correct PHP version and so on.
  • register_deactivation_hook()9
    The name says it all. This function works like its counterpart above, but it runs whenever your plugin is deactivated. I suggest using the next function when deleting data; use this one just for general housekeeping.
  • register_uninstall_hook()10
    This function runs when the website administrator deletes your plugin in WordPress’ back end. This is a great way to remove data that has been lying around, such as database tables, settings and what not. A drawback to this method is that the plugin needs to be able to run for it to work; so, if your plugin cannot uninstall in this way, you can create an uninstall.php11 file. Check out this function’s documentation for more information.

If your plugin tracks the popularity of content, then deleting the tracked data when the user deletes the plugin might not be wise. In this case, at least point the user to the location in the back end where they can find the plugin’s data, or give them the option to delete the data on the plugin’s settings page before deleting the plugin itself.

The net result of all our effort is that a user should be able to install your plugin, use it for 10 years and then delete it without leaving a trace on the website, in the database or in the file structure.

Documentation And Coding Standards Link

If you are developing for a big community, then documenting your code is considered good manners (and good business). The conventions for this are fairly well established — phpDocumentor12 is one example. But as long as your code is clean and has some documentation, you should be fine.

I document code for my own benefit as well, because I barely remember what I did yesterday, much less the purpose of functions that I wrote months back. By documenting code, you force good practices on yourself. And if you start working on a team or if your code becomes popular, then documentation will be an inevitable part of your life, so you might as well start now.

While not quite as important as documentation, following coding standards is a good idea if you want your code to comply with WordPress’ guidelines13.

Putting It Into Practice Link

All work and no play makes Jack a dull boy, so let’s do something with all of this knowledge that we’ve just acquired. To demonstrate, let’s build a quick plugin that tracks the popularity of our articles by storing how many times each post has been viewed. I will be using hooks, which we’ll cover in an upcoming installment in this series. Until then, as long as you grasp the logic behind them, all is well; you will understand hooks and plugins before long!

Planning Ahead Link

Before writing any code, let’s think ahead and try to determine the functions that our plugin will need. Here’s what I’ve come up with:

  • A function that registers a view every time an individual post is shown,
  • A function that enables us to retrieve the raw number of views,
  • A function that enables us to show the number of views to the user,
  • A function that retrieves a list of posts based on their view count.

Preparing Our Function Link

The first step is to create the folder and file structure. Putting all of this into one file will be fine, so let’s go to the plugins folder and create a new folder named awesomely_popular. In this folder, create a file named awesomely_popular.php. Open your new file, and paste some meta data at the top, something like this:

   Plugin Name: Awesomely Popular
   Plugin URI:
   Description: A plugin that records post views and contains functions to easily list posts by popularity
   Version: 1.0
   Author: Mr. Awesome
   Author URI:
   License: GPL2

Recording Post Views Link

Without delving too deep, WordPress hooks enable you to (among other things) fire off one of your functions whenever another WordPress function runs. So, if we can find a function that runs whenever an individual post is viewed, we are all set; all we would need to do is write our own function that records the number of views and hook it in. Before we get to that, though, let’s write the new function itself. Here is the code:

 * Adds a view to the post being viewed
 * Finds the current views of a post and adds one to it by updating
 * the postmeta. The meta key used is "awepop_views".
 * @global object $post The post object
 * @return integer $new_views The number of views the post has
function awepop_add_view() {
   if(is_single()) {
      global $post;
      $current_views = get_post_meta($post->ID, "awepop_views", true);
      if(!isset($current_views) OR empty($current_views) OR !is_numeric($current_views) ) {
         $current_views = 0;
      $new_views = $current_views + 1;
      update_post_meta($post->ID, "awepop_views", $new_views);
      return $new_views;

As you can see, I have added phpDocumentor-style documentation to the top of the function, and this is a pretty good indication of what to expect from this convention. First of all, using a conditional tag14, we determine whether the user is viewing a post on a dedicated page.

If the user is on a dedicated page, we pull in the $post object, which contains data about the post being shown (ID, title, posting date, comment count, etc.). We then retrieve the number of views that the post has already gotten. We will add 1 to this and then overwrite the orignal value with the new one. In case something goes wrong, we first check whether the current view count is what it should be.

The current view count must be set; it cannot be empty. And it must be numeric in order for us to be able to add 1 to it. If it does not meet these criteria, then we could safely bet that the current view count is 0. Next, we add 1 to it and save it to the database. Finally, we return the number of views that the post has gotten, together with this latest number.

So far, so good. But this function is never called, so it won’t actually be used. This is where hooks come in. You could go into your theme’s files and call the function manually from there. But then you would lose that functionality if you ever changed the theme, thus defeating the entire purpose. A hook, named wp_head, that runs just before the </head> tag is present in most themes, so we can just set our function to run whenever wp_head runs, like so:

add_action("wp_head", "awepop_add_view");

That’s all there is to the “mysticism” of hooks. We are basically saying, whenever wp_head runs, also execute the awepop_add_view function. You can place the code before or after the function itself.

Retrieving and Showing the Views Link

In the function above, I already use the WordPress get_post_meta()15 function to retrieve the views, so writing a separate function for this might seem a bit redundant. In this case, it might well be redundant, but it promotes some object-oriented thinking, and it gives us greater flexibility when further developing the plugin. Let’s take a look:

 * Retrieve the number of views for a post
 * Finds the current views for a post, returning 0 if there are none
 * @global object $post The post object
 * @return integer $current_views The number of views the post has
function awepop_get_view_count() {
   global $post;
   $current_views = get_post_meta($post->ID, "awepop_views", true);
   if(!isset($current_views) OR empty($current_views) OR !is_numeric($current_views) ) {
      $current_views = 0;

   return $current_views;

This is the same piece of code that we used in the awepop_add_view() function, so you could just use this to retrieve the view count there as well. This is handy, because if you decide to handle the 0 case differently, you only need to change it here. You will also be able to extend this easily and provide support for cases when we are not in the loop (i.e. when the $post object is not available).

So far, we have just retrieved the view count. Now, let’s show it. You might be thinking this is daft — all we need is echo awepop_get_view_count() . "views", no? That would certainly work, but what if there is only 1 view. In this case, we would need to use the singular “view.” You might also want the freedom to add some leading text or some other tidbit, which would be difficult to do otherwise. So, to allow for these scenarios, let’s write another simple function:

 * Shows the number of views for a post
 * Finds the current views of a post and displays it together with some optional text
 * @global object $post The post object
 * @uses awepop_get_view_count()
 * @param string $singular The singular term for the text
 * @param string $plural The plural term for the text
 * @param string $before Text to place before the counter
 * @return string $views_text The views display
function awepop_show_views($singular = "view", $plural = "views", $before = "This post has: ") {
   global $post;
   $current_views = awepop_get_view_count();

   $views_text = $before . $current_views . " ";

   if ($current_views == 1) {
      $views_text .= $singular;
   else {
      $views_text .= $plural;

   echo $views_text;


Show a List of Posts Based on Views Link

To show a list of posts based on view count, we create a function that we can place anywhere in our theme. The function will use a custom query and loop through the results, displaying a simple list of titles. The code is below, and the explanation follows.

 * Displays a list of posts ordered by popularity
 * Shows a simple list of post titles ordered by their view count
 * @param integer $post_count The number of posts to show
 function awepop_popularity_list($post_count = 10) {
  $args = array(
    "posts_per_page" => 10,
    "post_type" => "post",
    "post_status" => "publish",
    "meta_key" => "awepop_views",
    "orderby" => "meta_value_num",
    "order" => "DESC"
  $awepop_list = new WP_Query($args);
  if($awepop_list->have_posts()) { echo "<ul>"; }
  while ( $awepop_list->have_posts() ) : $awepop_list->the_post();
    echo '<li><a href="'.get_permalink($post->ID).'">'.the_title('', '', false).'</a></li>';
  if($awepop_list->have_posts()) { echo "</ul>";}

We start by passing a bunch of parameters to the WP_Query class, in order to create a new object that contains some posts. This class will do the heavy lifting for us: it finds 10 published posts that have awepop_views in the meta table, and orders them according to this property in descending order.

If posts meet this criterion, we create an unordered list element. Then, we loop through all of the posts that we have retrieved, showing each title as a link to the relevant post. We cap things off by adding a closing tag to the list when there are posts to show. Placing the awepop_popularity_list() function anywhere in your theme should now generate a simple list of posts ordered by popularity.

As an added precaution, place the call to this function in your theme, like so:

if (function_exists("awepop_popularity_list")) {

This ensures that if the plugin is disabled (and thus the function becomes undefined), PHP won’t throw a big ol’ error. It just won’t show the list of most popular posts.

Overview Link

By following the theory laid down in this article and using only a handful of functions, we have created a rudimentary plugin to track our most popular posts. It could be vastly improved, but it shows the basics of using plugins perfectly well. Moreover, by learning some patterns of WordPress development (plugins, hooks, etc.), you are gaining skills that will serve you in non-WordPress environments as well.

You should now be able to confidently follow tutorials that start with “First, create a WordPress plugin…” You now understand things not just on a need-to-know basis, but at a deeper level, which gives you more flexibility and power when coding your own plugins. Stay tuned for the upcoming article on hooks, actions and filters for an even more in-depth resource on the innards of plugins.


Footnotes Link

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15

↑ Back to top Tweet itShare on Facebook

Hallo, my name is Daniel :) I build plugins, themes and apps - then proceed to write or talk about them. I contribute to various other online sites. When not coding or writing you'll find me playing board games or running with my dog. Drop me a line on Twitter or visit my personal website.

  1. 1

    I created my first WordPress plugin called “Google+ Crossposting” (g-crossposting) a few days ago. It was not a big deal as there is good documentation in place. Now, the plugin is available on the official plugin repository, but I wonder how to get many testers so that I can get rid of any bugs hidden? Would be good if you could follow up your article with some ideas how to market new plugins so that we devs get some feedback.

    • 2

      Hi Sebastian,

      That’s a great article idea, I’ll keep it in mind! I’m sure if you post comments like the one you just did on sites that could go some way. Since you’re not shamelessly plugging your stuff (no pun intended) you’re just asking for help I’m sure a lot of people will be sympathetic.

      You could also try the wp mailing list, sending emails to developers who write personal blogs and so on to take a look. If the plugin is good some of them will like it and might write about it, hopefully the start of a snowball effect.

      If you want to write many plugins it might be a good idea to create a pseudo-business for it via a website, kind of a like a plugin portfolio.

      I’ll talk to the awesome people here at SM if anyone has extensive plugin promoting chops, I’m sure there are writers more experienced than I in this :)

      • 3

        How to put this code into widget?
        I tried like this in custom text widget, but not working

        if (function_exists(“awepop_popularity_list”)) {

  2. 4

    Recording post views, code example:

    ctype_digit is better than is_numeric, because you just want to implement a counter and therefore you don’t have to support floating point numbers.

    is_numeric(“-0123.45e6”) === true
    ctype_digit(“-0123.45e6”) === false

    Just to keep the stored data more clear, if anything is tampering with it.

    actually the best way to do it would be
    return (int) get_post_meta($post->ID, “awepop_views”, true);

    — same as with using ctype_digit (= only positive integers allowed) but with much less code and correct datatype usage.


    • 5

      Well commented Janik :)

      I think the second version is better, especially since this forces a data type. If you don’t force the data type, ctype_digit would return false for the string “12”. I think in most cases it is best to typecast.

      Thanks for expanding on that!

  3. 6

    Great post! It would be interesting to see how you could implement plugin settings within WP’s back end that would allow you to, say, set the # of posts that show up, or set the prefix text used before the # of views.

  4. 7

    Good article. I would love to see more information on filtering data to protect against attacks. If you are using update_option to put $_POST data into the db, do you still ned to sanitize data?

    I am checking that user has the authority, and am also curious if that can easily be spoofed.

    • 8

      Daniel Pataki

      October 1, 2011 1:51 am

      Hi Greg,

      Another article is coming up which deals with security measures you can take to make our website a bit more airtight. It is not just WordPress oriented, but will have a lot of WP specific code as well.

      It doesn’t answer your specific question, so here goes. There is no way the update_option could sanitize your data, since sanitization requires the knowledge of how to sanitize the data. If you look at the source code for the update_option function, you’ll notice that a sanitize_option function does exist, which you can find here:

      If you look at the switch in the function you’ll notice that it does sanitize known options, but not your custom ones. However, you can write a filter using the sanitize_option_[option name] filter. I hope that sufficiently answered question 1 :)

      As for question 2 I don’t think it can be spoofed easily. I am not a security expert so I’m sure others would know more about this that I. I would guess that the only way to spoof it would be to spoof the whole login system which is pretty secure as it uses a number of elements to make sure this doesn’t happen.

  5. 9

    Please, when you write PHP, try not to use this crappy Unix brace convention and use the recommended one :

    if ()

    • 10

      Daniel Pataki

      October 1, 2011 1:37 am

      I think this one is up to personal preference Joe. I’m sure that if you know about brace conventions you can read the code either way :)

    • 11

      Patrick Sweeney

      October 1, 2011 2:16 pm

      While I agree with you on which convention to use, you do realize it really is a personal preference right?

  6. 12

    How is it to build larger components (plugins) for WordPress? I just have experience with joomla.

    • 13

      Daniel Pataki

      October 1, 2011 10:32 pm

      Hi John,

      WordPress has become extremely competent in general CMS tasks as well, not just blogging. I highly recommend trying it out for larger projects.

  7. 14

    What about OOP? I’m developing class-based plugins and themes for about 2 years by now – makes a lot of troubles go away (aside of a cleaner code base), eg. function collisions.

    cu, w0lf.

    • 15

      Daniel Pataki

      October 1, 2011 11:49 am

      You’re absolutely right fwolf, but OOP is not for beginners for sure. For simple plugins it is not a path which is necessarily better than procedural. Lots of people who know OOP very well code horrible plugins because they fail to take other considerations into account.

      That said, I might write a more advanced tutorial incorporating some OOP awesomeness since that is definitely the way to go for advanced functionality.

  8. 16

    Good post. Just a small point, I think template_redirect would be a better hook to use than wp_head. I tend to see wp_head as being used to actually output stuff into the HTML header. AFAIK template_redirect is the earliest action you can hook onto after the post object is created, so it’s usually the best one to use for anything like this.

    • 17

      Daniel Pataki

      October 1, 2011 4:40 am

      There is certainly merit to this approach, semantically it is better for sure. As you say, wp _head is usually used to output things to the header or at least perform things which have something to do with it so using a different hook is a good idea, thanks for that.

  9. 18

    Great post!

    Personally I find the code quality of distributed wp plugins to be very low in general. Many wp-developers seem to lack the knowledge about the things that you’ve taken up in this post. That makes posts like these important, we have to spread the word about the things that should be considered common sense but for some reason isn’t :)

    OT, couldn’t if( !isset($current_views) OR empty($current_views) OR !is_numeric($current_views)) be shortened down to if(empty($current_views) OR !is_numeric($current_views)) ?

    • 19

      Daniel Pataki

      October 1, 2011 4:44 am

      Thanks Vic, I completely agree. There is actually pretty good documentation in the Code x so I don’t really know why plugin authors don’t take the time and have a look. There are tons of things on best practices and even code formatting, if such things exist I find it daft not to follow them (except for beta versions or tests).

      About your shortening question. It could, but it would generate a PHP warning if the $current views variable hasn’t been defined. If you slap isset into the beginning of an if statement you can stop that from happening. I tend to use the isset-empty combination on most variable checks as a “just-in-case” measure.

      • 20

        ah, you’r totally right!

        Not ensuring that a variable is defined before using it in a logical statement is another thing that you often see in the code of wp plugins. It’s actually the thing that frustrates me the most when working with wordpress. Especially when the suggested solution to the problem is to turn off error reporting, hiding the problem instead of solving it.

        • 21

          Daniel Pataki

          October 1, 2011 6:11 am

          I completely agree. It makes me especially cross when the solution is adding a simple isset() check. However there are so much more serious errors like people not enqueueing scripts and styles but outputting them directly to the header and so on.

          That said, its not as though I was born knowing how to enqueue scripts or knowing that isset is a good idea so I do give people the benefit of a doubt :)

  10. 22


    Great tutorial thanks. I only opened the box on wordpress a few days ago, so apols if this is a real newb problem I have.

    Implemented the above, and find it works-ish. Somehow, multiple records in the wordpress db are getting updated.

    EG – have two posts, “Hello World” with an id of 1 and “Goodbye World” with an id of 77.

    I view “Hello World”, and fine, it shows one view. Then I view “Goodbye World”, and it shows one view. But, interestingly enough, “Hello World” now shows 2 views.

    Every time I view ‘Hello World’, only its post count increments. Every time I view ‘Goodbye World’, both post counts increment.

    This is reflected in the postmeta table.

    Have gone over the code, can’t see any typos (copy and pasted it from above). Using the wp_head hook. Baffled. Any advice appreciated!

    • 23

      Daniel Pataki

      October 1, 2011 11:48 am

      Hi Ste H,

      No worries, there are no newbie questions, everyone has to start off somehow :) The problem you described sounds weird indeed. The odd thing is that it only updates both if you view the second post.

      The only thing I can think of is that apart from the view being automatically recorded when you load the page, you ALSO call the awepop_add_view() function separately from inside the post file.

      This is still a bit iffy since this would require you do have an if statement which would exclude this from happening when viewing the first post, I’m sure you would have noticed this.

      There are a few ways in which the behavior could happen though but if you didn’t make any modifications to the code this shouldn’t happen. If you tie the awepop_add_view() function to an incorrect hook (one which runs for each post the front page for example) it could record a view for both, but only if you remove the is_single() condition or in some other rare cases.

      Otherwise it could only happen if there is a php loop involved somewhere. The function works by adding +1 to the meta table for a SINGLE post. the update_post_meta is not capable of adding values for multiple posts, so if that DOES happen it is definitely placed in a loop somewhere.

      I hope I could help, let me know if you need some more assistance let me know

      • 24

        Thanks for the response. Afraid I’m still stuck – Like you I can’t work out why it is updating another record.

        More info – I viewed a further record, lets say 75. Now, when I view 75, the views are updated on 75 and 77, but not 1. When I view 75, it still updates 75 and 1. The only relation I can see between these records is their position in wp_postmeta – It seems that the correct record is having it’s count updated, and the next record in the db is also having it’s count updated.

        I put in a clause into awepop_add_view to try and catch it:

        if ($post->ID == 1){
        echo “we are in the first blog post…”;

        In this case, updating record 77 (which seems ‘paired’ with record 1) would occur properly. Record 77 would update, and record 1 wouldn’t be. Funny, I thought the whole thing should die, not just this function?

        By the way, I am using Thematic, if this has any bearing (maybe to how wp_head is called). I’ve tried putting the function in a different thematic hook, such as ‘thematic_singlepost’ but no change.

        Sorry if this isn’t clear!

        • 25

          GOT IT!

          It’s an issue with Firefox loading the header twice – see here, including fix, in case anyone else gets this problem:

        • 26

          Daniel Pataki

          October 2, 2011 3:53 am

          I find it highly unlikely that the position of postmeta would have anything to do with it. What seems more likely is that somehow it is included in a loop. If you are viewing a page which shows the full single post, and a snippet of the previous and next posts it could add 1 to all three somehow.

          Since these were created one after another their position is near in the database as well but this is just a coincidence.

          I could take a peek at your code if you can give me FTP details. Would you mind if I contacted you via email?

          • 27

            Hi Daniel,

            Thins our replies crossed – see my post above yours that I edited to include the solution – it’s a firefox issue. I’ve implemented the fix suggested and everything works ok. Hopefully others can use this, as I guess I won’t be the only one trying this with Firefox.

            Tell you what though, all the sneaking around I did in the core code trying to fix this has certainly got me to grips a bit more with hooks!

            Thanks for your input,


          • 28

            Daniel Pataki

            October 2, 2011 11:20 am

            Hi Ste H,

            I don’t see your edit, it might need to be approved before. If it isn’t would you mind posting it as a separate comment, I very interested to see what the problem was.

            I know from experience that I have learned FAR FAR more from failure than from success :)

          • 29

            Daniel Pataki

            October 3, 2011 2:01 am

            That is the weirdest error ever, thanks for tracking it down!

          • 30

            Hi Daniel,

            I couldn’t post any more replies, so new comment. The issue I was having was a firefox problem – Firefox seems to post the header twice, the full details are in the solution, the link of which is below.

            Thanks for a great post, by the way, and as you say, finding solutions to problems is a very effective way of learning.

            Solution & fix:

  11. 31

    I realy HATE when english/americans write about wordpress plugins. I know that you probably know only English, but please, imagine there are also other languages, so
    1. do not forget about i18n
    2. keep in mind, that majority of languages have more than one form of singular/plural words (see e.g. )

    you should read prior making any wordpress plugin.

    • 32

      Daniel Pataki

      October 3, 2011 2:00 am

      Hi Tomas!

      I’m actually Hungarian so my neglect of this area was not due to not understanding that there are many languages out there. There are TONS of other things that go into making a good plugin, I didn’t go into quite a few of them, perhaps I’ll write a follow up article.

      I believe that accounting for different languages is not a requirement for a well coded plugin. It IS a requirement for a high end, quality plugin, but the aim of the article is to teach the essentials.

      That said, you are right, it would have been worth mentioning this area at least to the extent of linking to resources. I will be sure to cover it in a follow up!

  12. 33

    Thanks. Very useful

  13. 34

    If I am not intending to distribute my plugin but simply want to add some custom functions, such as custom post types. I want to keep those separate so that as I change themes, I don’t lose everything.

    I have seen it done as you describe, creating a plugin but I have also see it done in functions.php, adding a line something like:
    require_once ($functions_path . ‘customfunctions.php’);
    and then you create a separate customfunctions.php which contains all of the special functions (or alternatively each function could be in its own file)

    Is one way or the other a better practice?

    • 35

      Daniel Pataki

      October 3, 2011 11:15 am

      Hi Carl,

      That’s a great question, and since many things CAN be done with only the functions.php file there isn’t one right answer, I think its mostly down to semantics and how you like to do things.

      For your specific scenario I would not recommend using functions.php. You don’t actually need to include a separate file into functions.php, you can write the custom post type right in there. However, since this file is found inside your theme, whenever you change a theme your site will loose that custom post type, or you need to define it in the new theme as well (kind of defeating the purpose).

      In 99% of the cases I would not recommend using functions.php for this since custom post types belong to your website as a whole, not to your theme which is just a skin for the website. The 1% where I would use the functions.php file is if I just wanted to test something right quick and then delete the code right away.

      As you said, you don’t want to loose everything when you change themes, so whenever this is the case you’ll need to use a plugin. If you need any more clarification let me know :)

      • 36

        Maybe I missed it, but all of the code snippets that are in this article are to be placed in the awesomely_popular.php file right, and not the theme’s functions.php? Forgive me if you already answered that!

      • 37


        Thanks. I am a novice and have seen both ways suggested and was trying to figure out which was better, partly b/c a number of sites seem to suggest minimizing plugins. So I was wondering if there was a difference between calling another function from functions.php or simply creating a plugin.
        I think for now I will go with the plugin, since I can then activate/deactivate from admin panel instead of editing functions.php

        I look forward to learning more and this will be a place I will check frequently.

  14. 38

    Very helpful article! Have found very few this thorough and meaningful. Thanks!

  15. 39

    Michael Marus

    October 11, 2011 2:26 am

    Beautifully written! Well-captured essentials! Bravo!

  16. 40

    The Impersonals (@impersonals)

    November 1, 2011 1:18 pm

    are you developing Twitament in WP?

  17. 41

    I’ve used a lot of wordpress plugins, but never yet attempted to craft my own.

    I think this will be my little Sunday project this week ;-)


  18. 42

    Hi! Nice read, as I’m just trying to develop a plugin for my bachelor project.
    But I have a small issue. I copied all the code to that 1 file + the two lines for functions.php When I activate the plugin my web site disappears – white screen. I found out that this happens when I add the last function – awepop_popularity_list. WP ver. 3.3
    Update: gives me an error “syntax error, unexpected ‘.’ ” at the following line:
    ID)."”>”.the_title(”, ”, false).”

  19. 43

    This is one of the best answer so far, I have read online. No crap, just useful information. Very well presented. Thanks for sharing with us. I have found another good collection of wordpress article which also explained very well.

  20. 44

    Thanks for this post. I decided to create a functionality plugin for my site because I’m always updating my theme and loosing my changes. Mine mostly contains shortcodes, CSS tweaks and my adsense calls.

  21. 45

    Just released the new LAX Slider – A Parallax Post Slider For WordPress.
    A Post/Page/Product etc Slider with content preview.
    Implement with simple shortcode.

  22. 46

    very good tutorial. Thanks for taking the time and writing something like this.

    I am trying to create my frist plugin, in that order there is something that I dont underestand:
    What is “get_post_meta” doing?
    Does it create a custom meta field, the same as add_post_meta?, if it doesnt why there is not an add_post_meta?


  23. 47

    I would recommend that anyone interested in learning how to develop their own plugin to first look at the documentation that WordPress houses. Thanks for the post!

  24. 48

    Jeff Gilden

    July 16, 2013 9:30 am

    I just created my first WordPress plugin and I am trying to get a link back to our website from the WordPress repository. How can I do that while adhering to their terms and conditions for the readme.txt file?

  25. 49

    Great post, lets start the development.

  26. 50

    Thanks for your post, this my my first plugin:

  27. 51


    Great tutorial. Easy to follow and understand. Still, not sure how I would fair if I was to try and build my own plugin from scratch!

  28. 52

    nice, take concept to create new plugins .

  29. 53

    hi Daniel , thanks for this useful article
    I’ve tried to get current post ID in loop , but Results did not
    while ( $awepop_list->have_posts() ) : $awepop_list->the_post();
    echo ($post->ID);

    how i can get post ID in loop?

  30. 54

    Shairyar Baig

    May 11, 2014 6:07 pm

    Very nicely done, i have two questions.

    Question 1,
    At the end you said to add the following code

    if (function_exists(“awepop_popularity_list”)) {

    Now if the plugin is being downloaded from wordpress plugin repository, no admin goes in manually and types the code in their theme function, they just activate and use it so in this case how to handle the big ol’ error you are referring to?

    My second question is, you said to add the following for first function only, but i am assuming this needs to be done for all functions other wise for example the function that is supposed to display data wont display it.

    add_action(“wp_head”, “awepop_add_view”);

    Thanks once again for the wonderful article, i hope to hear from you soon.

  31. 55

    Once I activate my plugin how do I put it on a page?


↑ Back to top