Steve Taylor photo

Forcing SSL on WordPress

There’s a few posts on this around. I’ve based my work doing this on the ever-reliable Chris Coyier’s post at CSS Tricks. However, here’s my own summary and notes…

Forcing SSL for admin

The easy bit. Add this to wp-config.php:

define('FORCE_SSL_ADMIN', true);

Forcing SSL for the front-end

Chris recommends the WordPress HTTPS plugin, but it’s not been updated for a while. Not always a sign of a bad plugin – sometimes a plugin does something simply well, and rarely needs updating. But that’s academic, as the plugin plain didn’t work for me. I just went straight for the ‘force everywhere’ .htacccess code:

RewriteEngine On
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_HOST} !^[^\.]+\.dev$ [NC]
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

I’ve added a line there to exclude local dev sites from this forcing. If you want to use a plugin, WP Force SSL looks like the best bet to me.

Do check for plugin conflicts. I found that activating the WooCommerce ‘Force SSL on checkout’ option created an infinite redirect loop with the above code, even on non-checkout pages.

The WP settings

Change the protocol under Settings > General settings for WordPress Address and Site Address.

Protocols in the HTML head

In 2010 Paul Irish advocated the protocol-relative URL. Basically, miss off the http: (or https:) bit, start the URL with the double-slash, and the protocol of the main request should be used. However, last year Paul added this note:

Now that SSL is encouraged for everyone and doesn’t have performance concerns, this technique is now an anti-pattern. If the asset you need is available on SSL, then always use the https:// asset.

With WordPress, all this is kind of obviated by use of these core functions:

All these functions will return URLs with the protocol the same as the main request.

If you have links to third-party sites, e.g. font providers, you could hard-code https links and just have SSL versions accessed in environments (e.g. local dev) where you’re not using SSL. I happen have this in all my themes:

define( 'PILAU_REQUEST_PROTOCOL', isset( $_SERVER[ 'HTTPS' ] ) ? 'https' : 'http' );

So I can just use that constant if necessary.

Catching strays

Sometimes there are stray, plain http protocols, maybe hard-coded by plugins (grrr!). To catch these, here’s a wrapper for wp_head():

Call this function in your template’s HTML head tag instead of wp_head(). The single parameter is used to say whether we need SSL replacements or not.

I’ve set it so it always does non-SSL locally (testing for the WP_LOCAL_DEV constant), but you can easily change this.

If replacements are required, output buffering is used to grab the output from wp_head() and do the replacements. Besides the protocol replacement, there’s an example of a situation where an actual domain in a URL needs replacing. The ShareThis widget supports SSL, but the WordPress plugin has the protocol and URL hard-coded – and the domain needs to be different for SSL. You can add more replacements to catch more pesky hard-coding.

Protocols on images and other assets in content

For this one – especially for the snippets to replace protocols in existing post_content, head over for Chris Coyier’s tasks 6 & 7!

FWIW, here’s my slimmed-down version of the code to make images inserted into the editor protocol-relative:

Finding ‘mixed content’

You can just browser your site with the browser console open, which should log warnings about mixed http and https content on a page. (I’m looking here at a staging site with a self-signed SSL certificate. I guess on a live site you’ll get an up-front warning from the browser – however, probably best to get all this sorted before going live!)

I’ve not tried it yet, but there’s the WordPress HTTPS Mixed Content Detector Plugin, which looks very promising.

Together, these tips have got me going with SSL. Hope they’re helpful!


  1. Charl Asuit avatar Charl Asuit

    Thanks, Steve! This bit saved the site that I’m working on – “Do check for plugin conflicts. I found that activating the WooCommerce ‘Force SSL on checkout’ option created an infinite redirect loop with the above code, even on non-checkout pages.”

  2. Steve Taylor avatar Steve Taylor

    I’ve not used it so I can’t say. I’m sure there’s other good plugins too – maybe ones that have been in the repo longer with a better reputation. Anyway, I often prefer to roll my own code, in order to learn and have a more precise handle on things :-)

Leave a comment

Your email address will not be published.