WordPress Action Hooks: The power behind the functions like wp_head()

Not only WordPress, even the plugins that extend WordPress rely on wp_head() to place their scripts and styles inside the <head> element. That means, every plugin that uses CSS or Javascript to style and modify the frontend output would be broke if there is no wp_head() inside the active theme’s header.php file.

So, how does the wp_head() work? How it allows us “the theme developers” and “the plugin developers” to inject code into the <head> element? 

These are the very important questions that you should ask yourself to develop better and usable WordPress themes and when you have questions like that, the only place where you can find the correct answer is the source code of the core WordPress files. 

It not only helps you understand how the WordPress works, but it also helps you make better decisions based on the situation. So, without further ado, let’s take a peek into the source code of the wp_head() function.

“Alright, how exactly do we see the source code of a predefined WordPress function?”

Fair Question! You can read any WordPress function’s source code in easy two ways:

1) Google the Function name and look for developer.wordpress.org search result. Trust me, this is the quickest and trustworthy way.

2) Use your code editor and search for “function wp_head()”. Now, it is important that you put the word function because we are looking for the function definition. Anyway, It can be found inside the wp-includes directory. Common go ahead, I am not going anywhere 😛

Did you find it? Here is the source code of wp_head() function:


function wp_head() {
    /**
     * Prints scripts or data in the head tag on the front end.
     *
     * @since 1.5.0
     */
    do_action( 'wp_head' );
}


“Wait! It only has a single executable line. How is that soo powerful?”

do_action( 'wp_head' );

Well, if you notice, that single piece of code is telling us something. Look at the function name, It says do action. Look at the comment above it. It says “Prints scripts or data in the head tag on the front end.”

This is WordPress way of telling us “Hey! I am giving you a chance to perform an action here, at this very position. That means you can execute your own code which can either output some HTML markup or some data at this very position, and you can even write some complicated code which modifies the way I behave. “

Simply put, do_action('wp_head')is an Action Hook and trust me, an Action Hook, in general, is very powerful.

WordPress Action Hooks

WordPress provides us Action Hooks at certain points of its running/execution to give us the ability to extend or modify the core functionality of the WordPress itself and it does so by allowing us to take actions at those certain points. 

do_action('wp_head') is the simplest example of a WordPress Action Hook. It allows us to take an action while WordPress is putting together the final <head> element. 

Now, you don’t have to say do action wp head action hook if you are having a conversation with your fellow developer. Every Action Hook is called with its name. In the above example, 'wp_head'is the name of the action hook. So, You can just say “Hey! wp head action hook is awesome!

And, 'wp_head'action hookis just one out of 200+ action hooks that WordPress ships with. WordPress gives you the ultimate control over its ecosystem by providing an action hook at every corner. And this is the reason why WordPress plugins and themes exist. More precisely, If it is not for Action Hooks, none of the themes in the WordPress repository would exist.

“Oh! that is insightful. But, what is an action? And how do we take an action anyway?” 

A WordPress action

An action is nothing but a custom PHP function with a bunch of code which either outputs or modifies some HTML markup or some data or you can even send an email using the popular wp_mail()function. 

The below custom function is the simplest example of an action. The only responsibility of the below action is to output Google Analytics Code. 


<?php
function nd_dosth_add_google_analytics_code_to_head() { ?>
    <!-- Google Analytics -->
    <script>
        (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
        m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
        })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

        ga('create', 'UA-XXXXX-Y', 'auto');
        ga('send', 'pageview');
    </script>
    <!-- End Google Analytics -->
<?php }

add_action() does the job of linking an Action Hook with our Action so that we can execute our action at the right time and right place

We use add_action() function to hook/attach an action like to an Action Hook like 'wp_head'. All you have to do is provide the name of the Action Hook as the first parameter and an Action as the second parameter, for example:


add_action( 'wp_head', 'nd_dosth_add_google_analytics_code_to_head', 10);

Internally, WordPress uses Action Hooks too

Yes, WordPress is utilizing the  do_action( 'wp_head' ) function to generating the favicon markup if we uploaded the favicon using the Site Identity options Panel and this makes me curious. If WordPress is able to do that, so do we! right? And, there are many things that we might want to put inside the <head> element. For example:

  • You may have to add Google Analytics code right before the closing </head> tag as per your client’s request
  • You want to include common Stylesheets and Javascript.
  • You can write a custom plugin which adds social sharing meta tags like <meta name="twitter:card" content="summary">
  • And so on…

Let’s try out Action Hooks

Now, Let’s go ahead and see it in live action. We’ll be outputting the Google Analytics code to the <head> element.

Open up the functions.php file inside the nd-dosth theme and put the following code in it.


<?php
add_action( 'wp_head', 'nd_dosth_add_google_analytics_code_to_head', 10 );
function nd_dosth_add_google_analytics_code() { ?>
    <!-- Google Analytics -->
    <script>
        (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
        m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
        })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

        ga('create', 'UA-XXXXX-Y', 'auto');
        ga('send', 'pageview');
    </script>
    <!-- End Google Analytics -->
<?php }

