I'm wondering what is the best way to implement Google Analytics tracking code along with the turbo linking in Rails 4. Will the normal snippet work? I've also seen a gems for this but I'm not sure what it does.
-
Can you please accept my answer? It looks like it helped some ones – vladCovaliov Aug 13 '14 at 05:42
8 Answers
I like vladCovaliov's solution because it seems most new accounts use Universal Analytics by default (which is also better featured in my opinion). However, I think this answer needs to be combined with the other suggestions that comment out the initial pageview, use the page:change
event, and track pageviews, not events.
For example, in your <head>
:
<% if Rails.env.production? %>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXXX-X', 'auto');
//ga('send', 'pageview');
</script>
<% else %>
<script>
function ga () {
var params = Array.prototype.slice.call(arguments, ga.length);
console.log("GoogleAnalytics: " + params);
};
</script>
<% end %>
And then in a js file you have loaded through the asset pipeline:
$(document).on('page:change', function() {
ga('send', 'pageview', window.location.pathname);
});
This will record a pageview for each page you load with or without Turbolinks. Note that the window.location.pathname
is required, otherwise you can get the URL of the first page loaded for all the subsequent page loads. (This also gives you a nice place to edit the URL reported if you wanted to, say, strip out :id
path segments from RESTful URLs.)
You can also then easily call:
ga('send', "event", category, action, label, count);
To report Events for other interesting javascript events in your site.

- 819
- 1
- 7
- 8
-
I have to say, I looked at many questions of this nature and ultimately went with this answer because of its simplicity. It also works flawlessly! Thank you very much! I'm using the `jquery-turbolinks` gem, so I replaced `$(document).on('page:change', function() {` with `$(document).ready(function() {` – Alexander Feb 28 '15 at 20:34
-
Even with `jquery-turbolinks`, if I change it to `$(document).ready`, it compounds pageviews reported to Google Analytics. First click is 2 views, 2nd is 4, 3rd is 8, etc. Tread lightly. (P. S. I may have been doing something wrong!) – Chris Peters Mar 06 '15 at 19:47
-
The `window.location.pathname` part is what I was looking for. Thanks a lot! – animatedgif Feb 21 '16 at 15:49
-
1Hi all, I implemented this code a long time ago and was wondering why my Site Searches were not being tracked. I ended up changing the last code snippet in the answer to: `ga('send', 'pageview', window.location.pathname + window.location.search);` The `window.location.search` includes search queries in the URL being sent to Google Analytics. – Alexander Feb 21 '16 at 21:03
-
I've went with a different approach that I saw on some web site but it seems reasonable.
Add GA to your header like usual but with a small modification of commenting out the trackPageview
event from happening automatically.
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-FOOBAR']);
//_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>
Then add this somewhere in your body
because the body gets reloaded for turbolinks.
<% if Rails.env.production? %>
<script>_gaq.push(['_trackPageview']);</script>
<% end %>
The production check is optional but this is a nice way to not have GA track localhost hits if you're actively developing. The other perk is you don't have to worry about messing with page:change or page:load bindings and that you can be confident that it'll work on any browser that's trackable by GA without having to worry about double hits or anything weird.

- 1,736
- 1
- 16
- 27
I think a better idea is to use the new Universal Analytics (from analytics.js file).
Universal Analytics Solution
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', "#{GA_UA}", "#{GA_URL}");
ga('send', 'pageview');
And then when you wanna send an event for example, you can use
<script> ga('send', "event", "#{category}", "#{action}", "#{label}", "#{count}"); </script>
Be careful to render this code in the body, and not in the head. Turbo-links only replaces the body.
And also be careful:
1) The GA_URL needs to match your pages's url
2) The Events show up in real time, but in the events tab, they only appear after 24h +
3) Your account's property need to be 'Universal' for this solution to work
Universal Analytics docs:
https://support.google.com/analytics/answer/2790010?hl=en&ref_topic=2790009

- 37,240
- 11
- 105
- 116

