MP Logo

Tutorial - DAU/MAU

DAU/MAU is a common metric used to measure stickiness (i.e. how engaged your users are). It's derived by dividing DAU (Daily Active Users) by MAU (Monthly Active Users). In this case we'll be substituting 'active user' for 'Button clicked' events.

More specifically, we'll be calculating the mean of the daily number of unique button clicks over one month and dividing that by the number of monthly unique button clicks for that same month. For example:

// the following example uses a week instead of a month for simplicity
var dau = {
    'Button clicked': {
        '4-1-2015': 10, // 10 unique users clicked a button on this day
        '4-2-2015': 1,  // 1 unique user clicked a button on this day (and every day thereafter)
        '4-3-2015': 1,
        '4-4-2015': 1,
        '4-5-2015': 1,
        '4-6-2015': 1,
        '4-7-2015': 1,
    }
}

// ≈ 2.4
var dauAverage = (10 + 1 + 1 + 1 + 1 + 1 + 1 + 1) / 7;

// assumes the same user clicked a button each day from 4-1 to 4-7 and that 9 other unique users clicked
// a button on 4-1-2015 for a total of 10 unique during that period of time
var mau = 10;

// = .24
var dauMau = dauAverage / mau;

// assumes 10 unique users clicked a button on 4-1-2015 and that each click from 4-2 to 4-7 was done
// by a different user
mau = 16;

// = .15
dauMau = dauAverage / mau;

In addition to that, we'll be segmenting those numbers by country (i.e. DAU/MAU by country). Now that we have a good understanding of what we'll be computing, let's break it down into steps so that we can build it from the ground-up using Mixpanel Platform:

1. Getting set up

2. Getting DAU by country

3. Getting MAU by country

4. Waiting for both data sets

5. Calculating DAU/MAU by country

6. Displaying the data

7. Sorting the data




Getting set up

If you haven't already done so, create a new blank slate report and call it DAU/MAU Tutorial:


Click the RUN button in the upper right corner of the editor; a new tab should open and you should see "Hello, World!" displayed in the upper left corner of your custom report:


Go back to your editor tab; remove the <h1>Hello, World!<h1> header at line 10 and add the following JavaScript code between the two bottom-most <script> tags so that your custom report looks like this:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <link rel="stylesheet" type="text/css" href="https://cdn.mxpnl.com/libs/mixpanel-platform/css/reset.css">
    <link rel="stylesheet" type="text/css" href="https://cdn.mxpnl.com/libs/mixpanel-platform/build/mixpanel-platform.v0.latest.min.css">
    <script src="https://cdn.mxpnl.com/libs/mixpanel-platform/build/mixpanel-platform.v0.latest.min.js"<>/script>
  </head>
  <body class="mixpanel-platform-body">
    <script>
      alert('Hello, world!');
    </script>
  </body>
</html>

Run your code again; an alert should pop up with that text. If that's all working, great! The foundation is set up and now we can begin filling your custom report with meaningful data.




Getting DAU by country

