---
title: "Your own domain"
description: "Serve a deployed agent from a hostname you own — one CNAME for a subdomain (or three records for a root domain); Guuey verifies ownership and provisions TLS."
---

Every deployed agent already answers at its **always-on domain** — the
stable `https://<app-id>.agents.…` address that `guuey deploy` prints as
`Live at`. That is the agent's _infrastructure_ address: it is where the
[client SDK](/sdk/) invokes the agent, where `/readyz` answers, and the
CNAME target for your custom domains. It does not serve a page — open it
in a browser and you get a bare `404`. The agent's **standalone page**
lives on the hosts meant for people: its **slug host**, a **custom
domain**, and the first-party [share page](/embed/#share-links).

Every deployed agent also has a **slug host** from its first deploy: the
platform claims a default slug (`<your-agent-name>-<4 characters>`) the
moment the first build goes live, and `guuey deploy`, `guuey agent apply
--wait` and Studio print it as `Your agent's page: https://…`. Nothing to
set up — and if you'd rather have a name of your own, `guuey slug claim
<name>` replaces it (a slug you claim yourself is never overwritten).

A **custom domain** puts the agent — the page, the live chat stream, and
the conversation history, all same-origin — behind a hostname you own,
like `chat.example.com`, with TLS provisioned for you. You create exactly
one DNS record, once; every migration after that happens on Guuey's side,
and your DNS never changes again.

Custom domains are available on the **Pro** and **Scale** plans — see
[Plans & billing](/plans-and-billing/) for what each plan includes.

## Three kinds of hostname

| Hostname         | What it is                                                                                                                                                                                                                                                                                                 | Plan        |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| Always-on domain | `<app-id>.agents.…` — exists for every deployed agent, nothing to configure. The agent's endpoint (invoke URL, `/readyz`) and the CNAME target for your custom domains. Serves the API, not the page.                                                                                                      | Every plan  |
| Slug host        | A Guuey-owned name (`your-slug.agents.guuey.com`) — claimed automatically at first deploy (`<agent-name>-<4 characters>`); change it with `guuey slug claim`, which also reserves the portal path `/agent/<slug>`. Serves the standalone page — every deployed agent's shareable address, with zero setup. | Every plan  |
| Custom domain    | A hostname you own: a subdomain pointed at the always-on domain with one CNAME, or a root domain with three records (see below). Serves the standalone page.                                                                                                                                               | Pro / Scale |

:::note
`guuey domains` is not the same thing as the **allowed origins** list
(`guuey apps update --domains`), which controls which websites may embed
your agent's widget. A custom domain is where your agent is _served_; an
allowed origin is where it may be _embedded_. See
[Embed](/embed/) for the latter.
:::

## Add a custom domain

You can do this from the console or the CLI — both drive the same flow.

- **Console** — open your app and choose **Domains** in the sidebar.
  Copy the always-on domain (your CNAME target), or add a custom domain
  below it.
- **CLI** — `guuey domains add`, `list`, `verify`, `remove`; every
  subcommand accepts `--app-id <id>` if you're outside a project
  directory.

### 1. Add the domain

```sh
guuey domains add chat.example.com
```

The response shows the record to create:

```
chat.example.com → CNAME → <app-id>.agents.us-east-1.guuey.com
```

Root domains (`example.com`) are supported too, with a different set of
records — see [Root (apex) domains](#root-apex-domains) below. Each app
can have up to 4 custom domains.

### 2. Create the CNAME record

At your DNS provider, create a CNAME from your subdomain to the target
shown. Order doesn't matter — you can create the record before or after
adding the domain.

### 3. Verification runs by itself

Guuey checks the record about once a minute for 7 days and verifies
automatically as soon as the CNAME resolves. To check on demand, press
**Verify now** in the console or run:

```sh
guuey domains verify chat.example.com
```

The command exits non-zero until the domain verifies, so it's safe to
use in scripts and CI.

### 4. TLS provisions, then it serves

Once verified, a certificate is issued for your hostname — no TXT
records, no certificate files, nothing to renew. The domain starts
serving automatically, usually within minutes:

```
Domain chat.example.com verified — TLS is provisioning, usually live in minutes.
```

## Root (apex) domains

A root domain like `example.com` can't hold a CNAME record — that's a rule
of DNS, not ours. So a root domain is verified and served differently:

```sh
guuey domains add example.com
```

Guuey detects a root domain automatically (a name that has its own SOA
record). If your zone isn't live yet, force it with `--txt`. The response
lists **three** records to create instead of one:

```
_guuey-challenge.example.com → TXT   → guuey-verify=<app-id>.agents.us-east-1.guuey.com
example.com                  → ALIAS → <edge-endpoint>.cloudfront.net
_cf-challenge.example.com    → TXT   → <edge-endpoint>.cloudfront.net
```

1. **Ownership TXT** — what Guuey checks to verify you own the domain
   (the same 7-day window and **Verify now** as a subdomain).
2. **Root ALIAS** — where the domain actually serves from. Your DNS
   provider must support **ALIAS, ANAME, or CNAME flattening at the
   root** (Route 53, Cloudflare, DNSimple, DNS Made Easy, Namecheap and
   Porkbun do; many providers don't). A plain A record won't work — the
   edge's addresses rotate.
3. **Edge certificate TXT** — lets the edge verify the domain and issue
   its certificate. Until this record resolves, the domain shows
   **Verified** but doesn't serve; press **Check edge record** in the
   console (or run `guuey domains verify example.com` again) once it's in
   place and serving converges within seconds instead of at the next
   hourly check.

**Recommended instead:** serve at `www.example.com` (one CNAME, like any
subdomain) and forward `example.com` → `https://www.example.com` at your
registrar — the standard setup for hosted services, and it works with
every DNS provider.

**What's different about a root domain, honestly:** a subdomain points at
Guuey's own hop, so if we ever move our edge, we repoint that hop and your
DNS never changes. A root domain points straight at the edge, so if we
ever move it, we'll ask you to update records 2 and 3. We don't plan to —
but the difference is real, and it's why `www` + forward is the
recommendation.

## Statuses

`guuey domains list` and the console's **Domains** page show two axes:

| Status           | Meaning                                                                                                                                                |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Pending          | Waiting for the CNAME to resolve. The 7-day verification window is open.                                                                               |
| Verified         | Ownership proven; TLS provisioning begins.                                                                                                             |
| Failed           | The 7-day window elapsed before the CNAME resolved. Fix the record, then verify again — a fresh window opens.                                          |
| TLS provisioning | Certificate being issued for the hostname.                                                                                                             |
| Serving          | Live — your domain serves the agent over HTTPS.                                                                                                        |
| TLS failed       | The certificate couldn't issue. Most commonly a CAA record on your domain that doesn't permit `amazon.com`; issuance retries automatically once fixed. |

## Troubleshooting

- **Verification never completes** — for a subdomain, confirm the CNAME
  with `dig CNAME chat.example.com`: it must answer with your app's
  always-on domain. A proxied/flattened record (some providers rewrite
  CNAMEs) won't verify. For a root domain, confirm the ownership TXT with
  `dig TXT _guuey-challenge.example.com`: it must contain the exact
  `guuey-verify=…` value shown.
- **A root domain is Verified but never starts serving** — the edge
  certificate TXT is missing: `dig TXT _cf-challenge.example.com` must
  answer with the edge endpoint. Create it, then press **Check edge
  record** (or run `guuey domains verify`). Also confirm the root ALIAS
  resolves: `dig A example.com` should return the edge's addresses.
- **My DNS provider has no ALIAS/ANAME/flattening** — serve at `www` (one
  CNAME) and forward the root at your registrar; see
  [Root (apex) domains](#root-apex-domains).
- **TLS failed** — check for a `CAA` record on your domain or its
  parents; if one exists, it must permit `amazon.com` to issue.
- **The domain is claimed by another app** — a hostname can belong to
  one app at a time. If the existing claim never **verified**, you can
  take the domain over: point your DNS at the new app's target (the
  CNAME for a subdomain, or the `_guuey-challenge` TXT for a root
  domain) and add it there — proof of ownership replaces the stale
  claim, immediately verified. If the domain is already **verified** on
  the other app, adding it is refused; remove it from that app first
  (`guuey domains remove`), then add it to the new one. This applies
  when moving a domain between your own apps, too.
- **After a plan downgrade** — custom domains **stop serving** within
  about an hour of the app leaving Pro or Scale; the slug host and
  always-on domain keep working. The domain rows are kept (shown as
  failed with plan-loss copy in the console). After upgrading back,
  serving resumes automatically at the next hourly check — your DNS
  record is still in place, so there is nothing to redo. (For a root
  domain, `guuey domains verify` can trigger re-promotion right away.)
  Pending domains can't be promoted while the app is off Pro or Scale.

## Who signs in on your domain?

By default, visitors on your custom domain chat as guests. If your app
uses Guuey sign-in, visitors get Guuey's login. If it uses bring-your-own
auth (configured under **Users → Authentication**), visitors sign in
either through your [identity endpoint](/identity-endpoint/) (set under
**Settings → General → Standalone page**; custom domains only) or through
a redirect to [your own identity provider](/page-sign-in/) (any host the
page is served on, including the slug host and the share page) — the full
table is on [Sign-in on the agent's page](/page-sign-in/).

## The page itself

What your custom domains, your slug host and the first-party share page
serve is the app's **standalone page** — one page policy for all of them,
under **Settings → General → Standalone page** (or `guuey apps update`).
The always-on domain is not one of these hosts: it answers the agent's
API and nothing else. Since every deployed agent gets a slug host at its
first deploy, the share page is a second door rather than the only one;
an agent whose slug was released (`guuey slug release`) is reachable by
people only through its share page until a slug is claimed again.

- **On / off** — turn the page off and every standalone host shows
  "This agent doesn't have a public page." Embeds, the Portal listing and
  the agent keep working; only the page is hidden.
- **Welcome line** — the sentence shown before the first message, and the
  share-link description. The page's title is always the app's name.
- **Call-to-action** — an optional button under the welcome line (label +
  https link, opens in a new tab). Set both or neither.
- **Hide from search engines** — adds `noindex, nofollow`; anyone with the
  link can still open the page.
- **Identity endpoint** — see above.

```bash
guuey apps update <appId> --page on --welcome-copy "Ask me about shipping." \
  --cta-label "Book a demo" --cta-url https://www.example.com/demo --noindex off
```