Understanding WordPress Hooks

WordPress, the most popular CMS (Content Management System) is known for its flexibility. It’s highly customizable, and making any changes is incredibly easy. One of the most important aspects of WordPress and its flexibility is WordPress hooks. In this post, we are going to explore what exactly a WordPress hook is, how it works and how we can use them.

Users are able to extend WordPress functionality by using plugins. WordPress.org has more than 55,000 plugins in its repository – many of which are free. There are some premium plugins hosted by WordPress.org as well.

So, even by looking at the plugin’s stats, we see that a lot of developers create plugins for WordPress. This is due to the flexible nature of the WordPress structure. So where do hooks come into play? They are an integral part of how plugins work with WordPress core.

What is a WordPress hook?

Let’s break it down. A WordPress hook will let you know that something is happening. In other words, a hook will let you run custom codes when loading a WordPress website to add, remove or modify certain functionality or data. You can do the following with a hook:

  • Executing a code to send a welcome email right after a new user has registered to the site.
  • Running a custom code to clear site cache after saving new changes in customizer.
  • Modifying the default admin footer text.
  • Changing the label of the “Register” button on the registration page.
  • Modifying the markup of the page right before the page loads.
  • Including new styles in certain conditions.

The main point of using hooks is that you don’t need to touch WordPress core files that are required by WordPress to work. If you edit any file in WordPress core, you’ll lose it after updating WordPress.

These are some basic examples of WordPress hooks. As previously mentioned, they work with certain functionality or data. So, there are two different types of WordPress hooks:

  • Actions
  • Filters

WordPress Actions

Action hooks can be used to add custom functionality when needed. For instance, imagine that you want to run a code to log the last login time for each user. You’ll need to run a piece of code that records the time right after a user logs into the site. So you’ll need to run an additional functionality at a certain time. In this case, we would have to use action hooks. Action hooks work with functionality – they are doing something new.

How do action hooks work?

Action hooks are similar to informing everyone that you want to do a specific thing such as saying, “Hey buds, I’ve just arrived” or “Bye guys, I’m leaving.” When you inform others, they are aware of what you did or what you want to do, and they can say something in response, remind you of something or react in any other type of way.

While WordPress is loading and reaches a specific point, it’ll let us know about it. So, you can run your codes to add specific functionality or to extend existing functionality.
Some examples of actions include the following:

wp_head When you reach the <head> tag, WordPress lets you know by running the wp_head hook. Remember it as a name. We will provide you with some codes and an explanation about how to use hooks.

publish_post This runs when a post is published or if it is edited and its status is changed to “published.” So, Imagine that you want to tweet a post automatically after publishing it to your WordPress site. This hook makes it easy for you to do it.

wp_footer This action hook is triggered near the tag. That means you are reaching the end of document markup. Many developers use this hook to include their javascript files to the footer of the page.

WordPress Filters

Photo by Luca Bravo on Unsplash

Filter hooks work with data. By data, we mean a simple text, HTML markups and even a PHP variable that could be the value of an option. This means that you can change an option value on the fly. Or you can change a certain text in the admin dashboard without editing WordPress core files. Also, filters could be used to modify multiple things at the same time. For example, you can add a new class name and data attribute simultaneously to the navigation menu items using a filter.

How do filter hooks work?

Filter hooks differ from action hooks. When you reach a certain code, WordPress allows you to make changes to something. Imagine that your child wants to go to school and right before going out, you put an extra book in their backpack. In this example, you’ve changed the content of the backpack and filtered it when you had access to it. Filters work in the same way. They will let you know that content is going to be printed or when an option is going to be used – and you’ll be able to modify it if you want.

Some real example of filters are:

login_erros This runs whenever an error is going to be shown to the user in the login page.

body_class This fires (runs) while generating the tag. Use this filter hook if you want to modify the class names of the body tag.

pre_delete_post This fires right before deleting a post. You may want to avoid sending them to the trash and delete them completely. This filter hook will be useful for you.