“Hey! You have put add_action()function first followed by the function definition. Are you sure this is the correct order?”

It doesn’t matter where you declare your functions in PHP in most cases and WordPress takes this a step forward by function definitons as callbacks.

As long as our custom function definition and the add_action()function stays inside functions.php file, the order doesn’t really matter. You’ll learn the reason behind it in a moment.

And if we open up the home page of the website (http://localhost:3000/dosth) and if we view the page source, the Google Analytics Code is indeed getting outputted into the <head> element. 

We can attach an unlimited number of actions to a single Action Hook and we can certainly control their execution order with the priority parameter

We can attach any number of actions to a single Action Hook. There is no limit. All the actions are processed by WordPress based on the priority that we have provided for individual action. An Action with Priority 1 will be executed first and action with priority 999 will be executed last. If two actions have the same priority, WordPress will execute the actions in the order it found them.

You can specify the priority of individual action by filling the third parameter of the add_action() function. For example, in the below code, the priority of the action is 10. By the way, if you don’t specify the priority, 10 is the default for any action.


add_action( 'wp_head', 'nd_dosth_add_google_analytics_code_to_head', 10 );

Common, let’s try out the priority parameter. This time, let’s add some basic styles right after the Google Analytics code.

Because the priority of action which is printing the Google Analytics code is 10, we should use a number that is higher than 10. So, you can any number that is higher than 10. For example, 11, 12, 99 or you can even take the liberty and go for 999. It’s a liberal world I say!

So, put the following code anywhere inside the functions.php file. The position doesn’t really matter because you are controlling the order of execution using the priority parameter.


add_action( 'wp_head', 'nd_dosth_add_css_styles_to_head', 11 );
function nd_dosth_add_css_styles_to_head() { ?> 
    echo '<style>body{ background-color:teal }</style>';  
<?php }

If you notice, this time I went with the priority of 11.

Now, let’s go back to the Homepage in the browser and view the page source.

The priority parameter is indeed working. In fact, to prove the point that the order doesn’t really matter, I have put the above code at the beginning of functions.php file.

Also, if you notice, WordPress is printing out the Favicon markup at the very end, that means out of all the actions that are attached to the wp_head Action Hook, the action which is generating the favicon markup has the least priority. Of course, you can still take control and print some markup right above the closing </head> tag. All you have to do is play with the priority number.

Here is my final functions.php file for this lesson:


<?php
add_action( 'wp_head', 'nd_dosth_add_css_styles_to_head', 11 );
function nd_dosth_add_css_styles_to_head() { ?> 
    echo '<style>body{ background-color:teal }</style>';  
<?php }

add_action( 'wp_head', 'nd_dosth_add_google_analytics_code_to_head', 10 );
function nd_dosth_add_google_analytics_code_to_head() { ?>
    <!-- Google Analytics -->
    <script>
        (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
        m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
        })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

        ga('create', 'UA-XXXXX-Y', 'auto');
        ga('send', 'pageview');
    </script>
    <!-- End Google Analytics -->
<?php }

Also, if you notice, both the above actions are echoing out some markup to the <head> element. But they are doing so using two different PHP ECHO techniques. There might be some performance trade-offs between them, but, at the end of the day, it is all about code readability that matters to most of the Developers. 

I prefer the latter (the Google Analytics function definition in the above code) because it is more clean, readable and it allows you to write the markup without worrying about the quotes.

More examples of an Action Hook

wp_footer Action Hook

The action hooks names are always self-descriptive. This action hook will let us take an action when WordPress is putting together the Footer of the website. This action hook is commonly used for including the Javascript in the footer.

publish_post Action Hook

This action hook will let us run some PHP code as soon as we publish a post. 

Not all action hooks will let us output markup. Some of the action hooks are generally used to communicate with a third party API like Twitter or add more user roles to the WordPress admin area. 

The publish_post action hook is the best example of the API communication scenario. We usually use put this action hook to use when the author wants to tweet about the post as soon as it got published.

And, the list goes on and on. In fact, action hooks are divided into more than a dozen categories. Take a peek at them by visiting the WordPress codex’s Action Reference page.

Get it?

Still confused? Sorry, my bad!

Understanding the WordPress execution flow could make it more clear

Don’t worry. Let’s bust the confusion by understanding the execution flow of WordPress at a highly simplified level by omitting all the unnecessary details like the existence of a child theme and some internal tasks:

1) It all starts with a user accessing our website’s homepage in the browser

http://localhost:3000/dosth

2) As soon as the user hits enter, the browser does its job and sends the request to the server asking for the home page.  

3) The server receives the request and starts executing the WordPress core starting with the index.php file in the root directory:

Application/MAMP/htdocs/dosth/index.php for MAC/MAMP users
C:/wamp/www/dosth/index.php for windows/wamp users

From here onwards, WordPress takes the control. 

4) WordPress connects to the database server and continues to load up and go through the individual internal files.

5) Once all the core WordPress files are loaded, WordPress will then load all the plugins.

