Async or Defer JavaScript Files in WordPress

There are a lot of articles out there about how to async or defer scripts in WordPress, but they assume you’ll be writing all the code or using one of the bloated plugins to make it happen.

In my case, I just needed the ability to async or defer a few scripts in a custom plugin or theme. Sure, I could add all the filters every time to make that work, but I’m a programmer. Why should I have to constantly write the same code over and over again? Why not create a simple module to handle this for me and allow me to async and defer scripts in a truly WordPress way? So I did just that.

Introducing the WordPress Async/Defer Scripts Module

A Composer library for asynchronously loading or deferring scripts in WordPress. View on GitHub or Packagist.

Requirements

  • PHP 5.3+
  • WordPress 4.2+

Installation

Add the module to your code base via Composer:

composer require wpscholar/wp-async-defer-scripts

Be sure to require the Composer autoloader in your project:

<?php

require __DIR__ . '/vendor/autoload.php';

Usage

Asynchronously load a script using the wp_scripts()->add_data() method:

<?php

add_action( 'wp_enqueue_scripts', function() {
    wp_enqueue_script( 'recaptcha', 'https://www.google.com/recaptcha/api.js' );
    wp_scripts()->add_data( 'recaptcha', 'async', true );
} );

Defer loading of a script using the wp_scripts()->add_data() method:

<?php

add_action( 'wp_enqueue_scripts', function() {
    wp_enqueue_script( 'recaptcha', 'https://www.google.com/recaptcha/api.js' );
    wp_scripts()->add_data( 'recaptcha', 'defer', true );
} );

Initialization

In most cases, you can simply follow the installation instructions and things will just work. However, if you are including this library outside of a WordPress plugin or theme, you may have to manually initialize the class:

<?php

wpscholar\WordPress\AsyncDeferScripts::initialize();

Conclusion

I’d love to see simple async and defer functionality added to WordPress core, but in the meantime, this has worked out quite well for my own personal projects and I thought I’d share it with you. What do you think?

WordPress Post Expiration Module

WordPress plugins are great, but sometimes you want to avoid having additional settings screens or giving a client access to make changes that could break functionality on their website.

If you aren’t a coder and you want to automatically expire a post in WordPress, I’d recommend that you check out the Post Expirator plugin. However, if you want a nice and simple way to expire posts without having to deal with extra admin configuration, then you should check out my WordPress Post Expiration module.

Composer Installation

All the Composer users out there can just run

composer require wpscholar/wp-post-expiration

to add the module to your WordPress project.

If added to a WordPress theme or plugin, the only code you will need to add is a line of code for each post type that should support expiration:

add_post_type_support('post', 'expiration');

You can also just add ‘expiration’ to the ‘supports’ array when defining a custom post type.

Viola!

You now have a meta box on all posts that allow you to set an expiration date and time. If no date is set, then the post will live on forever. Otherwise, it will use the WordPress cron functionality to run a task every hour and automatically trash any posts that have an expiration date in the past.

Manual Installation

Not using Composer? Just download the module into your project, require the PostExpiration.php file. Then, add this line of code:

add_action( 'init', [ '\wpscholar\WordPress\PostExpiration', 'initialize' ], 1000 );

Be sure to add the ‘expiration’ post type support to the desired post types and you are good to go!

View wpscholar/wp-post-expiration on Packagist.

New Plugin Release: Simple Website Redirect

Piggybacking off of my last post regarding how to redirect an entire website except for the WordPress admin, I’m announcing the release of a new plugin: Simple Website Redirect.

After being asked by someone “Where do I put the code?”, I went looking knowing I would find a plugin that does the same thing that I could recommend for a non-developer type. However, what I found is that there isn’t a single plugin in the WordPress.org plugin repository that made it easy for people to redirect an entire website.

This plugin allows you to set the URL you want to redirect to, select whether to use a permanent or temporary redirect and toggle the redirect functionality on and off from a very simple admin screen.

When enabled, redirects happen on the front end of the site while still allowing the WordPress admin to be accessible. All redirects will retain the URL path and query string for further handling on the new site.

Since it is a plugin, it doesn’t matter what web server you are running, it will just work. The only word of caution I have is to make sure and test things with the ‘Redirect Type’ in ‘Temporary’ mode first. Otherwise, your browser will cache the redirects and things will appear not to work correctly as you continue to make changes.

Go ahead, download the plugin and give it a try!

