Skip to content

Websites / Cloudflare

Site Launch Gate

Platform
Websites / Cloudflare
Owner
Website Specialist
Assignee
Jakob
Supports
SEO Specialist, CSM
Needs review — This SOP contains our content but has not been verified by Nick. Treat as a working draft until marked Live.

Last Updated: 2026-06-08 Version: 1.2 Tier: Pre-Launch Quality Gate (MANDATORY)


No Tekton-built client site ships to the client until every item in this checklist is green. This SOP exists because broken tracking on a launched site is invisible — the client sees the site work, they never complain, and then three months later we realize we’ve lost 90 days of attribution data with no way to reconstruct it.

This gate catches tracking failures while they’re still cheap to fix.

When to Use:

  • Before the “ready to ship” handoff to CSM for any new client site
  • Before any major site rebuild or platform migration
  • After adding a new form, lead magnet, or conversion point to an existing site

Owner: Website Specialist (runs the checks), SEO Specialist (signs off), CSM (does not ship until sign-off received) Timeline: 30 minutes to run through. Zero launches without this complete.


Status = GREEN or site does not ship.

A single YELLOW or RED item blocks launch. No exceptions for “we’ll fix it later” — tracking that isn’t working at launch rarely gets fixed after launch.


Run through these in order. Stop and fix anything that isn’t green before moving on.

  • Site property appears in Google Search Console under nick@tektongrowth.com
  • Property shows as Verified (not pending)
  • Tekton service account (seo-brain@core-depth-472801-t2.iam.gserviceaccount.com) is an Owner on the property

How to verify: GSC → pick property → Settings → Users and permissions. Service account email should be listed with Owner role.

2. Custom production sitemap built, compared, and submitted

Section titled “2. Custom production sitemap built, compared, and submitted”

When a site is approved to launch and go live, the same launch pass that flips robots.txt, removes preview noindex, and removes X-Robots-Tag blocks must also build a fully custom production sitemap. Do not rely on old CMS sitemaps, exported WordPress/Yoast sitemap files, or the default Astro sitemap output as the final launch sitemap. Those often include stale CMS paths, wrong hosts, missing hierarchy, thin placeholder routes, or paths that are not actually going live.

  • Build a custom sitemap from the approved pages going live, using the production canonical host.
  • Include only indexable, canonical, 200-status pages that should rank. Exclude preview pages, parked/noindexed sections, form thank-you pages unless intentional, 404s, old CMS utility URLs, and duplicate host variants.
  • Structure the sitemap so search engines understand the page hierarchy: homepage, core service hubs, child service pages, service-area pages, gallery/project pages, blog/resources, contact/conversion pages, and any other approved live sections.
  • Use clean production URLs with trailing-slash/canonical behavior matching the live site.
  • Compare the new custom sitemap against the old/source sitemap before launch. Every valuable old URL must either exist in the new sitemap/live site or have a mapped 301 redirect.
  • Add any needed 301s before launch, then re-check that redirected old URLs land on the correct new canonical page.
  • Verify live custom-domain sitemap XML, not only *.pages.dev or local dist.
  • Submit the final custom sitemap through Search Console API.
  • Shows 0 warnings, 0 errors in GSC Sitemaps view.
  • Submitted via submit_to_gsc.py, not via GSC UI (leaves an audit trail).

Default sitemap URL: use https://<domain>/sitemap.xml when the site exposes the custom sitemap there. If the repo intentionally uses an index file, use https://<domain>/sitemap-index.xml, but the index must still point to the custom production sitemap set, not a blind default generator output.

How to verify submission:

Terminal window
python3 /Users/nick/Projects/scripts/submit_to_gsc.py <domain> --site-url https://<domain>/ --list

Output must show the submitted sitemap with 0/0 warnings/errors.

3. Cloudflare managed robots.txt and crawler permissions are checked

Section titled “3. Cloudflare managed robots.txt and crawler permissions are checked”

This check is mandatory whenever a new site goes live, especially during the launch step where preview noindex, X-Robots-Tag, and robots blocks are removed. Do not rely only on the repo, Pages preview, or *.pages.dev robots file. Cloudflare can inject managed robots content at the active custom-domain zone after the deploy is clean.

  • Confirm whether the production domain is managed by Cloudflare nameservers. Check both apex and www if both resolve.
  • In the active Cloudflare zone, turn off Managed robots.txt / managed AI crawler blocking unless a client-specific approval says otherwise.
  • Double-check crawler permissions for domains managed by Cloudflare nameservers before launch sign-off.
  • After deploy, fetch the live custom-domain robots files, not just the Pages URL:
    • https://<domain>/robots.txt
    • https://www.<domain>/robots.txt when www is active
  • Live robots allows normal crawl with User-agent: * + Allow: / and includes the production sitemap.
  • Live robots does not contain Cloudflare Managed Content blocks for approved AI/search crawlers such as GPTBot, ClaudeBot, CCBot, Google-Extended, Bytespider, or similar, unless Nick/client explicitly approved blocking them.
  • Live robots does not include unexpected Content-Signal restrictions that conflict with the launch policy.