How to use WordPress hooks

We’ve covered the basics of WordPress hooks. It’s time to learn code and use actions and filters in the real world. In this section, we’ll see some new things such as Hooked functions, Hook priority and Hook arguments.

Basic WordPress hooks usage

add_action( ‘init’, function(){
     // Do something.
 } );
Code explanation:

add_action: This is a function from WordPress. You’ll need to use this whenever you want to register a new action hook (run an action).

init: This is the hook name. Each event has a unique hook name. You can find a list of existing WordPress hooks on the Plugin API/Action reference page.

function(): This is the callback. The code that you want to execute when reaching the event.

For filters, it is a bit different:

add_filter( ‘excerpt_length’, function( $value ){
     // Do something and change $value.
     return $value
 } );

add_filter: Same as actions, this is a function name from WordPress. You’ll need to use this whenever you want to register a new filter hook.

excerpt_length: Again, this is the hook name. Hook names are meaningful. So, while using excerpt_length you can expect that it will change the excerpt length of the post excerpt.

function(): This is the callback and the code that you want to execute in order to change something.

And the big difference with actions:

return $value

Filters need to return something. Why? Because using filters, you’re going to change something, not destroy it. If you don’t return, your variable/value will be missed. So, keep in mind, always return in filter callback.

Another way to implement this:

add_action( ‘init’, ‘my_callback’ );

 Function my_callback(){
    // Do something.
}

In this mode, we have separated the callback function instead of using an anonymous function. There is no difference.

Hook Priority

add_action( ‘init’, ‘my_callback_early’, 9  );
add_action( ‘init’, ‘my_callback_normal’, 10 );
add_action( ‘init’, ‘my_callback_late’, 11 );

The priority determines when the callback function will be executed in relation to the other callback functions associated with a given hook.

In the above example, my_callback_early is the first function that runs when reaching the init hook. After that, the my_callback_normal will run and at the end my_callback_late.

When there are multiple registered callback functions for the same hook with the same priority, the order of registering them will be used to running callback functions.

Hook Arguments

A callback function can take some arguments. For example, the excerpt_length hook will pass the current length as a parameter. So you have access to it in your callback function.

add_filter( ‘excerpt_length’, ‘my_custom_excerpt_length’, 10, 1);

function my_custom_excerpt_length( $length ) {
  $length = 50;
  return $length;
}

In the above example, 10 is the priority of the running callback, and 1 is the number of the callback function parameters. Because both of them are like default values, you can avoid writing them. The following code does exactly the same thing:

add_filter( ‘excerpt_length’, ‘my_custom_excerpt_length’ );

Practical Examples of WordPress Hooks

Add new admin menu and page:
function register_my_custom_menu_page() {
     add_menu_page( 'Custom menu page title', 'Custom menu label', 'manage_options', 'myplugin-settings.php', '', '
 dashicons-menu-alt3', 6 );
 }
 add_action( 'admin_menu', 'register_my_custom_menu_page' );
Change the excerpt length
function my_custom_excerpt_length( $length ) {
     return 35;
 }
 add_filter( 'excerpt_length', 'my_custom_excerpt_length', 999 );
Insert custom content after each post
function my_custom_post_footer($content) {
        if(!is_feed() && !is_home()) {
                $content.= "<p>Share your idea about this post in comments.</p>";
        }
        return $content;
}
add_filter('the_content', 'my_custom_post_footer');
Disable autosave
function my_prefix_disable_auto_save(){
    wp_deregister_script( 'autosave' );
}
add_action( 'wp_print_scripts', 'my_prefix_disable_auto_save' );
Change the login page message
function my_prefix_the_login_message( $message ) {
    if ( empty($message) ){
        return "<p>Welcome to this site. Please log in to continue</p>";
    } else {
        return $message;
    }
}
add_filter( 'login_message', 'my_prefix_the_login_message' );
Remove login error messages
function my_prefix_remove_login_errors( $error ) {
    return "Incorrect login information";
}
add_filter( 'login_errors', 'my_prefix_remove_login_errors');

Final Thoughts

Wrapping up, WordPress hooks are one of the most important concepts that allow us to develop plugins and add new custom functionality to WordPress. Again, don’t forget to return when using a filter hook ;).

