Skip to content
This repository was archived by the owner on Sep 28, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Lane 1 — Google Ads conversion placeholder tag re-verification (2026-08-15)

Item: `d2c8a852ff` — "[unreviewed-by-opus] The funnel's only Google Ads
conversion measurement is dead by construction: placeholder tag"

Branch: `fix/ads-conversion-placeholder-rereverify-2026-08-15-lane1`
Base: `origin/main` at `c62211c` (2026-08-15)

## Verdict

**Finding stays closed — no code change required.** The dead-by-construction
Google Ads conversion tag was removed by PR #172 (`60d045c`, merged
2026-08-13): the worker now generates the tag at request time from
`GOOGLE_ADS_CONVERSION_ID` / `GOOGLE_ADS_CONVERSION_LABEL`, emits it only on
`/brief-requested` when both are configured and well-formed, and emits
nothing otherwise. The CI guard in `scripts/check-site.mjs` makes the
placeholder shape impossible to return. The fix remains intact on both
current main (`c62211c`) and the live deployment.

## Changes since the 2026-08-15 #227/#228 re-verification (base 23e24d6)

No commits since `23e24d6` (#227/#228) touched the ads-conversion surface:
the diff range `23e24d6..HEAD` is empty for `src/worker.js`,
`public/brief-requested.html`, `public/brief-requested.js`,
`scripts/check-site.mjs` and `specs/003-wellness-clinic-launch/tracking-setup.md`.

## Source verification (head c62211c)

- `git merge-base --is-ancestor 60d045c HEAD` → yes.
- `src/worker.js` lines 1350-1383: `googleAdsConversion()` returns `null`
unless both env values are present and match `/^AW-\d{6,15}$/` and
`/^[A-Za-z0-9_-]{10,50}$/`; injection confined to `/brief-requested`
and `/brief-requested.js`.
- `public/brief-requested.html` / `public/brief-requested.js`: no loader,
no placeholder — only the explanatory comment; the script is a static
no-op the worker replaces when configured.
- `npm run check` passes (including the Google Ads guard section).
- `npm test` passes end to end: check-site, headings 6/6, sitemap 7/7,
worker 80/80 (incl. the three ads-tag tests), agent-UI 16/16,
product-contract 8/8, first-viewport 4/4, narrow-viewport — zero
failures across all suites.

## Live verification (2026-08-15)

- `GET https://tinystudio.io/brief-requested.html` → 307 →
`/brief-requested` → 200, strict CSP, zero `googletagmanager` / `AW-`
references (single "gtag" hit is the explanatory comment).
- `GET https://tinystudio.io/brief-requested.js` → 200, static no-op, no
`gtag(` / `dataLayer`.

With the secrets unset, the funnel ships zero tracking rather than a dead
tag — exactly the designed behavior — and the tag activates from env with
no code change the moment the real conversion ID and label are set via
`wrangler secret put`.

## Outcome

Closed, no code change. Full evidence:
`docs/evidence/ads-conversion-placeholder-rereverify-2026-08-15-lane1.md`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# Google Ads conversion placeholder tag — re-verification 2026-08-15 (lane 1)

Item: `d2c8a852ff` — "[unreviewed-by-opus] The funnel's only Google Ads
conversion measurement is dead by construction: placeholder tag"

## Verdict

**Already fixed on main and live — re-verified, stays closed. No code change
was needed.** The dead-by-construction shape was removed by PR #172
(`60d045c`, merged 2026-08-13); the close-out has been recorded by #215
(`0e483ca`, 2026-08-14), #216 (`76ee0e7`, 2026-08-15) and #227/#228
(`23e24d6`, 2026-08-15). This lane (1) re-verified the fix against the
current `origin/main` head (`c62211c`) and the live deployment on
2026-08-15.

## What was dead (pre-#172)

- `public/brief-requested.html` hardcoded the gtag loader with placeholder
`AW-XXXXXXXXX` (from the page's first commit `c90c8a4` / PR #14).
- `public/brief-requested.js` fired the conversion event to the same
placeholder (`AW-XXXXXXXXX/YYYYYYYYYYYYYYYYYYY`).
- The production CSP (`script-src 'self'
https://static.cloudflareinsights.com`) blocked `googletagmanager.com`
entirely, so even a real id pasted in could never load or record.

## The merged fix (PR #172, `60d045c`)

- The conversion tag is generated by the worker at request time from
`GOOGLE_ADS_CONVERSION_ID` / `GOOGLE_ADS_CONVERSION_LABEL`, emitted only
on `/brief-requested` when both are configured and well-formed
(`GOOGLE_ADS_ID_PATTERN` `/^AW-\d{6,15}$/`, `GOOGLE_ADS_LABEL_PATTERN`
`/^[A-Za-z0-9_-]{10,50}$/` — strict patterns, safe to interpolate).
- With either value missing or malformed, the page ships with **no tag at
all** — a dead tag is never served.
- gtag's CSP allowances (`GOOGLE_ADS_CSP`) are scoped to that one noindex
page's response; every other page keeps the strict CSP.
- `public/brief-requested.js` is a documented static no-op; the worker
serves the generated conversion script in its place when configured.
- CI (`scripts/check-site.mjs` "Google Ads conversion tag" guard) refuses
any placeholder or hardcoded gtag in `public/` or `src/worker.js`, and
requires the env-driven wiring to stay wired — the dead-by-construction
shape cannot return.
- `specs/003-wellness-clinic-launch/tracking-setup.md` documents the
`wrangler secret put` steps that activate the tag once the console-side
conversion action exists.

## Source checks on the current head (c62211c)

1. `git merge-base --is-ancestor 60d045c HEAD` → yes, the fix commit is in
the current head. No commit since the #227/#228 close-out
(`23e24d6`, 2026-08-15) touched `src/worker.js`,
`public/brief-requested.html`, `public/brief-requested.js`,
`scripts/check-site.mjs` or `specs/003-wellness-clinic-launch/tracking-setup.md`
(empty diff range `23e24d6..HEAD` for those files).
2. `src/worker.js` lines 1350-1383: `googleAdsConversion()` returns `null`
(emits nothing) unless both env values are present and well-formed; the
loader/script injection is confined to `/brief-requested` and
`/brief-requested.js`.
3. `public/brief-requested.html` carries only the explanatory comment that
the worker injects the tag; no loader, no placeholder.
4. `public/brief-requested.js` is a documented static no-op (8 lines).
5. `npm run check` passes — including the "Google Ads conversion tag" guard
section (placeholder scan, no hardcoded gtag in public files, worker
wiring present).
6. `npm test` passes end to end on this head: check-site, headings 6/6,
sitemap 7/7, worker 80/80 (including the three ads-tag tests: no tag +
strict CSP while unconfigured; injected loader + generated script +
page-scoped CSP when configured; nothing emitted for partial or
malformed config), agent-UI 16/16, product-contract 8/8, first-viewport
4/4, narrow-viewport — zero failures across all suites.

## Live re-verification 2026-08-15

Plain-fetch probes against the live `https://tinystudio.io` (current
deployment of current main):

```
GET https://tinystudio.io/brief-requested.html → HTTP 307 → /brief-requested
GET https://tinystudio.io/brief-requested → HTTP/2 200
content-security-policy: default-src 'self'; img-src 'self' data:;
style-src 'self' https://fonts.googleapis.com; font-src 'self'
https://fonts.gstatic.com; script-src 'self'
https://static.cloudflareinsights.com; connect-src 'self'
https://cloudflareinsights.com; base-uri 'self'; frame-ancestors
'none'; form-action 'self'
body: zero googletagmanager / AW- references; the single "gtag" hit is
the explanatory HTML comment (line 18) — no loader, no event
GET https://tinystudio.io/brief-requested.js → 200, static no-op, no
gtag( / dataLayer
```

The served `/brief-requested` contains no loader and no conversion event,
and carries the strict CSP — the page-scoped `GOOGLE_ADS_CSP` is not
applied because the env values are unconfigured, so no tag is emitted.
This is exactly the designed behavior: with the secrets unset, the funnel
ships zero tracking rather than a dead tag, and the tag activates the
moment the real conversion id/label are set via `wrangler secret put`
(per `specs/003-wellness-clinic-launch/tracking-setup.md` §3) — without
any code change.

## Repro steps

1. Source guard: `npm run check` — the "Google Ads conversion tag" section
fails if any placeholder or hardcoded gtag reappears in `public/` or
`src/worker.js`, or if the env-driven wiring is removed.
2. Worker behavior: `node --test scripts/test-agent-worker.mjs` — the ads
tests cover unconfigured / configured / partial-malformed config.
3. Live probe:
`curl -s https://tinystudio.io/brief-requested | grep -c googletagmanager`
→ 0, and the response carries the strict CSP (no `googleadservices` /
`googletagmanager` allowances) while the secrets are unset.

## Close-out

The item as stated — "The funnel's only Google Ads conversion measurement
is dead by construction: placeholder tag" — is **closed against current
main and live**: the dead-by-construction shape was removed by PR #172
(`60d045c`), the CI guards in `scripts/check-site.mjs` make the placeholder
shape impossible to return, `npm run check` and `npm test` pass on the
current head (`c62211c`, zero failures), and the live site serves
`/brief-requested` with no tag, the static no-op script, and the strict
CSP while the env values are unconfigured — nothing dead is shipped, and
the tag activates from env with no code change the moment the real
conversion ID and label are set.
Loading