Redirect Entire Website Except WordPress Admin

I get asked a lot about how to handle different types of website redirects. Usually, someone wants to redirect an entire site, or maybe just redirect a subdomain.  Other times, they want to do simple one-off redirects.

Many web servers that run WordPress use Apache, which means that .htaccess rules will work. Other web servers like Nginx don’t look at your .htaccess file at all. So the most reliable way of creating a redirect regardless of the web server is to implement it in the WordPress code itself. After all, in this scenario, you want to keep the WordPress admin available… so you obviously aren’t getting rid of the old domain or site instance.


<?php

if ( ! is_admin() ) {
    wp_redirect( 'https://www.mynewwebsite.com' . $_SERVER['REQUEST_URI'], 301 );
    exit;
}

The code snippet above will get the job done and will make sure that the path the user was trying to go to is kept so you can properly handle any further redirects on the new site.

Not a coder? Don’t worry, you can download the Simple Website Redirect plugin which will do the same thing!

Get the Title for the Posts Page in WordPress

This little tidbit is for all you WordPress themers out there.  It is important that your theme displays the proper title on the page no matter what settings a user has on their site.  As you probably are already aware, a user can go to ‘Settings’ -> ‘Reading’ in the WordPress admin menu and change what pages are used for the front page and the posts page (aka blog page)…

(more…)

First Steps to WordPress Security

WordPress security is an important consideration, but often site owners don’t think about it until it is too late. Like most things, the Pareto principle applies: If you can do a few simple things (20%), you can prevent most security issues (80%). In addition to prevention, you can also take a few simple steps that will help ensure you are able to restore your site in the event that it is compromised, corrupted, or even just accidentally deleted.

This article isn’t really targeted at developers, but rather non-technical site owners who want to make sure they have at least done the bare minimum when it comes to security. On that note, here are my quick and dirty recommendations:

  • Keep WordPress up to date. – Older versions of WordPress are more likely to be hacked as they don’t include many of the security fixes that newer versions do. Just be sure you update all of your plugins as well as your theme before upgrading WordPress core to avoid potential issues when upgrading.
  • Keep your theme and plugins up to date. – Again, older versions are more likely to be hacked as they don’t include many of the security fixes that newer versions do.
  • Only use quality themes and plugins. – WordPress core is very secure and most often it is a bad theme or poorly coded plugin that makes your site vulnerable. Make sure that the software you install is of reasonable quality. If you are using a theme or plugins from the WordPress repository, you can do a little checking to see the last time it was updated, what types of reviews its had and how many downloads or active installs its had. For premium themes and plugins, you’ll just have to do more research on the company and ask experienced WordPress developers and/or users if the company and plugin are reputable. As a rule of thumb: Never download free plugins that aren’t listed in the WordPress repository.
  • Set a secure password and change it often. – You should change your password about once every one to three months. Hackers have scripts that will try to guess your password. A more secure password will be harder to guess and changing your password occasionally will ensure that they have to start the guessing process over again and aren’t given an unlimited amount of time to discover your password. If an easy to remember password is important to you, then create an admin user with a super-complicated password and then create another user that has the ‘Editor’ role. You can then use that ‘Editor’ role to log in and do your normal content publishing. However, I’d recommend just using a tool like LastPass to help you keep track of your passwords.
  • Backup your site regularly. – If your site is ever hacked or otherwise lost, at least you will be able to restore it. Obviously, your backup schedule will depend on how often you update the site and/or perform software upgrades. Be sure that you backup not only the filesystem, but also the database. There are some great tools out there for handling backups, like these:
  • Make sure your site backups are stored offsite. – In other words, don’t count on or trust backups from your web host or backups that are stored on your site’s server. Your data needs to be somewhere that a hacker isn’t likely to delete it if they gained access to the server. Ideally, your web host will also provide backups so that you have some built-in redundancy.

If you do these things, you will be well on your way to securing your site and will be able to easily recover if something does happen. This is by no means an exhaustive list, so once you’ve taken care of these things be sure to check out the Next Steps section below.

If you are technical enough to add a line to your wp-config.php file, you will get bonus points for adding this line to disable the WordPress file editor:

define('DISALLOW_FILE_EDIT', true);

Next Steps

The tips listed here cover just a few things you can do to improve security. Here are a few resources to help you take security to the next level:

Add Helper Classes to WordPress Navigation Menus

