
Getting a certificate installed on a WordPress site is rarely the hard part anymore. In 2026, hosts like SiteGround, Cloudways, Kinsta, WP Engine, and Hostinger provision a free Let's Encrypt or ZeroSSL certificate the moment a domain points at them, and renewal is automatic. The headaches that actually consume your afternoon come after the green padlock should be there: the padlock that won't appear, the login page that loops forever, the front end that loads but throws a console full of warnings. Almost all of these trace back to WordPress storing absolute URLs in its database and to the gap between where the TLS handshake terminates and where PHP thinks it is running.
WordPress hardcodes the full http:// or https:// site address into wp_options (the siteurl and home values) and into every post that contains an image, a link, or an embed. It does not store relative paths. That single design decision is the source of roughly 80% of WordPress SSL complaints. When you flip a site to HTTPS, the certificate changes instantly but the thousands of stored URLs do not. The browser then loads your page securely and immediately requests a logo over plain HTTP, and you get the dreaded "not fully secure" warning.
The second structural cause is TLS termination at a proxy. On most managed hosts and behind Cloudflare, HTTPS is decrypted at a load balancer or CDN edge, and the request reaches your PHP over plain HTTP internally. WordPress reads $_SERVER['HTTPS'], sees it empty, concludes the request is insecure, and rewrites links back to http://. That mismatch is what produces redirect loops.
Mixed content means the page itself arrived over HTTPS but pulled in a sub-resource over HTTP. Open DevTools, look at the Console and the Network tab, and identify whether the offending URLs are your own domain or a third party.
For your own domain, the correct fix is a one-time database rewrite, not a plugin that rewrites on every page load. Plugins like Really Simple SSL are excellent for getting unblocked in five minutes, but their content-rewriting filter adds a small amount of work to every request. The permanent fix is WP-CLI:
wp search-replace 'http://example.com' 'https://example.com' --all-tables --dry-run
Run it with --dry-run first to see the count of replacements, then run it for real. The --all-tables flag matters because page builders such as Elementor, Divi, and Beaver Builder store data in serialized arrays and sometimes in custom tables; WP-CLI's search-replace correctly walks serialized PHP so it won't corrupt that data the way a raw SQL UPDATE would. If you can't use the command line, the Better Search Replace plugin does the same serialization-safe job through the dashboard.
Two stubborn sources survive a database rewrite. First, URLs hardcoded into theme files. A well-built theme uses get_template_directory_uri() or wp_enqueue_script(), both of which inherit the site protocol; older or hand-edited themes sometimes contain literal http:// asset tags that must be edited in the template. Second, you can ask the browser to upgrade the rest automatically by sending an upgrade-insecure-requests Content-Security-Policy header, which silently rewrites HTTP sub-resource requests on your own domain to HTTPS. It's a clean safety net, not a substitute for fixing the database.
"Too many redirects" or ERR_TOO_MANY_REDIRECTS almost always means two layers are each trying to force HTTPS and disagreeing about the current state. The classic case is Cloudflare set to Flexible SSL: Cloudflare talks HTTPS to the visitor but HTTP to your origin, WordPress sees an insecure request and redirects to HTTPS, Cloudflare sends that back over HTTP, and the cycle never ends. The fix is to set Cloudflare's SSL mode to Full (strict) so the connection is encrypted end to end. Flexible mode should be considered broken for any real site.
When TLS terminates at a proxy, tell WordPress to trust the forwarded header by adding this near the top of wp-config.php, above the "stop editing" line:
if ( isset( $_SERVER['HTTP_X_FORWARDED_PROTO'] )
&& $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https' ) {
$_SERVER['HTTPS'] = 'on';
}
This makes is_ssl() return true and stops WordPress generating HTTP links behind the proxy. Most managed hosts already inject this, which is why the loop appears mainly on self-managed VPS setups and DIY Cloudflare configurations.
Before you touch redirect rules, confirm Settings → General shows both the WordPress Address and Site Address as https:// with the exact www-or-not form your certificate covers. Then make sure you have one canonical redirect, not three. If your host already forces HTTPS, an extra rule in .htaccess or in a plugin is redundant and a frequent loop cause. After any change, purge every cache layer in order: page-cache plugin, host object cache, then the CDN, because a cached HTTP response will keep redirecting long after the config is correct.
HTTP Strict Transport Security sends a header telling browsers to refuse plain HTTP for your domain for a set duration. It closes the brief window where a visitor typing your bare domain could be hijacked before the redirect. The danger is the max-age. If you ship max-age=31536000 (one year) and your certificate later breaks, every browser that saw the header will hard-refuse to load the site, and there is no server-side undo, you wait for each visitor's cache to expire.
Roll it out in stages. Start with Strict-Transport-Security: max-age=300 (five minutes), confirm nothing breaks for a day, then raise it to one year. Only add the preload directive and submit to the browser preload list once you are certain you will never serve this domain or its subdomains over HTTP again, because removal from the preload list takes weeks.
A padlock-with-a-warning usually means a name mismatch: the certificate is issued for example.com but the visitor reached www.example.com, or vice versa. Let's Encrypt certificates routinely cover both via Subject Alternative Names, but only if both were requested. Multisite installs and sites that serve from a subdomain need a wildcard certificate (*.example.com), which Let's Encrypt issues only through DNS-based validation, something not every host automates. If you run a subdomain network, check that wildcard coverage exists before debugging anything else.
Sometimes your own site is spotless and the warning comes from an embedded YouTube, Vimeo, or Google Maps frame, or an ad or analytics script, requesting HTTP. Modern WordPress oEmbed handling outputs HTTPS embed URLs automatically, so the offenders are usually old embeds pasted years ago or a script you added by hand. Re-paste the embed, or swap the script's URL to its https:// equivalent. For the rare service with no HTTPS option, proxy it through your domain or drop it, there is no safe way to mix it in.
Once the changes are in, verify rather than assume:
FORCE_SSL_ADMIN constant left in wp-config.php; on a fully-HTTPS site you simply set the Site Address to HTTPS and remove that constant entirely.www form, and an old HTTP link all land on the single canonical HTTPS URL with one redirect hop.SSL on WordPress is less about cryptography and more about keeping three things in agreement: the URLs stored in your database, the protocol your PHP believes it is serving, and the single canonical address every layer redirects to. Get those aligned and the padlock takes care of itself.
Site
Tools
We do not sell your email. We do not spam.
© 2026 RevealTheme. All rights reserved.