As you might have guessed, we need to query Mixpanel to get this data (if you're unfamiliar with how to do that with Mixpanel Platform, you might want to quickly read through Querying Mixpanel). The query that makes the most sense to use here is MP.api.segment (check out the examples and API reference).

Remove the alert('Hello, world!'); at line 11 and replace it with the following:

      var eventName = 'Button clicked';                         // replace with event name of your choice
      var $dau = MP.api.segment(eventName, 'mp_country_code', { // use segment query on eventName, and segment the data by country
          from: moment().subtract(30, 'days'),                  // 'from' date should be one month ago
          to: moment().subtract(1, 'days'),                     // 'to' date should be yesterday; partial data for today impacts DAU more than it does MAU
          unit: 'day',                                          // we want the number of button clicks for each day of the month
          type: 'unique'                                        // daily counts should be unique; multiple clicks by the same person in one day should be counted only once
      });

      $dau.done(function(results) {
          console.log(results.values());
      });

(Note: take a look at our Mixpanel Platform library dependencies if you're unfamiliar with Moment, the date/time JS library.)

(Note: if the .done() syntax is unfamiliar to you, make sure to read up on deferred objects, an instance of which is returned by the segment query.)

You can always see the current state of the code in the tutorial if you want a reference.

Run your code again and open up your JS console in the preview tab. You should see something reminiscent of this:


If your data is empty, make sure you replaced 'Button clicked' with an event (case sensitive) that exists in your project. While we've been testing what we've been writing, we haven't saved our progress; if we were to reload the page (do not do that yet!), we'd lose all our changes. Click the COMMIT button in the upper right corner of the editor to save your changes. It should bounce slightly and turn green, indicating your changes have been saved.


Nice job! You've queried Mixpanel for some meaningful data and are well on your way to building a useful dashboard.




Getting MAU by country

This very similar to getting DAU; we can reuse the DAU query by copying it and changing the unit from 'day' to 'month'. Copy the code below and paste it after the last line of code currently in the editor so that line 22 is blank:

      var $mau = MP.api.segment(eventName, 'mp_country_code', { // use segment query on eventName, and segment the data by country
          from: moment().subtract(30, 'days'),                  // 'from' date should be one month ago
          to: moment().subtract(1, 'days'),                     // 'to' date should be yesterday; partial data for today impacts DAU more than it does MAU
          unit: 'month',                                        // we want the number of button clicks that occured over the month
          type: 'unique'                                        // multiple clicks by the same person during any point in the month should be counted only once
      });

      $mau.done(function(results) {
          console.log(results.values());
      });

You can always see the current state of the code in the tutorial if you want a reference.

Commit and run your code. Look at your console and you should see two objects this time; one from the DAU query and another from the MAU query. Inspect the second object and you should see something like this:


(Note: it's OK if you have two dates per country; it just means those two values need to be summed because 30 days back spans over two different months [e.g. 2/14-2/28 and 3/1-3/15].)




Waiting for both data sets

Right now each query is logging the response data to the console when it arrives. Because these queries are made asynchronously, there's no guarantee the queries will finish in the order in which they were fired (e.g. the MAU query might finish before the DAU one). What we want to do, however, is act on the data when we've received both datasets. Since each query returns a jQuery Deferred, we can leverage this by using jQuery's $.when() function. We can essentially say, "When A and B have finished, do C." Or, in this case, "When the DAU and MAU queries have finished, execute the callback function in .done()."

Let's try this out. Remove the two .done()s in your editor and add the following after your $mau code:

      $.when($dau, $mau).done(function(dau, mau) {
          alert('Success!');
      });

You can always see the current state of the code in the tutorial if you want a reference.

Commit and run your code. Your browser should alert you with 'Success!' once the two queries have finished. If that worked, you're one step closer to completing your custom report!




Calculating DAU/MAU by country

We have DAU, we have MAU, and we're in a good position to act on the data once all of it has arrived. Now we need to perform the actual calculation. Luckily Mixpanel Platform comes with some utility methods to make this easy for us. The data passed to the callback executed by .done() are instances of Mixpanel Platform's MP.Data object (read up on it if you haven't already!). We can leverage this to easily perform the computation. Replace the alert() with the following:

        // average the DAU values and divide them by the MAU ones
        // (we sum the MAU in the case where the 30 days spans over two months)
        var dauMau = dau.avg().divide(mau.sum()).values();
        console.log(dauMau);

You can always see the current state of the code in the tutorial if you want a reference.

Commit and run your code. Look at your console again and you should see something like the following:





Displaying the data

Now that we have our data, let's look at it! We'll use Mixpanel Platform's bar chart for this. This is pretty straightforward. Replace the call to console.log with with the following:

        $('<div></div>').appendTo('body').MPChart({ // create chart
            chartType: 'bar',                       // make it a bar chart
            data: dauMau                            // set its data
        });

You can always see the current state of the code in the tutorial if you want a reference.

Commit and run your code. Your report should now be filled with a colorful bar chart showing DAU/MAU by country:


Congratulations; you've got a working custom report! Now it's time for the finishing touch.




Sorting the data

Everything is functional, but it'd be a bit more useful and easier on the eyes if the data was sorted. We can do this easily using Underscore, which is included as a Mixpanel Platform library dependency. Add the following between lines 29 and 30 in your custom report and replace dauMau with sortedData on line 32 (before you've made the insertion, or line 40 after):

        var sortedData = _.chain(dauMau) // enables function chaining
            .pairs()                     // convert each object to an array for sorting
            .sortBy(function(dauMau) {   // sort by the dau/mau value in descending order
                return -dauMau[1];
            })
            .object()                    // convert each array back to an object
            .value();                    // end the chaining and return the value

You can always see the current state of the code in the tutorial if you want a reference.

Commit and run your report. You should now have a beautiful chart sorted by descending values:


Congratulations! You've finished your first tutorial! If you want to take your custom report making to the next level, check out the next one, where you'll create a network funnel with D3.