First-Party CNAME Proxy

By default the tracker loads from omni.karmaflow.ai. Ad-blockers (uBlock Origin, Brave, Pi-hole, etc.) ship blocklists that include known analytics hosts — your traffic from blocker-using visitors silently disappears. A first-party CNAME — routing the tracker through a subdomain on the customer's own domain — moves the request to a hostname the blocker has no reason to block.

Conceptual Setup

  1. Customer adds a DNS CNAME: analytics.customer.exampleomni.karmaflow.ai.
  2. Their CDN/load-balancer (if any) forwards Host: analytics.customer.example to our Cloud Run service.
  3. The customer updates the snippet src to https://analytics.customer.example/p/SITE_KEY/k.js.
  4. The tracker auto-detects the new origin from document.currentScript.src and uses it for /collect and /p/.../container.json too — no separate config.
  5. Requests look like they're going to the customer's own domain, so blocklists don't fire.

Provisioning the CNAME

Open Web Analytics > Custom Domain for the site. The UI walks you through:

Step 1: Choose Your Subdomain

A short, generic name is best (analytics, metrics, track). Avoid names that obviously hint at analytics from a blocklist's perspective (google-analytics, gtm, etc. — those are themselves blocked).

The UI checks the subdomain isn't already in use by another tenant before letting you proceed.

Step 2: Add the DNS Record

You'll be shown two records:

analytics.customer.example  CNAME  cnames.karmaflow.ai.
_karma-verify.customer.example  TXT  karma-verify=<one-time token>

Step 3: Verify

Click Verify DNS. The server runs:

DNS propagation can take a few minutes. The UI shows the current resolution state and re-checks on a 30-second loop.

Step 4: TLS Cert

Once DNS verifies, the certificate manager auto-provisions a cert for the new hostname via Google Cloud Load Balancer's managed certificates (which use Let's Encrypt). This takes 10–60 minutes depending on LB warm-up.

You can poll status from the UI; once the cert is active, the new hostname starts serving 200 OK.

Step 5: Update the Snippet

The site's snippet automatically switches to the new hostname on the Sites > Snippet page — copy + paste the updated <script src=...> onto the customer site. The new src looks like:

<script async src="https://analytics.customer.example/p/16efa189f624da8c/k.js"></script>

Once deployed, the tracker reads document.currentScript.src, sees the new host, and routes every subsequent call there.

What the Server Does Differently for CNAME Requests

Almost nothing. The HTTP handlers don't look at Host for anything except logging. The key requirement is that Cross-Origin-Resource-Policy: cross-origin is set on every public asset (k.js, container.json, /collect/*/p) — that header was always required for the third-party-domain case and stays required for the CNAME case (the customer's own domain is still a cross-origin host relative to wherever the customer's main app runs).

The Access-Control-Allow-Origin header echoes the request's Origin header dynamically, so the same allow-list logic works whether requests come in via omni.karmaflow.ai or via the customer's CNAME.

Verifying the Tracker Routes Through the CNAME

Open DevTools on the customer site. With the CNAME live, you should see:

If any of those still go to omni.karmaflow.ai, the snippet wasn't updated.

If /collect/ returns from omni.karmaflow.ai but /p/.../k.js correctly loads from analytics.customer.example, there's a cached old version of the tracker still running. The 5-minute cache on k.js clears within ~5 min for visitors who hard-reload; gradual rollout is fine for the rest.

Rolling Back

To stop using the CNAME without deleting the configuration:

  1. Update the snippet back to omni.karmaflow.ai.
  2. The CustomDomain record stays in place (so verification doesn't need to redo).
  3. The DNS record can stay too — no traffic, no harm.

To fully unprovision: delete the CustomDomain record from the UI. The cert is left in place for 24 h in case you change your mind, then auto-revoked.

Edge Cases

Brand-name domains and EV certs

If the customer uses EV (Extended Validation) certs, our managed cert won't match their certificate authority. You can either:

Cloudflare proxying

If the customer's domain is behind Cloudflare with the orange-cloud proxy on, Cloudflare strips the CNAME and serves directly from their edge. Disable the proxy for the analytics subdomain ("DNS only" / grey cloud) or use Cloudflare's CNAME flattening rules to ensure the request reaches us.

Apex domain (e.g. customer.example without subdomain)

CNAMEs at the apex aren't legal per the DNS spec. Use analytics.customer.example, never customer.example. If the customer absolutely needs apex, they need ALIAS / ANAME records (provider-specific) or Cloudflare's CNAME flattening.

Subdomain takeover risk

If the customer ever deletes the CNAME record but leaves the verification TXT, then later registers a different cnames.karmaflow.ai mapping under a different tenant, the new tenant would inherit the existing TXT verification. The UI defends against this by requiring the TXT to be re-verified every 90 days.

Privacy Implications

A first-party CNAME makes requests look first-party for the browser too. Cookies for analytics.customer.example are sent by the browser even though the server treats them as anonymous. The tracker explicitly sends credentials: 'omit' on fetch, but sendBeacon always sends credentials — this is one of the reasons we use a text/plain blob to avoid CORS preflight regardless of CNAME setup.

If the customer is in a privacy-sensitive jurisdiction (DACH, etc.), the CNAME effectively moves the data path closer to first-party — many privacy frameworks treat first-party analytics differently from third-party. Talk to legal before claiming this changes the compliance posture, though.