Learning Google Analytics 4
Google Analytics 4 counts every user interaction as an event, and every one of its reports is built on that single idea. If you take one thing from this lesson, take this: the standard reports and the explorations are two separate engines, and the data retention setting limits only the second one.
- Lesson 12 of 15
- Intermediate
- Free, no signup
The four GA4 steps, in this order
Most people start at the third step and then complain about the numbers.
-
1
Install the tag and test it
Check in Realtime or DebugView that events actually arrive
-
2
Mark the key event
The action that matters to the business, not every click
-
3
Check data retention
Two months or 14; it limits explorations only
-
4
Link Search Console
Then publish its report collection from Library
None of these steps brings traffic. Analytics is a tool for seeing, not for growing.
Last checked: Facts and tool names in this lesson are re-checked against their sources on this date.
What exactly does GA4 count?
In GA4 the unit of measurement is the event: a page loading, a link click, a video starting, a purchase completing. Even system behaviour is an event, such as an app crashing. Earlier versions of Analytics treated a pageview and an event as two different things; here there is only one thing, and everything else is a name for it.
Events arrive in four kinds, and knowing those four ends half the confusion. Two are collected for you: automatically collected events, which arrive with the tag, and enhanced measurement events, which arrive when that option is on. Two you have to implement: recommended events, which have predefined names and parameters, and custom events, which you define yourself.
And there is one sentence in Google's documentation that changes the whole plan: custom events do not show up in most standard reports, so you need custom reports or explorations for meaningful analysis. Which means the moment you decide to create a custom event, you are also deciding to build its analysis yourself. Google's own advice is to create custom events only when no other event works for your use case.
Any event can become a key event: you mark the action that matters to your business so it is reported separately. And to check whether an event actually arrived there are two places: the Realtime report, which shows events triggered in the last 30 minutes, and DebugView, which shows every event from one user and exists for testing. If you see nothing in either after installing the tag, your problem is not in the reports; it is in the installation.
Four kinds of event, and which ones are your job
-
no work
Automatically collected
They arrive with the tag
-
one toggle
Enhanced measurement
Collected when that option is on
-
you implement
Recommended
They have predefined names and parameters
-
last resort
Custom
Only when no other event works for your use case
A custom event does not show up in most standard reports, and you have to build its analysis yourself.
Reports or explorations: which one do I open?
GA4 has two different places to look at data, and people usually cannot work out why their numbers disagree. The standard reports are aggregated and pre-built. Explorations are the tool for building your own report: funnel, path, cohort, free-form table.
And here is the thing almost no tutorial says, straight out of Google's help: the data retention setting does not affect the standard aggregated reports and only affects explorations and funnel reports. For an ordinary property you have two options, two months and 14 months. So if your property sits on two months, the standard reports will happily show you last year while your exploration hits a wall at the two-month line. Nobody sees an error; the data is simply not there.
So the first thing to do in a new property is open that setting and see which option it is on. Google writes that when you increase the retention period it is applied to data you have already collected. One more detail: the two-month period is always applied to age, gender and interest data regardless of your setting.
Two more behaviours get read as bugs and are not. First, data thresholds: if a row has too few users, Google withholds it so that nobody can infer an individual's identity from demographic data. You cannot adjust these thresholds, but a wider date range usually brings the same data back. Second, the "(other)" row: when a table needs more rows than its limit, Analytics keeps the most common values and condenses the rest into one row. Google writes that any dimension with more than 500 values should be considered high cardinality, which is exactly what heavily parameterised page URLs turn into.
Reports and explorations, two separate engines
One of the two is sensitive to the data retention setting and the other is not. That single difference explains most of the "why is there no data" moments.
Standard reports
- Aggregated and pre-built data
- The data retention setting does not affect them
- Custom events do not appear in most of them
- Right for the question "what is going on"
Explorations
- Funnel, path, cohort, free-form table
- They hit a wall at the retention boundary
- The only place to analyse a custom event
- Right for the question "why and at which step"
Neither replaces the other. Your question decides which one you open.
Link Search Console, then do one more thing
Linking Search Console to Analytics adds two reports: one for organic search queries with Search Console metrics, and one for organic search traffic that puts landing pages next to metrics from both tools. What the link does, and what neither tool does alone, is that second one: from the query to what the user did after arriving, in one table.
And now the one more thing, which is the reason for half the "I linked it and there is nothing there" messages: the Search Console collection of reports is unpublished by default. You have to find it under Library in the left navigation and publish it yourself. Until you do, the link works and nothing is visible.
It carries a few limits worth knowing before you spend time on it. Search Console metrics are only compatible with Search Console dimensions plus three Analytics ones: landing page, device and country. These reports do not support time-series charts. Search Console data becomes available in Analytics 48 hours after it is collected. And because Search Console keeps 16 months of data, these reports hold no more than 16 months either.
There is a structural limit too: a web data stream links to exactly one Search Console property and the other way round. For a site with several Search Console properties, one per language for instance, that means choosing which one goes to Analytics. The Search Console lesson covers why a multilingual site needs several properties in the first place.
Why the Analytics number never equals the Search Console number
This question comes up in every monthly reporting meeting, and the short answer is that the two tools count two different things at two different points. Search Console counts the click on Google's side; Analytics counts the visit on the user's browser side. Between those points sit things neither of them controls.
Google lists the reasons for the gap itself: some data is not shown in order to protect privacy, for instance queries searched a very small number of times; processing of the source data can shift numbers, for example to eliminate duplicates; there is a lag between calculation and visibility, and collected data is usually available in two to three days; Search Console labels days in Pacific Time, so if your other system runs another time zone the daily views will not match exactly; and tools like Analytics only see traffic from users who have JavaScript enabled.
That last one matters more in practice than it sounds, and it has a variant Google does not write about because it belongs to you rather than to them: if the tag file does not load at all, no event is recorded and no error appears anywhere. The user sees the page, Search Console counts the click, and Analytics believes nothing happened. For an Iranian site that case is not theoretical: the tag file comes from a Google domain, and whether that domain is reachable from inside Iran is not a given.
So the working rule: a gap between the two numbers is normal and you should know its usual size. A small, steady gap means the reasons above. A gap that suddenly widens overnight means something in the installation broke, and the next section is where to look.
Where on the page should the analytics script sit?
This section is not in the tutorials, because you do not run into it until you operate a real site. The standard GA4 snippet is two pieces: a script tag that fetches the file from a Google domain, and a few lines of JavaScript that configure it. Both pieces carry risk in the real world.
The first piece is a dependency on an outside domain. If that domain is slow or unreachable from where your users are, the tag does not load and no data is recorded. Our answer is to host the file on our own domain, with a daily cron that fetches the current version. Collection is deliberately not proxied and still goes straight to Google, because if the hits passed through our server Google would see the server's IP and the geographic reports would break.
The second piece is where it sits. If your site defers scripts until the first user interaction, queue order starts to matter: whatever appears earlier in the document loads earlier and everything else waits behind it. Analytics is a fairly heavy file and it costs nothing to make it wait; the captcha on your contact form cannot wait. So the analytics snippet belongs at the end of the queue rather than the front.
And a trap that only shows itself on sites with a long edge cache: if the script filename changes with a hash of its content and the previous file is deleted, every page still sitting in the edge cache points at the old name and lands on a deleted file. Analytics does not run on those pages and no error appears in the dashboard. The right rule is to keep the file path stable and do the cache busting with a query string; then even a stale page reaches a healthy file. If site speed itself is your subject, site speed work is where this argument goes deeper.
The fast path, with AI
The fast path here is not what you expect. A language model does not have your Analytics data and should not have it; what genuinely gets faster is designing the measurement. That is, going from a business question to whether a ready-made report already answers it, to exactly which exploration is needed if it does not, to what has to be sent if the required event does not exist at all. A model does those three quickly and correctly, because the job is mapping language onto structure. Before any of it comes one simple check nobody runs and that saves the most time: make sure the tag actually loads on a cached page too. A cheap fast model is enough for this; our current pick is in the <a class="text-link" href="/en/ai/">AI section</a>.
- First run the shell command below against a real page of the site. It pulls the tag file address out of the HTML itself and checks what that address returns. If you get a 404, the rest of this lesson is meaningless until you fix it.
- Copy your current event list from Admin and the Events page. Only the event names are needed, no user data at all; keep that line.
- Run the stage two prompt with your business question and that list. The output must say plainly which ready-made report answers it, or if none does, the required exploration with its technique, dimensions and metrics named.
- If the output says the required event does not exist, put the suggested snippet on the site and test it in DebugView. Until you have seen the event in DebugView, nothing has been built.
Copy-ready recipe
U="https://example.com/"
# Pulls the tag file address out of the page itself and checks it comes back healthy.
# If the site defers scripts, the address may sit in data-src.
H=$(curl -s -A "Mozilla/5.0" "$U")
SRC=$(printf '%s' "$H" | grep -oE '(data-)?src="[^"]*(gtag|analytics|gtm)[^"]*"' | head -1 | cut -d'"' -f2)
echo "tag: $SRC"
curl -s -o /dev/null -w '%{http_code} %{size_download}\n' "$SRC"
---- Stage 2: the model prompt ----
Role: measurement designer for Google Analytics 4. You have no access to this
site's data and know no numbers from it.
Business question:
{question, for example: how many people open the consultation form and abandon it}
Events that exist in the property right now:
{list of event names}
Answer in exactly three parts:
1) Does a standard report already answer this? If yes, name the report and its
path and stop there.
2) If not, specify the exploration needed: technique, dimensions, metrics,
filters and date range. If the range needed is longer than two months, say
plainly that the data retention setting has to be 14 months.
3) If the required event is not in the list above, give the suggested event name
and its parameters, plus a ready gtag snippet.
Rules:
- Write no number about this site. You do not have its data.
- If the suggested event has a standard Google name, use that name rather than
inventing one.
- If the question cannot be answered from Analytics data at all, say so and say
where the answer does come from.
Before you trust the output: Finish two things yourself. First, any event the model suggests has to be seen in DebugView before you build a report on it; a snippet that looks right and does not fire is exactly the case that shows no error anywhere. Second, move no user data through this workflow. Google's own policy is that no data may be passed to it that could identify an individual, and page URLs and titles are where that data usually slips through unintentionally. A list of event names is enough for this job and nothing more is needed.
AI in this kind of work
Our position here is the opposite of what has become normal: do not give the model your Analytics data, give it the measurement design. There are two reasons. First, an Analytics export is behavioural data about your users, and sending it to an outside service is a legal decision rather than a shortcut. Second, a model genuinely is fast at turning a business question into a report structure, and that is exactly where people lose the most time.
Tools that actually help
- Gemini Suits the measurement-design stage, because it knows the report names and exploration techniques more accurately. Our own entry notes Iran is not on Google's supported-countries list; the payment route is in <a class="text-link" href="/en/ai/buy/">buying AI access</a>.
- Claude Better for writing and reviewing the event snippets, because when you say use the standard name and do not invent one, it improvises less. Iran is on neither of Anthropic's two supported-countries lists.
- BigQuery Export Not AI, and the answer to both the data threshold and the "(other)" row. It hands you the raw events so you can aggregate them yourself. It is not free and needs a Cloud project; Google also writes that Google signals data is not exported to BigQuery, so the numbers will not match the dashboard.
Where it backfires
The first risk is privacy, and it is not yours; it belongs to your users. Google's own policy states plainly that no data may be passed to Analytics that Google could use to identify an individual, and it writes that such data is often sent inadvertently through page URLs and titles. Put those same URLs in an export and send them to an outside service and you have moved the problem one step further out; whether your conversation is used for training depends on that service's plan and settings and is written on its own page. The second risk is technical: a model produces event snippets and dimension and metric names fluently, and part of what it produces does not exist in GA4 at all. It is hard to catch, because a name like "landing page engagement rate" looks exactly like something that ought to exist. The only reliable check is seeing that event in DebugView and that dimension in the interface itself.
Sources: Analytics Help: best practices to avoid sending personally identifiable information Analytics Help: about data thresholds Analytics Help: set up BigQuery Export Anthropic: is my data used for model training Google: Gemini Apps Privacy Hub
Where this advice stops
Analytics only sees what the browser reported, and only when the tag ran. A user without JavaScript, or one for whom the tag file never loaded, is in no report at all. Data thresholds and the "(other)" row hide some rows, and the retention setting is the ceiling on explorations. And above all: Analytics says what happened, not why. The why comes from talking to customers and looking at the page itself, not from the dashboard.
From our own work
This site serves gtag.js from its own domain rather than from Google's. On the day this lesson was written the file is 525,880 bytes on disk, about 513 KB, and about 169 KB compressed; at 07:35 that morning the daily cron fetched a new version and the ver query changed without the file path moving at all. The reason for that design is a real failure: the filename used to be a hash of its content and the previous file was deleted the moment a new one arrived, while the HTML pointing at the old name stayed alive in the edge cache for up to 30 days. In the logs not one of those historical names ever returned a 200, only 404s, which means Analytics effectively did not run on cached pages and no error appeared in the dashboard; the numbers were simply lower than reality. On that same day a page served from the edge cache was still asking for the previous ver and still got a healthy file back, which is exactly what used to 404. Now the path is stable, seven older copies are still on disk because they are deliberately kept for 45 days, and 45 is more than the 30 day edge cache. Where the snippet sits changed too: while it printed at the top of the page it was first in the deferred script queue and the captcha widget waited behind it, so it moved to the end of the queue. Analytics can wait; a captcha cannot.
Real follow-up questions
Should I set data retention to 14 months or two?
If you are never going to build an exploration, it makes no difference. If you are, and year-on-year comparison matters to you, 14 months is the only option. Google writes that increasing the period applies it to data already collected, so deciding late is not as expensive as you might think.
Why does my exploration say "(other)" instead of real data?
Because the number of rows needed went past the table's limit, so Analytics kept the most common values and condensed the rest into one row. The culprit is usually a dimension with very many values, such as page URLs carrying parameters. Google writes that any dimension with more than 500 values should be considered high cardinality.
I linked Search Console but I see no reports.
Because the Search Console report collection is unpublished by default. Find it under Library in the side navigation and publish it. And if you have only just linked them, remember that Search Console data becomes available in Analytics 48 hours after it is collected.