Back to the blog

Blog

Every GA4 event your server container sees, and where each one comes from

Published · Updated · 5 min read

Routing GA4 through a server container does not change which events exist. What changes is that you can finally see which ones arrive — the container page counts every event name it forwards. That list surprises people in both directions: events they never configured show up, and events they expected do not. Both have simple explanations once you know where each event comes from.

Four events the Google tag sends on every property

The moment the Google tag loads with your measurement ID, four events flow with no setting behind them. Nothing in Analytics turns them off, and nothing in your container needs to ask for them.

  • page_view — one per page load, or per route change on a single-page app when the stream's "page changes" option is on.
  • session_start — the first hit of a new session. A session ends after thirty minutes of inactivity, so a returning visitor two hours later starts another.
  • first_visit — once per browser, on the first session GA4 has ever seen from it. Clearing cookies produces another.
  • user_engagement — sent when the page has been in the foreground for ten seconds, or when the visitor leaves after engaging. This is where GA4's engagement time comes from.

If you see page_view and nothing else, the tag is working. That is not a fault; it is a site nobody has scrolled to the bottom of yet.

Nine events from Enhanced Measurement — and the switch that decides whether you get any of them

GA4's Enhanced Measurement collects nine more events in the browser, without a tag for any of them. They are configured on the data stream, not in Tag Manager, which is why a server container forwards them without knowing they exist.

Each one has a condition that is stricter than its name suggests.

  • scroll — once per page, and only when 90% of the page's height has been visible. Not on any scroll: on reaching the bottom. A page shorter than the viewport never fires it at all.
  • click — an outbound click, to a domain other than the current one. Internal links do not count. The event is named click, with an outbound parameter; there is no outbound_click.
  • view_search_results — a page load whose URL carries a search query parameter (q, s, search, query or keyword by default).
  • file_download — a click on a link ending in a document, archive, audio, video or spreadsheet extension.
  • form_start and form_submit — the first interaction with a form on the page, and its submission.
  • video_start, video_progress and video_complete — for embedded YouTube players only, and only when the embed has JS API support enabled.

Here is the part that costs people weeks. Every one of those nine depends on the stream's Enhanced Measurement master switch, and a stream created through the Analytics Admin API — rather than in the Analytics interface — has that switch OFF. Read the settings through the API and every individual toggle reports true; the master switch is simply absent from the response, because it is false and the API omits false booleans. So the setup looks fully enabled and delivers page_view only.

We found this on our own property. SignalHost turns the master switch on when it creates a property for you; if yours was created another way and scroll never arrives, open the data stream in Analytics and check "Enhanced measurement" itself, not the toggles beneath it.

Sixteen events only your site can send

The events that make money — a sale, a lead, a sign-up — are the only ones on this page that nothing sends automatically. GA4 defines their names and their shape; your site has to push each one to the dataLayer, by exactly that name, at the moment it happens.

Every SignalHost container has a trigger and a GA4 event tag waiting for sixteen of them:

  • Nine for a shop's funnel: view_item_list, view_item, add_to_cart, remove_from_cart, view_cart, begin_checkout, add_shipping_info, add_payment_info and purchase, each with an ecommerce object attached.
  • Five for leads: generate_lead, contact, schedule, submit_application and subscribe.
  • Two for sign-ups: sign_up and start_trial.

A stock Shopify theme pushes none of them, and neither does WooCommerce core: a dataLayer app or plugin does, and on Shopify the checkout events need a Custom Pixel because the theme's container never loads on the checkout pages. The moment your site pushes one, the tag is there to forward it — the push is yours to arrange, and the Shopify and WooCommerce article covers exactly what to install.

The Supported events button on your container's Events card lists all of them, what each one means and what to push. If your container already sends one of them to GA4 with a tag of your own, SignalHost leaves that event to your tag rather than counting it twice.

What the container page counts

Every measurement request that passes through your container is counted by event name, per day, for 400 days. Only the name is kept — not the URL, not the client ID, not a single parameter — which is what makes it safe to keep that long. The list is what arrived at your hostname, so it answers a question Analytics itself cannot: did the browser send it at all?

Expect the counts to be uneven. Every page load is a page_view; only page loads that reach the bottom are a scroll; only sessions that pass ten seconds are a user_engagement. A site with ten page views and two scrolls is a normal site.

Two things will keep the two lists from ever matching exactly. A visitor who has not answered your banner still sends every event, as a cookieless ping, and the container counts it while Analytics drops it — the page shows both numbers so you can see which is which. And session_start and first_visit never appear on the container page at all: the browser does not send them as events, it sets two flags on the first page_view, and Analytics manufactures the events on its side.

Above the list, the card counts how many of those sixteen events arrived in the last 30 days, so the one your site forgot to send stands out.

When an event is missing

Two cases, and the container page tells them apart.

If the event is not in the container's list, your site never sent it. The container cannot forward what did not arrive. For a standard event, check the stream's Enhanced Measurement switch; for one of the sixteen, check that the dataLayer push happens, with the right name, on the page where it should.

If the event is in the container's list but not in Analytics, it arrived and was forwarded, and the problem is on Google's side of the line: the wrong measurement ID, a data filter, a property in a different account than the one you are looking at, or simply the reporting delay — realtime shows it within seconds, standard reports can take a day.

Starting from zero? How to set up server-side Google Tag Manager, step by step.

Stop losing data to ad blockers

Start free. Get your first container running in minutes.