Mixed content WordPress oplossen in 4 stappen

Mixed content WordPress oplossen: van console-check en Better Search Replace tot hardcoded thema-URLs en CDN-cache. Rustig probleem naar fix.

· 1 september, 2026 · 7 min lezen
In het kort
  • Mixed content ontstaat als HTTPS-pagina's HTTP-resources laden: slotje verdwijnt.
  • Spoor problemen op via browser-console: elke waarschuwing is een actiepunt.
  • Vervang database-URLs met Better Search Replace of WP-CLI voor serialized data.
  • Vergeet hardcoded URLs in thema-CSS, JS-bestanden en pagebuilder-configs niet.
  • Content Security Policy en upgrade-insecure-requests-header dwingen HTTPS af.
In dit artikel

Mixed content WordPress oplossen is meestal geen mysterie. Je site draait op HTTPS, maar één of meer assets worden nog via HTTP geladen en de browser haalt daarom het slotje weg. Deze how-to loopt in vier stappen door: opsporen, WP-instellingen, database-replace en hardcoded thema-URLs. Geen plugin verplicht, wel commando’s die veilig met serialized data omgaan.

De symptomen zijn herkenbaar. Het slotje-icoontje verdwijnt of wordt doorgestreept. In Chrome krijg je “Not secure”. In de console verschijnt “was loaded over HTTPS, but requested an insecure element”. De inhoud werkt vaak nog, maar het vertrouwen richting bezoekers zakt. Voor webshops kan het zelfs de checkout blokkeren als de betalingsprovider strikte CSP-headers heeft.

Browser-console met mixed content-waarschuwing

Wat mixed content is en waarom het slotje verdwijnt

Een HTTPS-pagina verwacht dat alle onderliggende bronnen (afbeeldingen, scripts, stylesheets, iframes) óók via HTTPS worden opgehaald. Als één script via http:// binnenkomt, breekt de belofte van een volledig versleutelde verbinding. De browser reageert daarop met een waarschuwing.

Er zijn twee categorieën:

  • Actieve mixed content (scripts, iframes, CSS, XHR). Wordt door moderne browsers actief geblokkeerd. Een script dat niet laadt, breekt vaak functionaliteit.
  • Passieve mixed content (afbeeldingen, video’s, audio). Krijgt alleen een waarschuwing. De asset laadt nog wel, maar het slotje blijft weg.

Sinds Chrome 80 (feb 2020) upgradet Chrome mixed audio/video-content automatisch naar HTTPS; vanaf Chrome 81 (apr 2020) geldt hetzelfde voor images. Werkt waar dat kan. Werkt de bronserver ook op HTTPS: opgelost. Werkt de bronserver niet op HTTPS: de asset laadt niet en je krijgt alsnog een broken image. Vertrouw dus niet blind op auto-upgrade.

Voor de exacte specificatie en achtergrond is de web.dev-uitleg over mixed content de aangewezen bron. Voor de bredere HTTPS-configuratie op je site verwijs ik naar WordPress-beveiliging en HTTPS-config.

Mixed content WordPress oplossen: 4 stappen in overzicht

Voor je begint een korte preview van de workflow. Elke stap komt daarna uitgebreid aan bod.

  1. Opsporen. Chrome DevTools open, tab Console, filter op “mixed content”. Noteer welke URLs binnenkomen via HTTP.
  2. WordPress-instellingen. Site Address en WordPress Address op https://. Optioneel FORCE_SSL_ADMIN in wp-config.php.
  3. Database-replace. Alle oude http://voorbeeld.nl naar https://voorbeeld.nl met Better Search Replace of WP-CLI. Serialized-safe.
  4. Hardcoded thema-URLs. Via SSH grep door je child-theme, custom CSS en widget-content. Handmatig aanpassen wat de replace-tool niet raakt.

Extra afsluiting: cache flushen op elk niveau, en optioneel een upgrade-insecure-requests-header als vangnet.

Stap 1: opsporen in de browser-console

De snelste route: open je site in Chrome, druk F12, ga naar tab Console. Herlaad de pagina. In de console verschijnen meldingen als:

Mixed Content: The page at 'https://voorbeeld.nl' was loaded over HTTPS,
but requested an insecure element 'http://voorbeeld.nl/wp-content/...'

Klik door de meldingen. Elke regel bevat de exacte URL die het probleem veroorzaakt. Noteer ze allemaal. Voor sites met veel content is een gratis online scanner handig: Why No Padlock (whynopadlock.com) crawlt je pagina en geeft een lijst URLs terug.

Voor een volledige site-scan draai ik lokaal een crawler zoals Screaming Frog SEO Spider in “internal + external”-modus met filter op “http://”. Dat vindt ook mixed content op pagina’s die je zelf niet dagelijks bezoekt.