In this article, we guided you through the basics of WordPress hooks, including what they are and how they work. We also gave you some examples of how they are used in code to add further functionality to your website.

In the comments section below, please share your experiences and thoughts with us!

Is WordPress Secure Enough? A WordPress Security Review

WordPress Security Featured Image

Let’s consider for a moment a hot topic when it comes to the web: security. Poor security on WordPress websites could lead to secrets being exposed, reputations getting lost in the market and even a service getting shut down.

Yes, security is the most important thing on the web and, unfortunately, many users and even administrators don’t have enough know-how about this matter.

In this post, we’ll take a glance at WordPress security to become familiar with the most crucial things about securing a WordPress website.

As an immense open-source project, WordPress is the most well-known CMS (content management system). Based on statistics, WordPress powers 34% of websites on the internet and more than 60% of websites that use a known CMS use WordPress. This also makes it the most attractive platform for hackers as well. Indeed, if you find an important security hole in WordPress, you can affect 34% of the internet.

You may have heard about WordPress websites getting hacked, and the main question that comes to mind is: “Is WordPress secure enough?” In this post, we’ll address this question by reviewing some stats, layers of WordPress installation security and the performances of administrators. Read until the end to get a good idea of the state of WordPress security.

WordPress Security Statistics

WordPress Security Report Sucuri.Net
Image from sucuri.net

According to a report from Sucuri & GoDaddy, from a total of 25,466 infected sites in 2018, 90% of them used WordPress. The report reveals an increase in WordPress infections from 2017.

When looking at the most significant problems, you won’t find anything related to WordPress core security. Interestingly, common issues with WordPress security are not related to WordPress itself. What matters are the configuration, the usage and what administrators do.

We know that WordPress is an open-source project, meaning that everyone can see the codes and make some changes to them. On the one hand, this would seem to be an open-source CMS that could potentially cause more security problems because anyone can see the codes, discover a security bug and later use it to attack websites.

On the other hand, any individual can watch the status of a project’s security and report any possible security issue privately to the team. WordPress applies security patches immediately, and a new version becomes available to download as soon as possible. Each time a new version comes out, they mention how many security problems have been fixed in the changelog.

Based on the statistics, there is no common effect on websites due to WordPress core security problems. In other words, it works!

Layers of WordPress Security

We first need to wrap our heads about the fact that the security of a WordPress site is not only about WordPress itself. It depends on some other aspects such as themes and plugins, as well as some third-party tools like hosts and servers – and above all, site administrators.

WordPress Core Security

We briefly reviewed WordPress core security in the previous paragraph and mentioned that WordPress patches any security problems immediately. But, what will happen if you don’t upgrade your WordPress installation with the latest version? Then, you’re an excellent target for hackers.

WordPress Core Security

Detecting the version of WordPress is not hard to do. Even if you use plugins and codes to hide which version of WordPress your site is using, there’s no guarantee that hackers won’t be able to detect the version of your WordPress. And after that, there’s a list of security problems (which are fixed in the latest version) that you won’t have access to it unless you upgrade WordPress. With a list of potential security holes in your site, the chances of being hacked increase. Therefore, it’s better to constantly keep your WordPress site up to date.

Security of Themes & Plugins

Unknown Sources

Most WordPress sites get hacked because of their backdoors. So, if you download a theme or plugin from an unknown source or a site that provides a nulled version of premium themes, you are at risk. It’s all too easy to inject some codes into the package and provide a zip package to download. Unfortunately, some users are not aware of this and, for that, administrators are responsible.

