Introduction to Hooks: a basic WordPress building block


WordPress hooks are arguably the basis of WordPress development, forming a large part of the core functionality and used by almost every plugin and theme available to date. The concept of hooks can also be somewhat daunting for users who are starting out with developing for WordPress. Today, we’ll jump in and find out a bit more about just what exactly WordPress hooks are and how they can help you on your way to WordPress rock stardom.

What exactly *are* WordPress hooks anyways?

WordPress hooks are, essentially, triggers of sorts that allow users to, with short snippets of code, modify areas a WordPress theme or plugin, or add their own code to various parts of WordPress without modifying the original files. An example of this could be along the lines of either “when WordPress chooses which template file to load, run our custom code” or “when you generate the content for each post, add social bookmarking links to the end of the content”. These examples will be expanded upon once we’re a bit more familiar with what exactly the different types of hooks are.

Hooks can be divided into “Action” and “Filter” hooks, the former allowing for insertion of custom code at various points (not unlike events in JavaScript) and the latter allowing for the manipulation of various bits of content (for example, the content of a page or blog post). Lets take a closer look at each of these, shall we?

Action Hooks

Action hooks are designated points in the WordPress core, theme and plugin code where it is possible for outside resources (outside of the scope of where the hook is… either in the core, theme or plugin) to insert additional code and, there by, customise the code to do additional functions they may desire. An example of this is the commonly used wp_head action hook, used by many themes and plugins to inject additional CSS stylesheets, processing code or anything else they require to sit between the <head> and </head> tags of their WordPress theme’s XHTML structure. This is the reason for including wp_head(); in all WordPress themes.

To hook on to an action, create a function in your theme’s functions.php file (or in your plugin’s code) and hook it on using the add_action() function, as follows:

	add_action( 'wp_head', 'wpcandy_actionhook_example' );

	function wpcandy_actionhook_example () {

		echo '<meta name="description" content="This is the meta description for this page." />' . "

	} // End wpcandy_actionhook_example()

The above code adds the text “Hello WPCandy Readers!” between your theme’s <head> tags. Placing “wp_head” in the call to add_action() with “get_header” would display this text above your theme.

The way I like to explain action hooks, in a single sentence, is: “When you get to this point, do that.”

Filter Hooks

Filter hooks are used to manipulate output. An example of this would be to add a line or text (or a hyperlink, or a signature sign-off—whatever you’d like) to the end of the content of each of your blog posts. Filter hooks can also be used for truncating text, changing formatting of content, or just about any other programming manipulation requirement (for example, adding to or overriding an array of values).

Custom code is added as a filter using the add_filter() function. The following code adds a sign-off to the end of each blog post, only when viewing the full blog post screen:

	add_filter( 'the_content', 'wpcandy_filterhook_signoff' );

	function wpcandy_filterhook_signoff ( $content ) {

		if ( is_single() ) {

			$content .= '<div class="sign-off">Th-th-th-th-th That\'s all, folks!</div>' . "

		} // End IF Statement

		return $content;

	} // End wpcandy_filterhook_signoff()

The above code adds a new div tag to the end of the content of our blog post, only when on a single blog post screen.

A filter hook is like using the str_replace() function in PHP. You give it some data, manipulate, replace or reformat the data and return the new content out at the end.

… and now, for a few commonly asked questions… answered.

Are custom hooks available only to the theme or plugins I’ve got activated?

Custom hooks and filters that are added by a theme or plugin, only apply if that theme or plugin is active. There are many hooks, however, that are global (get_header, wp_head and wp_footer are three examples). If you’d like to switch themes regularly and maintain the functions you’ve hooked onto these, or other, global hooks or filters, I’d recommend writing them into a plugin.

Themes and plugins are able to specify custom filters and actions. We’ll get more into this in part two.

Where can I learn more about action and filter hooks?

My favourite resource is, without a doubt, the WordPress Codex. While there are many tutorials available online regarding filter and action hook applications, the best understanding comes, as they say, when heard from the horse’s mouth. The Codex provides useful examples, as well as up to date and informative explanations, which aid in gathering an overall understanding of the Plugin API (the API that handles action and filter hooks).

Right. Now that we’ve answered a few questions, lets show some practical examples that can be used right off the bat with any WordPress theme.

Add “time ago” time display at the end of each post.

	add_filter( 'the_content', 'wpcandy_time_ago' );

	function wpcandy_time_ago ( $content ) {

		$content .= "
" . __( 'Posted ', 'wpcandy' ) . human_time_diff( get_the_time('U'), current_time('timestamp') ) . __( ' ago', 'wpcandy' );

		return $content;

	} // End wpcandy_time_ago()

Use WordPress conditional tags to detect the user’s web browser and add a class with it’s name to the body tag.

