Architecting an Analytics layer

A better way of integrating Analytics SDK combining the Observer and the Adapter patterns.

Fernando Martín Ortiz
iOS App Development

--

Suppose that you want to integrate Google Analytics SDK. You start by following the guide, tracking the events that you want to measure. Everything is going well, because it just works, right?

But things get worse when you have to implement Mixpanel Analytics. You have to track some events using Google Analytics, and some other using Mixpanel. After that, you are requested to integrate Flurry, to track other events. Everything become a mess, and you have analytics code everywhere. Your code is not maintainable anymore.

You might be thinking “Hey! Wait a second… Why in the Earth would you add more than one Analytics provider to a single project? 😶” Well, I really don’t know. But I have been asked to do that a couple times before and I had to face this problem. The point here is: Reduce coupling between your external dependencies and your code. Even if you don’t have to add more than one analytics provider, it’s always a best practice to not depend on a particular implementation. Keep this in mind.

TL;DR

Here is the diagram for the pattern I always use to add Analytics services:

Key points:

  1. Although analytics SDKs have different interfaces, they have similar functionalities. So, we have to use an Adapter for each one to make them implement the same interface.
  2. Analytics Services (the adapters) subscribe to a list of events that they are interested to be notified when fired. Each service could subscribe to a different list of events. This is important, in order to get flexibility.
  3. There is a class, called AnalyticsManager, that is the only class you know from the application, and you notify it when an event is fired in the app.
  4. Whenever an event is fired in the app, the AnalyticsManager notifies Analytics Services that were subscripted to that event. (Observer pattern)
  5. You can extend this pattern if you need to add more functionalities to the adapters.

The two main parts in Analytics SDKs

Every analytics SDK has at least two important steps in its usage:

  1. Initialize the SDK in AppDelegate
  2. Track events in your app.

It seems like a perfect fit for a protocol!

Every Analytics SDK you integrate in your app should implement AnalyticsService protocol.

What is an Event anyway?

Events are anything that you would like to measure in your app. If you are wondering what events you would be tracking I really recommend you this guide, it’s REALLY worth reading. The most natural way to implement Events is with an enum:

Sample analytics service

Here is an analytics service example, wrapping Mixpanel SDK:

The core

As I said before, from your app, you don’t know which SDKs you are really using. From the app, you only want to know two things from your analytics layer:

  1. The list of Events
  2. The AnalyticsManager

The AnalyticsManager class is often implemented as a Singleton, but it’s up to you. If you really dislike Singletons, you are free to inject it as a dependency. But if you ask me, it’s kind of over engineering. It isn’t a bad thing that your code has a dependency to your AnalyticsManager. It’s way better than depending on the concrete SDKs.

The analytics services can subscribe to AnalyticsManager specifying a list of events to which them will be observing.

Here is a sample implementation of AnalyticsManager:

Usage

As I’ve said before, there are two main functionalities in Analytics SDKs. Initialization and tracking.

Initialization

Tracking

As simple as this:

AnalyticsManager.instance.track(event: Event.loginWithEmail)

That’s all. 🎉

Conclusion

Depending on an implementation is always a bad thing. It’s always better to code against an interface, keeping flexibility and reducing coupling. Whenever you want to change the Analytics SDK that you are using, if you have followed this pattern, It would be really easy!

This pattern can be extended. If you want to add more functionalities to Analytics services, you can extend the protocol, and the AnalyticsManager class. But the çore idea would be the same.

If you know a better way of doing this, just let me know, below in the comments 👇🏼

Thank you!

--

--