You’ve done the hard work. You purchased an SSL certificate (or generated a free Let's Encrypt one via your ServerSpan dashboard), you installed it on your server, and you updated your WordPress URL settings to start with https://. You navigate to your homepage, expecting to see that reassuring, secure green padlock next to your URL. Instead, you are greeted by a glaring "Not Secure" warning, or worse—a broken layout where styles are missing and images refuse to load.
This is the "Mixed Content" trap, and it is the single most common hurdle webmasters face immediately after migrating to HTTPS. In our experience managing thousands of virtual private servers (VPS) and WordPress environments, we estimate that nearly 60% of manual SSL migrations result in mixed content warnings if the database content isn't properly handled.
It does not mean your SSL certificate is broken. It means your website is suffering from an identity crisis: while the main page is being delivered securely over HTTPS, it is still asking the visitor's browser to fetch insecure resources (images, scripts, fonts) over the old HTTP protocol. The browser, detecting a potential security breach, blocks or flags these resources.
In this extensive guide, we will move beyond basic advice. We will provide a deep-dive tutorial on diagnosing these issues using developer tools, understanding the browser security model, and fixing mixed content permanently at the source—without relying on performance-draining plugins.
Understanding the Security Model: Why Browsers Panic
To fix the problem, you must first understand why modern browsers like Chrome, Firefox, and Safari react so aggressively to mixed content. It comes down to the integrity of the connection.
When a user connects to your site via HTTPS, the connection is encrypted. This guarantees three things:
- Authentication: The user is talking to the real server, not an imposter.
- Data Integrity: The data hasn't been modified in transit.
- Encryption: No third party can read the data.
Mixed content breaks this guarantee. If a secure page loads a JavaScript file over insecure HTTP, a hacker on the same Wi-Fi network could perform a Man-in-the-Middle (MitM) attack, modify that script, and steal the user's secure session cookies or login credentials. Because one insecure asset can compromise the entire secure page, browsers treat mixed content as a severe vulnerability.
The Two Types of Mixed Content
Browsers distinguish between two types of mixed content, handling each differently. Knowing the difference helps you prioritize your fixes.
1. Passive Mixed Content (Display Content)
This category includes content that cannot interact with the rest of the page's code, primarily images, video, and audio files.
Browser Behavior: Most browsers typically allow this content to load but will penalize the site's security indicator. In Google Chrome, for example, the padlock disappears or is replaced with a "Not Secure" warning. While the page functions, user trust is eroded immediately.
2. Active Mixed Content (Scripting Content)
This is the dangerous category. It includes scripts (JavaScript), stylesheets (CSS), iframes, and fonts (WOFF/TTF). Since these assets can alter the Document Object Model (DOM) of the page, they have full access to secure data.
Browser Behavior: Modern browsers block active mixed content by default. They simply refuse to load the file. This is why your website might look like an unstyled HTML skeleton or why dropdown menus and checkout forms stop working after an SSL migration. The assets aren't missing; the browser is protecting the user from them.
Phase 1: Diagnosing the Problem
Before running any bulk fixes, you need to identify exactly what is breaking. While online scanners exist, they often miss dynamic content loaded by JavaScript. The most reliable tool is already installed on your computer: the Web Browser Developer Tools.
Step-by-Step Diagnosis via Chrome DevTools
This method reveals exactly which files are triggering the warnings.
- Open Developer Tools: Right-click anywhere on your website and select Inspect, or press
Ctrl+Shift+I(Windows) /Cmd+Opt+I(Mac). - Navigate to the Console Tab: Look for the tab labeled "Console" at the top of the developer panel.
- Identify the Errors: Mixed content errors are distinctive. They will usually be highlighted in red (for blocked active content) or yellow (for passive content warnings).
A typical error message looks like this:
Mixed Content: The page at 'https://example.com/' was loaded over HTTPS, but requested an insecure image 'http://example.com/wp-content/uploads/2024/01/hero-bg.jpg'. This content should also be served over HTTPS.
Analysis: In this example, the page is secure, but the background image is hardcoded with http://. The browser might display it but will show a warning.
Checking the Network Tab for "Blocked" Requests
If your layout is broken, check the Network tab in DevTools.
- Click the Network tab.
- Reload the page (F5 or Cmd+R).
- Look at the "Status" column. If you see status (blocked:mixed-content) in red text, that asset was prevented from loading entirely.
This is common with external scripts (like old jQuery libraries) or fonts loaded from third-party non-SSL servers.
Phase 2: The Database Fix (The Correct Way)
In 90% of WordPress cases, mixed content arises because the database still contains absolute URLs pointing to http://. When you upload an image in WordPress, it saves the full path (e.g., http://domain.com/image.jpg) in the wp_posts table. Changing the Site URL in settings does not update these thousands of existing references.
Why You Should NOT Use a Plugin for This
Many beginners install plugins like "Really Simple SSL" or "SSL Insecure Content Fixer." While these plugins work, they often function by using PHP Output Buffering. They intercept the HTML page before it is sent to the user, scan it for http:// links, and replace them with https:// on the fly.
The Problem: This adds processing time to every single page load. It increases Time to First Byte (TTFB) and masks the problem rather than solving it. At ServerSpan, we advocate for clean, performant solutions: fixing the data permanently.
Understanding Serialized Data
Crucial Warning: You might be tempted to run a simple SQL query like UPDATE wp_posts SET post_content = REPLACE(...). Do not do this.
WordPress stores theme settings and widget data in "serialized arrays." This is a format where the data length is stored alongside the data (e.g., s:4:"http"). If you change http to https (4 characters to 5 characters) without updating the serialization count, the data becomes corrupt, and your site settings will disappear.
Method A: The Professional Fix via WP-CLI (Recommended)
If you are hosting on a ServerSpan VPS, you have root access and can use WP-CLI (WordPress Command Line Interface). This is the gold standard for updating URLs because it handles serialization automatically and takes seconds to execute.
- Connect to your server via SSH.
- Navigate to your site root:
cd /var/www/yourdomain.com/public_html - Back up the database first:
wp db export pre-ssl-fix.sql - Run a dry run: This shows you how many replacements would be made without actually changing anything.
wp search-replace 'http://yourdomain.com' 'https://yourdomain.com' --dry-run - Execute the replacement:
wp search-replace 'http://yourdomain.com' 'https://yourdomain.com' - Clear the cache:
wp cache flush
Your database is now permanently updated. No plugins required.
Method B: The "Better Search Replace" Plugin (No Code)
If you aren't comfortable with the command line, the Better Search Replace plugin is the best GUI alternative. Unlike "fixer" plugins, this one runs once, updates the database correctly (handling serialization), and then can be uninstalled.
- Install and activate Better Search Replace.
- Go to Tools > Better Search Replace.
- In the "Search for" field, enter:
http://yourdomain.com - In the "Replace with" field, enter:
https://yourdomain.com - Select all tables.
- Check "Run as dry run" first to verify.
- Uncheck "dry run" and click "Run Search/Replace".
- Delete the plugin after you are done.
Phase 3: Fixing Stubborn Assets (Theme & Builders)
Sometimes, the database fix isn't enough. Theme files or page builders might have their own way of storing links.
Scenario 1: Elementor Stylesheets
Elementor saves CSS files in a specific upload folder. Even after updating the database, Elementor may still serve the old CSS files containing HTTP links.
The Fix:
- Go to your WordPress Dashboard.
- Navigate to Elementor > Tools.
- Click on the Regenerate CSS & Data tab.
- Click the Regenerate Files button.
This forces Elementor to rebuild its external stylesheets using the new HTTPS URLs found in the database.
Scenario 2: Hardcoded Theme Files
If a developer customized your theme, they might have hardcoded a link directly into a PHP or CSS file (e.g., background-image: url('http://...') in style.css). The database search won't find these.
How to find them using GREP (Linux):
From your terminal, run a recursive search inside your theme folder:
grep -r "http://" /var/www/yourdomain.com/public_html/wp-content/themes/
This will list every file containing "http://". Open these files and manually update the links to https://.
Pro Tip: Instead of hardcoding https://yourdomain.com/image.png, use WordPress dynamic functions like get_stylesheet_directory_uri() in PHP. This ensures the link always matches the current site protocol.
Phase 4: The "Nuclear Option" (Content Security Policy)
There are rare cases where you cannot find the source of the insecure content. Perhaps it's coming from a third-party ad script that dynamically generates HTTP frames, or it's buried in a legacy plugin you can't edit.
In these cases, you can use a specific HTTP Response Header called Content Security Policy (CSP) to force the browser to fix the issue for you.
Upgrade-Insecure-Requests
By adding the upgrade-insecure-requests directive to your server's header, you are telling the browser: "Even if the code asks for HTTP, treat it as HTTPS automatically."
Implementation on Nginx (ServerSpan Default)
Add this line to your Nginx server block configuration:
add_header Content-Security-Policy "upgrade-insecure-requests";
Implementation on Apache/OpenLiteSpeed (.htaccess)
Add this to the top of your .htaccess file:
<IfModule mod_headers.c>
Header always set Content-Security-Policy "upgrade-insecure-requests"
</IfModule>
Note: This directive essentially "patches" the issue client-side. It effectively removes mixed content warnings, but it assumes the resource is actually available over HTTPS. If you link to an external image on a server that has no SSL certificate, the browser will attempt to load it securely, fail, and the image will break. However, your green padlock will remain.
Special Case: Cloudflare and the "Flexible SSL" Loop
We often see users who enable Cloudflare encounter massive mixed content issues or "Too Many Redirects" errors. This is usually due to the Flexible SSL setting.
The Scenario:
- Visitor to Cloudflare: Connects via HTTPS.
- Cloudflare to Your Origin Server: Connects via HTTP (Flexible mode).
Because your origin server receives a request over port 80 (HTTP), WordPress thinks it is being accessed insecurely. It generates all its internal links (menus, images, headers) using http:// URLs. The visitor receives a secure page filled with insecure links.
The Fix:
- Install a valid SSL certificate on your origin VPS (ServerSpan provides free AutoSSL/Let's Encrypt).
- Go to your Cloudflare Dashboard > SSL/TLS.
- Switch the mode from Flexible to Full (Strict).
This forces the connection between Cloudflare and your server to be secure, allowing WordPress to correctly detect the HTTPS protocol and generate links accordingly.
Conclusion
Mixed content errors can be frustrating, but they are a solvable logic puzzle. By methodical diagnosis using browser tools and applying permanent fixes to your database and code—rather than relying on temporary plugins—you ensure your site remains fast, professional, and secure.
Fixing mixed content is a critical step in server administration, but it's just one part of maintaining a healthy infrastructure. If manual database serialization and Nginx header configuration sound like distractions from your core business, consider exploring ServerSpan's Managed VPS solutions.
Our team handles the heavy lifting of security hardening, SSL implementation, and performance tuning, so your green padlock is just the standard, not a struggle.
Source & Attribution
This article is based on original data belonging to serverspan.com blog. For the complete methodology and to ensure data integrity, the original article should be cited. The canonical source is available at: Mixed Content After Enabling SSL: Finding and Fixing Insecure Assets.