Stand With Ukraine. Stop Putin. Stop War.

I like numbers, and analyzing them to see what is going on. As a result of that, I spend too much time in my Google Analytics code figuring out what is going on with my site and what content is most appreciated. However, I keep on finding non-public URLs for blogs which haven't been published yet in my stats.. but no more.

These visits are from when I visit a blog post which I've written to give it a quick proof-read, or to make sure the code blocks show up like they should. While not a disaster, I want to tackle this inconvenience and stop tracking my own visits. And hey, perhaps you can improve the quality of your clients' statistics with the same thing as well?

The Different Options and Considerations

There's a few things you can do. You can disable tracking for your IP through a Google Analytics filter, or by setting up a special page on your website/domain which sets a user cookie indicating we don't want Google Analytics to track us. While that would work, I also use my phone with HandyMan on 3G to work on my site or respond to comments and it would become a bit cumbersome to keep visiting a no-track page everytime I want to check my own site (as I'm pretty sure my phone's 3G IP changes quite often).

I just want to make sure anyone that is logged into the manager is not being tracked. So, perhaps I should just whip up a quick plugin that sets the Analytics cookie from the manager? Too bad that doesn't solve the issue when working on content on my phone yet...

Let's just get rid of the code!

The option I ended up going with is to just get rid of the entire Google Analytics code whenever I'm logged in on the Manager. This will work with HandyMan, as that simply logs you in to the manager as well, and I can live with seeing my own pageviews in my stats when I'm commenting on something without being logged in - after all, that's pretty much a valid request, right? :)

For this I first tried the "memberof" output filter on the 0 tag, however that gave problems when there was no user logged in as it returned a fatal error.. oops. I suspect this has been addressed in MODX 2.2, but as I haven't had the chance to test some quick-'n-dirty custom coding on my site in 2.2, I'm delaying doing the upgrade for now (tho it is a frick'n awesome release and I did launch some sites on it already!).

Now what? Custom snippet to the rescue!

Instead I quickly rolled my own code in a tiny snippet I called "isAdmin". The snippet looks somewhat (well, exactly) like this:

if ($modx->user instanceof modUser) {
  if ($modx->user->hasSessionContext('mgr')) { 
    return true;
  }
}
return false;

All it does is check to make sure we've got an active user account, and if we do it checks if we are authorized for the "mgr" context. It either returns true (which translates to 1) or false (0), so on its own it's not too useful yet.. however that does work pretty well with the "empty" and "notempty" output filters/modifiers.

Using the Snippet & Output Filters

To cut to the chase (this was supposed to be a quick tip) here's my Google Analytics chunk with the all new isAdmin snippet in action.

[[!isAdmin:notempty=`
<!-- Not tracking GA for Manager Users -->
 
`:default=`
<script type="text/javascript">
  var _gaq = _gaq || [];
  _gaq.push(['_setAccount', '[[++ga]]']);
  _gaq.push(['_trackPageview']);
  _gaq.push(['_trackPageLoadTime']);
  (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>
`]]

What's going on here:

  1. We're calling the isAdmin snippet uncached, as per Caching Guideline 2 for MODX Revolution.
  2. We're checking if the result of the snippet is notempty (so we see if it has data, in the case of our snippet that's a boolean "true" or "1" when a Manager user is logged in). If the snippet returns something we put in an HTML comment, that way you still know the Google Analytics is being parsed.
  3. Next we check the output with the "default" output filter, which is the same as "empty". As we've chained these output modifiers, the snippet would have the HTML comment as value at this point in case the snippet originally returned "1". If it returned "0" it would still be considered empty at this point, which means we dump our Google Analytics code to the screen.
  4. And of course don't forget to close the tag at the end :)

Something else: as you can see I'm also using a setting with key "ga" to store my Google Analytics code in a system-wide or context-specific setting, allowing me to reuse the chunk across contexts without having to change it, by simply setting the right analytics profile ID in the context setting. I'm also telling Google Analytics to track the page load time, which is a nifty statistic to have.

Alright, that's it for now! Enjoy!

Adam Smith

Nice :)

I have a similar setup outside of modx in code I rolled myself. I find there is value to the IP tracking and blocking as well. By doing so you don't track yourself (even when not admin). Thus not over inflating the numbers.

Great use of output filter. Already has my mind thinking of better solutions to things I am already doing.

Mark Hamstra

There's definitely a value to adding the IPs! I'm just too lazy to keep that updated when it changed :)

Someone actually made a MODX snippet based on the code here (he optimized the analytics code as well).. can install that via package management or from the MODX site: http://modx.com/extras/package/analytics

John Camacho

I love that isAdmin snippet. Really handy when I need to display something 'draft' on a page that needs to remain live for the public.

Comments are closed :(

While I would prefer to keep comments open indefinitely, the amount of spam that old articles attract is becoming a strain to keep up with and I can't always answer questions about ancient blog postings. If you have valuable feedback or important questions, please feel free to get in touch.