WordPress automatically outputs many helpful CSS class names for menus. If you use the wp_nav_menu() function to display your menus, as all good themes should do, you don’t have to settle for just the default class names.

The wp_nav_menu() function calls the wp_nav_menu_objects filter, which allows you to manipulate the menu objects before being converted into HTML and displayed on the site. One of the things you can do is add a few custom class names, like this:

// Add extra classes for the first and last items in all WordPress menus
add_filter( 'wp_nav_menu_objects', function ( $items ) {
   if ( ! empty( $items ) ) {
      $items[1]->classes[] = 'menu-item-first';
      $items[ count( $items ) ]->classes[] = 'menu-item-last';
   }

   return $items;
} );

This adds a menu-item-first class to the first menu item and a menu-item-last class to the last menu item. These extra utility classes are helpful when styling menus in a custom theme.

Prevent Directory Browsing with .htaccess

Directory browsing allows visitors to your site to see and browse through the contents of folders on your web site. Anyone on the web could potentially visit a directory on your site, see what files exist there and open them at will. Typically, web hosts disable directory browsing for security reasons. However, there are still plenty of web hosts out there that don’t disable it.

Basically, if directory browsing is enabled and you don’t have an index.html or index.php file in a given directory, the web browser will display the contents of the directory along with a link back to the parent directory.

Obviously, revealing the inner workings of your website to the public could entice hackers or at least make their job easier. Hackers can perform Google searches to find sites with directory browsing enabled and then choose sites which have known vulnerabilities based on their findings.

How to Check Your Site

You can check to see if directory browsing is enabled on your site by creating a folder and adding a basic text file. If you visit the directory in your web browser and it displays a link to the text file, then directory browsing is enabled. If you get a ‘Page Not Found’ or ‘Forbidden’ message, then directory browsing is disabled.

Web Host Checklist

If you find that your web host has directory browsing enabled, leave a comment below and we’ll start a running list. Meanwhile, if your web host uses an Apache server, you will want to apply the fix at the end of this article.

Directory Browsing and WordPress

By default, a self-hosted installation of WordPress has a built-in safeguard against directory browsing. A new WordPress installation will contain a blank index.php file in each folder so that a user visiting a folder, such as the plugins directory, will be presented with a blank screen. However, many WordPress plugins don’t do this. This means that hackers can likely see what plugins, and versions of those plugins, that you have installed on your site.

Securing Access to your Directories with .htaccess

The easiest way to disable directory browsing is to add a line to your site’s .htaccess file. Just be aware that this only works for sites running on an Apache web server.

Keep in mind that you can have .htaccess files in multiple locations, but you want to make your change in the .htaccess found in the root directory for your domain. This will cause the change to take place across your entire site.

Here is what you will need to do:

  • Download your .htaccess file and make a copy. You should always keep a copy of your .htaccess file when making changes, for when things don’t work as planned.
  • Add these lines to your .htaccess file:
# Disable Directory Browsing
Options All -Indexes
  • Upload the new .htaccess file and overwrite the existing one.
  • Verify that directory browsing is disabled. You can visit a folder that previously allowed you to view the directory contents and be sure you are getting a ‘Page Not Found’ or ‘Forbidden’ error message.

Browser Caching of 301 Redirects

Many people don’t realize that browsers cache 301 redirects. A 301 redirect is a permanent redirect from one URL to another. It only makes sense that a browser should cache a 301 redirect, after all, it is permanent.

Our natural tendency after setting up redirects is to check and see if they are working properly. However, if you made a mistake and had to tweak one of your 301 redirect rules, guess what is going to happen when you go to test your change? Yep. Your browser is going to send you to the same place it redirected you to last time.

Clear your browser cache each and every time you make a change to a 301 redirect.

If you put a 301 redirect into operation, that redirect will be cached in the browser for any visitor’s on your site. You can’t clear the browser cache for your users, so if you need to change or undo a 301 redirect, the old redirect is still going to be in effect until their cache expires.

Never put a 301 (permanent) redirect in place unless it is truly permanent!

When you are setting up redirects and aren’t sure if they work yet, do you really want them to be permanent? No, you still need to test them! As a best practice, you should always implement 302 (temporary) redirects first. This way you will avoid having to constantly clear your browser cache and you will never have a situation where a subset of your users are constantly redirected into oblivion because their browser cached a bad redirect.

Always implement 302 (temporary) redirects first, then change them to 301 (permanent) redirects once you’ve tested them!