How to verify:

Terminal window
curl -sL -H 'Cache-Control: no-cache' https://<domain>/robots.txt
curl -sL -H 'Cache-Control: no-cache' https://www.<domain>/robots.txt

Block launch if: the repo/Pages robots file is clean but the live custom domain shows Cloudflare managed crawler blocks. That means the active Cloudflare zone is injecting policy at the domain layer. Fix the Cloudflare setting first, then re-check the live custom-domain robots file.

  • Created under Tekton Growth account (accounts/326886214)
  • Displays <Client Name> with a Web data stream for the production URL
  • Measurement ID captured in site config (Astro: site-config.json → tracking.ga4Id; static HTML: direct reference in tracking JS)
  • Entered into clients.json → ga4PropertyId and ga4MeasurementId
  • Visit the live production URL in an incognito window
  • Open DevTools → Network → filter collect
  • Reload the page
  • Confirm a POST to https://www.google-analytics.com/g/collect?...&tid=G-XXXXXXXX&...&en=page_view returns 204

If nothing fires: the gtag script didn’t load (ad-blocker check first — disable and retry; if still dead, config is broken).

  • Open DevTools console on the live site
  • Type window.bctGetAttribution()
  • Should return {utm_source, utm_medium, utm_campaign, ..., landing_page, referrer, submission_page} — may be empty strings on first visit, but the object must exist

If bctGetAttribution is undefined: the tracking JS file isn’t loaded on every page, or it’s loaded from the wrong path.

  • DevTools console on the live site
  • Type typeof window.bctTrackLead
  • Should return "function"

If undefined: the tracking JS is missing the bctTrackLead helper. Copy it from the BCT reference.

8. Every form fires generate_lead on submit

Section titled “8. Every form fires generate_lead on submit”
  • Identify every form on the site (newsletter, contact, lead magnet, waitlist, tool submit)
  • For each form, submit with a test email
  • In GA4 Realtime, confirm a generate_lead event appears within 30 seconds
  • Check the event params include form_name, source_channel, and any UTM values

If missing for any form: grep the repo for the form’s submit handler, verify it calls bctTrackLead('<form_name>') on the success branch. Redeploy.

  • For every API endpoint that creates a lead (typically /functions/api/subscribe.js, /functions/api/contact.ts), confirm it has sendGa4Event wired
  • CF Pages env vars GA4_MEASUREMENT_ID + GA4_MP_SECRET are set on Production
  • Submit a test form while blocking trackers in the browser (use Privacy Badger or uBlock)
  • GA4 Realtime should still show a generate_lead event with source_channel=server

If no server event: env vars missing in CF Pages, OR the MP secret is invalid, OR the API endpoint doesn’t call sendGa4Event. Check CF Pages → Settings → Environment variables first.

  • GA4 Admin → Events
  • generate_lead row shows the “Mark as key event” toggle ON (green)

If not toggled: flip it now. This is what makes the event count as a conversion in reports.

  • GA4 Admin → Product links → Search Console links
  • Shows an active link to the GSC property for this site
  • GA4 → Reports → Acquisition → Search Console traffic — section exists (data takes 24-48h to populate, but the report must exist)

If not linked: GA4 Admin → Product links → Search Console links → Link → pick the property. No API for this — must be done in UI.


If you hit a blocker on any item and cannot resolve within 30 minutes, escalate to:

  • Tracking stack issues (GSC, GA4, MP secret, CF Pages env vars): SEO Specialist, then Nick if unresolved
  • Form handler code changes: Website Specialist (yourself) — fix, redeploy, rerun gate
  • CF Pages access / env var issues: Nick directly (he owns the CF account)

Do not ship a site with any item in the YELLOW/RED state. If the client is pressuring for launch, launch the site WITHOUT announcing it, keep tracking fixes in progress, and inform CSM that the site is live but not client-facing yet.


When all 11 items are green:

  1. Screenshot GA4 Realtime showing both source_channel=client AND source_channel=server for generate_lead after a test submission
  2. Screenshot GSC Sitemaps page showing “0 warnings, 0 errors”
  3. Post both to the client’s launch task in TaskTracker with the comment: “Launch tracking gate: GREEN. OK to ship.”
  4. CSM does not announce the site publicly until this comment is present

  • v1.1 (2026-05-30): Added mandatory Cloudflare Managed robots.txt / crawler-permission check for every new site launch during noindex removal and indexing cutover.
  • v1.0 (2026-04-21): Initial SOP. 10-item pre-launch gate derived from the /gsc-verify skill post-onboarding checklist.