Permalink
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
280 lines (252 sloc) 24.1 KB
<!DOCTYPE html>
<html>
<head>
<title>Finding Your Most Active Users - topdan.com</title>
<meta charset="UTF-8">
<meta name="description" content="Google Analytics is normally used to track a website's visitors and pageviews, but it can also track specific users, which can be invaluable information as you develop your customer base. Who is the most active? What are they using? Whose usage is fading?">
<meta name="author" content="Dan Cunning">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="twitter:card" content="summary">
<meta name="twitter:site" content="@itopdan">
<meta name="twitter:title" content="Finding Your Most Active Users">
<meta name="twitter:description" content="Google Analytics is normally used to track a website's visitors and pageviews, but it can also track specific users, which can be invaluable information as you develop your customer base. Who is the most active? What are they using? Whose usage is fading?">
<meta name="twitter:url" content="http://www.topdan.com/ruby-on-rails/finding-your-most-active-users-with-google-analytics.html">
<meta name="og:locale" content="en_US">
<meta name="og:type" content="article">
<meta name="og:url" content="http://www.topdan.com/ruby-on-rails/finding-your-most-active-users-with-google-analytics.html">
<meta name="og:title" content="Finding Your Most Active Users">
<meta name="og:description" content="Google Analytics is normally used to track a website's visitors and pageviews, but it can also track specific users, which can be invaluable information as you develop your customer base. Who is the most active? What are they using? Whose usage is fading?">
<link rel="shortcut icon" href="/assets/favicon-e45cdd6cc07e8858a985e6014e38a603.png">
<link rel="stylesheet" media="all" href="/assets/site-d30c732907c1f2982374b8bab9355d72.css"><!--[if lt IE 9]><script src='//html5shim.googlecode.com/svn/trunk/html5.js'></script><![endif]-->
<script type="text/javascript">
if (!document.cookie || document.cookie.indexOf('tracking_off') == -1) {
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-12957077-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
}
</script>
</head>
<body id="finding-your-most-active-users-with-google-analytics">
<div class="container bg-black full-width">
<div class="row navigation">
<a id="top"></a> <a href="/ruby-on-rails/ajax-toggle-buttons.html" class="previous"><span class="fa fa-arrow-left">&nbsp;</span> <span class="desktop">Ajax Toggle Buttons</span><span class="mobile">Previous</span></a> <a href="/ruby-on-rails/simple-infinite-scrolling.html" class="next"><span class="desktop">Infinite Scrolling with AJAX</span><span class="mobile">Next</span> <span class="fa fa-arrow-right">&nbsp;</span></a>
<p><a href="/"><span class="fa fa-home">&nbsp;</span></a> &nbsp;»&nbsp;<span class="title desktop"><a href="/ruby-on-rails/index.html">Ruby on Rails</a></span><span class="mobile"><a href="/ruby-on-rails/index.html"><span class="fa fa-folder-open">&nbsp;</span></a></span></p>
</div>
<div class="row bg-white">
<div class="col-md-12">
<div class="width-640 ml-auto mr-auto">
<p class="mt-05e mb-15e ta-right c-ccc">Published by Dan on May 29, 2014</p>
<h1 class="center of-yh mb-0"><a href="/ruby-on-rails/finding-your-most-active-users-with-google-analytics.html">Finding Your Most Active Users</a></h1>
<p class="mb-0 center">Filed under <a href="/ruby-on-rails/web-services.html">Web Services</a></p>
</div>
</div>
</div>
<div class="row bg-white">
<div class="col-md-12">
<div class="width-640 ml-auto mr-auto post">
<!-- post:content:start -->
<ul>
<li>
<a href="#the-introduction">Introduction</a>
</li>
<li>
<a href="#tracking-user-ids">Tracking User IDs</a>
</li>
<li>
<a href="#querying-google-analytics">Querying Google Analytics</a>
</li>
<li>
<a href="#generating-an-email">Generating an Email</a>
</li>
<li>
<a href="#scheduling-the-email">Scheduling the Email</a>
</li>
<li>
<a href="#conclusion">Conclusion</a>
</li>
</ul>
<h2 id="the-introduction"><a href="#the-introduction">Introduction</a></h2>
<p>You're using Google Analytics to track your web app's visitors, but you don't have visitors: you have users. Don't you want to know what they are doing? Who are your most active users? What do they use the most? Who should you contact directly about a feature improvement? Whose usage has dropped off?</p>
<h2 id="tracking-user-ids"><a href="#tracking-user-ids">Tracking User IDs</a></h2>
<p>Google Analytics accepts custom, site-specific data. It's really simple, just add one line to the snippet Google Analytics provides. The new Google Analytics snippet uses <a href="https://developers.google.com/analytics/devguides/collection/analyticsjs/custom-dims-mets">custom dimensions</a>, which you need to <a href="https://support.google.com/analytics/answer/2709829?hl=en">set up explicitly</a>. The older snippet uses <a href="https://developers.google.com/analytics/devguides/collection/gajs/gaTrackingCustomVariables">custom variables</a>, which doesn't require any set up.</p>
<div class="highlight">
<pre><span class="c1">// For New Snippets</span>
<span class="nx">ga</span><span class="p">(</span><span class="s1">'set'</span><span class="p">,</span> <span class="s1">'dimension1'</span><span class="p">,</span> <span class="o">&lt;%=</span> <span class="nx">current_user</span><span class="p">.</span><span class="nx">id</span> <span class="o">%&gt;</span><span class="p">);</span>
<span class="c1">// For Older Snippets</span>
<span class="nx">_gaq</span><span class="p">.</span><span class="nx">push</span><span class="p">([</span><span class="s1">'_setCustomVar'</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="s1">'User'</span><span class="p">,</span> <span class="o">&lt;%=</span> <span class="nx">current_user</span><span class="p">.</span><span class="nx">id</span> <span class="o">%&gt;</span><span class="p">,</span> <span class="mi">1</span><span class="p">]);</span>
</pre>
</div>
<h2 id="querying-google-analytics"><a href="#querying-google-analytics">Querying Google Analytics</a></h2>
<p>Now that you're associating a specific user with each pageview, you can use the Google Analytics API to group pageviews by user. I use <a href="https://rubygems.org/gems/garb">garb</a>.</p>
<div class="highlight">
<pre><span class="c1"># For Newer Snippets</span>
<span class="k">class</span> <span class="nc">UserActivity</span>
<span class="kp">extend</span> <span class="no">Garb</span><span class="o">::</span><span class="no">Model</span>
<span class="kp">extend</span> <span class="no">Garb</span><span class="o">::</span><span class="no">Queryable</span>
<span class="n">metrics</span> <span class="ss">:pageviews</span><span class="p">,</span> <span class="ss">:uniquePageviews</span>
<span class="n">dimensions</span> <span class="ss">:dimension1</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">struct</span><span class="p">)</span>
<span class="vi">@pageviews</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">pageviews</span><span class="o">.</span><span class="n">to_i</span>
<span class="vi">@user_id</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">dimension1</span><span class="o">.</span><span class="n">to_i</span>
<span class="vi">@user_id</span> <span class="o">=</span> <span class="kp">nil</span> <span class="k">if</span> <span class="vi">@user_id</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">user</span>
<span class="vi">@user</span> <span class="o">||=</span> <span class="no">User</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="nb">id</span><span class="p">:</span> <span class="vi">@user_id</span><span class="p">)</span><span class="o">.</span><span class="n">first</span> <span class="k">if</span> <span class="vi">@user_id</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">email</span>
<span class="n">user</span><span class="o">.</span><span class="n">email</span> <span class="k">if</span> <span class="n">user</span>
<span class="k">end</span>
<span class="k">end</span>
</pre>
</div>
<div class="highlight">
<pre><span class="c1"># For Older Snippets</span>
<span class="k">class</span> <span class="nc">UserActivity</span>
<span class="kp">extend</span> <span class="no">Garb</span><span class="o">::</span><span class="no">Model</span>
<span class="kp">extend</span> <span class="no">Garb</span><span class="o">::</span><span class="no">Queryable</span>
<span class="n">metrics</span> <span class="ss">:pageviews</span><span class="p">,</span> <span class="ss">:uniquePageviews</span>
<span class="n">dimensions</span> <span class="ss">:customVarName1</span><span class="p">,</span> <span class="ss">:customVarValue1</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">struct</span><span class="p">)</span>
<span class="vi">@pageviews</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">pageviews</span><span class="o">.</span><span class="n">to_i</span>
<span class="vi">@user_id</span> <span class="o">=</span> <span class="n">struct</span><span class="o">.</span><span class="n">custom_var_value1</span><span class="o">.</span><span class="n">to_i</span> <span class="k">if</span> <span class="n">struct</span><span class="o">.</span><span class="n">custom_var_name1</span> <span class="o">==</span> <span class="s1">'User'</span>
<span class="vi">@user_id</span> <span class="o">=</span> <span class="kp">nil</span> <span class="k">if</span> <span class="vi">@user_id</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">user</span>
<span class="vi">@user</span> <span class="o">||=</span> <span class="no">User</span><span class="o">.</span><span class="n">where</span><span class="p">(</span><span class="nb">id</span><span class="p">:</span> <span class="vi">@user_id</span><span class="p">)</span><span class="o">.</span><span class="n">first</span> <span class="k">if</span> <span class="vi">@user_id</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">email</span>
<span class="n">user</span><span class="o">.</span><span class="n">email</span> <span class="k">if</span> <span class="n">user</span>
<span class="k">end</span>
<span class="k">end</span>
</pre>
</div>
<div class="highlight">
<pre><span class="k">module</span> <span class="nn">Garb::Queryable</span>
<span class="c1"># Instead of returning a Struct, return instances of the given class</span>
<span class="k">def</span> <span class="nf">query</span><span class="p">(</span><span class="n">profile</span><span class="p">,</span> <span class="n">options</span> <span class="o">=</span> <span class="p">{})</span>
<span class="n">results</span><span class="p">(</span><span class="n">profile</span><span class="p">,</span> <span class="n">options</span><span class="p">)</span><span class="o">.</span><span class="n">inject</span><span class="p">(</span><span class="o">[]</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">arr</span><span class="p">,</span> <span class="n">result</span><span class="o">|</span>
<span class="n">arr</span> <span class="o">&lt;&lt;</span> <span class="kp">new</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</pre>
</div>
<h2 id="generating-an-email"><a href="#generating-an-email">Generating an Email</a></h2>
<p>Emails are a passive way of tracking information. You don't need to go anywhere: it comes to you and fits nicely into most people's daily routines. Let's run a Rake task that authenticates with GA and delivers an email via ActionMailer.</p>
<div class="highlight">
<pre><span class="k">class</span> <span class="nc">AnalyticsMailer</span> <span class="o">&lt;</span> <span class="no">ActionMailer</span><span class="o">::</span><span class="no">Base</span>
<span class="k">def</span> <span class="nf">user_activity_report</span><span class="p">(</span><span class="n">to_email</span><span class="p">,</span> <span class="n">profile</span><span class="p">)</span>
<span class="c1"># Back one week from midnight last night</span>
<span class="n">start_at</span> <span class="o">=</span> <span class="no">Date</span><span class="o">.</span><span class="n">today</span> <span class="o">-</span> <span class="mi">1</span><span class="o">.</span><span class="n">week</span>
<span class="n">end_at</span> <span class="o">=</span> <span class="no">Date</span><span class="o">.</span><span class="n">today</span>
<span class="vi">@activities</span> <span class="o">=</span> <span class="no">UserActivity</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">profile</span><span class="p">,</span> <span class="ss">start_date</span><span class="p">:</span> <span class="n">start_at</span><span class="p">,</span> <span class="ss">end_date</span><span class="p">:</span> <span class="n">end_at</span><span class="p">)</span>
<span class="vi">@activities</span><span class="o">.</span><span class="n">sort!</span> <span class="p">{</span><span class="o">|</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">|</span> <span class="n">b</span><span class="o">.</span><span class="n">pageviews</span> <span class="o">&lt;=&gt;</span> <span class="n">a</span><span class="o">.</span><span class="n">pageviews</span> <span class="p">}</span>
<span class="k">return</span> <span class="k">if</span> <span class="vi">@activities</span><span class="o">.</span><span class="n">empty?</span>
<span class="n">mail_to</span><span class="p">({</span>
<span class="ss">to</span><span class="p">:</span> <span class="n">to_email</span><span class="p">,</span>
<span class="ss">subject</span><span class="p">:</span> <span class="s2">"[</span><span class="si">#{</span><span class="n">profile</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s2">] User Activity"</span>
<span class="p">})</span>
<span class="k">end</span>
<span class="k">end</span>
</pre>
</div>
<div class="highlight">
<pre><span class="c">&lt;!-- views/analytics_mailer/user_activity_report.html.erb --&gt;</span>
<span class="nt">&lt;h2&gt;</span>Active Users<span class="nt">&lt;/h2&gt;</span>
<span class="nt">&lt;table&gt;</span>
<span class="nt">&lt;thead&gt;</span>
<span class="nt">&lt;tr&gt;</span>
<span class="nt">&lt;th&gt;</span>Email<span class="nt">&lt;/th&gt;</span>
<span class="nt">&lt;th&gt;</span>Pageviews<span class="nt">&lt;/th&gt;</span>
<span class="nt">&lt;th&gt;</span>Unique Pageviews<span class="nt">&lt;/th&gt;</span>
<span class="nt">&lt;/tr&gt;</span>
<span class="nt">&lt;/thead&gt;</span>
<span class="nt">&lt;tbody&gt;</span>
<span class="cp">&lt;%</span> <span class="vi">@activities</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">activity</span><span class="o">|</span> <span class="cp">%&gt;</span>
<span class="nt">&lt;tr&gt;</span>
<span class="nt">&lt;td&gt;</span><span class="cp">&lt;%=</span> <span class="n">activity</span><span class="o">.</span><span class="n">email</span> <span class="cp">%&gt;</span><span class="nt">&lt;/td&gt;</span>
<span class="nt">&lt;td&gt;</span><span class="cp">&lt;%=</span> <span class="n">activity</span><span class="o">.</span><span class="n">pageviews</span> <span class="cp">%&gt;</span><span class="nt">&lt;/td&gt;</span>
<span class="nt">&lt;td&gt;</span><span class="cp">&lt;%=</span> <span class="n">activity</span><span class="o">.</span><span class="n">unique_pageviews</span> <span class="cp">%&gt;</span><span class="nt">&lt;/td&gt;</span>
<span class="nt">&lt;/tr&gt;</span>
<span class="cp">&lt;%</span> <span class="k">end</span> <span class="cp">%&gt;</span>
<span class="nt">&lt;/tbody&gt;</span>
<span class="nt">&lt;/table&gt;</span>
</pre>
</div>
<div class="highlight">
<pre><span class="c1"># lib/tasks/analytics.rake</span>
<span class="n">namespace</span> <span class="ss">:analytics</span> <span class="k">do</span>
<span class="n">namespace</span> <span class="ss">:user_activity_report</span> <span class="k">do</span>
<span class="n">desc</span> <span class="s1">'Delivers the user activity report'</span>
<span class="n">task</span> <span class="ss">deliver</span><span class="p">:</span> <span class="ss">:environment</span> <span class="k">do</span>
<span class="n">email</span> <span class="o">=</span> <span class="s1">'dan@topdan.com'</span>
<span class="n">password</span> <span class="o">=</span> <span class="s1">'use-two-factor-auth-instead'</span>
<span class="n">site_name</span> <span class="o">=</span> <span class="s1">'www.topdan.com'</span> <span class="c1"># name of your Google Analytics "Property"</span>
<span class="no">Garb</span><span class="o">::</span><span class="no">Session</span><span class="o">.</span><span class="n">login</span><span class="p">(</span><span class="n">email</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>
<span class="c1"># Garb::Session.api_key = api_key # required for 2-step authentication</span>
<span class="n">profiles</span> <span class="o">=</span> <span class="no">Garb</span><span class="o">::</span><span class="no">Management</span><span class="o">::</span><span class="no">Profile</span><span class="o">.</span><span class="n">all</span>
<span class="n">profile</span> <span class="o">=</span> <span class="n">profiles</span><span class="o">.</span><span class="n">detect</span> <span class="p">{</span><span class="o">|</span><span class="nb">p</span><span class="o">|</span> <span class="nb">p</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="n">site_name</span> <span class="p">}</span>
<span class="no">AnalyticsMailer</span><span class="o">.</span><span class="n">user_activity_report</span><span class="p">(</span><span class="n">email</span><span class="p">,</span> <span class="n">profile</span><span class="p">)</span><span class="o">.</span><span class="n">deliver</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</pre>
</div>
<h2 id="scheduling-the-email"><a href="#scheduling-the-email">Scheduling the Email</a></h2>
<p>The <a href="http://rubygems.org/gems/whenever">whenever</a> gem provides a slick interface for managing your application's <a href="http://en.wikipedia.org/wiki/Cron">cronjobs</a>, with an easy integration into Capistrano.</p>
<div class="highlight">
<pre><span class="c1"># config/schedule.rb</span>
<span class="n">every</span> <span class="ss">:monday</span><span class="p">,</span> <span class="ss">at</span><span class="p">:</span> <span class="s2">"8:00am"</span> <span class="k">do</span>
<span class="n">rake</span> <span class="s2">"analytics:user_activity_report:deliver"</span>
<span class="k">end</span>
</pre>
</div>
<div class="highlight">
<pre><span class="c1"># config/deploy/production.rb</span>
<span class="nb">require</span> <span class="s2">"whenever/capistrano"</span>
</pre>
</div>
<h2 id="conclusion"><a href="#conclusion">Conclusion</a></h2>
<p>Now you'll get an email every Monday morning telling you who your most active users were last week. The email takes just a couple seconds to browse over and can really improve and target your customer service and product development.</p>
<p>Finding your most active users is only the beginning. Google Analytics can answer a lot more questions:</p>
<ul>
<li>How much time did a user spend on each page? What was the average?</li>
<li>What individual pages did a specific someone use? In what order?</li>
<li>Who are the major users of a specific page?</li>
<li>Who had 50% more/less pageviews this week than last week?</li>
</ul>
<p><a href="https://developers.google.com/analytics/devguides/reporting/core/dimsmets">Check out all the Dimensions & Metrics</a></p><!-- post:content:end -->
</div>
</div>
</div>
<div class="row navigation bb-ccc">
<a href="/ruby-on-rails/ajax-toggle-buttons.html" class="previous"><span class="fa fa-arrow-left">&nbsp;</span> <span class="desktop">Ajax Toggle Buttons</span><span class="mobile">Previous</span></a> <a href="/ruby-on-rails/simple-infinite-scrolling.html" class="next"><span class="desktop">Infinite Scrolling with AJAX</span><span class="mobile">Next</span> <span class="fa fa-arrow-right">&nbsp;</span></a>
<p><a href="/"><span class="fa fa-home">&nbsp;</span></a> &nbsp;»&nbsp;<span class="title desktop"><a href="/ruby-on-rails/index.html">Ruby on Rails</a></span><span class="mobile"><a href="/ruby-on-rails/index.html"><span class="fa fa-folder-open">&nbsp;</span></a></span></p>
</div>
<div class="row introduction pb-2e bb-ccc mb-1e">
<div class="col-md-6 mt-2e center">
<h1 class="mt-0"><a title="Dan Cunning" class="fs-45 fw-normal shadow-silver" href="/">Dan Cunning</a></h1>
<p class="reference mt-05e"><a title="github" class="white" href="https://github.com/topdan"><span class="fa fa-github">&nbsp;</span> GitHub</a> <a title="Twitter" class="white" href="https://www.linkedin.com/in/dancunning"><span class="fa fa-linkedin-square">&nbsp;</span> LinkedIn</a> <a title="Email" class="white" href="mailto:dan@topdan.com"><span class="fa fa-envelope">&nbsp;</span> Email</a></p>
</div>
<div class="col-sm-offset-1 col-md-4 mt-2e">
<img width="75" height="75" class="img-circle fl-left mr-10" src="/assets/dan-79508ca0775ace507f1dc34d151bba0f.jpg" alt="Dan">
<p class="underline-links">I'm a <a href="/ruby-on-rails/index.html">Ruby on Rails</a> contractor from Atlanta GA, focusing on simplicity and usability through solid design. <a class="nowrap" href="/dan-cunning.html">Read more »</a></p>
</div>
</div>
<div class="row fs-12 mt-1e center">
<div class="col-md-6">
<p class="underline-links mb-1e">View Source: <a href="https://github.com/topdan/www/blob/master/ruby-on-rails/finding-your-most-active-users-with-google-analytics.html">HTML</a> | <a href="https://github.com/topdan/www/blob/master/ruby-on-rails/finding-your-most-active-users-with-google-analytics.json">JSON</a> | <a href="https://github.com/topdan/www/blob/master/ruby-on-rails/finding-your-most-active-users-with-google-analytics.html.md">View</a></p>
</div>
<div class="col-md-6">
<p class="mb-1e">© 2012-2019 Dan Cunning. All rights reserved.</p>
</div>
</div>
</div>
</body>
</html>