Cleaning up WordPress plugin script and stylesheet loads over SSL

This post is more than 12 years old.

It’s quite common to use WordPress as the host for an online shop, and that often means having an order page that needs to be encrypted via SSL. You don’t want your customers providing credit card details or other sensitive information over an unencrypted connection! But many WordPress plugins don’t take SSL into account, and merrily load scripts and stylesheets without encryption. Here’s a couple of ways to fix this problem.

Update: now available as a plugin

First of all, you might ask why this is a problem. Well, modern web browsers show some pretty scary warnings to your visitors, telling them about “insecure content” and the perils that may entail. This is a good thing! Loading scripts and other assets without encryption can undermine the secure communications you have established by loading your page over SSL.

The root cause in WordPress plugins is often that the plugin author has used the WP_PLUGIN_URL constant to locate their base folder, rather than use a function call. This constant is set right up front, before other plugins and themes get a chance to tell WordPress to switch to the HTTPS protocol to load pages. What they should be doing instead is calling plugin_dir_url or one of the other plugin URL functions, like this:

$url = plugin_dir_url(__FILE__);

To get around this with scripts and styles that are loaded via WordPress’ register and enqueue functions (which they all should, but some don’t), you can clean up the registration information after the fact but before the scripts are output. It’s a dirty hack, but it works! NB: I’m only bothering to do this on the main website, not the admin pages which I don’t need to worry about. YMMV.

// fix some badly enqueued scripts with no sense of HTTPS
add_action('wp_print_scripts', 'enqueueScriptsFix', 100);
add_action('wp_print_styles', 'enqueueStylesFix', 100);

/**
* force plugins to load scripts with SSL if page is SSL
*/
function enqueueScriptsFix() {
    if (!is_admin()) {
        if (!empty($_SERVER['HTTPS'])) {
            global $wp_scripts;
            foreach ((array) $wp_scripts->registered as $script) {
                if (stripos($script->src, 'http://', 0) !== FALSE)
                    $script->src = str_replace('http://', 'https://', $script->src);
            }
        }
    }
}

/**
* force plugins to load styles with SSL if page is SSL
*/
function enqueueStylesFix() {
    if (!is_admin()) {
        if (!empty($_SERVER['HTTPS'])) {
            global $wp_styles;
            foreach ((array) $wp_styles->registered as $script) {
                if (stripos($script->src, 'http://', 0) !== FALSE)
                    $script->src = str_replace('http://', 'https://', $script->src);
            }
        }
    }
}

Some plugins don’t play nice, and directly load their scripts and stylesheets outside of the standard practice. The Links Shortcode plugin, for example, directly writes a link for its stylesheet using the wp_head action to trigger when to write it:

add_action('wp_head', 'linkssc_css');

function linkssc_css()
{
    echo '<link rel="stylesheet" type="text/css" media="screen" href="'. WP_PLUGIN_URL . '/links-shortcode/links-shortcode.css"/>';
}

But that’s OK, we can handle that too, by replacing it with a properly enqueued script. Just add this into the enqueueStylesFix() function above:

// force links-shortcode to load CSS with SSL if page is SSL
if (function_exists('linkssc_css')) {
    remove_action('wp_head', 'linkssc_css');
    $url = plugins_url('links-shortcode.css', WP_PLUGIN_DIR . '/links-shortcode/');
    wp_enqueue_style('links-shortcode', $url);
}

It might take a little gentle persuasion, but in the end, job is done.