Case: putting cardonaseo.com into production without relying on the dashboard
By Carlos Alberto Cardona B. · published
This case is this very site. I tell it because a domain migration is the fastest way to disappear from Google, and because everything I claim here you can check with one command.
It's also the case closest to what a team asks for when it says «site migration, redirects, JavaScript rendering»: steps measured before and after, and what wasn't measured written down as pending.
What needed solving
On the morning of September 15, cardonaseo.com didn't resolve: the Cloudflare zone had zero DNS records. The only live host was the platform's URL, and it served noindex, as it should.
There was something worse than a dead domain. Base44 serves crawlers a template of about 350 words that is not the page's content, and its sitemap and llms.txt included /gracias and /privacidad, two noindex pages. Two files from the same site saying different things about the same URLs.
DNS: zero records in the zone; www returned NXDOMAIN.
Rendering: all 15 routes served the same body to the crawler; the real content only appeared in the rendered DOM.
Sitemap and llms.txt: listed noindex pages and described each one with a template («Blog Core Web Vitals page»).
Social metadata: zero Open Graph tags, so a link shared on LinkedIn came out without title or description.
What was done
First a read-only phase: DNS, zone, headers, HTML requested with the Googlebot user agent, raw HTML and rendered DOM. Nothing was changed until the inventory existed. Then the changes, one by one, each with its measurement.
I confirmed through RDAP the registrar and the registration date before touching anything: the plan said IONOS and the registry said Cloudflare.
I unlinked the domain from the platform through the documented path (the dashboard), not through an undocumented endpoint that could delete instead of unlink.
I set the Worker up as a custom domain and not as a route: with the origin in another Cloudflare zone, a route doesn't work. I closed workers.dev and the preview URLs.
My own prerender: the build generates one HTML file per route from the real components and fails if an H1 doesn't match or code leaks in. The Worker rewrites /route to /route/index.html without changing the URL.
301 from www to the apex and from trailing slashes; real 404 for every route outside the manifest; sitemap and llms.txt derived from the same manifest, with no noindex pages.
Open Graph and Twitter Card in the served HTML, and structured data with stable @id so pages can reference each other (commit of Sep 17).
$ curl -sI https://www.cardonaseo.com/ | grep -i locationlocation: https://cardonaseo.com/ (301)$ curl -sI https://cardonaseo.com/portafolio/ | grep -i locationlocation: https://cardonaseo.com/portafolio (301)$ curl -s -o /dev/null -w "%{http_code}" https://cardonaseo.com/no-existe-123404$ curl -s -A "Googlebot" https://cardonaseo.com/ | wc -w574 visible words, 1 <h1>, 3 JSON-LD blocks
How it turned out later
Four days after indexing there's no traffic to show, and I won't dress it up. What there is: edge health and the status of every discrepancy I left open on September 15.
9,820
requests served by the Worker from September 15 to 19
Cloudflare GraphQL Analytics, Worker cardonaseo-edge-router
0
errors in those requests
read on Sep 19, 2026
0.93 ms
median CPU per request (p99: 3.65 ms)
14 days · Cloudflare
Daily requests to the cardonaseo.com Worker since going live
Includes crawlers, browsers and my own verifications. It isn't human traffic: it's proof that the edge answers.
Source: Cloudflare GraphQL Analytics, Worker cardonaseo-edge-router · read on 2026-09-19
Show the chart values
| Week of | Requests |
|---|---|
| 2026-09-15 | 1060 |
| 2026-09-16 | 1760 |
| 2026-09-17 | 1700 |
| 2026-09-18 | 3140 |
| 2026-09-19 | 2160 |
The 7 discrepancies from the Sep 15, 2026 audit and their status on Sep 19, 2026
| Discrepancy | Reading on Sep 15 | Status on Sep 19 |
|---|---|---|
| Sitemap | Served with 200; GSC said «couldn't be read» | Served with 200 and authoritative header (curl). GSC reading: pending confirmation in the interface |
| robots.txt | Served with 200; GSC said «no file» | Served with 200 and the correct Sitemap line. GSC report: pending |
| Home page indexing | API: «crawled, not indexed». Interface: «is on Google» | Confirmed: the home page has impressions in the GSC API since Sep 15 |
| Analytics beacon injected at the edge | Present in what's served, absent at the origin | Pending: origin unconfirmed; affects the privacy policy |
| Assets and API under the domain | Googlebot requested them while rendering; unmeasured | Pending: measure what the Worker answers |
| noindex on the platform URL | Two contradictory readings the same day | Closed: historical, no impact |
| Open Graph | Zero tags on all 15 routes (Sep 17) | Resolved: in the served HTML since the Sep 17 commit |
Google Search Console (API), propiedad de dominio · Aug 20 to Sep 17, 2026 · 10 impressions and 1 click in total · four days since indexing
| Page | Clicks | Impressions | Average position |
|---|---|---|---|
| / | 1 | 2 | 1.0 |
| /sobre-mi | 0 | 3 | 4.3 |
| /blog/core-web-vitals | 0 | 5 | 77.6 |
| /portafolio/seo-app-react-base44 | 0 | 1 | 5.0 |
| /portafolio/investigacion-de-keywords | 0 | 1 | 7.0 |
| /blog/mi-pagina-no-aparece-en-google | 0 | 1 | 7.0 |
| /auditoria-seo | 0 | 1 | 100.0 |
What I learned, mistakes included
A text search over a configuration file returned an API key in plain text in the session log. Nobody used it, but it was written down: the new rule is to search by server name, never by whole file, and to rotate the key instead of waiting.
A script from the read-only phase wrote five files inside the repository tree while the report said «nothing was changed». The data wasn't affected, but the sentence was false. Now temporary files go outside the repo, always.
And an assistant claimed that clicking «Verify» on the platform had recreated the DNS records. It was false: what wrote DNS was linking the domain, at a different hour. What a dashboard, or an assistant, says is not evidence until the API confirms it.
If you want to check it yourself
Everything above answers from your terminal. If something doesn't match, write to me: I'd rather hear it from you than from Search Console.
curl -sI https://www.cardonaseo.com/ | grep -iE 'HTTP|location'→ 301 to https://cardonaseo.com/curl -s https://cardonaseo.com/sitemap.xml | grep -c '<loc>'→ exactly the indexable pages, without /gracias or /privacidadcurl -s -A "Googlebot" https://cardonaseo.com/portafolio | grep -c "<h2"→ the real headings, not a template
The same method, applied to a client's site, is in the case of the React app that Google received empty.
How I decided what to sell before publishing this site: the keyword research.
This is the first thing I check in the free diagnosis.
What I can't claim
I don't claim traffic: it's 10 impressions in four days. I don't know who wrote the DNS records that appeared in the zone in the early hours of September 15: the token had no access to Cloudflare's audit log, and I wrote that down instead of assuming.
I don't claim that Google has already read the sitemap either: the server delivers it correctly, but the Search Console report gets re-read in the interface, which the API doesn't expose.
Next measurement
The dates are written before the data exists. If I haven't updated this page by then, call me on it.
| Date | What gets measured |
|---|---|
| Re-read the 7 discrepancies; 30-day impressions; sitemap and robots reports in the GSC interface |