Google Analytics Sessions and Non-Interaction Events in BigQuery
Successfully recreating metrics from the Google Analytics (GA) interface in BigQuery (BQ) requires an understanding of the nuances in metric definitions and data capture in GA. During a client engagement, we found ourselves in a scenario where we had logically recreated the GA sessions in BQ yet there were unexplained differences in the counts. In this blog, we will walk through a few of these nuances, specifically those dependent on the number of interaction events per session which proved to be the root cause driving differences in our scenario.
Interaction/Non-Interaction Events
The categorization of an event hit as either interaction or non-interaction event determines how the bounce rate is calculated on each page. By default, event hits are classified as interaction events. However, there is an optional Boolean parameter that when set to TRUE, classifies the hit as a non-interaction event. As such, a hit will not be counted towards the single interaction event present in a bounced session.
Sessions
A session is widely understood to encapsulate all actions a user takes on a site during a single visit, which can be concluded by exiting the site or due to a 30-minute idle period. But in GA, a visit to a website only increments the overall session count if the user completes one or more interaction events. Standard practice dictates that a basic page view should be classified as an interaction event. In this case, if a user stays on-site long enough for the initial page view event to fire, then this visit will be captured by GA and included in the total session count. It’s worth noting if your website experiences uncharacteristically slow load times delaying the firing of the page view event, then this may also cause lower session counts than expected and ultimately impact your bounce rate.
Bounce Rate
Google Analytics defines a bounce rate as the ratio of bounces (sessions with precisely one interaction event) to sessions. If a page view counts as an interaction event then any additional user interactions on the landing page could set the user over the 1 interaction event threshold and disqualify the session from being considered a bounce, even if only one page is viewed during the session. An example of this could be a modal that pops up when a visitor enters the site for the first time asking them to agree to your cookie policy. If clicking “agree” triggers an interaction event then you may see an incredibly low bounce rate on your site, because anyone who clicks “agree” and proceeds to exit your site in the next few seconds would no longer be considered a bounce even if they engaged very little with your site content. Therefore, the way events are defined on each landing page – non-interaction vs. interaction can greatly impact the number of bounces. Think about what constitutes an engaged consumer when determining whether or not to classify a user engagement as an interaction event.
Users
While Google Analytics requires at least one interaction event for a visit to be qualified as a session, there is no such requirement for users. Each new user to the site is counted, regardless of the number of interaction events.
Recreating GA Metrics in BigQuery
The google analytics UI transforms, aggregates, and filters raw site data before it is displayed in the interactive console. BigQuery, on the other hand, provides access to the raw data prior to these transformations. Take sessions for example. As discussed earlier, only visits containing one or more interaction events are considered sessions by GA. Any visits without an interaction event are filtered out on the backend. BigQuery, by contrast, grants you access to all session data, even visits lacking interaction events (delineated by the totals.visits field). Totals.visits is set to one for sessions with one or more interaction event and otherwise left null. So the addition of a simple where clause to a query (WHERE totals.visits =1) allows you to mirror the session count in GA by limiting it to only sessions containing an interaction event.
Example Scenario
After working closely with stakeholders to understand the business objectives, we aligned on building a Tableau dashboard, containing a mixture of data points from both on-site (captured in GA) and CRM touchpoints. Both data sources were configured to send data feeds to BigQuery, so we were tasked with constructing robust SQL queries to stitch this data together in BQ before aggregating and creating finalized tables for ingestion into Tableau. Before pushing this data to Tableau, we wanted to validate the GA metrics pulled in BQ were matching the counts shown in the GA console or were at least within a reasonable margin of error. In an effort to replicate the counts in the GA console we included the standard filter (WHERE totals.visits = 1) in our queries to limit to sessions with at least one interaction event. As expected, the inclusion of this filter resulted in the BQ session counts matching exactly with the reported session count in the GA console. Surprisingly, however, the addition of this filter resulted in other GA metrics (product views, checkouts, and purchase) differing from the console reports. After holding everything else constant and removing the filter, product views, checkouts, and purchase were in line with what the console displayed. Of course, without the filter, the number of sessions counted in BQ now exceeded that of the console (see table below). The observed differences in product views, checkouts, and purchase, therefore, could only be attributed to “sessions” without any interaction events.
It goes without saying, the three-custom user-defined metrics in question (product views, app views, and purchase) were classified as non-interaction events. Consequently, for the visits containing these metrics to be counted as sessions by GA, the user had to perform an interaction event in addition to this metric. In most cases, a page view would suffice to cross the single interaction event threshold. This is particularly strange in this case because these events should only fire after the page view event, not to mention that these are not typical landing pages. Especially in the case of application submissions, but equally valid for the other two metrics, users typically perform multiple actions on the site prior to reaching this stage of the application flow.
The most logical explanation for how users would be landing on these pages would be via a bookmark, in which case the traffic source should be direct. The second piece is a bit more peculiar. There are two explanations for how a user could perform these events without the visit being categorized as a “session”. The first would be users exiting before the landing page fully loads and triggers the page view event. If somehow the custom metric (non-interaction event) fired, but the page view event (interaction event) did not, then this visit would not qualify as a session and would not be returned when the filtering clause is included in the query. The other possible explanation would be if the page view event on these pages was classified as a non-interaction event as well. In this case, even if the page loads, but the user takes no further actions prior to session expiration it would not technically be considered a “session”.
Takeaways
The way on-site user interactions are defined (interaction vs non-interaction events) plays a crucial role in two commonly used GA metrics – sessions and bounce rate. GA defines a session as any visit with at least one interaction event and a bounce as any session with exactly one interaction event. Being familiar with these nuances is critical when extracting GA data sets from BigQuery.
If you observe a bounce rate or session count which deviates significantly from the expected value or suddenly experience a huge change in one of these metrics, then it may be worth visiting or revisiting these decisions and inspecting the GTM configuration to confirm it reflects the expected treatment.