DexioView only
Sign inMake a copy

Dexio / how-we-build-dexio / site

Google Analytics with a consent banner only where it is required

How dexio.wiki and app.dexio.wiki measure visits and sign-ups. The site itself: astro-marketing-site. How its pages get found: agentic-seo-content-engine.

This is how we built it and why. It is not legal advice; check the rules that apply to you.

What it is

Why it is built this way

How to build it

  1. Write the time-zone test:

    var ASK = /^(Europe\/|Arctic\/Longyearbyen$|Atlantic\/(Azores|Canary|Faroe|Madeira|Reykjavik)$|Africa\/Ceuta$|Asia\/(Nicosia|Famagusta)$|America\/(Cayenne|Guadeloupe|Marigot|Martinique|St_Barthelemy)$|Indian\/(Mayotte|Reunion)$|(CET|EET|MET|WET|GB|GB-Eire|Eire|Iceland|Poland|Portugal)$)/;
    function mustAsk() {
      try { return ASK.test(Intl.DateTimeFormat().resolvedOptions().timeZone || ""); }
      catch (e) { return true; }   // cannot tell, so ask
    }
    

    Europe/* alone misses parts of the EU: the Canaries, Madeira, the Azores, Ceuta, Cyprus, Réunion, Mayotte, French Guiana and the French Caribbean all have other time zone names.

  2. Trim what the tag reads, before it loads:

    var KEEP = /^(utm_[a-z]+|gclid|gbraid|wbraid)$/;
    gtag("config", ID, { page_location: trimmedLocation(), page_referrer: trimmedReferrer() });
    

    trimmedLocation keeps the origin, the path and the KEEP parameters. trimmedReferrer returns just the origin when the referrer is your own domain.

  3. Write load() and stop(). load() sets window["ga-disable-" + ID] = false and injects gtag.js once. stop() sets it to true and deletes _ga and _ga_<id> both on the host and on the parent domain. If the script fails to load (a blocker), fire an event, so a page that waits on analytics moves on at once.

  4. Wire the banner with data attributes, so any page can carry it: buttons with data-consent="granted" or data-consent="denied" inside #consent, and any link with data-consent-open to reopen it. Give Accept and Decline the same button style.

  5. Include the script in production builds only (in Astro, behind import.meta.env.PROD), so development never sends hits.

  6. Record sign-ups with a hop. After a new account, redirect through /joined, which sends sign_up with the method (password, Google or GitHub) and moves on: at most 1.5 seconds, and at once if the tag failed or consent was declined. Skip it for invited teammates, who are not acquisition.

  7. In GA4, turn Google signals off, link Google Ads with personalized advertising off, mark sign_up as a key event and remove the value GA fills in for it, so conversions carry no made-up money. In Ads, make the imported sign-up the primary conversion.

  8. Say all of this in the privacy policy, and change the policy whenever the tag changes.

Verify

In headless Chromium with Google's requests intercepted:

Pitfalls