Ga naar inhoud
Begin met HitKeep Cloud

Custom Tracking Domains

Deze inhoud is nog niet vertaald.

Ad blockers and restrictive network filters are more likely to block shared analytics hostnames than a first-party subdomain controlled by the site owner.

HitKeep custom tracking domains let team admins verify multiple tracker hostnames for a team. Every active team domain can serve tracker assets and browser ingest for every site in that team. When users generate tracking code for a site, Site Settings lets them choose the instance URL or any active team domain for the hk.js snippet. Cloud and self-hosted deployments use the same database model, dashboard flow, API, and tracker behavior. The difference is TLS operations: HitKeep Cloud issues certificates on demand with Caddy, while self-hosted operators either use the optional Caddy profile or terminate TLS in their own reverse proxy.

Terminal window
HITKEEP_CUSTOM_TRACKING_TLS_MODE=caddy-on-demand
HITKEEP_CADDY_TLS_ASK_TOKEN=$(openssl rand -hex 32)
HITKEEP_PUBLIC_URL=https://hitkeep.example.com

See the configuration reference for all custom-domain runtime switches.

  • Domains belong to a team, not an individual site.
  • A team can verify multiple domains.
  • Every active team domain works for every site in that team.
  • Site Settings does not assign domains to the site. It only chooses which available host to use in the generated snippet.
  • The instance URL always remains available as a tracker endpoint.
  • Hostnames are normalized as lowercase ASCII fully qualified domain names.
  • Hostnames cannot conflict with the configured HITKEEP_PUBLIC_URL host, existing site domains, or another team’s custom tracking domain.

Custom tracking hosts are tracking-only. HitKeep serves only:

  • GET /hk.js
  • GET /hk-vitals.js
  • POST /ingest
  • POST /ingest/event
  • POST /ingest/web-vitals
  • matching OPTIONS preflight requests for ingest

Dashboard, API, auth, share links, MCP, QR redirects, and SPA fallback routes return 404 on a custom tracking host.

Add the domain in Team Settings -> Tracking domains. HitKeep shows the exact DNS records to create.

TXT _hitkeep-tracking.analytics.example.com
Value hitkeep-domain-verification=<token>
CNAME analytics.example.com
Value <target shown in HitKeep>

HitKeep checks three things before a domain can be used as a tracker endpoint:

  1. DNS ownership TXT record exists and matches the generated token.
  2. DNS routing target matches the deployment target. By default this is the host from HITKEEP_PUBLIC_URL; managed cloud uses the regional origin target shown in the dashboard.
  3. https://analytics.example.com/hk.js returns the tracker asset with valid TLS.

The HTTPS probe is what turns a DNS-verified domain into an active tracker endpoint. Until then, the domain can exist in Team Settings, but Site Settings does not offer it as a snippet host.

  1. Open Team Settings -> Tracking domains.
  2. Add a subdomain such as analytics.example.com.
  3. Create the TXT ownership record.
  4. Point the subdomain to the cloud target shown in the dashboard.
  5. Click Verify.
  6. Wait for TLS to become ready.
  7. Open the site’s tracking settings and choose the instance URL or any active team tracker domain for the generated snippet.

The generated snippet changes from the regional cloud host to the selected domain:

<script async src="https://analytics.example.com/hk.js"></script>

Cloud uses Caddy on-demand TLS behind the same HitKeep allow endpoint described below. Teams do not need to configure Caddy themselves in the managed product.

Self-hosted HitKeep uses the same dashboard flow and verification checks, but the operator controls DNS, TLS, and the reverse proxy.

For a normal externally terminated proxy, set:

Terminal window
HITKEEP_CUSTOM_TRACKING_TLS_MODE=external

Then point each tracker hostname at the same host as HITKEEP_PUBLIC_URL, and configure your proxy to:

  • terminate TLS for each verified tracking hostname
  • forward requests to the HitKeep process
  • preserve the original Host header
  • publish /hk.js, /hk-vitals.js, and the ingest routes

HitKeep still enforces the tracking-only host boundary, so an accidentally proxied dashboard route on a custom tracking host returns 404.

The HitKeep repository includes external-TLS examples for operators who manage certificates outside Caddy:

Kubernetes installs can use the official Helm chart’s customTrackingDomains values to set the HitKeep runtime mode and optionally create a tracking-only Ingress for static tracker hostnames. See the Kubernetes guide.

In external mode, add each tracking hostname to the proxy before clicking Verify. The proxy must already present a valid certificate for https://<hostname>/hk.js; otherwise HitKeep keeps the domain inactive.

Use Caddy on-demand TLS when self-hosted teams should be able to add tracker domains from the dashboard without the operator editing a Caddyfile for every hostname.

Generate an ask token:

Terminal window
export HITKEEP_CADDY_TLS_ASK_TOKEN="$(openssl rand -hex 32)"

Enable Caddy mode on HitKeep:

Terminal window
HITKEEP_CUSTOM_TRACKING_TLS_MODE=caddy-on-demand
HITKEEP_CADDY_TLS_ASK_TOKEN=$HITKEEP_CADDY_TLS_ASK_TOKEN

Configure Caddy with a restricted ask endpoint:

{
email ops@example.com
on_demand_tls {
ask http://hitkeep:8080/internal/caddy/on-demand-tls/{$HITKEEP_CADDY_TLS_ASK_TOKEN}
}
}
https:// {
tls {
on_demand
}
reverse_proxy hitkeep:8080 {
header_up Host {host}
header_up X-Forwarded-Host {host}
header_up X-Forwarded-Proto {scheme}
}
}

Caddy calls the ask URL with ?domain=<hostname> before issuing a certificate. HitKeep returns 204 only when the token matches and the hostname is an enabled, DNS-verified custom tracking domain. Unknown, disabled, malformed, or wrong-token requests are denied.

Do not enable Caddy on-demand TLS without ask. Caddy treats any 2xx ask response as allowed, and the ask gate is the control that prevents arbitrary certificate issuance. See Caddy’s official on-demand TLS overview, Automatic HTTPS, and global options documentation.

The HitKeep repository includes example files:

Browser ingest still resolves the tracked site from the page Origin, not from the tracker host. When the request host is a custom tracking domain, HitKeep additionally checks that the custom tracking domain and the resolved site belong to the same team. That prevents another team from reusing someone else’s verified tracker host.

The Go binary does not embed Caddy and does not require Caddy. The optional profile is an operational convenience for TLS automation; HitKeep remains a single-binary application when you terminate TLS elsewhere.