Mixed content is what happens when a page delivered over HTTPS pulls in a resource, such as an image, a script or a stylesheet, over plain HTTP. If you finished your HTTPS migration, installed a valid certificate and still see a broken padlock, a console full of warnings or a page section that quietly stopped working, mixed content is the first suspect. Fixing it is rarely glamorous. The real work is finding every leftover insecure address, and then deciding when it is safe to tell browsers, with HSTS, that your site will never go back.
This guide is written for site owners, developers and technical SEOs who have just moved to HTTPS or are about to. It starts with how browsers decide what to block and what to upgrade, then walks through the practical difference between active and passive resources. After that it covers the Strict-Transport-Security header, including the staged rollout that the preload service itself recommends and the reasons preload is a heavier commitment than it looks. The last two sections cover a post-migration crawl routine and a verification and rollback plan. No product screens are described; the principles apply to any CMS, host or CDN.
What Mixed Content Is and How Browsers Treat It
MDN defines mixed content as a securely loaded page that uses resources fetched over HTTP or another insecure protocol. It also describes mixed downloads: a file download that starts from a secure page but travels over an insecure connection. A link such as an HTTP file on an HTTPS page counts, and browsers are expected to block it. In practice they commonly warn the visitor and let them keep or discard the file.
The reason this matters is simple. An HTTPS page promises that what the visitor sees was not read or altered on the way. One insecure request breaks that promise for the part of the page it feeds. If that part is a photo, the damage is limited. If it is a script, whoever can tamper with the connection can rewrite the page. Browsers therefore treat the two cases very differently, and your cleanup priorities should follow the same logic.
From active and passive to upgradable and blockable
MDN’s mixed content reference (Opens in a new tab) explains that older specifications used two labels. Active (blockable) content could change other parts of the page, like scripts and stylesheets, and browsers had to block it. Passive (optionally blockable) content, such as images, video and audio, could not change anything else, so browsers could display it, block it or ask the user. Many audit tools still print these two labels.
The current model sorts requests into upgradable and blockable instead. Browsers should automatically upgrade upgradable requests from HTTP to HTTPS, a set that was seeded from the old optionally blockable group. Everything that is not upgradable is blockable and gets blocked. The practical meaning is that an old inline image usually keeps working because the browser quietly rewrites its address, while a script on HTTP simply does not run. Blocked resources announce themselves through broken pages. Upgraded ones hide, because they work.
Hiding has a cost. An upgrade only succeeds if the remote server actually serves the same file over HTTPS. That consequence is an inference from how upgrading works rather than a sentence from MDN, but it explains why some old third-party images turn into broken icons the day a browser starts upgrading them.
What the console and search engines see
MDN notes that the developer console prints warnings when mixed content is upgraded or blocked, so your own browser is the first diagnostic tool. Search engines are a separate audience. Google’s guidance on duplicate URLs (Opens in a new tab) says Google prefers HTTPS pages over equivalent HTTP pages as canonical, except when there are issues or conflicting signals. The examples it lists are an invalid SSL certificate, insecure non-image dependencies and redirects from HTTPS to HTTP. So a leftover insecure script is not only a user-experience bug. It can be one of the conditions under which Google weighs the HTTP address more heavily. The documentation does not quantify the effect on rankings, so treat it as hygiene, not as a lever.
Active vs Passive Mixed Content: Images, Scripts, Iframes
The table below condenses MDN’s classification into the elements you will actually meet in a template. Browser behavior evolves, so confirm the result in the browsers your audience uses before you decide that something is safe to leave.
| Resource | Element or API | Category | Typical result |
|---|---|---|---|
| Image | img src | Upgradable | Rewritten to HTTPS |
| Image set | img srcset, picture | Blockable | Blocked |
| Audio and video | audio, video, source | Upgradable | Rewritten to HTTPS |
| Script | script src | Blockable | Blocked |
| Stylesheet | link href | Blockable | Blocked |
| Frame | iframe src | Blockable | Blocked |
| Data request | fetch, XMLHttpRequest | Blockable | Blocked |
| Web font | @font-face | Blockable | Blocked |
Two details in that table deserve attention. First, the same photo can behave differently depending on the tag that requests it: img src is upgraded, while srcset and picture sources are listed as blockable. A product page can show its desktop image and lose its mobile one for exactly this reason. Second, MDN contradicts itself on CSS images. One section lists background-image and similar properties as upgradable, another says every url() value in CSS is blockable. The page does not resolve the conflict, so the safe habit is to correct every http:// address inside stylesheets instead of relying on an upgrade.
Images, audio and video
These are the upgradable group, and they make up most of the clutter on an older site. Think of product photos that were embedded in descriptions years ago, newsletter archives that point at a former image host, or galleries that a previous theme hard-coded. MDN lists one important exception: upgrading is skipped when the URL’s host is an IP address instead of a domain name. An image requested from http://example.com/photo.png will be upgraded, but the same file requested by numeric IP is blocked.
Fictional example: a regional online shop keeps a back catalog of seasonal landing pages. The current catalog looks fine after the move because its images live on the shop’s own domain. The seasonal pages, however, load banners from a former print supplier’s server that never got a certificate. Visitors see empty rectangles, and nobody notices for weeks because those pages sit deep in the navigation. The example is illustrative and contains no numbers or real site results; it shows that the unglamorous long tail is where mixed content tends to survive.
Scripts, stylesheets, frames and data requests
The blockable group breaks things visibly, and sometimes invisibly. An HTTP script is not executed, so a menu, a cookie notice, a checkout widget or a measurement tag can silently stop working. An HTTP stylesheet is not applied, which leaves a page unstyled. An embedded form, map or video player in an iframe turns into a blank box. A component that calls an HTTP API with fetch or XMLHttpRequest gets nothing back and renders empty. The most expensive failures are the ones nobody sees directly, such as analytics or consent scripts that stop loading while every page still looks perfect.
Web fonts belong here too. A font file referenced through an old @font-face rule on HTTP is blocked, and the page falls back to a system typeface. Headings change width, layout shifts, and icon fonts turn into empty squares. That is not an SEO problem on its own, but it is the kind of regression that makes a migration look unfinished.
Links and downloads
An ordinary link is not mixed content. MDN explicitly says that a navigation from a secure context to an insecure top-level page does not count. Internal links that still point at HTTP are nevertheless worth fixing, because such links generally add a redirect hop and can waste crawl effort. Downloads need separate attention: a link with the download attribute that points to an HTTP file on an HTTPS page is a mixed download. Check PDFs, price lists, brochures and spreadsheets on their own.
Choosing the fix
When the resource is yours, the repair is straightforward: change the address to HTTPS or remove the hostname and use a relative path. MDN’s recommended order is to serve everything over HTTPS, use relative or HTTPS links for resources on your own domain, and prefer the HTTPS version of third-party resources. When a third party offers no HTTPS endpoint, the options narrow to switching provider, hosting the file yourself if the license allows it, or dropping the component.
There is also a header shortcut. The MDN page mentions, in its related links, that the Content-Security-Policy upgrade-insecure-requests directive upgrades all requests to HTTPS, including blockable mixed content. That is a useful safety net during cleanup. It is not a repair, because a target server that does not speak HTTPS still fails, and the wrong address remains in your source code for the next developer to find.
HSTS: When to Enable It and Preload Risks
HSTS stands for HTTP Strict Transport Security. Through the Strict-Transport-Security response header, a site tells browsers that the host should only be reached over HTTPS and that future HTTP attempts should be upgraded automatically. A redirect asks the browser to go to HTTPS this time. HSTS asks it to remember to do so on its own, for a period you choose. That memory is the whole point and also the whole risk, so the order of work matters: clean mixed content first, enable HSTS second.
Syntax in plain terms
The header starts with max-age, the number of seconds the browser should remember the rule. Adding includeSubDomains extends the policy to every subdomain of the host’s domain. The preload token marks an intent to join the preload list, and MDN’s HSTS reference (Opens in a new tab) says that when you use it, max-age must be at least 31536000 seconds (one year) and includeSubDomains must be present.
| Part | Effect | What can go wrong |
|---|---|---|
| max-age | How long browsers remember the rule | Every response pushes the expiry further, so a fixed value never runs out |
| includeSubDomains | Applies the rule to all subdomains | An HTTP-only subdomain becomes unreachable |
| preload | Signals intent to join the browser-shipped list | Removal is slow and depends on browser updates |
Two behaviors from MDN shape how you deploy it. The header is honored only when it arrives over HTTPS. Browsers ignore it on an HTTP response, because an attacker in the middle could otherwise add it or make it expire early. The redirect that sends HTTP visitors to HTTPS should therefore not carry the header. And HSTS does nothing on the very first visit: the browser must complete one secure connection and read the header before the policy applies. Preload exists to close that first-visit gap, which brings us to its risks.
When to switch it on
Three conditions should be true. The certificate is valid and renews automatically, since MDN states that when an HSTS host presents a TLS error such as an invalid certificate, the browser offers no way to click through. An expired certificate then means total loss of access, not a dismissible warning. Second, every important page builds without insecure resources, because HSTS removes the option of quietly falling back to HTTP. Third, HTTP-to-HTTPS redirects work for every path and have been tested. Google’s site move documentation (Opens in a new tab) recommends server-side permanent redirects where possible, with codes like 301 and 308, and keeping them in place for as long as possible, generally at least one year.
Google’s duplicate-URL page lists HSTS next to redirecting HTTP to HTTPS and adding a canonical link from the HTTP page as ways to reinforce the HTTPS version. It also warns that bad certificates and HTTPS-to-HTTP redirects make Google prefer HTTP very strongly, and that HSTS cannot override that preference. Read that as a sequencing rule: HSTS is a layer added on top of working redirects and canonicals, not a replacement for them.
A staged rollout
MDN gives reference values, one year as the minimum for preload and two years in its example, but it does not describe a gradual plan. The preload service does. hstspreload.org (Opens in a new tab) advises examining all subdomains, including nested ones, to be sure they work over HTTPS, and then raising max-age in stages with includeSubDomains each time. Its example stages are five minutes (max-age=300), one week (max-age=604800) and one month (max-age=2592000). Between stages you watch for broken pages and for changes in traffic and revenue, and you wait the full max-age of a stage before moving on.
- Inventory every hostname that sits under the domain, including old campaign and staging names.
- Start with a very short max-age and watch errors, crawl statistics and server logs.
- Wait out each stage completely before lengthening it.
- Add includeSubDomains only when the inventory shows that every subdomain serves HTTPS.
- Write the rollback steps before the first header goes live.
Treat this list as one reading of the preload service’s approach. Your own risk tolerance may justify slower or faster steps. What matters is not starting with a year-long value, because a mistake found later cannot be undone faster than the stored policy expires.
Preload: a different class of decision
The preload service lists its requirements: a valid certificate, a redirect from HTTP to HTTPS on the same host if you listen on port 80, HTTPS on all subdomains including www when its DNS record exists, and an HSTS header on the base domain with max-age of at least 31536000, includeSubDomains and preload. Three warnings from the same page change how casually you should apply.
First, inclusion in the preload list cannot easily be undone. Removal is slow, Chrome users only receive it through a browser update, and other browsers are not guaranteed to follow. Second, preloading covers all subdomains, including internal ones that are not publicly reachable, so a subdomain that cannot serve HTTPS may break and the page calls this a common reason site operators later ask for removal. Third, the site itself says HSTS is recommended but preloading is not, since browsers already upgrade HTTP navigations to HTTPS and preload mainly helps against an active attacker.
A fair decision test is to ask who owns every hostname under the domain, whether each one will serve HTTPS for years, and what happens if the domain moves to another team. If any answer is uncertain, a one-year HSTS header without preload and possibly without includeSubDomains already delivers most of the practical benefit, with a rollback you control. If all answers are firm, preload becomes a deliberate extra step rather than a default.
Turning HSTS off
To disable HSTS, send max-age=0 over HTTPS. MDN explains that this only takes effect once the browser makes a secure request and receives that response, and that by design you cannot disable HSTS over insecure HTTP. Removing the header from responses does not clear the policy; the previous one stays until its expiry. When the domain that set includeSubDomains is deleted with max-age=0, separate policies that subdomains sent for themselves are not removed. In short, HSTS exits are slow, which is why the rollback plan has to exist before the header does.
Crawling After Migration to Find Leftover Insecure Resources
Insecure addresses hide in three places: templates, stored content and third-party components. No single method sees all three, so the routine below layers several methods and keeps evidence from each.
Step 1: sample pages in a browser
Open one page per template type: home, category or listing, detail page, search results, cart or contact form. Read the console for mixed content messages. MDN also suggests testing with all mixed content blocked, which is already the default in Safari and available in most other browsers through some setting. With that mode on, you see exactly what disappears and therefore which resources were being upgraded quietly. Save the console output for each template, because findings repeat per template.
Step 2: crawl the whole site
A console covers one page at a time. For thousands of URLs you need a crawler. MDN lists HTTPSChecker, a desktop crawler, mcdetect, a command-line tool, and an online Mixed Content Checker. Whichever tool you choose, read its documentation for scope: some inspect only HTML attributes, while the failures you care about may sit inside CSS url() values, script strings or inline JSON. Check manually where the tool cannot look.
Step 3: search the stored content
Old content is where absolute addresses accumulate. Search the database or content store for your own domain and former domains written with http://, in article bodies, product descriptions, widget text, menu entries and custom fields. Before any bulk replacement, take a backup, rehearse on a copy and use a method that respects serialized values. If the system stores revisions, saving the change as a revision makes rollback easier.
Step 4: templates, themes and plugins
Hard-coded addresses in theme files, loaders inside plugins and third-party script tags need their own search. Open each external component one by one, such as fonts, analytics, chat, maps, embedded forms and video players, and confirm that the HTTPS version actually responds. If an old component has no HTTPS endpoint, this is the moment to replace or remove it.
Step 5: signals outside the visible page
Mixed content hygiene does not stop at the visible page. The same sweep should confirm that canonical tags, hreflang links, Open Graph and social image URLs, url and image fields in JSON-LD, the Sitemap line in robots.txt and the sitemap files themselves all use HTTPS. Google’s site move guide tells you to update sitemaps with the new URLs and submit the new sitemap in Search Console. It also says the Change of Address tool is not needed for an HTTP to HTTPS move, and that warnings about the old sitemap are expected. None of these signals produces a browser warning when it stays on HTTP, yet each one gives Google conflicting address information.
Test the redirects as well. The same guide tells you to test them and notes that people frequently redirect to wrong, non-existent URLs on the new site. A scripted check of a sample of old HTTP URLs, comparing status codes and final destinations, is far more reliable than clicking around. For the www, non-www and trailing-slash side of redirect behavior, the guide on www vs non-www, HTTPS and trailing slash standardization goes deeper, so this article stays with the browser security layer.
Step 6: rank the findings
A crawl produces a list, and a list is not a plan. Mark each finding with three attributes: blockable or upgradable, which template repeats it, and who owns it. Blocked scripts and stylesheets come first, template-level sources that repeat across many pages come second, and one-off images in old articles come third. Most of the volume usually traces back to a handful of source points, which means one line in a template can repair thousands of URLs while hundreds of stray images need a database pass.
Fictional example: a documentation site discovers that an embedded sample-code widget and an analytics snippet both load over HTTP from one shared footer partial, while a few hundred older pages carry hard-coded screenshots. The footer fix is a two-minute change and clears most warnings. The screenshots take a scripted replacement run. The point is to rank by repetition, not by page count, and no real site numbers are implied.
To fold these findings into a wider audit, the technical SEO audit checklist and prioritization article shows how crawl, index, redirect and performance issues share one priority order. Adding mixed content as one more row there keeps it from living in a separate spreadsheet that nobody reads.
Verification Checklist and Rollback Plan
After the fixes ship, collect proof, define a monitoring window and write the way back. The checklist below works before launch and after it.
Verification checklist
- Is the certificate chain valid, renewing automatically and monitored for expiry?
- Does every HTTP URL reach its HTTPS equivalent in a single 301 or 308 hop?
- Is the HSTS header absent from the HTTP redirect and present, with the intended value, on HTTPS responses?
- Do sampled templates show zero mixed content messages in the console?
- Did the site-wide crawl return clean results for both blockable and upgradable resources?
- Are canonical, hreflang, Open Graph, JSON-LD, robots.txt and sitemap addresses all HTTPS?
- Are downloads, PDFs and brochures served over HTTPS?
- Do third-party components work over HTTPS?
- Is there a complete subdomain inventory behind the includeSubDomains decision?
- Are rollback steps written and is an owner named?
Monitoring after launch
Three sources deserve regular attention for the first weeks. Search Console’s indexing and crawl statistics show whether HTTPS URLs are represented in the index. Server logs confirm how often bots still request HTTP addresses and whether they receive the redirects; reading them next to the HTTP status codes guide makes it quicker to separate 301, 302 and 5xx patterns. Browser-side error reporting rounds out the picture by showing which resources real browsers refuse to load.
Google’s move guide says to expect temporary fluctuation in ranking and that for a small to medium-sized site most pages can take a few weeks to move. Those are expectations, not promises. Duration depends on size and crawl frequency, so judge progress by consistency of redirects, canonicals and sitemaps rather than by a calendar.
Rollback plan
Write the plan layer by layer, because every layer has its own cost of going back.
| Change | How to roll back | Risk level |
|---|---|---|
| Address fixes in templates and content | Restore the previous file version or database backup | Low if a backup exists |
| CSP upgrade-insecure-requests | Remove the header | Low; resources that need it were already failing |
| Short HSTS max-age | Send max-age=0 over HTTPS; applies once browsers revisit | Moderate; HTTP stays blocked until then |
| Long max-age with includeSubDomains | max-age=0, though subdomain policies remain separate | High |
| Preload submission | Removal process plus browser updates | Very high; slow with no fixed timeline |
| HTTP to HTTPS 301 redirects | Repair rather than reverse | Reversing them damages search signals |
The last row is the one people get wrong under pressure. When something breaks, switching back to HTTP looks like the quickest fix. Google’s duplicate-URL page, however, says that HTTPS-to-HTTP redirects cause Google to prefer HTTP very strongly. Fix the faulty resource or the certificate instead. A staged HSTS rollout doubles as a rollback plan for the same reason: while max-age is short, an error costs minutes, not months.
Common mistakes
- Enabling HSTS before cleaning mixed content: blocked resources become harder to escape.
- Starting with a one-year max-age: a mistake lives until the policy expires.
- Adding includeSubDomains without an inventory: forgotten HTTP hosts become unreachable.
- Treating preload as routine: removal is slow and depends on browser releases.
- Crawling HTML only: CSS url() values, inline scripts, JSON-LD and sitemaps stay untouched.
- Ignoring upgraded images: they work today and break when the remote host lacks HTTPS.
- Calling the CSP directive a fix: it defers cleanup instead of completing it.
- Stopping monitoring after launch: a plugin update or a pasted old snippet can bring insecure addresses back.
Frequently Asked Questions
What is mixed content on an HTTPS site?
Mixed content means a page loaded over HTTPS requests an image, script, stylesheet, frame or other resource over HTTP. Because an insecure request can be read or changed in transit, browsers either upgrade it to HTTPS automatically or block it, and the developer console records a warning.
Does mixed content hurt search rankings directly?
Google's documentation does not say so. Google states that it prefers HTTPS pages as canonical, unless there are issues such as an invalid certificate or insecure non-image dependencies. The size of any ranking effect is not quantified, so treat mixed content as a quality problem to clean up, not as a guaranteed ranking lever.
Is HSTS a replacement for redirecting HTTP to HTTPS?
No. The header only counts when it arrives over HTTPS and does nothing on a first visit. Google lists it as one way to reinforce the HTTPS version, alongside redirects and canonical links, so a permanent 301 or 308 redirect is still required for HTTP requests.
Should every site join the HSTS preload list?
No. The preload service itself recommends HSTS but not preloading in general. Joining covers all subdomains, including internal ones, and removal is slow and tied to browser updates. Consider it only if every hostname will serve HTTPS for the long term.
How do I undo HSTS if I enabled it too early?
Send max-age=0 over HTTPS. It applies only after a browser makes a secure request and receives the response, and simply dropping the header does not erase the earlier policy. A preload entry follows a separate and slower removal process.
If browsers upgrade images automatically, do I still need to fix them?
Yes. An upgrade works only if the remote host serves the same file over HTTPS, and requests to a bare IP address are not upgraded but blocked. Some uses, such as srcset or certain CSS url() values, may fall in the blockable group. Correcting the address removes the guesswork.
Conclusion
Mixed content and HSTS are the closing checks of an HTTPS migration, and their order carries the risk. Learn what your audience’s browsers block and what they silently upgrade, then clean insecure addresses layer by layer: templates, stored content, third-party components and the signals outside the page. Switch HSTS on only when certificate renewal, redirects and the subdomain inventory are solid, start with a short max-age and lengthen it in stages, and handle preload as its own, hard-to-reverse decision. Keep evidence at every step: console output, crawl reports, redirect tests and a written rollback note.
Once the technical foundation is stable, the content that gets crawled and indexed decides what happens next. For planned, sourced and readable pages, you can review Akua Adforce’s SEO content writing service; scope and terms are described on the product page. This guide is general technical advice and does not guarantee any ranking, crawl rate or indexing result.
Post a comment
Please log in to leave a comment. Login