At Adswerve, we work with sophisticated enterprise clients who typically know their way around web analytics. However, when it comes to adding analytics to their apps, many clients often feel a bit uncomfortable, at least at the beginning. We’re often asked, “How do we do this right?” While there are a lot of best practices that can be provided in response to that question, like “Think about your analytics data model from the analyst’s perspective” and “Develop and enforce consistent cross-platform naming conventions,” one of the most important things from a technical perspective is to start by building an analytics helper class.
What is a Helper Class?
A “helper class” can mean any number of things in computer programming, but in this case, it means a piece of code that you create for your analytics implementation that “wraps” the Firebase Analytics SDK’s methods and provides an intermediary between your app and Firebase. Rather than call Firebase methods directly from your app’s code (e.g., logEvent), you call similar methods in your analytics helper code and those methods, in turn, call the Firebase methods. By introducing a layer between your application and Firebase, you then have the opportunity to evaluate the data you’re collecting—and modify it, if needed—before you pass it to Firebase and Google Analytics. This can be handy for a number of reasons.
Validating Events Against Firebase/GA4 Rules
Google Analytics 4 and the Firebase Analytics SDK are powerful tools, but they have some very strict rules regarding the naming of events, parameters and user properties. If you fail to abide by these rules, important analytics data will be lost. For example, you’re not allowed to start an event name with “ga_” (or “firebase_” or “google_”). If you do, the Firebase SDK will balk and fail to send the event. Similarly, event parameter names can only contain up to 40 characters and must start with an alphabetic character. And event parameter values can’t exceed 100 characters. If you violate any of these rules, the parameter will be dropped from the event before it leaves the device, so it won’t even show up in BigQuery.
If you’re paying close attention to your Logcat log (Android) or Xcode log (iOS) during app testing, you may notice Firebase error messages when a rule is violated. In our experience, it is not uncommon for even experienced enterprise dev teams to miss (or misunderstand) these warnings until after they release the app and someone in the business asks, “Why isn’t there data for ‘parameter X’ on this event?” However, if you’re running your events through a helper class, it’s relatively easy to write code that validates that all the rules have been followed and grabs your attention by logging the issue and throwing an exception (or any other behavior you prefer that helps you root out bugs). That way you can easily head off issues while you’re still in development.
Adding Additional Parameters
In complex analytics implementations, it’s quite common to want to pass a certain set of parameters on every event that’s logged. While it’s theoretically possible to include every desired parameter on every event, that can be difficult in practice when event code is scattered across multiple components in your app, especially if the list of parameters changes over time. Firebase offers a setDefaultEventParameters method that lets you specify a list of parameter names and values that should be added to every event by default, but the values for those parameters are static: You set them when you make the API call and they don’t change for events that follow unless you make another call to setDefaultEventParameters with updated values. However, by using a helper class to centralize your calls to Firebase’s methods, you can easily add parameters and current values to any or all of your events. (Think of a timestamp parameter that should be updated for each event.)
Best practice in programming, especially in app analytics, is that you should avoid using text (string) values in your code. Instead, you should define constants to represent all event, parameter and user property names in your app, as well as recurring or discrete values that might be passed for each. For example, rather than log a screen view event by passing the text “screen_view” as the event name, you would define a constant representing the string “screen_view” and then use that constant anywhere you log the event. This dramatically reduces the chances of introducing typos, and if the values you need to pass change over time, you can simply update the value of the constant and be assured that the new value will be used throughout your app with no additional code changes.
While the Firebase SDK exposes a number of constants, they typically only represent a small subset of the constants you need in an enterprise analytics implementation. Defining your own set of constants (even if you map them to the values exposed by Firebase when applicable) will simplify your coding and avoid hard-to-detect bugs. It also makes it easier to review your constants with your analytics stakeholders in advance to ensure that the values in the app align with values those users want to see in Google Analytics (GA).
Tracking Complex Events
Firebase collects a small handful of useful “automatic events,” like first_open, session_start and firebase_campaign, which supplement the custom events that clients typically collect; however, it’s not unusual to want to track more complex events, like app_open or app_close, that aren’t automatic and require custom code on Android to determine when the event has occurred. Since this custom code is central to the analytics implementation, an analytics helper class is an excellent place to house this.
Another common use case for an analytics helper class is to provide a means of enabling or disabling analytics collection, or setting certain values before the app starts logging events. For example, you may want to set or update a Firebase user property each time the app starts up. Or, for debugging purposes, you might want to set flags on the device, or in a supporting library, whenever you launch the app as a test build. Having a centralized analytics helper class provides a place to organize this custom logic, where it can be updated over time without having to touch code in your core application.
Some Sample Code
When we deliver an implementation spec to a client new to Firebase/GA4 app analytics, we typically provide sample code illustrating how to construct a basic analytics helper class. (Sample code is available on GitHub in Java, Kotlin, Swift and Objective-C.) While this code is fully functional and requires only minor tweaks to add it to your app, the code is primarily intended as an example that shows how you might implement your own helper class. If you aren’t keen on using the whole class, you can just lift whatever portions may be of assistance for your own implementation, or use it as a jumping-off point for your own helper class. Our sample “AnalyticsHelper” code provides the following features:
- Sets various user properties and other settings on startup
- Validates events and user properties against Firebase/GA4 rules, with various options for bringing errors to your attention
- Truncates event parameter and user property values to the maximum lengths supported
- Defines an illustrative list of constants for events, parameters and user properties
- Adds common parameters (with current values) to all events
- Android: Automatically logs app_open and app_close events, with engagement time, based on Android’s application lifecycle
- iOS: Enables DebugView in test builds not launched directly from Xcode (e.g., when using TestFlight)
- Universal Analytics (UA): Provides code to send GA hits in the background (on iOS). Also sets the GA dispatch interval on test builds so that hits can be seen immediately during development and testing.
A quick note about the last item: While GA4 is clearly the future of Google Analytics, using Google’s GA360 Universal Analytics platform is still best practice for enterprise analytics, including app analytics, and will be for some time to come. But there are a few tricks to a UA app implementation, which our sample code helps with: Like the need to send any buffered hits when a production iOS app goes into the background (to prevent them from getting lost), and the need to set the dispatch interval to the minimum (one second) during testing on both platforms, so that hits are dispatched immediately rather than buffered. (By default, UA hits are buffered for two minutes on iOS and thirty minutes on Android.)
Note: If you implement the shorter dispatch interval, it’s important that you only do so in test builds; dispatching hits immediately in production could have a significant impact on device battery life.
Questions about app analytics setup, Firebase, Google Analytics or Google Tag Manager? We can help! Please contact us.