GA4 not showing data? The full checklist
Google Analytics 4 shows nothing. The tag looks installed, the property exists, and the reports are empty. This is one of the most common problems in analytics and one of the most badly explained, because the usual advice is “wait 48 hours” — which is sometimes right and often a way of avoiding the actual diagnosis.
What follows is the full checklist, in the order worth checking, written after debugging exactly this on my own site. Two of the four failure modes below were mine.
What actually happens between a pageview and a GA4 report
First, understand what has to happen
Between someone loading your page and a number appearing in a report, five things happen. Knowing them turns “GA4 is broken” into a specific question:
- Your HTML loads, containing the gtag snippet.
- gtag.js downloads from googletagmanager.com and defines the
gtag()function. - A beacon fires — a request to
google-analytics.com/g/collectcarrying your measurement ID. - Realtime updates, usually within 30 seconds.
- Standard reports process, taking 24 to 48 hours.
Each step can fail independently, and each fails in a way that looks identical from the GA4 interface: an empty report.
Debugging order — stop at the first failure
Step 1: Is the tag actually on the page?
Obvious, and still the most common cause. Open your live site, press F12, go to the Console tab and paste this:
document.documentElement.innerHTML.includes('G-XXXXXXXXXX')
Replace the ID with your own. true means the tag is present in the rendered page.
If it returns false, nothing else in this article matters — deploy the tag first. Check every page template too, not just the homepage. On my site the tag was missing from all 49 pages, because I had added the property in GA4 and never added the snippet to the HTML. Creating a property does not install anything.
Step 2: Is a Content Security Policy blocking it?
This one is invisible unless you look for it, and it is what caught me.
A Content Security Policy is a security header that tells the browser which domains are allowed to load scripts, send data, or fetch images. It is genuinely worth having. It will also silently break analytics if the policy does not name Google’s domains.
Open F12 → Console and look for red errors mentioning “Content Security Policy”. GA4 needs two directives:
| Directive | Must allow | Why |
|---|---|---|
script-src | www.googletagmanager.com | to download gtag.js |
connect-src | *.google-analytics.com | to send the beacon |
www.google-analytics.com. Depending on the visitor’s location it may use region1.google-analytics.com or another regional host. If your policy names only one, visitors from other regions are dropped silently while your own visits work fine — which is a genuinely confusing failure. Use the wildcard https://*.google-analytics.com.
My policy allowed region1 only. Worse, I had also blocked scripts.clarity.ms, which meant Microsoft Clarity had been installed but collecting nothing for weeks without a single visible symptom.
Step 3: Does the beacon fire, and where does it go?
This is the decisive test. F12 → Network tab → type collect in the filter → reload the page.
| What you see | What it means |
|---|---|
| A request returning 204 | Data reached Google. 204 means “accepted, no content to return” — the correct response. |
| Request blocked or failed | CSP or an ad blocker. The Console will name which. |
| No request at all | gtag never ran. Go back to step 1. |
Then click the request and read the tid parameter in the query string. That is the measurement ID receiving the data. If it is not yours, something else is tracking your site — a plugin, a theme, or an edge-injected tag such as Cloudflare Zaraz — and you are watching an empty property while data flows elsewhere.
tid values that all belonged to Google, wondering why none matched mine.
Step 4: Realtime, not Reports
These are two different systems and people conflate them constantly.
| Realtime | Standard reports | |
|---|---|---|
| Delay | ~30 seconds | 24–48 hours |
| Use it to | confirm tracking works | analyse behaviour |
| Empty means | something is broken | possibly just processing |
So “wait 48 hours” is bad advice as a first response. If Realtime shows you while you are on the site, everything works and the reports will populate. If Realtime is empty while you are actively browsing, waiting changes nothing.
One more thing worth knowing: GA4 cannot backfill. It only records from the moment the tag goes live. Traffic before that is gone permanently, which is why installing analytics on day one matters more than configuring it perfectly.
Step 5: Exclude yourself
Once data arrives, your own visits will distort it badly on a low-traffic site. If you get 40 visits a month and you check the site daily while working on it, most of your analytics describes you.
In GA4: Admin → Data Streams → your stream → Configure tag settings → Define internal traffic. Add a rule matching your IP address and leave traffic_type as internal, because that exact value is what the built-in filter looks for.
Note that most home connections use dynamic IP addresses that change periodically, so the rule can silently stop matching. Worth re-checking every few weeks.
Do you need Google Tag Manager?
Probably not, and the naming makes this confusing. The gtag snippet loads from googletagmanager.com, which makes people think they have installed GTM. They have not. Tag Manager has its own container ID beginning GTM-; a GA4 measurement ID begins G-.
GTM exists so non-technical marketers can add tracking without touching site code. If you control your own code and have one or two tags, it adds a layer of indirection for no benefit. It becomes genuinely worthwhile when you manage tags across client sites, run several ad platforms, or need someone non-technical to add tags safely.
The short version
- Confirm the tag is in the rendered HTML — via Console, not View Source
- Check the Console for CSP errors, and allow both
googletagmanager.comand*.google-analytics.com - Confirm a
collectrequest returns 204, and thattidis your ID - Test in Realtime; reports lag by a day or two
- Exclude your own IP, and remember to set the filter to Active
Related: which metrics actually matter once data arrives, what belongs in an SEO report, and check your page setup with the free analyzer.