How This Site Is Tracked
I set up measurement and consent on other people's websites, so this one should survive the same scrutiny. Below is everything it does, from the moment the page starts loading to the events GA4 receives, and how you can check it yourself.
In short: a small consent banner I wrote myself, Consent Mode V2 in advanced mode, one Google Tag Manager container, six events in Google Analytics 4, and a Content Security Policy that only lets Google's tag domains in.
The Setup
The site is built with Astro and served as static files from Cloudflare Pages. There is no consent platform and no tracking plugin. Everything to do with measurement lives in three small files:
consent.tsis the first script in the page’s<head>. It sets the consent defaults, applies a stored choice, and loads Google Tag Manager.ConsentBanner.astrodraws the banner and records your choice.analytics.tspushes the events as you browse.
- consent.ts Sets every Google signal to denied
- Stored choice Applied from local storage, if there is one
- Google Tag Manager Loads and fires the GA4 tag
- ConsentBanner.astro Shows the banner, then analytics.ts pushes events as you browse
- Analytics allowed Full GA4 hits with the _ga cookie
- Analytics denied Cookieless pings, no identifiers
Consent Comes First
Consent Mode depends on order. consent.ts is the first script on every page and also the script that loads Google Tag Manager, so no Google tag can run before it has set the default state:
| Signal | Default |
|---|---|
analytics_storage |
Denied |
ad_storage |
Denied |
ad_user_data |
Denied |
ad_personalization |
Denied |
It also sets wait_for_update to 500 ms and turns on ad data redaction. If you have chosen before, your choice is read from local storage and applied straight away, so a returning visitor never sends a page view with the wrong state.
This is advanced mode. Google Tag Manager always loads, and until you allow analytics, GA4 sends cookieless pings without identifiers. I get an aggregate picture of traffic and nothing is stored on your device. Basic mode, which blocks Google entirely until consent, is stricter, and it is the right choice for sites that handle sensitive data, like the dental practice I set up tracking for.
The Banner
The banner is a small Astro component: about 60 lines of TypeScript and some CSS in the site’s own design. Writing it myself kept third-party scripts off the page and let me get the details right:
- Reject is as easy as accept. Both buttons sit side by side with the same weight, which is what European regulators expect.
- Analytics and advertising can be allowed separately under Customize.
- Every choice sends a Consent Mode update and a
consent_updateevent the moment you click, without waiting for the next page. - Turning analytics off deletes any
_gacookies already set. - Cookie settings in the footer reopens the banner on every page.
- The choice expires after 12 months, and then the banner asks again.
The Events
Page views alone don’t tell me whether the site does its job, which is helping people decide to work with me. So the site pushes six events to the data layer, each tied to a question I want answered:
| Event | When it fires | Parameters |
|---|---|---|
cta_click |
A main call-to-action button is clicked | cta_text, link_url |
email_click |
An email link is clicked | link_text |
package_click |
A package link on the Hire page is clicked | package |
contact_submit |
The contact form is sent successfully | None |
case_study_read |
The last section of a case study scrolls into view, once per page | case_study |
tracking_check |
The Tracking Check returns a report | issues, warnings |
The names are generic and use the snake case GA4 expects. Google Tag Manager picks up each one with a custom event trigger and forwards it to GA4. contact_submit and email_click count as key events, since they are the closest thing this site has to a lead.
A case study counts as read when its final section reaches the screen. A fixed scroll depth like 90% would mean something different on a short page than on a long one, so this keeps the number comparable between case studies.
What I Leave Out
What a setup refuses to collect matters as much as what it collects.
- Nothing from the contact form:
contact_submitcarries no name, email address, or message. The message goes from a Cloudflare function straight to my inbox and never touches the data layer. - No addresses from the Tracking Check:
tracking_checkcarries only how many issues and warnings were found, never the page that was checked. - No advertising tags: the site doesn’t run Google Ads or any other pixel. The advertising choice exists so the four Consent Mode signals are always set correctly.
- No test traffic: Google Tag Manager only loads on
studio.sultankautsar.com, so local previews and staging deployments never reach GA4. The consent banner and the data layer still work there, which keeps them easy to test. My own visits to the live site carrytraffic_type: internal, and a GA4 data filter removes them from reports. - No third-party embeds: fonts, images, and the video are served from the same domain, so no other company learns about your visit.
Security Headers
Tracking scripts are someone else’s code running on your page, so the site limits what they can do with a Content Security Policy, set in Cloudflare’s _headers file:
- Scripts may come only from this site and Google Tag Manager.
- Data may be sent only to this site and Google’s analytics and tag domains.
- Styles, fonts, and media may come only from this site.
- Framing is blocked entirely, and forms may only submit to this site.
If a tag ever tried to load a script from anywhere else, the browser would refuse it. The same file adds HSTS, X-Content-Type-Options, a strict referrer policy, and a Permissions Policy that turns off the camera, microphone, and location.
Check It Yourself
You don’t have to take any of this on trust. Open your browser’s developer tools on this page:
- In the Console, type
dataLayerto see the consent default, any update, and every event pushed so far. - In the Network tab, filter for
collect. Before you choose, thegcsparameter readsG100, meaning everything is denied. After you accept all, it readsG111. - In Application, look at local storage for the
consentkey, and at cookies for_ga, which only appears once you allow analytics. - In the response headers of the page itself, read the
Content-Security-Policy.
The privacy policy covers the same setup in legal terms. If you want your own site to hold up to this kind of inspection, get in touch.
Related Notes
- Consent Mode V2 Consent Mode V2 set up by a Google Tag Manager expert, so the site follows GDPR and other privacy rules and the data your decisions depend on still holds up.
- Google Tag Manager Clean up, speed up, and secure your Google Tag Manager container: GTM audits, server-side tagging, and a data layer the site and the container can both rely on.
- Google Analytics 4 Google Analytics 4 setup and full customer-journey tracking by a Google Tag Manager expert, built so the reports hold up when someone asks them a hard question.
Next step
Have a project in mind? Let's talk.
Tell me what you have and what you need. I'll usually reply within one working day with how I'd approach it.