Moving to HTTPS is technically a change of address for every page on the site. The certificate and the redirect are the visible half; the other half is telling everything else that the addresses changed.
Get the certificate working first
Before redirecting anything, confirm the secure version of the site loads correctly. The bare domain and the www form, deep pages, images, the login.
Redirecting to a certificate that does not cover both hostname forms takes the site down for half your visitors. For checking coverage, see SSL for subdomains and addon domains.
1. Redirect one to one
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
Each plain address must go to its own secure equivalent, permanently. Not to the homepage. That is read as pages that are gone rather than pages that moved.
Forcing HTTPS deals with the rule and the loop it can create when an application is configured for the other hostname form.
2. Canonical tags
Every page carries a canonical tag stating its preferred address. If those still say http://, the site is redirecting visitors to the secure version while telling search engines the insecure one is preferred.
That contradiction is the single most common reason a properly redirected migration still loses visibility.
In WordPress this follows the site address setting, so changing that setting handles it. There is more on doing it without breaking serialised data in changing your WordPress site URL.
3. The sitemap
Regenerate it. A sitemap listing plain addresses is another contradiction, and it is submitted directly to search engines rather than merely discovered.
curl -s https://example.com/sitemap.xml | grep -c 'http://'
The answer should be zero.
4. Internal links and assets
Links inside your own pages should point at the secure addresses directly.
Relying on the redirect works and costs an extra round trip on every internal link, which is a real speed cost on a site people navigate.
More importantly, assets: images, stylesheets, scripts, loaded over plain HTTP on a secure page are blocked or warned about by browsers, which breaks the padlock and sometimes the page. Fixing mixed content warnings goes over finding them.
Register the secure version separately
Search tools treat https://example.com as a different property from http://example.com. The old one stops reporting anything useful after the migration.
Add the secure version, submit the new sitemap, and keep the old property for a while so you can watch the transition rather than guess at it.
Everything else that points at the site
Analytics configuration, the address given to any third-party service, webhook endpoints, and anything with a callback URL.
These do not fail loudly. A payment provider posting to a plain address that redirects may follow the redirect, or may not, and a callback that silently stops arriving is discovered days later through missing orders. Webhooks and integrations walks through that failure mode.
Expect a short dip
Rankings usually wobble for a week or two while the change is processed. That is normal and it recovers.
A dip that persists for months is not normal, and it is nearly always one of the four items above; most often the canonical tags. Check those before concluding anything else.
Only then consider HSTS
Once everything is genuinely working over HTTPS, the header that stops browsers ever trying plain HTTP is worth adding, carefully, because it cannot be taken back.
Setting up HSTS safely explains the sequence, and doing it before the migration is settled is how sites lock themselves out of their own subdomains.
Collapse the redirect chain
A site with both a protocol redirect and a hostname redirect frequently ends up with visitors making three requests before they see anything.
curl -sIL -o /dev/null -w '%{num_connects} hop, son: %{url_effective} (%{http_code})\n' http://example.com/
curl -sI http://example.com/ | grep -i location
curl -sI https://example.com/ | grep -i location
Follow it manually and count. Plain HTTP to secure, then non-www to www, then a trailing slash added, is three round trips on every first visit and on every link from elsewhere.
One rule that goes straight to the final address fixes it. Order the conditions so the protocol and the hostname are corrected in the same step rather than by separate rules that each fire once. Redirecting a domain or page goes into writing them.
Mixed content is not only images
The visible warnings come from images and scripts. The failures that cost money come from places nobody inspects.
A form whose action posts to the insecure address. A request made by JavaScript to a plain HTTP endpoint, which the browser blocks outright. A stylesheet loading a font or a background image over HTTP. And absolute addresses stored in the database from before the change.
grep -rn 'http://example.com' ~/public_html --include='*.php' --include='*.css' --include='*.js' | head -20 wp search-replace 'http://example.com' 'https://example.com' --dry-run --all-tables
Run the replacement as a dry run first and read what it proposes. Serialised data in the database is why a plain text find and replace corrupts a site, and why the tool that understands it is the one to use. Fixing mixed content warnings covers the browser side.
The things outside your site that hold the old address
Several systems store your address and keep using it until you change it there, and none of them will tell you.
Payment gateways. Callback and return addresses, which fail silently and leave orders pending.
Webhooks. Anything that posts to you: a form service, a shipping provider, a CRM.
Authentication. Redirect addresses registered with any provider you sign in through, which are usually matched exactly.
Analytics and search tools. The property is registered per protocol in some of them.
Make the list before the switch and work through it after. Configuring payment gateways deals with the first, which is the one that costs immediately.
Verify the whole site, not a sample
Checking a few pages by hand misses the ones that matter, and the sitemap gives you the full list.
curl -s https://example.com/sitemap.xml | grep -o '<loc>[^<]*' | cut -c6- > urls.txt
while read u; do
printf '%s %s\n' "$(curl -s -o /dev/null -w '%{http_code}' "$u")" "$u"
done < urls.txt | grep -v '^200' | head
Anything that is not a direct success is either a redirect that should have been resolved or a page lost in the move.
Then read the access log for requests still arriving on plain HTTP after a week. A steady stream from one source is a system nobody updated, and it is the fastest way to find the item missing from the list above.