Skip to content

Custom tracking domains

Serve short-link redirects and ingestion from your own subdomain instead of api.retidal.com, via Cloudflare custom hostnames or NS delegation.

A custom tracking domain lets Short links redirects and event ingestion resolve under your own subdomain (e.g. track.yourbrand.com) instead of api.retidal.com — useful for first-party cookie durability and brand consistency in ad destination URLs.

This is the tracking domain, not the email sending domain

This page covers GET /api/projects/{projectId}/domains and POST /api/projects/{projectId}/domains, the tracking-traffic custom domain. Retidal also has a separate email sending domain feature (GET /api/projects/{projectId}/email/domains) for deliverability (SPF/DKIM) — that is a different feature with its own onboarding flow, not covered here. Don’t point one at the other’s DNS setup.

  • Ownership of the subdomain you want to onboard, and (for ns_delegation mode) the ability to update your registrar’s nameserver records for that subdomain.

Every /api/projects/{projectId}/domains... endpoint on this page is a Management API call — host https://retidal.com, authenticated with the trackly_session cookie from a logged-in console user, not a project API key. The redirect endpoint itself (GET https://api.retidal.com/s/{code}, used to verify a domain in the last step below) is the separate Ingestion API — see Authentication for the full two-API split.

GET https://retidal.com/api/projects/{projectId}/domains
POST https://retidal.com/api/projects/{projectId}/domains
hostnamebodystringrequired

The subdomain to onboard, 3–255 characters (e.g. track.yourbrand.com).

displayNamebodystringrequired

A human-readable label shown in the console.

onboardingModebodystring

cloudflare_custom_hostname (Cloudflare manages the hostname directly) or ns_delegation (you delegate the subdomain’s nameservers to Retidal’s Route53 zone).

POST /api/projects/{projectId}/domains returns 409 if the hostname is already occupied by another domain record.

Console → Projects → Settings → Domains is where a domain is created and its provisioning status tracked end to end.

Which provisioning call you make depends on onboardingMode:

POST https://retidal.com/api/projects/{projectId}/domains/{id}/cloudflare/provision

For cloudflare_custom_hostname domains — provisions the Cloudflare-managed custom hostname. POST /api/projects/{projectId}/domains/{id}/cloudflare/provision returns 400 if called on an ns_delegation domain, or if the domain’s current state doesn’t allow provisioning yet.

POST https://retidal.com/api/projects/{projectId}/domains/{id}/route53/provision

For ns_delegation domains — provisions the Route53 hosted zone and returns the nameservers you must point your registrar at. POST /api/projects/{projectId}/domains/{id}/route53/provision returns 400 if called on a cloudflare_custom_hostname domain.

POST https://retidal.com/api/projects/{projectId}/domains/{id}/cloudflare/refresh
POST https://retidal.com/api/projects/{projectId}/domains/{id}/route53/verify

cloudflare/refresh re-checks a Cloudflare-mode domain’s hostname status. route53/verify checks whether your registrar’s NS delegation has propagated and, once it has, triggers the one-shot Cloudflare hostname supply that finishes an ns_delegation domain’s setup.

GET https://retidal.com/api/projects/{projectId}/domains/{id}
DELETE https://retidal.com/api/projects/{projectId}/domains/{id}

DELETE /api/projects/{projectId}/domains/{id} retires the Cloudflare hostname before soft-deleting the record — it returns 502 if the Cloudflare-side retire call fails, so a failed delete does not silently leave an orphaned hostname pointed at Retidal.

A verified custom domain lets short links redirect from your own host, so ad destination URLs carry your brand instead of api.retidal.com. The redirect sets a host-only cookie on that subdomain, which improves attribution continuity for repeat visits on the same device.

It does not link devices. A custom domain’s cookie is scoped to that host and is not shared with your site; connecting a phone to a laptop still depends entirely on both calling identify with the same userId — see cross-device attribution.

  1. Confirm domain status

    Console → Projects → Settings → Domains shows the domain’s status directly. Equivalently, from a browser session already logged into the console (so the trackly_session cookie is sent automatically):

    bash
    curl -s https://retidal.com/api/projects/{projectId}/domains/{id} \
    -H "Cookie: trackly_session=$SESSION_COOKIE"
    # expect: 200 with the domain's status showing fully provisioned — Cloudflare
    # hostname active, or Route53 delegation verified
  2. Confirm redirects resolve on the custom hostname

    bash
    curl -s -o /dev/null -D - https://api.retidal.com/s/{code} | grep -i location
    # expect: HTTP/2 302 — repeat the same request against your own provisioned
    # subdomain instead of api.retidal.com and confirm it redirects identically
    # (see Short links)
  • If DNS/TLS provisioning never completes and nothing sent through the domain arrives at all, work through Events not arriving.
  • If you’re stuck mid-setup with no single clear symptom yet (nameservers not showing as delegated, hostname status stuck pending), work through the health checklist.

Onboarding track.example-brand.com via NS delegation:

POST /api/projects/{projectId}/domains
{
"hostname": "track.example-brand.com",
"displayName": "Example Brand — Tracking",
"onboardingMode": "ns_delegation"
}
POST .../domains/{id}/route53/provision response
{
"ok": true,
"nameServers": [
"ns-1234.awsdns-12.org",
"ns-567.awsdns-34.com",
"ns-890.awsdns-56.net",
"ns-345.awsdns-78.co.uk"
]
}

Point track.example-brand.com’s nameservers at the four values returned above at your registrar, then call route53/verify to confirm delegation and trigger the final Cloudflare hostname supply.

DNS propagation is not instant — calling route53/verify before your registrar has actually applied the nameserver change reads as stuck provisioning, not a Retidal failure; re-check after normal DNS TTL windows (often up to 24–48 hours) before treating it as broken. Separately, deleting a domain (DELETE /api/projects/{projectId}/domains/{id}) retires the Cloudflare hostname first — if that retire call fails, the whole delete fails with 502 rather than leaving an orphaned hostname silently pointed at Retidal after the record is gone from your console.