- 4,333
- 2
- 43
- 58
-
3I figured it would be unnecessary to load Analytics on each Turbolinks page load, so I read up on [page tracking with Universal analytics](https://developers.google.com/analytics/devguides/collection/analyticsjs/pages) and did some tests, and came to the conclusion that you should put all but the last line in the so that it only loads once, and then put `ga('send', 'pageview')` in the . The GA_URL argument can be replaced with 'auto', since the 'pageview' call will always determine the URL correctly – even with Turbolinks. – hannes_l Aug 28 '14 at 09:43
-
4@hannes_l That didn't work for me. It just sends the original URL on every subsequent Turbolinks page change. However, I noticed in the docs you linked to that you can do `ga('send', 'pageview', '<%= request.path %>');` to override the URL - which *does* work for me. – Tim Jones Aug 28 '14 at 15:27
-
Yes, you're right. I probably overinterpreted what I read about how the current path is calculated. So it seems to be a good idea to put your last snippet in the and everything else in the – at least that's what I'm going with for now. – hannes_l Aug 29 '14 at 06:50
A quick glance into the source shows, that the only thing this gem does is to add some javascript to the asset-pipeline
# google-analytics-turbolinks/lib/assets/javascripts/google-analytics-turbolinks.js.coffee
if window.history?.pushState and window.history.replaceState
document.addEventListener 'page:change', (event) =>
# Google Analytics
if window.ga != undefined
ga('set', 'location', location.href.split('#')[0])
ga('send', 'pageview')
else if window._gaq != undefined
_gaq.push(['_trackPageview'])
else if window.pageTracker != undefined
pageTracker._trackPageview();
That's all there is to it. You can either use the gem or add something like this code-snippet manually to your javascript-assets.

- 6,297
- 3
- 23
- 33
I appreciate scottwb's answer, but unfortunately it does not work with Rails 5. In Rails 5 Turbolinks events were renamed. The 'page:change' event was renamed to 'turbolinks:load'. This is why his example does not work anymore.
You can find an overview of how they were renamed here: https://github.com/turbolinks/turbolinks/blob/master/src/turbolinks/compatibility.coffee
Since this took me some time to figure out, I am posting the proper Rails 5 implementation for everybody coming after me.
Put the following code in your <head>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-XXXXXXXX-X', 'auto');
//ga('send', 'pageview'); //moved to an asset file because of turbolinks
</script>
And then in a js file (eg. application.js
) in you asset pipeline:
$(document).on('turbolinks:load', function() {
ga('send', 'pageview', window.location.pathname + window.location.search);
});
Remember to replace "UA-XXXXXXXX-X" with your Google Analytics ID.

- 945
- 7
- 10
This solution has worked the best for me: http://reed.github.io/turbolinks-compatibility/google_analytics.html.
It requires at least Turbolinks v2.1.0 or greater.

- 8,312
- 5
- 32
- 28
We just took the standard snippet provided by Google, translated it to CoffeeScript, then modified the last action so it is bound to both the "ready" and "page:load" events. We also added conditional statement to only send the data if the current visitor is not at an admin (so our data remains as clean as possible).
((i, s, o, g, r, a, m) ->
i["GoogleAnalyticsObject"] = r
i[r] = i[r] or ->
(i[r].q = i[r].q or []).push arguments
return
i[r].l = 1 * new Date()
a = s.createElement(o)
m = s.getElementsByTagName(o)[0]
a.async = 1
a.src = g
m.parentNode.insertBefore a, m
return
) window, document, "script", "//www.google-analytics.com/analytics.js", "ga"
ga "create", 'UA-XXXXXXXX-XX', "yourdomain.com"
$(document).on 'ready page:load', ->
ga "send", "pageview", window.location.pathname unless $('body').data('admin') is true

- 459
- 4
- 12
According to this site, you only need to do a slight modification. The problem with Turbolinks is that it only updates parts of the website and therefore, Google Analytics often doesn't perceive that the page has changed. Thus, you must notify it manually by adding the following CoffeeScript to a file in your assets/javascript folder:
$(document).on 'page:change', ->
if window._gaq?
_gaq.push ['_trackPageview']
else if window.pageTracker?
pageTracker._trackPageview()
NOTE: this is not my code, it is taken directly from the previously linked website

- 1,545
- 13
- 16