GA4 Setup from Scratch — A Pragmatic Walkthrough
Property, data stream, consent mode, conversions and a sane event taxonomy. Skip the bloat.
- Step 01
Create the property
In the Admin panel, create a new GA4 property. Pick the reporting time zone that matches your finance close, not your office — it'll save you a quarter-end argument later.
Currency: set to the currency your revenue is reported in, not the visitor's currency. GA4 will not convert historical data if you change this later.
- Step 02
Add a web data stream
Enable Enhanced Measurement, then turn off the events you don't actually want. Defaults that are usually noise:
scroll— fires on 90% scroll, drowns out real signals.video_progress— only useful if video is core to the experience.file_download— keep if you publish PDFs/whitepapers; off otherwise.
- Step 03
Wire GTM
Install the GTM container in
<head>. Use the official snippet — do not lazy-load it; consent mode depends on it being available early.// GTM container snippet — top of <head> (function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start': new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0], j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f); })(window,document,'script','dataLayer','GTM-XXXXXXX');In GTM, create one GA4 Configuration tag firing on All Pages, then one GA4 Event tag per custom event. Do not enable "Send a page view event" on the Config tag if you're pushing your own
page_viewfrom the dataLayer (you'll double-count). - Step 04
Consent mode v2 (required in EU/UK)
Set default consent before GTM loads:
<script> window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('consent', 'default', { ad_storage: 'denied', ad_user_data: 'denied', ad_personalization: 'denied', analytics_storage: 'denied', wait_for_update: 500 }); </script>Then call
gtag('consent', 'update', {...})after the user chooses. - Step 05
Define your event taxonomy
Pick a verb-noun pattern and stick to it:
wallet_funded,p2p_send_completed,merchant_pay_completed. Document it in a spreadsheet shared with engineering. - Step 06
Set conversions
Mark only the events that map to revenue or product-qualified leads. For a wallet, that's
wallet_funded,p2p_send_completedandmerchant_pay_completed— notpage_view. - Step 07
Cross-domain and subdomain
If you have
app.example.comandwww.example.com, configure them as one data stream with cross-domain measurement to preserve session continuity. - Step 08
Validate with DebugView before you ship
Use the GA Debugger Chrome extension or
?_dbg=1URL parameter, open Admin → DebugView, and walk every critical flow. If you can't see the event there, it isn't being recorded.