Add HSTS and security headers

Templ issues and renews your SSL certificate and redirects HTTP to HTTPS automatically, but it does not add HSTS or other security response headers for you. You add those at the application level with a plugin or a bit of PHP, or ask us to add them at server level if you need them on static files too. This is what security scanners are flagging when they report a missing Strict-Transport-Security header.

What is HSTS

HSTS (HTTP Strict Transport Security) is a response header that tells browsers to always load your site over HTTPS, even if someone types http:// or follows an old http:// link. Once a browser has seen the header, it refuses to connect over plain HTTP for the duration you set, which protects against downgrade and cookie-hijacking attacks.

Because Templ already redirects HTTP to HTTPS and serves a valid certificate, adding HSTS is a hardening step on top of a working setup, not a fix for a broken one.

Option 1: Use a plugin

The no-code path is a plugin that manages response headers. The free Redirection plugin can add headers under Redirection → Site → HTTP Headers → Add Header: add a Strict-Transport-Security header with a value like max-age=63072000; includeSubDomains. Most security plugins (for example Wordfence or All In One Security) can also add HSTS and related headers from their settings.

Option 2: Add the headers with PHP

If a plugin can't do exactly what you need, add the headers with a bit of PHP. There are two common ways to run it, in order of least to most technical:

  • Code Snippets plugin - install it, go to Snippets → Add New, paste the code below, set it to Run everywhere, and activate. No files to touch.
  • Your theme's functions.php - paste the code below at the end of the file. Use a child theme so a theme update doesn't wipe it out.
function templ_security_headers() {
    $siteurl = get_option('siteurl');
    if (strpos($siteurl, 'templweb.com') !== false || strpos($siteurl, 'templtrial.com') !== false) {
        return;
    }
    header('Strict-Transport-Security: max-age=63072000; includeSubDomains');
}
add_action('send_headers', 'templ_security_headers');

The guard skips the header on temporary templweb.com and templtrial.com domains, so HSTS only applies once you're on your real domain. Leaving it out could pin HSTS to a throwaway hostname you no longer control.

Optional additional headers

You can add more headers inside the same function. These are safe defaults that don't depend on your site's specific setup:

header('X-Content-Type-Options: nosniff');
header('X-Frame-Options: SAMEORIGIN');
header('Referrer-Policy: strict-origin-when-cross-origin');
header('Permissions-Policy: geolocation=(), camera=(), microphone=(), payment=()');
  • X-Content-Type-Options: nosniff stops browsers from guessing a file's type and running it as something it isn't.
  • X-Frame-Options: SAMEORIGIN blocks other sites from embedding your pages in a frame (clickjacking protection).
  • Referrer-Policy controls how much of the referring URL is shared when visitors click away.
  • Permissions-Policy turns off browser features your site doesn't use, like geolocation, camera, microphone, and payment. Only disable what you're sure you don't need - a booking or checkout plugin may rely on one of them.

Skip Expect-CT and X-XSS-Protection - both are deprecated and ignored by modern browsers. A Content-Security-Policy (CSP) is powerful but site-specific: a blanket policy usually breaks scripts, styles, or embeds, so add one only after testing it against your own theme and plugins.

Preloading HSTS

You'll see preload in many HSTS examples. It submits your domain to a browser-baked list that forces HTTPS before the first visit ever happens.

Option 3: Ask us to add them at server level

Options 1 and 2 only cover responses that WordPress generates - HTML pages, including Templ Cache hits. They do not apply to static files like CSS, JS, and images, which nginx serves directly without running PHP. If a security scanner or a compliance requirement expects the headers on every response, we can add them to your site's nginx configuration instead.

Contact support with the headers and values you want, and we'll add them for you.

We recommend the application-level options where they're enough, because you can change or roll back a header yourself without opening a ticket. Server-level headers also apply to your templweb.com and templtrial.com domains, so a long HSTS max-age will pin those hostnames too - start at max-age=300.

Verify the header

Confirm the header is live with curl from your terminal:

curl -sI https://yourdomain.com | grep -i strict-transport-security

You should see your Strict-Transport-Security line in the output. Headers sent from PHP are stored with the cached page, so they're served on Templ Cache hits too - a cached response (X-Cache-Status: HIT) carries the same security headers as an uncached one. They are not applied to static files such as CSS, JS, and images, which nginx serves without running PHP - see Option 3 if you need those covered. See How caching works for more on cache status.