The simple way to add a “force SSL” option in WordPress

There are plugins for just about everything in WordPress. But cluttering up your site with plugins isn’t always such a great idea. They add bloat that can slow down your site, and if poorly written can cause potential conflicts.

Plus, a lot of them are simply over-engineered. I hate that.

That said, I love good plugins, especially Advanced Custom Fields by Elliot Condon. I consider it essential to every WordPress site I build… which is a lot these days.

A site I’m currently working on has some pages that require SSL encryption. And I want the client to be able to turn SSL on or off on a per-page basis. But I didn’t want to use a plugin (besides ACF) to do it. [Disclaimer: you don’t actually need to use ACF for this; the standard Custom Fields capability will do.]

Before getting started, make sure your site actually has an SSL certificate installed and properly configured. And for this to work as shown, the cert needs to use the same domain name as the site itself. If it’s different, your redirect URLs will be a bit more complicated and will require some customization of this code, but it’ll still work.

First, set up your custom field. I’m using force_https as the field name, but it can be whatever. Make it a True/False field. (If you’re not using ACF, just remember you’ll be entering 0 or 1 as the value.)

Next, in your functions.php file, add the following:

add_action('template_redirect', 'my_force_https');
function my_force_https() {
  if (is_ssl()) { return null; }
  global $post;
  if (!empty($post->ID)) {
    if (!empty(get_field('force_https',$post->ID))) {
      $ssl_url = str_replace('http://','https://',get_the_permalink($post->ID));
      wp_redirect($ssl_url); exit;
    }
  }
  return false;
}

Picking this apart: We’re using the template_redirect hook. By this point the post has been loaded. We have all of the data we need, and it’s kind of our “last chance” to get WordPress to do a redirect before it starts rendering the page.

First we run the built-in WordPress function is_ssl(), because if we’re already on an SSL connection, there’s nothing to do. (And, if we didn’t do this check, we’d create a redirect loop.)

Next, if we have a post ID, we use the ACF function get_field() to check whether the force_https custom field is checked for this page. If it is, then we modify the page’s permalink to start with https:// and trigger the redirect. That’s it! [Note: If you’re not using ACF, you’ll need to use the built-in WordPress function get_post_meta() instead of get_field().]

Of course, that’s not quite it. You may notice after you have this working that your page loads with an https:// URL, but you’re still not getting the reassuring lock icon in your browser’s address bar. What gives?

Well, that’s because you probably have assets in the page that are loading over a non-SSL connection. In my experience, this is almost always because of images in your content that have a full, non-SSL URL. Browsers won’t give you the lock icon unless every asset on the page was loaded over an SSL connection.

So I’ve added this second function that strips the protocol from any instance of src="http://... in a text string. If you’re not familiar with “protocol-less” URLs, modern browsers allow you to omit the protocol — http:// or https:// — from URLs in your HTML, using just // instead, and the browser will automatically handle those with the same protocol used to load the page.

Using the filter the_content, this will automatically get applied to most page content and you’ll probably be good.

add_filter('the_content', 'my_strip_protocol');
function my_strip_protocol($content) {
  if (is_ssl()) {
    $content = str_replace('src="http://','src="//',$content);
  }
  return $content;
}

If you add this and you’re still not getting the lock, it means you probably have <img> tags within your theme that include full non-SSL URLs, or possibly some CSS or JavaScript assets that are being loaded over non-SSL connections. You’ll have to troubleshoot that yourself, but with the developer tools built into modern web browsers, that shouldn’t be too difficult. Remember, now that you have it, you can always use this my_strip_protocol() function directly in your theme files as well.

Just a side note about one of my idiosyncratic coding conventions: I always use !empty() when checking for a value that evaluates to true, but you don’t have to. It comes from my prior experience working with CakePHP. The benefit is that you won’t trigger any PHP warnings if the variable you’re evaluating hasn’t been declared.

Mac does Windows…

It’s old news that Apple‘s new computers all run the Intel Core Duo processor (or the unimaginatively — yet redundantly — named Core 2 Duo), and that thanks to Boot Camp, or a third-party app called Parallels (which I didn’t bother to buy, so I’m also not going to bother to track down the link), Apple’s computers can now run Windows natively.

Ultimately for no other reason than that it can be done, I naturally had to install Windows on my new MacBook. Tonight the “dream” (and I use that term without implying any positive connotations) became reality.

Sure, it’s great to have Windows, I guess. It benefits me mainly in that I can test my work in that most unpredictable of environments, Internet Explorer. I suppose it would also be handy for running Windows-only software, if there were any Windows-only software I actually wanted or needed to run.

The most striking characteristic I’ve noted so far is how obnoxious Windows software installers are. Installing a new application on Windows feels a bit like forcing your way through a crowded flea market, with aggressive hawkers pushing their wares on you. (In fact, come to think of it, that’s basically what it is.)

So far I’ve only installed 3 programs, aside from the OS itself (a harrowing experience in its own right), those being Adobe Reader, Firefox, and AOL Instant Messenger. I tried to install the latest version of Flash Player as well, but for some reason the installer just starts and then vanishes mysteriously. Ah, Windows.

Among those 3 installed programs, only Firefox did not accost me with multiple offers to install other, unwanted programs… or that perennial favorite, the browser toolbar. No thanks! I’m just coming for Adobe Reader. I really don’t care to also litter my hard drive (and desktop… and Start menu… and taskbar) with the likes of a 30-day trial of a watered-down version of Photoshop. And I definitely am not interested in the Adobe Yahoo! toolbar, nor can I even imagine what purpose it could possibly serve, other than to surreptitiously alert Adobe to the fact that I’ve surfed on over to my own website, wherein I’ve then proceeded to write and post a rant on the topic of invasive spyware.

It doesn’t have to be like this, people! (In fact, I am writing this once again having returned to the comfort of an operating system that just gets the hell out of the way and lets me do what I want to do thank you very much!)

Smile

Yes, it’s really here. It’s very existence is almost beyond comprehension… the fact that it is so brilliant, and was actually produced this year pushes it over the edge.

Brian Wilson has completed, and completely re-recorded, the legendary, long-lost SMiLE and it’s a masterpiece.