function browser_body_class($classes) {
	global $is_lynx, $is_gecko, $is_IE, $is_opera, $is_NS4, $is_safari, $is_chrome, $is_iphone;

	if($is_lynx) $classes[] = 'lynx';
	elseif($is_gecko) $classes[] = 'gecko';
	elseif($is_opera) $classes[] = 'opera';
	elseif($is_NS4) $classes[] = 'ns4';
	elseif($is_safari) $classes[] = 'safari';
	elseif($is_chrome) $classes[] = 'chrome';
	elseif($is_IE) $classes[] = 'ie';
	else $classes[] = 'unknown';

	if($is_iphone) $classes[] = 'iphone';
	return $classes;

Remove the WordPress 3.1 Admin Bar.

<?php add_filter( 'show_admin_bar', '__return_false' ); ?>

What about Twenty Ten?

With the introduction of Twenty Ten as the WordPress default theme, the theme received a large amount of documentation in the theme files, with several custom hooks or pluggable functions created specifically for it. Lets take a look at how we can use these hooks to enhance Twenty Ten.

The main custom hook in the TwentyTen theme serves a relatively simple purpose: adding content to the credits area in the footer. This is done by hooking on to the new “twentyten_credits” action hook. Here’s an example:

	add_action( 'twentyten_credits', 'wpcandy_credits' );

	function wpcandy_credits () {

		$html = '';

		$html .= 'Proudly brought to you by <a href="">WPCandy</a>.' . "

		echo $html;

	} // End wpcandy_credits()

The above function adds a simple line of credit text to the footer area in the Twenty Ten theme. In part two, we’ll discuss pluggable functions, which can be used in the Twenty Ten theme in particular to enhance and customise the output above and below the post content in the theme.

Coming in part two:

Creating your own hooks & filters and a brief introduction to pluggable functions; the hook’s lil’ sister. Please share your experiences with using WordPress action and filter hooks in the comments below.

26 thoughts on “Introduction to Hooks: a basic WordPress building block

  1. This is one wonderful, A to Z comprehensive, tutorial on these wordpress hooks. I am into it. I’ll play with the filter hooks, tempting to try. Thank you for the details!

  2. This is a good tutorial on the basics of hooks.

    I do have a few notes on the wp_head hook portion of the tutorial. Themes and plugins most definitely should not be injecting stylesheets directly on this hook. I know it’s just an example, but I hate having to deal with plugins/themes that don’t use the wp_enqueue_*() functions and hook them appropriately. And, the “Hello WPCandy readers!” text will be invalid HTML when using it there. Maybe an example with meta tags or CSS code would work better.

    • Themes that use the wp_head hook for scripts (or even worse, no hook at all), instead of wp_enqueue_ are one of the biggest head aches for plugin developers. I cannot tell you how many times I have received support questioned based around script conflicts that would have never happened if the theme author had just used wp_enqueue_

    • Thanks for your comment, Justin. You make a point regarding outputting text in the wp_head hook.

      The reason for the output of text is to show users a visual result once the hook code has been implemented.

      To emphasize to readers, the use of wp_head to include raw HTML is not appropriate. `wp_head` should be for meta tags, while wp_enqueue_*() should be used for loading CSS and JavaScript files.

      Thanks again for your kind and informative comment, Justin. 🙂

    • Action hook example has been updated to include a more appropriate meta tag. 🙂

  3. Great one! Thank you for sharing this. I would anyway like to mention that in TwentyTen 1.3 many of these problems / features / mentions will be gone.

  4. This is an excellent breakdown on hooks. Hooks are so powerful, that when you get your hooks right, building a theme or a plugin can proceed almost like snapping together Lego blocks.

    Can’t find the hook you need? Doesn’t exist? Add your own hook! WordPress is so cool.

  5. Thanks for the background on hooks. Really helpful. Actions/filters are starting to gel for me, so it’s good to hear it again.

    For next part—maybe this is part of the plan—the biggest questions left to be answered for me are:
    1. What functions are attached to any given hook (eg. Where’s all that crap in my header coming from?!)
    2. How do I remove function X from hook Y?

    Looking forward to hearing more.

  6. Pingback: Building a Complete Website With Thesis

  7. Very well written. WordPress is all about the way you use Hooks. Hooks make it simple and thats why i preffer Thesis. Give me a visit someday.

  8. Nice and simple intro ., thanks … I did not like the browser filter example though … it does not distinguish between brower versions, especially IE .. an example yes but the code seems a little out of date ..

    there is better IMHO in case anyone needs it Matt Varone – Browser Body Class

  9. Thank you for the useful article.
    I’m trying to customize the footer of twentyeleven theme.

    With this code in child theme

    add_filter(‘twentyeleven_credits’, ‘modify_admin_footer’);
    function modify_admin_footer () { ?>
    Developped by
    My site
    <?php }

    only add new lines to original “Proudly powered by WordPress”
    I’d like to override the default text with the custom text.
    Appreciate any help


    • Hi Paolo,

      To remove the “Powered by WordPress” credit ( not recommended, as WordPress is awesome 🙂 ), you’d need to override the footer.php file directly, manually removing the credit.

      The “twentyeleven_credits” action sits above (and outside of) this WordPress credit line.


  10. This is fantastic information.I am a beginner and in the process of learning the hooks so I could add some spice to my wordpress genesis framework site.
    Great work!

  11. Great tutorial and thank you for your insight on action and filters. I am running WP and an idea to share something with my readers but could not find a plugin. Now I have decided to learn and write my own plugin. It will be a challenge but I am sure I will be able to pull through if I work hard and learn from people like you.


  12. Hello,

    Thanks for the great article. But wp_head action hook is not working, kindly assist.

    I tried this on twenty ten theme.


Comments are closed.