What are hits and batched hits in GA4?
A hit is a single request a tag sends. To save round trips, GA4 often batches several events into one `POST` to `/g/collect`, with each event on its own line of the request body. A batch is still one network request.
Why it matters
Every time your site sends data to Google Analytics, that's a hit. Old tracking tools sent one HTTP request per event, which adds up fast. On a busy page, you might fire twenty analytics events. That's twenty network requests. That's wasteful.
GA4 cuts that noise by batching multiple events into one POST request. Instead of twenty requests, you get one request with twenty events crammed into the body. The browser makes one round trip to Google's servers, which saves bandwidth and time.
But batching creates a problem for debugging: when you look at the Network tab in DevTools, you see one row. The request body holds ten events, but the status code is one. If the batch succeeds, all ten events report a 204 status. If the batch fails, all ten fail together. You need to unpack the body to see which event lives where. That's what Scalpel Tags does.
How it works
GA4 decides when to batch based on page activity and time. Here's the mechanism:
Single events. If your page sends one event and then sits quiet, GA4 sends a GET request right away:
GET /g/collect?v=2&tid=G-XXXXXXXXXX&cid=12345&en=page_view
Simple. One event, one request.
Multiple events. If your page fires several events in quick succession (a button click triggers multiple tracking calls), GA4 holds them and batches them into one POST:
POST /g/collect?v=2&tid=G-XXXXXXXXXX&cid=12345
[newline-separated body with multiple events]
The body is newline-separated. Each line is one complete event with all its parameters. Shared parameters like v, tid, and cid go in the query string. Per-event parameters go on each line of the body.
Time-based batching. GA4 also batches by time. If an event sits waiting for more events to arrive, GA4 flushes the batch after a timeout (usually under a second).
The key point: a batch is still one network transaction. One request ID, one status code, one round trip. But inside it live many events.
What does not matter
You don't need to worry about batch size limits in most cases. GA4 handles batches of reasonable size. Only if you're an ecommerce site with a massive purchase event that includes hundreds of product lines might you need to think about it. For typical sites, GA4's defaults are fine.
Also, batch order matters less than you'd think. If a batch has ten events, Google Analytics processes them all and counts them all. One event's success doesn't depend on another's position in the batch. You can't use batch order to debug causality.
Code example
Here's what a batched request body looks like. The request is one POST, but the body holds two events (a page view and a button click):
POST /g/collect?v=2&tid=G-XXXXXXXXXX&cid=12345&sid=67890
tid=G-XXXXXXXXXX&cid=12345&en=page_view&dl=https%3A%2F%2Fexample.com%2F
tid=G-XXXXXXXXXX&cid=12345&en=button_click&ep.button_id=submit&epn.value=1
Each line is a complete event. Notice tid and cid repeat on each line (they could be omitted if they're in the query string). The en parameter changes per line: one is page_view, the other is button_click. Unique parameters like button_id appear only where they matter.
When you look at the Network response, you see one 204 status. Scalpel Tags splits that body into two rows so you can see each event separately.
How Scalpel Tags shows it
Scalpel Tags automatically unpacks batches. In the hit table, each line of the body becomes its own row. Every row gets a batched badge and a batchIndex showing which position it held in the batch (0, 1, 2, and so on).
All rows in a batch share one requestId. That's how Scalpel Tags knows they came in together. If the status code is 204, all rows show green. If it's a 4xx or 5xx error, all rows show red. The status is per-batch, not per-event, because only one HTTP request left the browser.
This makes it easy to spot when multiple events rode in one POST and to correlate them with the network request you see in DevTools.