HTTPS is a baseline requirement for every website, it encrypts data in transit, enables modern browser features that require secure contexts, and is a minor but confirmed Google ranking factor. The correct place to enforce HTTPS is at the server level through an .htaccess rewrite rule or Nginx configuration, because that handles the redirect before PHP loads. However, on some hosting environments, certain shared hosts, managed WordPress hosts with restricted server access, or setups behind a reverse proxy, server-level redirect configuration isn’t directly accessible. This snippet handles HTTPS enforcement from within WordPress itself as a reliable alternative.
The Code
Add this to your functions.php or a site-specific plugin. Only add it if your site already has a valid SSL certificate installed, the redirect will cause an SSL error for users if the certificate isn’t properly configured.
The HTTPS Check
The snippet checks two server variables to determine whether the current request is over HTTPS. $_SERVER['HTTPS'] is set to 'on' on most direct HTTPS connections. $_SERVER['HTTP_X_FORWARDED_PROTO'] is the header set by reverse proxies, load balancers, and CDNs like Cloudflare and Bunny.net, behind a proxy the connection between the proxy and your server may be HTTP even when the visitor’s browser used HTTPS. Checking both ensures the redirect works correctly in both direct and proxied environments.
The 301 Redirect
A 301 Permanent Redirect is the correct status code for HTTPS enforcement, it signals to browsers and search engines that HTTP is never the right URL for your site and that all link equity and ranking signals should be attributed to the HTTPS version. After Google processes the 301s, it will update its index to reflect HTTPS URLs and the redirect overhead for returning visitors diminishes as browsers cache the 301.
HTTP Strict Transport Security
The HSTS header tells browsers to automatically use HTTPS for all future requests to your domain, without needing to make the initial HTTP request and follow the redirect. Once a browser has seen the HSTS header, it will refuse HTTP connections to your domain entirely for the duration specified by max-age (one year in seconds here). includeSubDomains extends this protection to all subdomains.
Be cautious with HSTS on sites that have subdomains not yet on HTTPS, includeSubDomains will break those subdomains for users who’ve visited the main domain. Test thoroughly before enabling it.
wp-config.php Constants
If WordPress itself is generating mixed content warnings, loading admin assets over HTTP, set define( 'FORCE_SSL_ADMIN', true ); in wp-config.php. This ensures the admin area always uses HTTPS regardless of server configuration. Pair it with define( 'WP_HOME', 'https://yourdomain.com' ); and define( 'WP_SITEURL', 'https://yourdomain.com' ); to lock WordPress’s URL settings to HTTPS at the configuration level.
add_action( 'init', function() {
// Only redirect on the frontend, not in CLI or admin contexts
if ( is_admin() || ( defined( 'WP_CLI' ) && WP_CLI ) ) return;
if (
( ! isset( $_SERVER['HTTPS'] ) || $_SERVER['HTTPS'] !== 'on' ) &&
( ! isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) || $_SERVER['HTTP_X_FORWARDED_PROTO'] !== 'https' )
) {
wp_redirect( 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], 301 );
exit;
}
} );
// Add HTTP Strict Transport Security header
add_filter( 'wp_headers', function( $headers ) {
if (
( isset( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] === 'on' ) ||
( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] ) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' )
) {
$headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains';
}
return $headers;
} );
