Lawrence Gimenez

Mixpanel Code Refactor

Our app uses Mixpanel for analytical and strategic purposes. This post is about my refactoring journey.

Mixpanel introduced another parameter in their getInstance() method called trackAutomaticEvents which is of a boolean data type. Now, this is the part that I didn’t anticipate because located throughout our codebase is this single line.

MixpanelAPI.getInstance(this, Constants.MIXPANEL_TOKEN).track("Log In")

But right now it is broken since the proper way to implement on the new version is this.

MixpanelAPI.getInstance(this, Constants.MIXPANEL_TOKEN, true).track("Log In")

Behold them compile errors.

You might think why not use the Find All option in Android Studio? I could, but this is to future proof our codebase in case another getInstance() refactor in the future.

Kotlin Object

For the Kotlin singleton pattern, I always use object since they are good for one-time use purposes.

import android.content.Context
import com.mixpanel.android.mpmetrics.MixpanelAPI

object Mixpanel {

    fun track(context: Context, track: String) {
        return MixpanelAPI.getInstance(context, Constants.MIXPANEL_TOKEN, true)
            .track(track)
    }
}

Now that I have isolated or “wrapped” in a separate class, I can now implement condition statements inside it. Most of my Mixpanel method calls were wrapped in a !isDebuggable condition and are sprinkled everywhere in our codebase. Not good.

val isDebuggable = 0 != applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE
if (!isDebuggable) {
     MixpanelAPI.getInstance(this@MainActivity, Constants.MIXPANEL_TOKEN).track("Session - Employer")
}

Code Refactor

Now, that I have a separate object class, I can just call the condition there instead.

import android.content.Context
import android.content.pm.ApplicationInfo
import com.mixpanel.android.mpmetrics.MixpanelAPI

object Mixpanel {

    fun track(context: Context, track: String) {
        val isDebuggable = 0 != context.applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE
        if (!isDebuggable) {
            MixpanelAPI.getInstance(context, Constants.MIXPANEL_TOKEN, true).track(track)
        }
    }
}

So from this code block

val isDebuggable = 0 != context?.applicationInfo!!.flags and ApplicationInfo.FLAG_DEBUGGABLE
 if (!isDebuggable) {
      MixpanelAPI.getInstance(activity, Constants.MIXPANEL_TOKEN).track("Share Profile")
 }

to

Mixpanel.track(requireActivity(), "Share Profile")

Future Proof and Conclusion

If Mixpanel decides to update their getInstance() method, then I only have to change that one line in my object Mixpanel. This code refactor has been a long time coming. I’m just glad that I was able to push this out of the way. Now, on to the next refactor.