wp_head
Fires in the page's <head> section. Scripts such as jQuery, site CSS, and SEO metadata such as title, description, and robots are commonly output at this point. This is one of the primary WordPress theme hooks.
The event is invoked by wp_head(), which is called in the theme's header.php before the </head> tag.
Calling wp_head() is required for every WordPress theme:
... <?php wp_head(); ?> </head>
Many WordPress core functions run during this event. One of them, for example, outputs styles enqueued with wp_enqueue_style().
WordPress itself and many plugins, including SEO plugins, rely heavily on this event, so it is very important.
The hook is intended primarily for theme developers, who must add wp_head() to their themes so plugins can attach to the hook and add data to the HTML head.
The similar wp_footer event is invoked by wp_footer() in the theme footer file, footer.php.
Usage
add_action( 'wp_head', 'wp_kama_head_action' );
/**
* Function for `wp_head` action-hook.
*
* @return void
*/
function wp_kama_head_action(){
// action...
}
The hook passes no parameters. Like any action, it is used to run a PHP function at the required point and output the necessary HTML, such as code that loads a JavaScript or CSS file.
Examples
#1 Output custom CSS and JavaScript in the head
This demonstrates how to output HTML in the document HEAD:
## CSS in the document head
add_action( 'wp_head', 'hook_css' );
function hook_css(){
echo '<style>.wp_head_example{ background-color : #f1f1f1; } </style>';
}
## JavaScript in the document head
add_action( 'wp_head','hook_javascript' );
function hook_javascript() {
echo "<script> alert('Page is loading...'); </script>";
}
#2 Output page SEO meta tags
Search robots use the description, keywords, and robots meta tags. This example outputs all three.
add_action( 'wp_head', 'head_seo_meta_tags' );
function head_seo_meta_tags(){
// description
echo '<meta name="description" content="The article describes how to dynamically enqueue ..." />';
// keywords
echo '<meta name="keywords" content="Code, WordPress theory, jQuery, Optimization" />';
// robots
echo '<meta name="robots" content="index,nofollow" />';
// Mobile devices
echo '<meta name="viewport" content="width=device-width, initial-scale=1">';
}
Loading CSS and JavaScript files through wp_head
Styles and scripts should be loaded in the HEAD using wp_enqueue_style() and wp_enqueue_script(), rather than directly through the wp_head hook.
These functions queue files for output. The files are then output automatically during wp_head by the attached core functions wp_print_styles() and wp_print_head_scripts():
add_action( 'wp_head', 'wp_enqueue_scripts', 1 ); add_action( 'wp_head', 'wp_print_styles', 8 ); add_action( 'wp_head', 'wp_print_head_scripts', 9 );
Therefore, CSS and JavaScript files intended for wp_head should almost always be registered through wp_enqueue_style() and wp_enqueue_script().
Example of loading styles in wp_head
add_action('wp_enqueue_scripts', 'my_wp_head_css' ); // This hook runs automatically during wp_head
function my_wp_head_css() {
wp_enqueue_style( 'my_head_style', get_stylesheet_directory_uri() .'/css/my_style.css', array(), null );
}
This is equivalent to:
<?php
add_action('wp_head', 'my_wp_head_css', 1 );
function my_wp_head_css(){
?>
<link rel='stylesheet' id='theme_my_head_style' href='<?php echo get_stylesheet_directory_uri() ?>/css/my_style.css' type='text/css' media='all' />
<?php
}
Using wp_enqueue_style() is preferable because it is the standard approach. The second variant may not work with plugins that combine styles into a single file.
Sometimes it is more convenient to output styles directly instead of loading a file:
<?php
add_action('wp_head', 'my_wp_head_css');
function my_wp_head_css() {
?>
<style>
.selector{ display:none; }
</style>
<?php
}
Example of loading scripts in wp_head
Scripts are handled in the same way as styles:
add_action('wp_enqueue_scripts', 'my_wp_head_js' ); // This hook runs automatically during wp_head
function my_wp_head_js() {
wp_enqueue_script( 'my_head_js', get_stylesheet_directory_uri() .'/js/my_script.js', array(), null );
}
<?php
add_action('wp_head', 'my_wp_head_js', 1 );
function my_wp_head_js(){
?>
<script type='text/javascript' src='<?php echo get_stylesheet_directory_uri() ?>/js/my_script.js'></script>
<?php
}
An inline script without a separate file:
<?php
add_action('wp_head', 'my_wp_head_js');
function my_wp_head_js() {
?>
<script>
var my_var = 'variable value';
console.log('the script works!');
</script>
<?php
}
Priorities for loading JavaScript and CSS files
For scripts, unlike styles, execution order is very important. Running jQuery code before the jQuery library is loaded causes an error. A file containing jQuery code must therefore be loaded after jQuery itself.
Priority through WordPress enqueue functions
When loading files with wp_enqueue_style(), wp_enqueue_script(), wp_register_style(), or wp_register_script(), specify dependencies in the third $deps parameter. A script is then loaded after the scripts it depends on:
add_action( 'wp_enqueue_scripts', 'my_jquery_js' );
function my_jquery_js(){
// A custom script based on jQuery
wp_enqueue_script( 'my_jquery', get_stylesheet_directory_uri() . '/my_jquery.js', array('jquery') );
// jQuery is already registered in WordPress, so enqueue it by name
wp_enqueue_script('jquery');
// Calling this again, even from another file, still loads the script only once.
// This demonstrates why the dedicated enqueue functions are convenient.
wp_enqueue_script('jquery');
}
Although my_jquery.js is enqueued first, its jQuery dependency causes the HTML to load jQuery first and my_jquery.js second.
Priority through the wp_head hook
When inline code rather than a file is added, set its priority in the third add_action() parameter:
<?php
// Output the JavaScript variable
add_action('wp_head', 'my_wp_head_js2', 20);
function my_wp_head_js2() {
?>
<style>
alert( my_var );
</style>
<?php
}
// Register the JavaScript variable
add_action('wp_head', 'my_wp_head_js', 10);
function my_wp_head_js() {
?>
<script>
var my_var = 'The variable is defined';
</script>
<?php
}
The first callback has priority 20 and the second priority 10, so the latter appears first in the HTML. Hooks run from lower to higher priority: 10, then 20. The variable is therefore defined before it is displayed with alert().
Removing WordPress functions from wp_head
WordPress attaches many functions to wp_head by default. Most are registered in wp-includes/default-filters.php:
add_action( 'wp_head', '_wp_render_title_tag', 1 ); add_action( 'wp_head', 'wp_enqueue_scripts', 1 ); add_action( 'wp_head', 'wp_resource_hints', 2 ); add_action( 'wp_head', 'feed_links', 2 ); add_action( 'wp_head', 'feed_links_extra', 3 ); add_action( 'wp_head', 'rsd_link' ); add_action( 'wp_head', 'wlwmanifest_link' ); add_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10, 0 ); add_action( 'wp_head', 'locale_stylesheet' ); add_action( 'wp_head', 'noindex', 1 ); add_action( 'wp_head', 'print_emoji_detection_script', 7 ); add_action( 'wp_head', 'wp_print_styles', 8 ); add_action( 'wp_head', 'wp_print_head_scripts', 9 ); add_action( 'wp_head', 'wp_generator' ); add_action( 'wp_head', 'rel_canonical' ); add_action( 'wp_head', 'wp_shortlink_wp_head', 10, 0 ); add_action( 'wp_head', 'wp_site_icon', 99 );
To remove an attached callback, call remove_action() with the matching priority in a plugin or the theme's functions.php.
For example, remove feed links:
remove_action( 'wp_head', 'feed_links', 2 );
Ready-to-use code for removing unnecessary head output
// Remove unnecessary output from the site's head section
// 2.0
remove_action( 'wp_head', 'feed_links_extra', 3 ); // Additional feed links, such as category feeds
remove_action( 'wp_head', 'feed_links', 2 ); // Main feed links
// RSD link used to publish posts through third-party services
remove_action( 'wp_head', 'rsd_link' );
// Windows Live Writer manifest link
remove_action( 'wp_head', 'wlwmanifest_link' );
//remove_action( 'wp_head', 'index_rel_link' ); // Unsupported since version 3.3
add_filter('the_generator', '__return_empty_string'); // Remove the WordPress version
// 3.0
remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head', 10 ); // Links to adjacent posts
remove_action( 'wp_head', 'wp_shortlink_wp_head', 10 ); // Short non-rewritten URL
// 4.6
remove_action( 'wp_head', 'wp_resource_hints', 2); // Browser resource hints for prefetching, prerendering, and preconnecting.
- You can also disable the REST API.
- You can disable intermediate responsive image sizes: How to disable responsive image sizes (srcset) in WordPress 4.4.
Removing plugin styles and scripts
Disable a plugin script
Plugin scripts or styles can interfere with a theme or another plugin. Suppose plugin A's script prevents plugin B from working correctly. One solution is to dequeue plugin A's script and load it at the very end of the footer.
Remove a plugin script from the output queue with wp_dequeue_script(). Find its ID in the plugin code by locating wp_enqueue_script('ID') or wp_register_script('ID'); the first parameter is the script ID. Add this to the theme's functions.php:
add_action('wp_head', function(){ wp_dequeue_script( 'ID' ); }, 5 ); // Priority is important: use 2 through 7
The dequeued script can then be loaded independently at the required location.
Disable a plugin stylesheet
The stylesheet ID is easier to find. Inspect the page HTML, locate the stylesheet link, and read its id attribute:
<!-- ID = dashicons --> <link rel='stylesheet' id='dashicons-css' href='http://example.com/wp-includes/css/dashicons.min.css?ver=4.6.1' type='text/css' media='all' /> <!-- ID = admin-bar --> <link rel='stylesheet' id='admin-bar-css' href='http://example.com/wp-includes/css/admin-bar.min.css?ver=4.6.1' type='text/css' media='all' />
Disable it in the same way, using wp_dequeue_style():
add_action('wp_head', function(){ wp_dequeue_style( 'ID' ); }, 5 ); // Priority is important: use 2 through 7Changelog
| Since 1.5.0 | Introduced. |
Where the hook is called
do_action( 'wp_head' );
Where the hook is used in WordPress
add_action( 'wp_head', 'wpmu_activate_stylesheet' );
add_action( 'wp_head', 'wp_strict_cross_origin_referrer' );
add_action( 'wp_head', 'do_activate_header' );
remove_action( 'wp_head', $header_callback );
add_action( 'wp_head', '_block_template_viewport_meta_tag', 0 );
remove_action( 'wp_head', '_wp_render_title_tag', 1 ); // Remove conditional title tag rendering...
add_action( 'wp_head', '_block_template_render_title_tag', 1 ); // ...and make it unconditional.
add_action( 'wp_head', 'wp_admin_bar_header' );
add_action( 'wp_head', $header_callback );
add_action( 'wp_head', array( $this, 'customize_preview_loading_style' ) );
add_action( 'wp_head', array( $this, 'remove_frameless_preview_messenger_channel' ) );
add_action( 'wp_head', array( $this, 'print_head_enqueued_script_modules' ) );
add_action( 'wp_head', 'rest_output_link_wp_head', 10, 0 );
add_action( 'wp_head', '_wp_render_title_tag', 1 );
add_action( 'wp_head', 'wp_enqueue_scripts', 1 );
add_action( 'wp_head', 'wp_resource_hints', 2 );
add_action( 'wp_head', 'wp_preload_resources', 1 );
add_action( 'wp_head', 'feed_links', 2 );
add_action( 'wp_head', 'feed_links_extra', 3 );
add_action( 'wp_head', 'rsd_link' );
add_action( 'wp_head', 'locale_stylesheet' );
add_action( 'wp_head', 'wp_robots', 1 );
add_action( 'wp_head', 'print_emoji_detection_script', 7 );
add_action( 'wp_head', 'wp_print_styles', 8 );
add_action( 'wp_head', 'wp_print_head_scripts', 9 );
add_action( 'wp_head', 'wp_generator' );
add_action( 'wp_head', 'rel_canonical' );
add_action( 'wp_head', 'wp_shortlink_wp_head', 10, 0 );
add_action( 'wp_head', 'wp_custom_css_cb', 101 );
add_action( 'wp_head', 'wp_site_icon', 99 );
add_action( 'wp_head', 'wp_post_preview_js', 1 );
add_action( 'wp_head', '_custom_logo_header_styles' );
add_action( 'wp_head', 'wp_enqueue_img_auto_sizes_contain_css_fix', 0 ); // Must run before wp_print_auto_sizes_contain_css_fix().
add_action( 'wp_head', 'wp_print_auto_sizes_contain_css_fix', 1 ); // Retained for backwards-compatibility. Unhooked by wp_enqueue_img_auto_sizes_contain_css_fix().
add_action( 'wp_head', 'wp_maybe_inline_styles', 1 ); // Run for styles enqueued in <head>.
add_action( 'wp_head', 'wp_oembed_add_discovery_links', 4 ); // Printed after feed_links() and feed_links_extra().
add_action( 'wp_head', 'wp_oembed_add_discovery_links' ); // Unhooked the first time that wp_oembed_add_discovery_links() runs for back-compat.
add_action( 'wp_head', 'wp_oembed_add_host_js' ); // Back-compat for sites disabling oEmbed host JS by removing action.
add_action( 'wp_head', 'wp_print_font_faces', 50 );
remove_action( 'wp_head', 'feed_links_extra', 3 ); // Just do this yourself in 3.0+.
remove_action( 'wp_head', 'wp_custom_css_cb', 101 );
remove_action( 'wp_head', 'wp_oembed_add_discovery_links' );
remove_action( 'wp_head', 'wp_print_auto_sizes_contain_css_fix', $priority );
remove_action( 'wp_head', 'wp_custom_css_cb', 101 );
add_action( 'wp_head', $args[0]['wp-head-callback'] );
add_action( 'wp_head', $args[0]['wp-head-callback'] );
remove_action( 'wp_head', $support[0]['wp-head-callback'] );
remove_action( 'wp_head', $support[0]['wp-head-callback'] );
add_action( 'wp_head', array( $this, 'recent_comments_style' ) );
add_action( 'wp_head', 'wpmu_signup_stylesheet' );
add_action( 'wp_head', 'do_signup_header' );