[GA4 Bug] Midnight Sessions are worth Double

English version (versione italiana a fine articolo)

I received a request for assistance from a Linkedin user to understand an anomalous behavior in the calculation of total sessions. In the specific case, the total sessions in a time interval were very different, higher, when segments were applied in that interval. I explain it below.

Let’s start with the definition of Session, given in Google’s official documentation:

Fig. 1

So we know that:

  • a session_start event generates a session ID with which the events of that session are associated. We can then say that a session starts with the session_start event.
  • a session ends after 30 minutes of inactivity.
  • sessions don’t end at midnight or with a change of source/medium/campaign.
  • if the user returns to the page after the previous session has expired, a new session is started.

After this definition we move on to the case describing the anomaly.

The scenario

The report was presented with an example on the GA4 Google Merch Shop property, via a report in Explore based only on Sessions during the period February 1, 2024 – February 29, 2024. The result obtained was “68,888.”

Fig. 2

The same value was consistent by adding the Landing Page dimension to the report:

Fig. 3

We now apply two segments:

  • Include Sessions when Landing Page contains “/Google+Redesign/”
  • Include Sessions when Landing Page does NOT contain “/Google+Redesign/”

Since a Landing Page may or may not contain this string, we would expect to see two unique columns, with the sessions broken down according to whether or not the Landing Page contains that value. So the sum of the two totals should result in “68,888” (the total number of sessions seen in Fig. 2).

Actually, the result is completely different:

Fig. 4

The sum of the totals results in more than “95,000,” about 40% more than expected.

At this point, the eye falls on the number of (non set). In the previous image, the one from the report with only sessions and landing pages, there were “37,530.” After applying the segments, there are “26,697” more.

Knowing that the GA4 property of Google Merch Shop is somewhat altered and that due to a permissions issue it is not possible to drill down into user navigation or export the data for analysis, I ran the same tests on websites under my management. First on a high-traffic website, where I found similar anomalies (minor compared to the Google website, but still present). Then on my very low traffic website. On the latter, because the numbers were on a smaller scale, it was easier to isolate an anomalous case like the one shown so far.

For this reason, I will use it to explain the inference I arrived at.

The test on a low traffic website

Below is the report with Sessions and Landing Pages for the period November 10-11, 2023 on the analyzed website, where the total number of Sessions over the two days is “60”:

Fig. 5

Let us now apply the two segments. They are constructed similarly to those described at the beginning of the article, only the string to be distinguished on the landing page to match the URLs of the website in question changes. The result is as follows:

Fig. 6

The sum of the totals gives “61” (38+23) instead of “60,” as shown in Fig. 5. Also, it is easy to detect that there are 2 rows that have values in both one column and the other, while the others all belong to one column or the other.
One of these offending rows is characterized by the (not set). This results in 1 (not set) session in the segment that contains our string on the landing page. This session could then also be the same one found in the first column of row 5, the one associated with the landing page “/ga4-magic-audit-google-sheets-add-on/“.

In fact, opening the user view by clicking on row 2 (the one not set) or opening it from row 5 (in this case), the result is the same:

Fig. 7

By accessing its navigation you can observe this situation:

Fig. 8

The results of the user’s session are straddling midnight!

Without going into why in this case there is a page_view about 15 minutes after a session_start, what we can observe is the effect this condition generates on the collected data.

What happens, in fact, is that both session_start and page_view events, belonging to the same session, are linked to the same Session ID.
GA4 relies on the Session ID to calculate the number of sessions (the official documentation talks about estimation, but here we get into another aspect that involves the HyperLogLog++ algorithm and that is not provided in the reports shown above).
If we look at the landing page report, Fig. 5, we can see that the total sessions for the analyzed page are 2. Applying the 2 segments, Fig. 6, the sessions for the same page become 3 (2 in one segment and 1 in the other).

From this example, we can see that session segments such as the one applied, treat the sessions at the stroke of midnight as if they were two separate sessions, one with the landing page and the other (not set).

It doesn’t just happen with segments!

We have seen that the result of the total sessions on the two days is “60” (Fig. 5).

However, examining the same report by selecting the two days individually, the result is that:

  • the total number of sessions on November 10 is “50”.
  • the total number of sessions on November 11 is “11.”

The sum still results in “61” and not “60.”

The landing page in question results once on November 10 and the other on November 11. Also, there are 4 sessions on November 10 (not set) while there are 0 for the day November 11.

