Powerful Custom Dimensions in Universal Analytics

Custom Dimensions in Universal Analytics

Every now and then, your business requirements demand some metric or dimension that is not available out-of-the box in your analytics solution. Luckily, this is becoming less common as measurement systems evolve. With product developments like Universal Analytics, we have seen huge improvements in areas such as user-level segmentation. New technologies enable us to track and analyze user behavior in unprecedented ways.

This has also resulted in a decreased need for custom code implementation. With the shift to server-side data handling in Universal Analytics comes the ability to perform user-level segmentation directly in the Google Analytics interface. In fact, the new segmentation UI is so flexible and powerful that, before implementing any new custom code, you should think hard on whether your business requirement can already be satisfied by creating segments based on existing data.

Example: While in the past you needed to set user-level custom dimensions (previously custom variables) to ensure metadata would persist across sessions, you can now construct multi-visit conditions using the segmentation UI, rendering many custom dimension use cases somewhat obsolete. You may leverage 'Date of First Visit' to create cohorts, and user-level 'Conditions' and 'Sequences' to create buckets of visitors based on interactions.

Capturing First Time and Repeat interactions

However, there are still some gaps to fill for those of us interested in pushing the product to its limits by implementing custom code (yay!). While 'Date of First Visit' will show us when users visited our website or launched our application for the first time, enabling us to create cohorts, there are several other "firsts" which could be equally interesting to us. Additionally, there are many use cases for tracking the total number of various interactions per user. In this post, I will focus on what we may call First time and Repeat dimensions, using a mobile app as an example.

  • First timers: dimensions showing the date a user interacted with something for the first time, e.g. the date of a first purchase. This will expand our analysis beyond "Date of First Visit" to include the first of virtually anything.
  • Repeats: dimensions showing how many times a user has interacted with something, e.g. the number of purchases per user. This allows us to create additional user-level buckets based on recurrences.

These dimensions have tons of use cases and will enable us to answer questions such as:

  • How many users purchased product Y for the first time in a specific month?
  • How are users who performed X interaction at month Z behaving over time?
  • When did user-bucket A interact with content B for the first time?

This in turn cascades into a great number of sub-questions which we will now be empowered to answer.

Before moving on to the actual code and set up, let's look at some example segments you will be able to create through this implementation (after all, we want to make sure this kind of analysis is useful to your business before digging into the necessary code and configuration).

Example Segments

By measuring first time interactions as well as the total number of interactions per user, we open up for some really powerful analysis. Imagine the granularity you can reach with these types of segments available to you.

Show conversion rate for a given time period for users who made their first purchase in May

Conversion Rate segment

Show users who have made between 5-9 purchases in total, and made their first purchase during the first week of July

Repeated purchase segment

Show users who interacted socially for the first time on 4th of July

Social interaction segment

Show users who have made more than 10 downloads

Repeated conversion segment

The list goes on, and before implementing you should ask yourself: what additional segments would benefit my business analysis? Could I construct such segments with these First time and Repeat dimensions? If the answer is yes, let's get to it.

Time and Repeat Dimensions: A Mobile App Implementation

In this post I will provide an example of how to implement this approach in an Android app using the Google Analytics Android SDK (v3), which is built on top of the Universal Analytics platform (the methodology will therefore follow that of the new wire format). From an app development perspective, this will not entail any overly complicated logic or difficult client-side storage. In contrast, it is powerful in its simplicity.

At the root of this implementation lies the use of custom dimensions. Namely, we want to set the following two user-level custom dimensions:

  1. First {Interaction} Date
  2. Number of {Interactions}

For those unfamiliar, custom dimensions are just like the default dimensions available in Google Analytics, except you create them yourself, giving you the option to collect additional data that is not provided automatically.

Let's use in-app purchases as an example. For each user, we want to capture the 'First Purchase Date' as well as 'Number of Purchases'. However, the implementation can easily be extended to any type of interaction in the app: an event being triggered, particular content being viewed, etc.

Part A: Interface Configuration

The first step in getting started with custom dimensions is to create them in the GA interface (step-by-step instructions are available here). In the Admin section, we specify the Name and Scope of our new custom dimensions. Both of these should be set to a user-level as we want them to persist across sessions and be associated with all hits for our users.

Set up custom dimensions

In Universal Analytics, Custom Variables have been replaced by Custom Dimensions. These are very similar in concept, with the main difference that Custom Dimensions are considered "first class" dimensions in reports. Without going into too much detail here, this means that you set up the Custom Dimension, in terms of Name and Scope, in the GA interface. In your code implementation, you will only need to specify the Value and the corresponding Index. This means less bytes in the requests to GA servers, and more flexibility for you to rename or change the Scope of your Custom Dimensions in the future.

Part B: Code Implementation