Categoriseer wat je vindt in drie groepen: assets van je eigen domein (99 procent van de fixes), assets van externe bronnen (widget-embeds, oude analytics-code), en assets die alleen in specifieke templates verschijnen (mail-templates, PDF-generatoren).

Stap 2: WordPress-instellingen op HTTPS zetten

Ga naar Instellingen → Algemeen. Zet beide URL-velden om:

  • WordPress-adres (URL): https://voorbeeld.nl
  • Site-adres (URL): https://voorbeeld.nl

Opslaan. WordPress logt je uit. Log opnieuw in via de HTTPS-URL. Als de admin nu werkt: goede eerste stap.

Voor extra zekerheid in de admin, voeg toe aan wp-config.php (boven de “That’s all, stop editing”-regel):

define('FORCE_SSL_ADMIN', true);

Dat dwingt de admin-area en login-pagina altijd via HTTPS af, ook als iemand http://voorbeeld.nl/wp-admin/ probeert.

Waarschuwing: als deze instelling wordt gezet zonder werkend SSL-certificaat, kom je niet meer in de admin. Doe dit dus pas als je bevestigd hebt dat HTTPS werkt op de frontend.

Stap 3: database-URLs migreren met Better Search Replace of WP-CLI

Nu de kern. In je database staan honderden tot duizenden verwijzingen naar http://voorbeeld.nl. Die staan in post_content, in widget-instellingen, in ACF-velden, in serialized JSON van pagebuilders. Een simpele SQL-UPDATE ... REPLACE(...) breekt serialized data omdat de string-lengte-prefixen niet meer kloppen. Dat is de klassieke valkuil.

Route A: Better Search Replace (plugin). Installeer, ga naar Tools → Better Search Replace.

  • Zoek naar: http://voorbeeld.nl
  • Vervang met: https://voorbeeld.nl
  • Selecteer alle tabellen (ctrl-A in het lijstje).
  • Vink “Run as dry run” aan.
  • Klik “Run Search/Replace”.

De dry-run toont hoeveel matches per tabel er zijn zonder wijzigingen door te voeren. Bekijk het rapport. Als de aantallen kloppen (meestal duizenden in wp_posts, honderden in wp_postmeta), zet dry-run uit en draai opnieuw.

Route B: WP-CLI (voorkeur bij grote sites). Via SSH:

wp search-replace 'http://voorbeeld.nl' 'https://voorbeeld.nl' --dry-run --all-tables

Bekijk de output. Als het aantal wijzigingen redelijk lijkt:

wp search-replace 'http://voorbeeld.nl' 'https://voorbeeld.nl' --all-tables

WP-CLI behandelt serialized data correct. Voor multisite gebruik je --network erbij.