Non-updated Themes or Plugins

Similar to WordPress core, you should keep plugins or themes up to date because they are even more vulnerable. Sometimes it takes time to patch a security problem. If you read the fascinating facts surrounding the Panama Papers hack on Wordfence’s site, you may never forget to update your themes and plugins with the latest version.

Host, Server and WordPress Installation Configuration

Web Hosting WordPress Security
Photo by Web Hosting on Unsplash

Sometimes, a website gets hacked in shared hosting. After hacking a website, the hacker may penetrate the host and then access other websites on that server.

Consequently, it’s crucial to host your website in a known and secure host provider. And it’s better to configure the hosts accurately. There are many factors to consider while configuring a server for a WordPress installation. As a quick checklist, you should be aware of the firewall, backup system, SSL and SFTP, automatic security checks, malicious activity detector, email security, and file permission. We’ll take a deep dive into these matters in a later blog post.

Moreover, it’s necessary to be aware of configuring the installation. Changing default database table prefixes, using a strong password and not using “admin” as the username can decrease the chances of your website getting hacked. Following these simple steps can help you to avoid any possible security problems on your website. We’ll also describe in detail WordPress configuration problems in another blog post.

Administration

As mentioned previously, admin is one of the biggest problems and the main reason why websites get hacked. As we can gather from the statistics, the most prevalent problem is website administrators and webmasters. Unfortunately, not enough attention has been paid to this matter.

The security of a website is highly dependent on the performance of webmasters. They can simply allow hackers in by setting an easy-to-guess password or username like “admin” and “12345678.” Sometimes, webmasters aren’t informed about security patches or small updates, and it can put the website at risk. An administrator should be cautious about user roles and permissions when a website is open for new user registration.

Many of these precautions are easy to take when using a security plugin. We’ll have a blog post about WordPress security plugins that will include a review of the most popular ones.

As a result, it’s easy to say that the WordPress core is highly secure. The community will take care of WordPress security, and if you want to use it for your new project, it’s better to take some time to learn more about common security problems, find a good host provider and correct configuration.

How To Create WordPress Custom Admin Pages

WordPress, the world’s most popular CMS is also quite beloved by developers. Among many of its possible customizations and flexibilities that can be pointed out is extending the admin side of WordPress. In this post, we will show you how to use WordPress custom admin pages to bring more options for the user.

What is WordPress Custom Admin Pages?

The WordPress admin dashboard is the first page you’ll see after logging in. Using the side menu, you can navigate to other admin pages like Appearance, Plugins, Settings, Users, etc.

You may also see new menu items after activating a theme or a plugin that redirects you to a new admin page. It can be a settings page for the plugin, control panel of your theme, a page to show the status of your site or even a document page. The custom admin page is a very helpful feature which allows the developer to extend admin rights with new options.

How to Add WordPress custom Admin Pages

In order to add a custom admin page in WordPress, we need 2 things:

  1. An admin menu (add_menu_page function)
  2. Page content (custom function)

In order to add a new admin menu item, we can use the following function:

add_menu_page( string $page_title, 
string $menu_title, string $capability, 
string $menu_slug, callable $function = '', 
string $icon_url = '', int $position = null )

Let’s dive into each item to learn what they are.

1. $page_title The text to be displayed in the title tags of the page when the menu is selected. Choose a meaningful page title. For example, if your custom admin page is an options page for the plugin, it could be “My plugin options”. Note that it should be translatable. So use _ function like the following example: _( ‘My Plugin Options’, ‘my-plugin-textdomain‘)

2. $menu_title The text to be used for the menu.

3. $capability The capability required for this menu to be displayed to the user. For example, if it contains some general options for the site, manage_option could be the best choice. Just set it carefully to avoid any possible security issue.

Check out the WordPress Roles and Capabilities page and see what the proper capability is for your custom admin page.

