In this article I describe an alternative to GA4's default session control that works better for some tracking setups such as cross-domain or measurement protocol-based approaches. It is based on server-side processing of tracking data and thus requires a dedicated tracking server.
In the context of web analytics, a session is usually described as a time-related sequence of interactions by a user. Even if this model is only limitedly applicable today in view of parallelized and fragmented behaviors while surfing, it still remains a popular heuristic for deriving insights from interaction with web content.
Why client-side session control doesn't always work.
GA4, the new version of Google Analytics, introduced a new form of client-side session management that is fundamentally different from its predecessor, Universal Analytics. Universal Analytics still calculated the events associated with a session as part of its database-side post-processing of tracking data. So it was relatively easy to consolidate events across different devices and browsers into one session, as long as they were attributable to one user.
In its new version of the popular GA4 tracking tool, Google is taking a new approach: In order to link different events together the session ID is now required, a separate parameter in the data schema. This is generated by default by the GA4 library based on its own logic in the respective device or browser. So if you want to merge cross-domain sessions, either this parameter must first be synchronized between client or a custom session model must be created when evaluating the data.
In a cross-domain setup, for example, the user identity is transferred from one domain to the next - but the session is restarted on the new domain. This makes a coherent analysis more difficult afterwards and inflates the buzz of sessions unnecessarily.
How sessions can be managed server-side instead.
In a previous article I already described what - using GTM as an example - are the numerous advantages of server-side tracking. A big plus is the possibility to enrich the tracking data with additional information on the server side. However, it is also possible to match data on the server and determine, for example, whether an event should still belong to a session or not.
Data can be retained on the server side beyond various events by storing them in the Firestore. This incurs costs for reads or writes starting at 50,000 and 20,000 accesses, respectively, but these costs are manageable at $0.06 and $0.18 per 100,000 accesses, respectively.
In addition, this approach therefore makes use of the API
templateDataStorage, which allows records to be stored in the cache of the respective template. Since this storage is local, there is no guarantee that it will be present on the particular server instance handling the request. Therefore, it is always checked first whether a session already exists in the firestore. If the session already exists in the local storage, it is additionally checked how old it is and - if a certain expiration time is reached - the firestore is also queried for new session data.
In my own tests I was able to limit the number of read or write operations in the firestore to a minimal sum by using this mechanism. However, the template can also be configured to always use the firestore.
The template for a simple implementation of server-side session management.
To make the implementation easier, I have created my own variable template that takes care of the session management task. It is available for download here. It can be imported into your own container using the template feature of the server-side tag manager.
As you can see in the picture, the template is composed of two settings areas: The access to the Firestore and the definition of the session modalities.
Select own settings for a server-side session management.
In the further settings, the Session length is determined first. By default it is 30 minutes.
In order to assign the session to a user, the next step is to set the input variable for Identity of the user. Normally, the client ID can be used for this, which should already be included in the event.
Then the output of the variable can be selected. In addition to the Session ID, it is also possible to record the Session Counter and the Engagement Time on the server side. The latter differs from the client-side engagement time, however, in that it only captures the difference between the session start and the time of the event, and not the active time on the page.
In addition, it is possible to specify the time window in which the session should be refreshed. This event also updates the firestore, i.e. performs a write operation. It is therefore recommended to consider the possible number of events here to control costs. If the variable is used for multiple parameters, it makes sense to enable the refresh for only one.
If not every event should reactivate a session, certain event names can be included or excluded in the last setting.
Provide the GA4 events with their own session parameters
In the next step, the parameters can now be added to the GA4 event (on the server). For each parameter, a version of the variable with the respective output value (
engagement_time_msec) is created for this purpose.
In the "parameters to be added/edited" area these variables are inserted:
With this change, the parameters, if they should exist in the original event, will be overwritten with their own values.
Advantages of server-side session management.
This setup moves session management from the client to the server. This approach has particular advantages for situations where sessions are spread across multiple domains or devices or when the Measurement Protocol is used and sessions themselves would need to be manually managed. In combination with the server-side tag manager, a large amount of effort can be saved here.
The solution based on Firestore uses a function that is natively connected to the server-side tag manager and is easy to use. Nevertheless, in order to not perform countless reads and writes, session information is cached in the
templateDataStorage. This takes effect if a current session exists as a record in memory. Otherwise, session information is synchronized via the firestore.
Thanks to its server-side implementation, the data here is processed completely cookieless. Thus, this approach also supports the possibility of using GA4 without those infamous memory crumbs.