Adding Custom WordPress Hooks

All theme authors should have a vague idea of what WordPress hooks are: those things you have to remember to add to your header to stop plugin authors yelling at you. More technically, they’re a way of adding to or altering the content that WordPress outputs.

There are a fair few built into WordPress, and a number need to be correctly implemented by theme authors, but I don’t propose to go into that here. What I’m going to run through in this article is how you can add your own actions and filters to your theme, to make it more flexible and customisable.

Before I get started, a couple of notes on the WordPress development environment. Firstly, updates break things. When WP 2.1 came out we had to rewrite our SQL code to work with the new database structure. 2.2 brought widgets into the core and the link in Tarski’s Options page (which was pointing to the widgets plugin page) no longer worked. For 2.3 we’re going to have to strip out our UTW code and make the theme work with the new tagging system. In other words, themes need to be kept updated, even though this will destroy any alteration of the theme’s files. Themes should come with tools that allow customisation but don’t require the alteration of core files. Users shouldn’t be deterred from upgrading by the prospect of losing their tweaks—which of course is why plugins exist.

Anatomy of a theme hook

There are two kinds of hooks: actions and filters. This article deals mainly with actions, since they’re generally simpler, but all its lessons can be applied to filters without much difficulty.

Theme hooks are just functions; wp_head is a good example of one. It’s defined in wp-includes/general-template.php, and the definition is amazingly simple:

function wp_head() {

The do_action function that does the hard work, tying the wp_head function into WordPress’s hooks system. It’s incredibly simple to add new hooks in the same way.

Adding custom hooks

There are three steps to adding a custom hook to a theme. Firstly, add the hook function. Secondly, add the action to your theme in the spot where you want it to be executed. Thirdly, you can add a function defining the default behaviour—for example, if you were writing a hook for a header image, you’d need to write something to display a header image. Lastly, tie the two together with add_action. Note that the third and fourth steps are optional; your hook doesn’t have to do anything by default.

Since I’ve been working on adding hooks to Tarski, I’ll use an example from there. Unless stated otherwise, this code is being added to the theme’s functions.php file which is automatically included by WordPress. Below is the action definition: it adds an action named th_header to WordPress’s hooks listing.

function th_header() {

I then added the function call to the header template, so that whenever that template file is called it will do whatever actions have been added to the th_header hook:

<?php th_header(); ?>

Originally I was just going to use this to add a header image, thinking that if people wanted to make their header image rotate randomly, or display page-specific headers, they could do that with a plugin. But then I realised I could use the same hook to also display the title and the tagline. To do this, I just reused the existing header image, site title and tagline functions, and then added these lines of code to make the hook call them:


Notice that the first argument is the same for all three lines: th_header. This is the hook to which the actions are being added. The second argument is the actions (which, of course, are just functions which we’ve defined elsewhere). The third argument is the priority—the order in which the actions should be performed. This will make the header display first; then the title; then the tagline.

Tweaking with a plugin

Now the theme has its hooks, how does all this customisation work? It’s very simple—just write a plugin. This can be completely independent of the theme, so you can update the theme without fear of losing your tweaks (because they’re all in the plugin). I don’t propose to cover the basics of plugin development here; try this tutorial, or this one.

First things first: what do we want to do? Well, how about writing a little “About this site” blurb and adding it below the tagline? This is very easy: just add the function to output the blurb to your plugin, and then add an action to the requisite hook.

function output_about_text() {
    echo '<p>This site is amazing.</p>';

That does it for the text; how about the action?


Notice that we didn’t add a priority; this value defaults to 10, so the about text will be displayed after the tagline. If you want to add it before the header image, for example, try this:


Let’s now turn to a more complex example: replacing the header image with page-specific headers. Again, just write the function:

function page_specific_headers() {
    if(is_home()) {
        echo '<img alt="Home" src="home-page-header.gif" />';
    } elseif(is_page('about')) {
        echo '<img alt="About" src="about-page-header.gif" />';
    } else {
        echo '<img alt="Header" src="general-header.gif" />';

Then we need to do two things: add the new action, and remove the default one.


This should remove the default header image, and replace it with the page-specific one. Note that the priority needs to be specified for both the action being removed (since it’s set in the default action) and for the action being added (since we want the header to be displayed in the same place, before the title and tagline).

Theme hooks in this mould will be a new feature in Tarski 1.5. If you want to try them out in the meantime, just check out the latest build from our Subversion repository.

Last updated 13th Jan 2009


11 responses

Is there a reason we don’t just do do_action('th_header'); in header.php instead of having a wrapper function in functions.php as well?

~ ceejayoz

It keeps header.php cleaner, basically, and it’s good practice to define all the hooks somewhere so it’s clear what’s available, especially since not all hooks are as simple as wp_head—look up the_content’s definition, for example. Just file it under “Helpful abstraction.”

~ Benedict

I knew there was a reason you’re the brains of the outfit.

~ ceejayoz

Nice, I will give a try during my next rebuilding.

~ feirvsita

I think the last code line should read as

am i right ?

~ Sadish

You are indeed. Good catch, thanks; I’ve fixed the error.

~ Benedict

There is no such thing as do_filter, and you didn’t say how filters work.

Filters work like this:

$text = apply_filters('some_identifier',"Here's the text to filter");

This would apply the some_identifier filter to the text and set it in the variable $text. A filter would then look like this:

function my_filter($input) {
// do stuff to input
return $input;

~ Otto

You’re quite right, of course; serves me right for skimming over them. I’ve removed the offending section, thanks for pointing it out and explaining how filters work.

~ Benedict

Tahnks I think tyhis is the sourt of article I am looging for although I woul have liked a few good examples or sites where I can tryt out. Maybe you did provie them and i have not notced them as readily as I could have.

I am trying to find comprehensiove list of built in Wordpress functions and what they do. I want to update some themes to include the Custom Image Header. I gather that the code is built in but that many of the themes avialable have not coded in the hooks as yet.

I do nt want to reinvent the wheel and using inbuilt code is the way to go.

I like the suggestion that I code my hooks in a stand alone functions plugin… I will have to consider tyhis more as my knowledge on the insides of Wordpress

~ crikey

Sorry the message escaped before I could spell check… and there is no edit option… Anyway can you provide a good resource/documentation on the inside hooks of the latest version. What they do and how to use them.

I am very interested in the Photo re-size function of the customer header and believe this can be used in many different circumstances as part of the upload procedure

I have booked marked your site as I think it is very informative. Thanks again

~ crikey

Went back and look again and found some information. jst what I wnat thanks

~ crikey