Let's move on to the code. Step-by-step, this is what we need to do:

  1. Get an instance of Google Analytics and Calendar
  2. When a user makes a purchase, determine whether it is the first time
  3. If yes, set custom dimension 1 and 2. If no, simply update custom dimension 2
  4. Update the user's total number of purchases client-side for future reference

Step 1: Get an instance of Google Analytics and Calendar

Before we can use any of its methods, we need to get an instance of Google Analytics and a reference to our Tracker object. The Tracker object is responsible for tracking a particular tracking ID (UA-XXXX-Y), telling Google Analytics which property to send data to. We also need to get an instance of the Calendar class, which we will use to pass date values to our custom dimensions.

For simplicity, we will do this in onCreate of a main entry point of our app. During initialization we could also set custom configurations for the Tracker, such as modifying the dispatch period, anonymize IP, etc. (alternatively, we could use EasyTracker for our configurations, or initialize Google Analytics in a subclass of Application, to create a singleton that can be used throughout our app).

Step 2: Is the User Making a Purchase For the First Time?

We need some way of determining whether a user making a purchase in our app is doing so for the first time. To that end, we can easily utilize SharedPreferences, a class which allows you to save and retrieve persistent key-value pairs of primitive data types. We want to save a number in SharedPreferences called "numPurchases". We will set this number after the first purchase, with the value of 1. This means that "numPurchases" will only be present if a user has already made a purchase. By checking whether "numPurchases" exists or not when a user makes a purchase, we can determine whether the user is making a purchase for the first time.

Step 3: Set Custom Dimensions

If the user is making an in-app purchase for the first time (i.e. "numPurchases" equals zero), we're going to set custom dimension 1, "First Purchase Date". We will use our Calendar class to pass the current date as the value of the custom dimension in the format day/month/year. Additionally, We will set our second custom dimension, "Number of Purchases", with the value of 1.

If it is not the first time a user makes an in-app purchase, we will instead increment "numPurchases" by 1 and pass that value to our second custom dimension, "Number of purchases".

In both cases, we're attaching the custom dimensions to an appview hit (to send the data for processing, custom dimensions always need to be set prior to a tracking call). For an in-app purchase like this, you might instead want to use ecommerce measurement hits. For the purpose of this example, however, we're sticking with a simple appview. The screen name in the appview hit ("purchase") could be used as a Goal screen in Google Analytics.

Step 4: Update the number of purchases

Finally, we need to update our "numPurchases" number and save it in SharedPreferences. This way, the next time a user makes a purchase, "numPurchases" will reflect an updated value corresponding to that user's total number of purchases.

We're done! You may find the complete script below.

Complete Script: First Time and Repeat Dimensions In a Mobile App

public class ExampleActivity extends Activity {

    private Tracker gaTracker;
    private Integer mYear;
    private Integer mMonth;
    private Integer mDay;
    private SharedPreferences mPrefs;
    final String numPurchasesPref = "numPurchases";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // get instance of GoogleAnalytics and a reference to Tracker
        gaTracker = GoogleAnalytics.getInstance(this).getTracker("UA-XXXXX-Y");  // replace XXXXX-Y with your own tracker ID

        // get instance of Calendar and relevant fields
        final Calendar c = Calendar.getInstance();
        mYear = c.get(Calendar.YEAR);
        mMonth = c.get(Calendar.MONTH);
        mDay = c.get(Calendar.DAY_OF_MONTH);
    }

    public void onPurchase(View v) {
        mPrefs = PreferenceManager.getDefaultSharedPreferences(this);
        int numPurchases = mPrefs.getInt(numPurchasesPref, 0);

        if (numPurchases == 0) {
        gaTracker.send(MapBuilder
        .createAppView()
        .set(Fields.SCREEN_NAME, "purchase")
        .set(Fields.customDimension(1), String.valueOf(mDay + "/" + (mMonth +1 ) + "/" + mYear))
        .set(Fields.customDimension(2), "1")
        .build()
        );
        } else {
        gaTracker.send(MapBuilder
        .createAppView()
        .set(Fields.SCREEN_NAME, "purchase")
        .set(Fields.customDimension(2), String.valueOf(numPurchases + 1))
        .build()
        );
        }

        // update and save numPurchases
        int numPurchasesUpdate = numPurchases + 1;
        SharedPreferences.Editor editor = mPrefs.edit();
        editor.putInt(numPurchasesPref, numPurchasesUpdate);
        editor.commit();
     }

}

What do you think? I would love to hear your comments as well as other use cases for this implementation.

Related Content

  1. Google Universal Analytics For Offline Behavior
  2. Google Analytics Custom Dimensions - 5 Questions
  3. Universal Analytics Form & The Measurement Protocol
Online Behavior © 2012