6) Once the plugins are loaded, WordPress will then load the active theme’s functions.php file before any other template file that contains HTML markup. It does so because all the custom code which adds additional features to the theme goes inside the functions.php file.

In our case, the active theme is wp-content/themes/nd-dosth.

Anyway, so, as soon as WordPress loads up the functions.php file, it goes it through line-by-line and figures out that there are multiple add_action() function calls belonging to the same action hook called wp_headand it memorizes that “Oh! the theme developer is trying to perform multiple actions inside the  <head> element and I need to execute those actions as soon as I execute the do_action( 'wp_head' ) function”. 


add_action( 'wp_head', 'nd_dosth_add_css_styles_to_head', 11 );

add_action( 'wp_head', 'nd_dosth_add_google_analytics_code_to_head', 10 );

If you are coming from the world of Javascript, both the actions are just callback functions which will get executed when WordPress comes across and executes the do_action( 'wp_head' ) function.

Note: At this phase of WordPress execution, WordPress has not yet touched the template files like header.php or frontpage.php. So, it has no clue when and where it will find do_action( 'wp_head' ) function call.

7) WordPress continues its journey by parsing the URL. After parsing the URL, WordPress figures out what the user is trying to access. Then, WordPress uses Template hierarchy logic to choose a template file from the active theme. In our case, the user trying to access the Homepage of the website and So, WordPress loads the front-page.php file and starts processing it to generate the final webpage markup.

8) While processing the front-page.php file, it first line it finds is the get_header() function and executes it.

The Primary purpose of the get_header() function is to load up header.php file from the active theme.

So, once the WordPress loads up the header.php file and starts processing it, it comes across the wp_head() function and executes it.

Pro Realization: Remember, by the time WordPress starts processing the template files like header.php file, it has already loaded and processed all the core files, plugin files, and our active theme’s functions.php file

So the functions definitions like get_header(),language_attributes() and wp_head() are already loaded and we can execute them directly. Remember? at the early stages of the course, I said that WordPress comes with a lot of predefined functions and all we have to do is use them inside our theme without worrying about their scope. Get it now?

9) As soon as WordPress executes the  wp_head() function, it will run into the  do_action('wp_head') function and realizes that 

“Oh! There we go. I finally came across the do_action('wp_head') function and its time to execute all the actions that are hooked into it. “

WordPress stores all the functions that must be executed at this point in an array and it goes through it one by one and executes all of them based on their priority.

In our case, from thefunctions.php file perspective, nd_dosth_add_google_analytics_code() action (a callback function) will get first executed as it has a priority of 10 and  as soon as it gets executed, the Google Analytics code will be outputted to the inside of the <head> element. 

WordPress will then continue to execute all the actions with a priority of 10 (some plugin might add its own action with a priority of 

10 ) and once it finally runs out of all the actions with priority of 10, finally it executes the nd_dosth_add_css_styles_to_head()action callback which has a priority of 11 and outputs our custom styles at some place after the Google Analytics code. 

11) Execution of all the actions that belong to 'wp_head' action hook will mark the end of the wp_head() function call and WordPress comes back to header.php file to process the rest of the file and once it reaches the end of it, it comes back to the  to the front-page.php file, it will process the rest of the file and sends the final markup to the browser.

12) Finally, the browser renders the markup to the user.

The above execution flow applies to each and every page on our WordPress website

We have to realize that wp_head action hook gets triggered every time a user tries to access any webpage on our website.

This is because we will be using the same header.php file that triggers the wp_head action hook to render the header portion of every other webpage on our WordPress website. So, Unless caching is involved, the entire 12 step process that I mentioned above repeats every time you access a page, even if you refresh the same page.

The only thing that might change is step 7 from the above execution flow. In this step, based on what webpage URL user is trying to access, WordPress uses Template hierarchy logic to choose a template file from the active theme. 

For example, if the user is trying to access a blog post, WordPress will look for the single.php file instead of front-page.php file. 

But, since we will be using the same header.php file to render the header portion of blog post as well, wp_head action hook still gets triggered and WordPress will echo same styles and Google analytics script to the <head> element of this blog post.

Don’t worry! If you do not understand the above explanation, you’ll surely grasp it when we build the other pages of our website.

And, That’s it for this lesson. You’ve come a long way. 

Now you know almost everything about the WordPress Action Hooks. 

If you still don’t get it, that’s totally ok. When you are learning new concepts, often you might have to read multiple articles from the multiple authors. You might learn many new things that I missed in here. So, go browse the internet for more insights into WordPress Action Hooks.

And proceed forward only when you get hold of Actions Hooks. Because, from here onwards, I will be assuming that you do understand how Action Hooks in WordPress Works.

Introducing Filter Hooks

WordPress also ships with another type of hooks called Filter Hooks.

While action hooks allow us to execute an action at a certain point of WordPress execution, Filter hooks allow us to get and modify a piece of WordPress data before it is saved to the database or rendered on the browser. 

We will make use of filter hooks to solve our problems in the upcoming lesson.

In the next lesson, we will use this knowledge to efficiently include stylesheets and scripts into the head element. 

Things will speed up from here on! Get Ready!