4. $menu_slug The slug name that refers to this menu. It should be unique for this menu page and only include lowercase alphanumeric, dashes, and underscores to be compatible with sanitize_key(). This will be used as a parameter in the URL of your custom admin page as it’s shown in the picture.

5. $function The function to be called to show the output content for this page. For a simple example, we can use the following code to show a header in the admin page:

function my_admin_page_contents() {
	?>
		<h1>
			<?php esc_html_e( 'Welcome to my custom admin page.', 'my-plugin-textdomain' );
		</h1>
	<?php
}

6. $icon_url The URL of the icon to be used for this menu. You can use an image, encoded SVG, or dash icons.

  • In order to use an image, simply pass the URL of the image.
  • If you want to have an icon like WordPress defaults, which has a different color on hover, you can pass an encoded SVG file. The http://b64.io/ can convert your SVG file to base64 encoded data. After uploading your SVG, simply copy the link that starts with data:image/svg+xml;base64, and paste it.
  • You can use existing WordPress icons. Find a proper icon from WordPress Dashicons page and pass the class name like dashicons-schedule as icon URL argument.
  • Also, you can use none value to leave div.wp-menu-image empty, so an icon can be added via CSS.

7. $position The position in the menu order should appear. Here is the list of numbers of default admin menus:

  • 2 – Dashboard
  • 4 – Separator
  • 5 – Posts
  • 10 – Media
  • 15 – Links
  • 20 – Pages
  • 25 – Comments
  • 59 – Separator
  • 60 – Appearance
  • 65 – Plugins
  • 70 – Users
  • 75 – Tools
  • 80 – Settings
  • 99 – Separator

So, if you want to show your menu after Dashboard, you should use 3.

In the following table, you can see a piece of brief information about each item.

Add_menu_page arguments

WordPress Custom Admin Pages Arguments
WordPress Custom Admin Pages 1

Putting it all together, you’ll have:

function my_admin_menu() {
		add_menu_page(
			__( 'Sample page', 'my-textdomain' ),
			__( 'Sample menu', 'my-textdomain' ),
			'manage_options',
			'sample-page',
			'my_admin_page_contents',
			'dashicons-schedule',
			3
		);
	}

	add_action( 'admin_menu', 'my_admin_menu' );


	function my_admin_page_contents() {
		?>
			<h1>
				<?php esc_html_e( 'Welcome to my custom admin page.', 'my-plugin-textdomain' ); ?>
			</h1>
		<?php
	}

You should know that it is possible to add a submenu to existing menus or newly added menu using the following functions:

  • add_posts_page Adds a submenu under Posts menu
  • add_pages_page Adds a submenu under Pages menu
  • add_media_page Adds a submenu under Media menu
  • add_comments_page Adds a submenu under Comments menu
  • add_theme_page Adds a submenu under the Appearance menu
  • add_plugin_page Adds a submenu under Plugins menu
  • add_users_page Adds a submenu under Users menu
  • add_management_page Adds a submenu under Tools menu
  • add_options_page Adds a submenu under Settings menu

And all of them are a wrapper of add_submenu_page function, so we use them in the same way:

add_submenu_page( string $parent_slug, string $page_title, 
string $menu_title, string $capability, 
string $menu_slug, callable $function = '' );

And that’s it. We have a custom admin page. But, what about adding custom styles and scripts for its content?

Adding Styles and Scripts to WordPress Custom Admin Pages

Let’s see how we can put styles after adding page content:

function load_custom_wp_admin_style($hook) {
	// Load only on ?page=mypluginname
	if( $hook != 'toplevel_page_mypluginname' ) {
		 return;
	}
	wp_enqueue_style( 'custom_wp_admin_css', 
plugins_url('admin-style.css', __FILE__) );
}
add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_style' );

The above code will load admin-styles.css file only in the mypluginname page. If you wonder why we should do this, the reason is that loading styles in all admin pages can cause unwanted changes in other admin pages. For example, you don’t want to change the size of texts in the dashboard.