Conclusions

The session at the turn of midnight is considered single in the case where the time interval analyzed contains both days (the start and end days of the session), while it is split from a logical point of view (it is considered double within the reports) if the days are observed separately or across a session segment.

Side note

The situation just described was found in all the cases analyzed of websites with different traffic volumes.
Only in one case did I detect an anomalous situation in a report, although consistent with the discourse of sessions at the turn of midnight. In this case there was a session start on one date and only one scrolling event after a few days. Although more than 30 minutes of inactivity elapsed between the two events, it is as if the session ID remained the same even days later. In any case, since this is a sporadic case, it may be an isolated bug that does not require further investigation.

Acknowledgements

Special thanks to my “old” colleague Ilaria, these are the cases we enjoy and any exchange of views on them becomes immediately enlightening to get on the right track.
Thanks also to my colleague Eusebjo for support in the initial phase of experimentation that lasted well beyond office hours.

——————————————————————————————————————–

VERSIONE ITALIANA

[GA4 Bug] Le Sessioni a Mezzanotte valgono Doppio

Ho ricevuto una richiesta di supporto da un utente di Linkedin per comprendere un comportamento anomalo nel calcolo del totale delle sessioni. Nel caso specifico, le sessioni totali in un intervallo di tempo risultavano molto diverse, superiori, quando in quell’intervallo venivano applicati dei segmenti. Spiego tutto di seguito.

Partiamo con la definizione di Sessione come indicato nella documentazione ufficiale di Google:

Fig. 1

Per cui sappiamo che:

  • un evento session_start genera un session ID al quale sono associati gli eventi di quella sessione. Possiamo quindi affermare che una sessione inizia con l’evento session_start.
  • una sessione termina dopo 30 minuti di inattività.
  • le sessioni non si interrompono a mezzanotte o con il cambio di sorgente/mezzo/campagna.
  • se l’utente torna nella pagina dopo che la sessione precedente è scaduta verrà avviata una nuova sessione.

Dopo questa definizione passiamo al caso che descrive l’anomalia.

Lo scenario

La segnalazione è stata presentata con un esempio sulla Proprietà di GA4 Google Merch Shop, tramite un report in Esplora basato sulle sole Sessioni nel periodo 1 febbraio 2024 – 29 febbraio 2024. Il risultato ottenuto è stato “68,888”:

Fig. 2

Lo stesso valore è risultato coerente aggiungendo al report la Pagina di destinazione:

Fig. 3

Applichiamo adesso due segmenti, uno che Include le Sessioni che hanno Pagina di destinazione contenente la stringa “/Google+Redesign/” e l’altro che Include le Sessioni che hanno Pagina di destinazione che NON contiene la stringa “/Google+Redesign/”.

Dal momento che una Pagina di destinazione può contenere o può non contenere quella stringa, quello che ci potremmo aspettare di vedere sono due colonne esclusive, con sessioni divise in base al fatto che la Pagina di destinazione contenga o meno quel valore. Per cui la somma dei due totali dovrebbe dare come risultato “68,888” (le Sessioni totali viste in Fig. 2).

In realtà il risultato è completamente diverso:

Fig. 4

La somma dei totali risulta più di “95.000”, circa il 40% in più di quella attesa.

A questo punto, l’occhio cade sul numero dei (not set). Nell’immagine precedente, quella del report con sole sessioni e pagine di destinazione, erano “37,530”. Dopo l’applicazione dei segmenti ne risultano altre “26,697”.

Sapendo che la Proprietà di GA4 Google Merch Shop è un po’ alterata e che per una questione di permessi non è possibile effettuare approfondimenti sulla navigazione degli utenti o esportare i dati per analizzarli, ho effettuato gli stessi test su siti in mia gestione. Prima su un sito web ad alto traffico, dove anche in questo caso ho riscontrato simili anomalie (più contenute rispetto al sito di Google ma pur sempre presenti). Successivamente sul mio sito web a bassissimo traffico. Su quest’ultimo, essendo i numeri su piccola scala, è stato più semplice isolare un caso anomalo come quello mostrato finora.

Per questo motivo, lo utilizzerò per spiegare la deduzione alla quale sono arrivato.

Il test su un sito a basso traffico

Di seguito il report con Sessioni e Pagina di destinazione per il periodo 10-11 Novembre 2023 sul sito analizzato, dove il totale delle Sessioni nei due giorni risulta “60”:

