# Custom domain

> Serve the ClickClacks tracker and receive events on a subdomain of your own, such as cc.acme.com: the CNAME record, certificates and CAA, what the custom domain serves, and moving your sources over.

- Canonical URL: https://clickclacks.io/docs/custom-domain
- Section: Tracking
- Last updated: 2026-09-26

Load the tracker from a subdomain you own, such as cc.acme.com, and your events go there too. One CNAME record, and ClickClacks handles the certificate.

A project has one custom domain, shared by all of its sources. You set it up in **Settings › Custom domain** in the app. Connecting a domain is part of the Pro plan; a domain you’ve connected stays manageable on every plan.

## Why first-party {#why}

- **Your domain in the page source.** The script and its requests go to a hostname your visitors already trust.
- **Fewer blocked requests.** Filter lists that match on third-party analytics hostnames don’t match yours. It doesn’t override a visitor’s own choice: [opt-out](https://clickclacks.io/docs/consent.md) works the same.
- **A simpler Content Security Policy,** with one hostname of your own for scripts and events.

## Set it up {#set-up}

1. In **Settings › Custom domain**, enter a subdomain, such as `cc.acme.com`. A bare apex domain such as `acme.com` isn’t accepted.
2. At your DNS provider, create the one `CNAME` record the app shows you, and leave the TTL on automatic. It points to `cname.clickclacks.io`:

```title="dns"
cc.acme.com.   CNAME   cname.clickclacks.io.
```

3. ClickClacks checks your DNS and, once the record is right, issues an HTTPS certificate from Let’s Encrypt. **Check now** checks again straight away.
4. When the certificate is active, the domain is **live**.

> **Using Cloudflare for DNS?**
>
> Add the record under **DNS › Records**. The app notes where the record goes in common providers, such as Route 53’s **Create record**.

## Update the snippet {#snippet}

When the domain is live, the snippet on each source’s page loads from it. Only the script’s `src` changes; `data-key` and `data-domains` stay the same:

```html
<script async src="https://cc.acme.com/c.js" data-key="pk_live_3f9a1c7e5b2d4f6a8c0e1b3d" data-domains="acme.com,www.acme.com,app.acme.com"></script>
```

Loaded from `cc.acme.com`, the tracker sends its events to `cc.acme.com` as well. Nothing else in your code changes.

## What it serves {#what-it-serves}

Your custom domain answers only what the tracker needs. Every other path returns a 404.

| Path | What it is |
| --- | --- |
| `/c.js` | The tracker. |
| `/e` | Where the tracker sends events. |
| `/heatmap-screenshot.js` | The helper the tracker loads when a heatmap capture is due. |

- Heatmap captures themselves are still sent to `app.clickclacks.io`, so keep it in your [Content Security Policy](https://clickclacks.io/docs/install.md#csp).
- The [server API](https://clickclacks.io/docs/api.md) and the [MCP server](https://clickclacks.io/docs/mcp.md) are served on `app.clickclacks.io` only.

## Moving your sources over {#moving-over}

Update the snippet on each site to the new `src`. Settings › Custom domain lists any source still sending to the old endpoint, with its last event and volume.

- Events sent the old way are accepted for **30 days** after your domain goes live. After that, they’re refused while the custom domain is live.
- If your custom domain stops being live, for example because the DNS record was removed, `app.clickclacks.io` accepts events again and the snippet in the app goes back to loading from it.
- Removing the domain asks you to type its name to confirm.

## Troubleshooting {#troubleshooting}

- **“Almost — the record needs one change”.** ClickClacks found a different record on the hostname: another CNAME, an A record, or a wildcard answering for it. The app shows what it expected and what it found. Nothing is lost meanwhile; your snippet keeps sending to the old endpoint.
- **The certificate is blocked.** Your domain has `CAA` records that don’t allow Let’s Encrypt. The app shows the record to add.

## Next steps {#next}

- [Domains and identity](https://clickclacks.io/docs/domains.md): allowed domains and carry-over.
- [Debugging](https://clickclacks.io/docs/debugging.md): confirm events arrive through the new domain.