If you’re unsure what your $hook name is, use this to determine your hook name. And then, change it to the code below.

function load_custom_wp_admin_style( $hook ) {
	wp_die( $hook );
}
add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_style' );

Note: Don’t use wp_die while you’re editing a file from the plugin editor. It can cause you to lose access to the admin page until you remove it.

You can also use default registered styles in WordPress, like this:

function load_custom_wp_admin_style( $hook ) {
	// Load only on ?page=mypluginname
	if( $hook != 'toplevel_page_mypluginname' ) {
		 return;
	}
	// Load color picker styles. 
	wp_enqueue_style( 'wp-color-picker' );
}
add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_style' );

In the above code, we are not specifying any URL for the style file because it has already been registered once, and WordPress knows it. By registering a style file, you introduce it to WordPress without loading it. And then, you can load it by using a style handler name anywhere in the code. Have a look at the following code:

function register_my_plugin_styles() {

wp_register_style( 'my-plugin', plugins_url( 'my-plugin/css/plugin.css' ) );

}



// Register style sheet.

add_action( 'admin_enqueue_scripts', 'register_my_plugin_styles' );



function load_custom_wp_admin_style($hook) {

// Load only on ?page=mypluginname

if( $hook != 'toplevel_page_mypluginname' ) {

return;

}

// Load style

wp_enqueue_style( 'my-plugin' );

}



add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_style' );

Same as above, we can load custom scripts in admin pages:



function register_my_plugin_scripts() {

wp_register_script( 'my-plugin', get_stylesheet_directory_uri() . '/plugin-scripts.js', array( 'jquery' ) );

}



// Register style sheet.

add_action( 'admin_enqueue_scripts', 'register_my_plugin_scripts' );



function load_custom_wp_admin_scripts($hook) {

// Load only on ?page=mypluginname

if($hook != 'toplevel_page_mypluginname') {

return;

}

// Load style

wp_enqueue_script( 'my-plugin' );

}



add_action( 'admin_enqueue_scripts', 'load_custom_wp_admin_scripts' );

There are a lot of JavaScript libraries included in WordPress that you can use. There is also a list of default scripts included and registered by WordPress here.

Wrapping It Up in a Plugin

In this section, we put all codes in a single file, which you can install as a plugin to add new WordPress custom admin pages.

<?php

/*

Plugin Name: My custom admin page

Description: Adds a custom admin pages with sample styles and scripts.

Version: 1.0.0

Author: Artbees

Author URI: http://artbees.net

Text Domain: my-custom-admin-page

*/



function my_admin_menu() {

add_menu_page(

__( 'Sample page', 'my-textdomain' ),

__( 'Sample menu', 'my-textdomain' ),

'manage_options',

'sample-page',

'my_admin_page_contents',

'dashicons-schedule',

3

);

}



add_action( 'admin_menu', 'my_admin_menu' );



function my_admin_page_contents() {

?>

<h1>

<?php esc_html_e( 'Welcome to my custom admin page.', 'my-plugin-textdomain' ); ?>

</h1>

<?php

}



function register_my_plugin_scripts() {

wp_register_style( 'my-plugin', plugins_url( 'ddd/css/plugin.css' ) );

wp_register_script( 'my-plugin', plugins_url( 'ddd/js/plugin.js' ) );

}



add_action( 'admin_enqueue_scripts', 'register_my_plugin_scripts' );



function load_my_plugin_scripts( $hook ) {

// Load only on ?page=sample-page

if( $hook != 'toplevel_page_sample-page' ) {

return;

}

// Load style & scripts.

wp_enqueue_style( 'my-plugin' );

wp_enqueue_script( 'my-plugin' );

}



add_action( 'admin_enqueue_scripts', 'load_my_plugin_scripts' );

And the final result will be like this:

In the next post, we will show you how to add custom settings to WordPress Custom Admin Pages, how to process forms, and how to make them secure.