Fig. 5

Applichiamo ora i due segmenti. Sono costruiti in modo simili a quelli descritti a inizio articolo, cambia solo la stringa da distinguere nella pagina di destinazione in modo da corrispondere alle URL del sito in oggetto. Il risultato è il seguente:

Fig. 6

La somma dei totali dà “61” (38+23) anziché “60” come mostrato in Fig. 5. Inoltre, è facile identificare che ci sono 2 righe che hanno valori sia in una colonna che nell’altra, mentre le altre appartengono tutte o a una colonna o all’altra colonna.
Una di queste righe incriminate è caratterizzata dal (not set). Risulta 1 sessione (not set) nel segmento che contiene la nostra stringa nella pagina di destinazione. Questa sessione potrebbe essere pertanto la stessa che si trova anche nella prima colonna della riga 5, quella associata alla pagina di destinazione “/ga4-magic-audit-google-sheets-add-on/“.

Infatti, aprendo la visualizzazione degli utenti al click sulla riga 2 (quella dei not set) o aprendola dalla riga 5 (nel caso specifico), il risultato è il medesimo:

Fig. 7

Accedendo alla sua navigazione si può osservare questa situazione:

Fig. 8

La sessione dell’utente risulta a cavallo della mezzanotte!

Senza entrare nel merito della questione del perché in questa caso c’è una page_view circa 15 minuti dopo un session_start, quello che possiamo osservarne è l’effetto che questa condizione genera sui dati raccolti.

Quello che succede, infatti, è che sia l’evento session_start che page_view, appartenendo alla stessa sessione, sono collegati allo stesso Session ID.
GA4 si basa sul Session ID per calcolare il numero di sessioni (la documentazione ufficiale parla di stima, ma qui si entra in un altro aspetto che coinvolge l’algoritmo HyperLogLog++ che non è previsto nei report mostrati sopra).
Se guardiamo il report delle pagine di destinazione, Fig. 5, possiamo rilevare che le sessioni totali per la pagina analizzata sono 2. Applicando i 2 segmenti, Fig. 6, le sessioni per la stessa pagina diventano 3 (2 in un segmento e 1 nell’altro).

Da questo esempio si evince che i segmenti di sessione come quello applicato, considerano le sessioni a cavallo della mezzanotte come se fossero due sessioni distinte, una con pagina di destinazione e l’altra (not set).

Non succede solo con i segmenti!

Abbiamo visto che il risultato delle sessioni totali nei due giorni è “60”, Fig. 5.

Tuttavia, osservando lo stesso report selezionando singolarmente i due giorni il risultato è che:

  • il numero totale di sessioni del giorno 10 Nov è “50”.
  • il numero totale di sessioni del giorno 11 Nov è “11”.

La somma risulta ancora “61” e non “60”.

La pagina di destinazione in questione risulta una volta il giorno 10 Nov e l’altra il giorno 11 Nov. Inoltre, il giorno 10 Nov risultano 4 (not set) mentre ne risultano 0 per il giorno 11 Nov.

Conclusioni

La sessione a cavallo della mezzanotte viene considerata unica nel caso in cui l’intervallo di tempo analizzato contiene entrambi i giorni (quello di inizio e quello di fine sessione), mentre viene spezzata da un punto di vista logico (ovvero viene considerata doppia all’interno dei report) se si osservano i giorni in modo distinto o tramite un segmento di sessione.

Nota a margine

La situazione appena descritta è stata riscontrata in tutti i casi analizzati di siti web a diverso volume di traffico.
Solo in un caso ho rilevato in un report una situazione anomala se pur coerente con il discorso delle sessioni a cavallo della mezzanotte. In questo caso c’era un session_start in una data e un solo evento di scroll dopo alcuni giorni. Nonostante siano passati ben più di 30 minuti di inattività tra i due eventi, quello che è successo è come se il session ID fosse rimasto lo stesso anche a distanza di giorni. Ad ogni modo, essendo stato un caso sporadico, potrebbe trattarsi di un bug isolato che non richiede di essere ancora approfondito.

Ringraziamenti

Un ringraziamento speciale alla mia “vecchia” collega Ilaria, questi sono i casi che ci piacciono e ogni scambio di opinioni su di essi diventa subito illuminante per mettersi sulla strada giusta.
Grazie anche al mio collega Eusebjo per il supporto nella fase iniziale di sperimentazione protrattasi ben oltre l’orario di ufficio.