wp_headaction-hookWP 1.5.0

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 );
}


This is equivalent to:

<?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.

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 7

Changelog

Since 1.5.0 Introduced.

Where the hook is called

wp_head()
wp_head

Where the hook is used in WordPress

wp-activate.php 114
add_action( 'wp_head', 'wpmu_activate_stylesheet' );
wp-activate.php 115
add_action( 'wp_head', 'wp_strict_cross_origin_referrer' );
wp-activate.php 94
add_action( 'wp_head', 'do_activate_header' );
wp-includes/admin-bar.php 1390
remove_action( 'wp_head', $header_callback );
wp-includes/block-template.php 131
add_action( 'wp_head', '_block_template_viewport_meta_tag', 0 );
wp-includes/block-template.php 134
remove_action( 'wp_head', '_wp_render_title_tag', 1 ); // Remove conditional title tag rendering...
wp-includes/block-template.php 135
add_action( 'wp_head', '_block_template_render_title_tag', 1 ); // ...and make it unconditional.
wp-includes/class-wp-admin-bar.php 53
add_action( 'wp_head', 'wp_admin_bar_header' );
wp-includes/class-wp-admin-bar.php 70
add_action( 'wp_head', $header_callback );
wp-includes/class-wp-customize-manager.php 1947
add_action( 'wp_head', array( $this, 'customize_preview_loading_style' ) );
wp-includes/class-wp-customize-manager.php 1948
add_action( 'wp_head', array( $this, 'remove_frameless_preview_messenger_channel' ) );
wp-includes/class-wp-script-modules.php 445
add_action( 'wp_head', array( $this, 'print_head_enqueued_script_modules' ) );
wp-includes/default-filters.php 336
add_action( 'wp_head', 'rest_output_link_wp_head', 10, 0 );
wp-includes/default-filters.php 349
add_action( 'wp_head', '_wp_render_title_tag', 1 );
wp-includes/default-filters.php 350
add_action( 'wp_head', 'wp_enqueue_scripts', 1 );
wp-includes/default-filters.php 351
add_action( 'wp_head', 'wp_resource_hints', 2 );
wp-includes/default-filters.php 352
add_action( 'wp_head', 'wp_preload_resources', 1 );
wp-includes/default-filters.php 353
add_action( 'wp_head', 'feed_links', 2 );
wp-includes/default-filters.php 354
add_action( 'wp_head', 'feed_links_extra', 3 );
wp-includes/default-filters.php 355
add_action( 'wp_head', 'rsd_link' );
wp-includes/default-filters.php 356
add_action( 'wp_head', 'locale_stylesheet' );
wp-includes/default-filters.php 358
add_action( 'wp_head', 'wp_robots', 1 );
wp-includes/default-filters.php 359
add_action( 'wp_head', 'print_emoji_detection_script', 7 );
wp-includes/default-filters.php 360
add_action( 'wp_head', 'wp_print_styles', 8 );
wp-includes/default-filters.php 361
add_action( 'wp_head', 'wp_print_head_scripts', 9 );
wp-includes/default-filters.php 362
add_action( 'wp_head', 'wp_generator' );
wp-includes/default-filters.php 363
add_action( 'wp_head', 'rel_canonical' );
wp-includes/default-filters.php 364
add_action( 'wp_head', 'wp_shortlink_wp_head', 10, 0 );
wp-includes/default-filters.php 365
add_action( 'wp_head', 'wp_custom_css_cb', 101 );
wp-includes/default-filters.php 366
add_action( 'wp_head', 'wp_site_icon', 99 );
wp-includes/default-filters.php 496
add_action( 'wp_head', 'wp_post_preview_js', 1 );
wp-includes/default-filters.php 568
add_action( 'wp_head', '_custom_logo_header_styles' );
wp-includes/default-filters.php 661
add_action( 'wp_head', 'wp_enqueue_img_auto_sizes_contain_css_fix', 0 ); // Must run before wp_print_auto_sizes_contain_css_fix().
wp-includes/default-filters.php 662
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().
wp-includes/default-filters.php 663
add_action( 'wp_head', 'wp_maybe_inline_styles', 1 ); // Run for styles enqueued in <head>.
wp-includes/default-filters.php 735
add_action( 'wp_head', 'wp_oembed_add_discovery_links', 4 ); // Printed after feed_links() and feed_links_extra().
wp-includes/default-filters.php 736
add_action( 'wp_head', 'wp_oembed_add_discovery_links' ); // Unhooked the first time that wp_oembed_add_discovery_links() runs for back-compat.
wp-includes/default-filters.php 737
add_action( 'wp_head', 'wp_oembed_add_host_js' ); // Back-compat for sites disabling oEmbed host JS by removing action.
wp-includes/default-filters.php 812
add_action( 'wp_head', 'wp_print_font_faces', 50 );
wp-includes/deprecated.php 2416
remove_action( 'wp_head', 'feed_links_extra', 3 ); // Just do this yourself in 3.0+.
wp-includes/deprecated.php 6377
remove_action( 'wp_head', 'wp_custom_css_cb', 101 );
wp-includes/embed.php 345
remove_action( 'wp_head', 'wp_oembed_add_discovery_links' );
wp-includes/media.php 2202
remove_action( 'wp_head', 'wp_print_auto_sizes_contain_css_fix', $priority );
wp-includes/script-loader.php 2620
remove_action( 'wp_head', 'wp_custom_css_cb', 101 );
wp-includes/theme.php 2964
add_action( 'wp_head', $args[0]['wp-head-callback'] );
wp-includes/theme.php 2978
add_action( 'wp_head', $args[0]['wp-head-callback'] );
wp-includes/theme.php 3114
remove_action( 'wp_head', $support[0]['wp-head-callback'] );
wp-includes/theme.php 3128
remove_action( 'wp_head', $support[0]['wp-head-callback'] );
wp-includes/widgets/class-wp-widget-recent-comments.php 35
add_action( 'wp_head', array( $this, 'recent_comments_style' ) );
wp-signup.php 100
add_action( 'wp_head', 'wpmu_signup_stylesheet' );
wp-signup.php 37
add_action( 'wp_head', 'do_signup_header' );