Wat vaak vergeten wordt: ook de variant zonder subdomain (http://www.voorbeeld.nl als je site op non-www draait, of andersom) apart doen. En de subdomein-varianten van CDN’s (http://cdn.voorbeeld.nl naar https://cdn.voorbeeld.nl).

Better Search Replace dry-run resultaten

Stap 4: hardcoded thema- en CSS-URLs oplossen

De database is nu schoon, maar er is content die niet in de database staat: je child-theme-bestanden, custom CSS-blokken die naar images verwijzen, en soms harde URLs in third-party plugin-configs.

Via SSH:

grep -r "http://voorbeeld.nl" wp-content/themes/child-theme/
grep -r "http://" wp-content/uploads/ --include="*.css"
grep -r "http://" wp-content/plugins/mijn-custom-plugin/

Wat je vaak vindt:

  • Header.php met een hardcoded logo-URL.
  • Style.css met background-image: url(http://voorbeeld.nl/wp-content/...).
  • Custom widgets waar een img-tag in staat.
  • WooCommerce e-mail-templates met een hardcoded logo (Appearance → Customize → Emails, of in de template-overrides).

Voor elke vondst: verander http:// naar https:// of, nog beter, gebruik protocol-relative URLs (//voorbeeld.nl/...) of WordPress-functies (get_stylesheet_directory_uri()). Verbeteren boven herbouwen: één middag werk in plaats van een migratie.

Vergeet de custom CSS in de Customizer niet (Appearance → Customize → Additional CSS). Die staat wél in de database (in de option theme_mods_...), maar de search-replace vindt hem alleen als je exact op je oude domein-URL zoekt.

SSH grep-scan voor hardcoded http-URL's in child-theme

Extra: CDN, cache en Content Security Policy

Na de fix moet je alle caches legen om te zien of het echt opgelost is.

  • WordPress-cache-plugin. WP Rocket, W3 Total Cache, LiteSpeed Cache: elk heeft een “Purge all”-knop.
  • Object-cache. Bij Redis of Memcached: flush via WP-CLI (wp cache flush) of het hostingpaneel.
  • Server-cache. Bij Hostinger LiteSpeed, Kinsta of WP Engine: knop in het klantpaneel.
  • CDN. Cloudflare: Purge Everything. StackPath, KeyCDN: idem in dashboard.
  • Browser. Hard-refresh (Ctrl+Shift+R of Cmd+Shift+R). Of anonieme modus openen.

Als vangnet kun je een Content Security Policy-header toevoegen die de browser vraagt om HTTP-content automatisch als HTTPS te proberen. In nginx:

add_header Content-Security-Policy "upgrade-insecure-requests";

In Apache/.htaccess:

Header set Content-Security-Policy "upgrade-insecure-requests"

Deze header is een aanvulling, geen vervanging. Als de bronserver geen HTTPS heeft, valt de asset alsnog uit.

Wanneer een webmaster het overneemt

Voor een standaard-site met één taal, één subdomein en geen exotische plugins is dit een uur werk. Voor sites waar het complexer wordt, loont het om iemand te laten kijken. Concrete situaties:

  • Multisite waar je per site een replace moet doen.
  • WooCommerce met veel product-images en e-mail-templates die net anders ingericht zijn.
  • Een migratie waarbij het domein óók verandert (http://oude-site.nl naar https://nieuwe-site.nl): twee vervangingen tegelijk, meer risico.
  • Sites waar een eerdere replace half is uitgevoerd en de database inconsistent is.

Bij mij zit dit standaard onder het uurtarief van 95 euro voor serverwerk. Voor multisite of complexere WooCommerce zit het op 105 euro. Ik werk in de source-code voor wat er buiten de database zit en gebruik dry-runs voor alles wat de database raakt. Voor doorlopende hygiëne is onderhoud van je WordPress-installatie meestal goedkoper dan losse uren.

Andere stacks kennen hetzelfde patroon. Shopify Liquid-templates hebben zelden mixed content (Shopify serveert alles via HTTPS). Joomla vaker: menu-images en oude modules met hardcoded URLs. Drupal via Views en oudere versions van het File-module. Voor elk platform is de kern: opsporen, database (of config), templates, cache.

Serhii Lypii
Gratis meedenken

Slotje terug in de browser krijgen?

Stuur me je URL en een screenshot van de browser-console-melding. Ik loop de vier stappen door op staging, doe een serialized-safe database-replace en check hardcoded thema-URLs. Meestal in één sessie klaar.

Vraag een mixed content-fix aan
Vond je dit nuttig? Deel het:
FAQ

Veelgestelde vragen over mixed content in WordPress

Waarom zie ik nog een waarschuwing na een SSL-plugin?
Plugins als Really Simple SSL of SSL Insecure Content Fixer patchen de HTML on-the-fly, maar raken niet altijd de database of hardcoded thema-URLs. Ze zijn een goed vangnet, geen definitieve fix. Voor een schone site is de database-replace plus grep-scan de duurzame route.
Is Better Search Replace veilig voor serialized data?
Ja. De plugin herberekent de string-lengte-prefixen in serialized data. Een rauwe SQL-UPDATE ... REPLACE(...) doet dat niet en kan widgets, ACF-velden en pagebuilder-content breken. Kies altijd Better Search Replace of WP-CLI, nooit een handmatige SQL-update op serialized content.
Moet ik alle interne links handmatig aanpassen?
Nee. Een database-replace via Better Search Replace of WP-CLI pakt ongeveer 95 procent van de vervangingen. De resterende 5 procent zijn hardcoded template-URLs die je met een grep in het theme-bestand vindt en handmatig aanpast.
Wat is upgrade-insecure-requests?
Een Content Security Policy-header die de browser vraagt HTTP-assets automatisch als HTTPS te proberen. Handig als vangnet voor content die je niet direct kunt aanpassen. Geen vervanging voor de fix zelf: als de bronserver geen HTTPS aanbiedt, valt de asset alsnog uit.
Blijft het probleem terugkomen?
Alleen als je later plugins of thema's installeert die zelf HTTP-URLs meebrengen, of als iemand een oude blogpost importeert. Een periodieke scan (elk kwartaal, of na elke grote import) vangt dit vroeg af.
Serhii Lypii
Over de auteur

Serhii Lypii

Freelance webmaster · Terneuzen

Sinds 2012 werk ik met websites en leverde ik ruim 210 projecten op. Ik help mkb-ondernemers met onderhoud, snelheid, beveiliging en praktische automatisering. Nuchter, zonder hype.

Ik schreef dit artikel op en werkte het voor het laatst bij op .

Meer over Lypii
Even sparren over je site?

Loop je ergens tegenaan of twijfel je over je site? Ik denk graag mee. Kies hieronder hoe je contact opneemt.

Reactie binnen 4 uur op werkdagen
Navigatie
Home Over mij Kennisbank
Contact
+31 6 39 56 93 03 serhii@lypii.nl WhatsApp
Stuur een bericht