Wire in Google Analytics
Counting visits, with the one private page counted but never named.
The tag loads on every page in production and never in development, so the reports are visitors rather than the person building the site.
/privacy says what it does in plain words — a cookie, a random identifier,
which pages you opened, roughly where you are, what device — and says that
Google holds the underlying records on their terms. That section is a claim
about this code and has to stay true of it.
The holocron is counted, not named
The page is private and kept out of every index. Sending its address in a
pageview would give away by measurement what the headers and the sitemap are
careful not to say, so it reports as /(private). A number does not need a
name.
That took more than passing a different path. The tag's own automatic pageview
reads window.location at the moment it fires, which on a client-side
navigation is before anything could intervene — so it is off
(send_page_view: false) and every pageview is fired from analytics.tsx
instead. The scrubbed location is set rather than passed, because a scroll or
an outbound click carries a page_location too and those would have leaked the
real path on their own.
Referrer-Policy: no-referrer went on the same path in next.config.ts.
Nothing there links off-site today, which is exactly when to set it — the day
something does is not the day anyone remembers. That also answers part of
finding 3 in SC-21, for one route rather than the site.
Outstanding
One switch in the GA property, not in this repository: Enhanced Measurement's "page changes based on browser history events" has to be off. Left on, the tag keeps firing its own pageviews from the real URL on top of ours and the scrub is decoration.
Worth confirming in Realtime after the next deploy that a holocron visit shows
as /(private). That has not been observed yet — the headers and the tag
loading were checked against a production server, the reports were not.
Michael found it reporting nothing, 20 September
The property showed "No data received from your website yet" and zero active users in the last thirty minutes. Realtime is not a lagging report — a visit appears in it immediately — so this was never Google catching up.
The cause was in this repository. Google's snippet defines its shim as
function gtag(){dataLayer.push(arguments);}, and analytics.tsx was pushing
an array holding the same values instead. gtag.js reads its queue expecting
the arguments object, so every command sat in the queue unread. Nothing
errored, no request failed, the tag loaded exactly as it should, and nothing
arrived at the other end. The page looked perfect throughout, which is what
made it invisible — the same failure mode check:meta exists to catch in the
head.
Fixed by calling through Google's own shim, defined in the effect if the tag
has not landed yet. That also settles an ordering problem hiding behind it: the
tag loads afterInteractive while the first pageview fires on mount, so it was
being handed to something that did not exist yet.
What is still unproven. The tag shipped at 18:17 and this bug landed at
18:55, so there were thirty-eight minutes when the implementation was correct
and the reports were still empty at 18:45. That may only mean nobody opened the
production site in a browser during it. It may not. Worth ruling out a privacy
extension blocking googletagmanager.com before calling this closed — the
measurement ID is right and the script tag is in the page, so if a request
still never leaves the browser, something local is stopping it.
The test is a browser, not a curl: load the site, Network tab, filter
collect, and look for a request to google-analytics.com/g/collect coming
back 204.
Confirmed working, same day
Michael copied a real collect request out of the browser. It carries
tid=G-HLLDG0N99T, en=page_view, dl=https://scofti.com/ and dt=Scofti,
with an origin and referer of the live site — the pageview this file fires,
leaving the browser and reaching Google.
_fv=1 and _ss=1 on that request say it was the first hit ever recorded from
that browser, which closes the question left open above: nothing was arriving
before, and no local extension is blocking anything. The shim was the whole
fault.
The request was read, not replayed. Sending it again would have put a pageview in the reports that nobody made, and a visit nobody made is an invented figure like any other.
Still worth one look in the reports: one page_view per page rather than two.
Two would mean Enhanced Measurement's history-event pageviews are back on and
firing alongside these.
The scrub, observed
Realtime, the same day: views by page title read (private) 3 and Scofti 2.
The browser tab said "Holocron — Scofti" at the time. The page is counted and
does not name itself, which is the whole of what this ticket set out to do and
the one thing listed above as unobserved.
No duplicates either: page_view came to 5 events against 5 views. Enhanced
Measurement's history-event pageviews are off and staying off — left on, that
number would be roughly double.
One thing that report does not show is the page location, only the title.
page_location is set in the same call, so it should be scrubbed with it, but
seen is seen and inferred is not: confirming it needs a report by page path,
where the holocron has to read /(private) and never /holocron.