Tracking Google Analytics events in development environment with GoogleAnalyticsProxy »
Created at: 01.11.2009 21:55, source: Robby on Rails, tagged: Ruby on Rails PostgreSQL javascript analytics kpi googleanalytics events proxy opensource github prototype
As mentioned in a recent article1, I’ve been diving deep into Google Analytics lately while working on a few client projects. We’re aiming to use much more of the features of Google Analytics and have been hitting some roadblocks with the development versus production application environments. Once you begin to dive into event tracking and AJAX-driven goal conversions, relying on just the sample code that Google Analytics provides you is going to result in you looking at a handful of JavaScript errors.
another example from the firebug javascript console…
We see JavaScript errors like this because we don’t load the google analytics code in our development environments. As you can see, we are only loading this in our production environment.
<% if RAILS_ENV == 'production' -%>
<!--// Google Analytics //-->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-XXXXXX-1");
pageTracker._trackPageview();
</script>
<% end -%>To track an event with Google Analytics, you’d need to trigger something like:
pageTracker._trackEvent('Button', 'Click', 'Get in touch');As you can see from our code earlier, in development, the pageTracker variable isn’t defined and that’s why we’re getting those JS errors. We also don’t want to add conditionals everywhere in our application to check if we’re in development or production environment.. as that’d just make our views uglier than they need to be. So, I decided that I’d create a proxy class in JavaScript that would allow us to trigger _trackEvent() and _trackPageview() and handle it appropriately.
This class works with the following logic:
- if google analytics is loaded, pass the parameters to the real
pageTracker - if google analytics is NOT loaded, output the information to
console.log()for debugging purposes
For example, on a gallery on our web site… we track when people navigate next and/or previous through the photos. In our development environment, I can watch the JavaScript console output the following:
And in our production environment, we can see that this was sent to Google Analytics.
We’re able to do this by initializing the GoogleAnalyticsProxy class and calling these functions through it. For example:
_gap = new GoogleAnalyticsProxy();
_gap._trackEvent('Video', 'Play', 'Homepage video');
_gap._trackEvent('Video', 'Pause', 'Homepage video');
_gap._trackEvent('Button', 'Click', 'Call to action X');You’ll see that we’re just calling _gap versus pageTracker. We then replace all the instances of pageTracker (except where it is defined in the google analytics code block they provide you). You’ll find this located near the bottom of our application.html.erb file.
<% if RAILS_ENV == 'production' -%>
<!--// Google Analytics //-->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-XXXXXX-1");
pageTracker._trackPageview();
</script>
<% end -%>
<script type="text/javascript">
var _gap = new GoogleAnalyticsProxy();
</script>We now have _gap available throughout our project and can call _trackEvent() and _trackPageview() with it. Note: You can use any JS variable name that you want, _gap is just what I went with.
Get GoogleAnalyticsProxy
I’ve gone ahead and tossed this small JavaScript class (known as GoogleAnalyticsProxy) on Github for your enjoyment. I have some more articles in the works that will show you some tips for how to make the most of Google Analytics. If you have any questions and/or ideas for related article topics, don’t hesitate to let me know.
1 Tracking AJAX-driven events in Ruby on Rails for Google Analytics conversion goals
more »
Patterns Are Not Scary: Method Missing Proxy »
Created at: 08.08.2009 05:00, source: RailsTips - Home, tagged: patterns proxy
Method missing proxy? Ooooh! Sounds scary, right? I got news for you Walter Cronkite, it’s not. Lets start with the definition of proxy, according to Wikipedia.
Definition
A proxy, in its most general form, is a class functioning as an interface to something else.
An interface to something else. That sounds easy enough. You might be thinking that you have never used a proxy, but if you are reading this blog, you are wrong. Chances are you have used Rails, and if you have used Rails, chances are you have used has_many or some other ActiveRecord association, all of which are implemented using proxies under the hood.
Creating Your Own
Now that we have definition out of the way and have confirmed your use of proxies, let’s make one! Yay! The people rejoice! The basic idea of a proxy is a class that is an interface to something else. Lets call something else subject from now on. In order to get started, we’ll make a new proxy that has a subject.
class Proxy
def initialize(subject)
@subject = subject
end
end
proxied_array = Proxy.new([1,2,3])
puts proxied_array.size
# NoMethodError: undefined method ‘size’
FAIL! Our proxy has a subject (the array), but does not proxy anything yet. In order to proxy up the girl, lets throw in some method missing magic.
class Proxy
def initialize(subject)
@subject = subject
end
private
def method_missing(method, *args, &block)
@subject.send(method, *args, &block)
end
end
proxied_array = Proxy.new([1,2,3])
puts proxied_array.size # 3
Method missing takes 3 arguments: the method called, the arguments passed to the method and a block if one is given. With just that tiny method missing addition, we can now do fun things like this:
proxied_array = Proxy.new([1,2,3])
puts proxied_array.size # 3
puts proxied_array[0] # 1
puts proxied_array[1] # 2
puts proxied_array[2] # 3
puts proxied_array.select { |a| a > 1 }.inspect # [2, 3]
proxied_array << 4
puts proxied_array.size # 4
puts proxied_array[3] # 4
Just like that our proxied array behaves just like the original array. Well, almost like the original array.
puts proxied_array.class # Proxy
BlankSlate and BasicObject
Hmm, that is not quite what you would expect. We told the proxy to send everything to the subject, so it should output Array, not Proxy as the class, right? The problem is that any new class automatically has some methods included with it. In order for our Proxy class to be a true proxy, we need to remove those methods as well. In the Ruby 1.8 series, this is often done by defining a BlankSlate object which removes those methods and then have our Proxy inherit from BlankSlate.
class BlankSlate #:nodoc:
instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval|object_id/ }
end
class Proxy < BlankSlate
def initialize(subject)
@subject = subject
end
private
def method_missing(method, *args, &block)
@subject.send(method, *args, &block)
end
end
proxied_array = Proxy.new([1,2,3])
puts proxied_array.class # Array
Yay! Now we in fact get Array as one would expect. The great news is that Ruby 1.9 comes with a class like this already named BasicObject. The easy way to make this work with Ruby 1.8 and Ruby 1.9 is to just define BasicObject if it does not exist and then inherit from BasicObject, instead of dealing with BlankSlate.
class BasicObject #:nodoc:
instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval/ }
end unless defined?(BasicObject)
class Proxy < BasicObject
def initialize(subject)
@subject = subject
end
private
def method_missing(method, *args, &block)
@subject.send(method, *args, &block)
end
end
proxied_array = Proxy.new([1,2,3])
puts proxied_array.class # Array
Just like that our proxy is a full fledged proxy and it works with Ruby 1.8 and 1.9.
Example: MongoMapper Pagination
So other than ActiveRecord where else can you check out some proxies in the wild? In MongoMapper, pagination uses a method missing proxy. When someone uses paginate, instead of find, I wanted the result that was returned to also function much like WillPaginate::Collection does, but I didn’t want to inherit from Array.
You can view the pagination proxy on github. The paginate method that uses it looks like this:
def paginate(options)
per_page = options.delete(:per_page)
page = options.delete(:page)
total_entries = count(options[:conditions] || {})
collection = Pagination::PaginationProxy.new(total_entries, page, per_page)
options[:limit] = collection.limit
options[:offset] = collection.offset
collection.subject = find_every(options)
collection
end
Just like that, paginate returns results just like find, but also includes methods for total_pages, previous and next pages, total_entries and the like.
Example: HTTParty Response
In HTTParty, at first I just returned a ruby hash that was the parsed xml or json. Then, people started begging for response codes and headers, so I went with a Response proxy that looks like this:
module HTTParty
class Response < BlankSlate #:nodoc:
attr_accessor :body, :code, :message, :headers
attr_reader :delegate
def initialize(delegate, body, code, message, headers={})
@delegate = delegate
@body = body
@code = code.to_i
@message = message
@headers = headers
end
def method_missing(name, *args, &block)
@delegate.send(name, *args, &block)
end
end
end
Now I just pass the parsed response, the codes, headers, and such to Response.new and the people who want that information get it and those who don’t have no API change to wrestle with.
Conclusion
Hope this little primer on the Proxy pattern, specifically using Ruby’s method missing, is helpful. I also hope that because of this you check out some of the other great patterns that are out there. I know I avoided them for far too long. When applied correctly, they really lead to elegant solutions.
more »
Patterns Are Not Scary: Method Missing Proxy »
Created at: 07.08.2009 05:50, source: RailsTips - Home, tagged: patterns proxy
In which I show how to create a method missing proxy and provide some example uses in the wild.
Method missing proxy? Ooooh! Sounds scary, right? I got news for you Walter Cronkite, it’s not. Lets start with the definition of proxy, according to Wikipedia.
Definition
A proxy, in its most general form, is a class functioning as an interface to something else.
An interface to something else. That sounds easy enough. You might be thinking that you have never used a proxy, but if you are reading this blog, you are wrong. Chances are you have used Rails, and if you have used Rails, chances are you have used has_many or some other ActiveRecord association, all of which are implemented using proxies under the hood.
Creating Your Own
Now that we have definition out of the way and have confirmed your use of proxies, let’s make one! Yay! The people rejoice! The basic idea of a proxy is a class that is an interface to something else. Lets call something else subject from now on. In order to get started, we’ll make a new proxy that has a subject.
class Proxy
def initialize(subject)
@subject = subject
end
end
proxied_array = Proxy.new([1,2,3])
puts proxied_array.size
# NoMethodError: undefined method ‘size’
FAIL! Our proxy has a subject (the array), but does not proxy anything yet. In order to proxy up the girl, lets throw in some method missing magic.
class Proxy
def initialize(subject)
@subject = subject
end
private
def method_missing(method, *args, &block)
@subject.send(method, *args, &block)
end
end
proxied_array = Proxy.new([1,2,3])
puts proxied_array.size # 3
Method missing takes 3 arguments: the method called, the arguments passed to the method and a block if one is given. With just that tiny method missing addition, we can now do fun things like this:
proxied_array = Proxy.new([1,2,3])
puts proxied_array.size # 3
puts proxied_array[0] # 1
puts proxied_array[1] # 2
puts proxied_array[2] # 3
puts proxied_array.select { |a| a > 1 }.inspect # [2, 3]
proxied_array << 4
puts proxied_array.size # 4
puts proxied_array[3] # 4
Just like that our proxied array behaves just like the original array. Well, almost like the original array.
puts proxied_array.class # Proxy
BlankSlate and BasicObject
Hmm, that is not quite what you would expect. We told the proxy to send everything to the subject, so it should output Array, not Proxy as the class, right? The problem is that any new class automatically has some methods included with it. In order for our Proxy class to be a true proxy, we need to remove those methods as well. In the Ruby 1.8 series, this is often done by defining a BlankSlate object which removes those methods and then have our Proxy inherit from BlankSlate.
class BlankSlate #:nodoc:
instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval|object_id/ }
end
class Proxy < BlankSlate
def initialize(subject)
@subject = subject
end
private
def method_missing(method, *args, &block)
@subject.send(method, *args, &block)
end
end
proxied_array = Proxy.new([1,2,3])
puts proxied_array.class # Array
Yay! Now we in fact get Array as one would expect. The great news is that Ruby 1.9 comes with a class like this already named BasicObject. The easy way to make this work with Ruby 1.8 and Ruby 1.9 is to just define BasicObject if it does not exist and then inherit from BasicObject, instead of dealing with BlankSlate.
class BasicObject #:nodoc:
instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval/ }
end unless defined?(BasicObject)
class Proxy < BasicObject
def initialize(subject)
@subject = subject
end
private
def method_missing(method, *args, &block)
@subject.send(method, *args, &block)
end
end
proxied_array = Proxy.new([1,2,3])
puts proxied_array.class # Array
Just like that our proxy is a full fledged proxy and it works with Ruby 1.8 and 1.9.
Example: MongoMapper Pagination
So other than ActiveRecord where else can you check out some proxies in the wild? In MongoMapper, pagination uses a method missing proxy. When someone uses paginate, instead of find, I wanted the result that was returned to also function much like WillPaginate::Collection does, but I didn’t want to inherit from Array.
You can view the pagination proxy on github. The paginate method that uses it looks like this:
def paginate(options)
per_page = options.delete(:per_page)
page = options.delete(:page)
total_entries = count(options[:conditions] || {})
collection = Pagination::PaginationProxy.new(total_entries, page, per_page)
options[:limit] = collection.limit
options[:offset] = collection.offset
collection.subject = find_every(options)
collection
end
Just like that, paginate returns results just like find, but also includes methods for total_pages, previous and next pages, total_entries and the like.
Example: HTTParty Response
In HTTParty, at first I just returned a ruby hash that was the parsed xml or json. Then, people started begging for response codes and headers, so I went with a Response proxy that looks like this:
module HTTParty
class Response < BlankSlate #:nodoc:
attr_accessor :body, :code, :message, :headers
attr_reader :delegate
def initialize(delegate, body, code, message, headers={})
@delegate = delegate
@body = body
@code = code.to_i
@message = message
@headers = headers
end
def method_missing(name, *args, &block)
@delegate.send(name, *args, &block)
end
end
end
Now I just pass the parsed response, the codes, headers, and such to Response.new and the people who want that information get it and those who don’t have no API change to wrestle with.
Conclusion
Hope this little primer on the Proxy pattern, specifically using Ruby’s method missing, is helpful. I also hope that because of this you check out some of the other great patterns that are out there. I know I avoided them for far too long. When applied correctly, they really lead to elegant solutions.
more »
Patterns Are Not Scary: Method Missing Proxy »
Created at: 07.08.2009 05:50, source: RailsTips - Home, tagged: patterns proxy
Method missing proxy? Ooooh! Sounds scary, right? I got news for you Walter Cronkite, it’s not. Lets start with the definition of proxy, according to Wikipedia.
Definition
A proxy, in its most general form, is a class functioning as an interface to something else.
An interface to something else. That sounds easy enough. You might be thinking that you have never used a proxy, but if you are reading this blog, you are wrong. Chances are you have used Rails, and if you have used Rails, chances are you have used has_many or some other ActiveRecord association, all of which are implemented using proxies under the hood.
Creating Your Own
Now that we have definition out of the way and have confirmed your use of proxies, let’s make one! Yay! The people rejoice! The basic idea of a proxy is a class that is an interface to something else. Lets call something else subject from now on. In order to get started, we’ll make a new proxy that has a subject.
class Proxy
def initialize(subject)
@subject = subject
end
end
proxied_array = Proxy.new([1,2,3])
puts proxied_array.size
# NoMethodError: undefined method ‘size’
FAIL! Our proxy has a subject (the array), but does not proxy anything yet. In order to proxy up the girl, lets throw in some method missing magic.
class Proxy
def initialize(subject)
@subject = subject
end
private
def method_missing(method, *args, &block)
@subject.send(method, *args, &block)
end
end
proxied_array = Proxy.new([1,2,3])
puts proxied_array.size # 3
Method missing takes 3 arguments: the method called, the arguments passed to the method and a block if one is given. With just that tiny method missing addition, we can now do fun things like this:
proxied_array = Proxy.new([1,2,3])
puts proxied_array.size # 3
puts proxied_array[0] # 1
puts proxied_array[1] # 2
puts proxied_array[2] # 3
puts proxied_array.select { |a| a > 1 }.inspect # [2, 3]
proxied_array << 4
puts proxied_array.size # 4
puts proxied_array[3] # 4
Just like that our proxied array behaves just like the original array. Well, almost like the original array.
puts proxied_array.class # Proxy
BlankSlate and BasicObject
Hmm, that is not quite what you would expect. We told the proxy to send everything to the subject, so it should output Array, not Proxy as the class, right? The problem is that any new class automatically has some methods included with it. In order for our Proxy class to be a true proxy, we need to remove those methods as well. In the Ruby 1.8 series, this is often done by defining a BlankSlate object which removes those methods and then have our Proxy inherit from BlankSlate.
class BlankSlate #:nodoc:
instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval|object_id/ }
end
class Proxy < BlankSlate
def initialize(subject)
@subject = subject
end
private
def method_missing(method, *args, &block)
@subject.send(method, *args, &block)
end
end
proxied_array = Proxy.new([1,2,3])
puts proxied_array.class # Array
Yay! Now we in fact get Array as one would expect. The great news is that Ruby 1.9 comes with a class like this already named BasicObject. The easy way to make this work with Ruby 1.8 and Ruby 1.9 is to just define BasicObject if it does not exist and then inherit from BasicObject, instead of dealing with BlankSlate.
class BasicObject #:nodoc:
instance_methods.each { |m| undef_method m unless m =~ /^__|instance_eval/ }
end unless defined?(BasicObject)
class Proxy < BasicObject
def initialize(subject)
@subject = subject
end
private
def method_missing(method, *args, &block)
@subject.send(method, *args, &block)
end
end
proxied_array = Proxy.new([1,2,3])
puts proxied_array.class # Array
Just like that our proxy is a full fledged proxy and it works with Ruby 1.8 and 1.9.
Example: MongoMapper Pagination
So other than ActiveRecord where else can you check out some proxies in the wild? In MongoMapper, pagination uses a method missing proxy. When someone uses paginate, instead of find, I wanted the result that was returned to also function much like WillPaginate::Collection does, but I didn’t want to inherit from Array.
You can view the pagination proxy on github. The paginate method that uses it looks like this:
def paginate(options)
per_page = options.delete(:per_page)
page = options.delete(:page)
total_entries = count(options[:conditions] || {})
collection = Pagination::PaginationProxy.new(total_entries, page, per_page)
options[:limit] = collection.limit
options[:offset] = collection.offset
collection.subject = find_every(options)
collection
end
Just like that, paginate returns results just like find, but also includes methods for total_pages, previous and next pages, total_entries and the like.
Example: HTTParty Response
In HTTParty, at first I just returned a ruby hash that was the parsed xml or json. Then, people started begging for response codes and headers, so I went with a Response proxy that looks like this:
module HTTParty
class Response < BlankSlate #:nodoc:
attr_accessor :body, :code, :message, :headers
attr_reader :delegate
def initialize(delegate, body, code, message, headers={})
@delegate = delegate
@body = body
@code = code.to_i
@message = message
@headers = headers
end
def method_missing(name, *args, &block)
@delegate.send(name, *args, &block)
end
end
end
Now I just pass the parsed response, the codes, headers, and such to Response.new and the people who want that information get it and those who don’t have no API change to wrestle with.
Conclusion
Hope this little primer on the Proxy pattern, specifically using Ruby’s method missing, is helpful. I also hope that because of this you check out some of the other great patterns that are out there. I know I avoided them for far too long. When applied correctly, they really lead to elegant solutions.
more »




