Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add support for google analytics userId #15

Merged
merged 6 commits into from
Jan 26, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ request.env['tracker'] = {

* `:anonymize_ip` - sets the tracker to remove the last octet from all IP addresses, see https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApi_gat?hl=de#_gat._anonymizeIp for details.
* `:cookie_domain` - sets the domain name for the GATC cookies. Defaults to `auto`.
* `:user_id` - defines a proc to set the [userId](https://developers.google.com/analytics/devguides/collection/analyticsjs/user-id). Ex: `user_id: lambda { |env| env['rack.session']['user_id'] }` would return the user_id from the session.
* `:site_speed_sample_rate` - Defines a new sample set size for Site Speed data collection, see https://developers.google.com/analytics/devguides/collection/gajs/methods/gaJSApiBasicConfiguration?hl=de#_gat.GA_Tracker_._setSiteSpeedSampleRate
* `:adjusted_bounce_rate_timeouts` - An array of times in seconds that the tracker will use to set timeouts for adjusted bounce rate tracking. See http://analytics.blogspot.ca/2012/07/tracking-adjusted-bounce-rate-in-google.html for details.
* `:enhanced_link_attribution` - Enables [Enhanced Link Attribution](https://developers.google.com/analytics/devguides/collection/analyticsjs/advanced#enhancedlink).
Expand Down
15 changes: 15 additions & 0 deletions lib/rack/tracker/google_analytics/google_analytics.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
class Rack::Tracker::GoogleAnalytics < Rack::Tracker::Handler

ALLOWED_TRACKER_OPTIONS = [:cookie_domain, :user_id]

class Send < OpenStruct
def initialize(attrs = {})
attrs.reverse_merge!(type: 'event')
Expand Down Expand Up @@ -28,6 +31,18 @@ def tracker
options[:tracker].respond_to?(:call) ? options[:tracker].call(env) : options[:tracker]
end

def tracker_options
@tracker_options ||= begin
tracker_options = {}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i know its a matter of taste, but personally i don't like these temporary variables, tap is your fried to get rid of 'em

options.slice(*ALLOWED_TRACKER_OPTIONS).each do |key, value|
if option_value = value.respond_to?(:call) ? value.call(env) : value
tracker_options["#{key}".camelize(:lower).to_sym] = "#{option_value}"
end
end
tracker_options
end
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could this maybe more generic? always camelize the keys, support #call on every option....

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point and useful for the cookie_domain with an i18n multihost setup 17000d3


def render
Tilt.new( File.join( File.dirname(__FILE__), 'template', 'google_analytics.erb') ).render(self)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
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', '<%= tracker %>', <%= (options[:cookie_domain] ? {cookieDomain: options[:cookie_domain]} : {}).to_json %>);
ga('create', '<%= tracker %>', <%= tracker_options.to_json %>);
}

<% if options[:enhanced_link_attribution] %>
Expand Down
52 changes: 51 additions & 1 deletion spec/handler/google_analytics_spec.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
RSpec.describe Rack::Tracker::GoogleAnalytics do

def env
{misc: 'foobar'}
{
misc: 'foobar',
user_id: '123'
}
end

it 'will be placed in the head' do
Expand Down Expand Up @@ -30,6 +33,44 @@ def env
end
end

describe '#tracker_options' do
before do
stub_const("#{described_class}::ALLOWED_TRACKER_OPTIONS", [:some_option])
end

context 'with an allowed option configured with a static value' do
subject { described_class.new(env, { some_option: 'value' }) }

it 'returns hash with option set' do
expect(subject.tracker_options).to eql ({ someOption: 'value' })
end
end

context 'with an allowed option configured with a block' do
subject { described_class.new(env, { some_option: lambda { |env| return env[:misc] } }) }

it 'returns hash with option set' do
expect(subject.tracker_options).to eql ({ someOption: 'foobar' })
end
end

context 'with an allowed option configured with a block returning nil' do
subject { described_class.new(env, { some_option: lambda { |env| return env[:non_existing_key] } }) }

it 'returns an empty hash' do
expect(subject.tracker_options).to eql ({})
end
end

context 'with a non allowed option' do
subject { described_class.new(env, { new_option: 'value' }) }

it 'returns an empty hash' do
expect(subject.tracker_options).to eql ({})
end
end
end

describe "with events" do
describe "default" do
def env
Expand Down Expand Up @@ -93,6 +134,15 @@ def env
end
end

describe "with user_id tracking" do
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isn't that something that should only be tested in the integration spec?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the cookieDomain thingy is tested here too.
both can be tested again in the integration spec too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok i'm just a bit confused as to what i should test where

subject { described_class.new(env, tracker: 'somebody', user_id: lambda { |env| return env[:user_id] } ).render }

it "will show asyncronous tracker with userId" do
expect(subject).to match(%r{ga\('create', 'somebody', {\"userId\":\"123\"}\)})
expect(subject).to match(%r{ga\('send', 'pageview'\)})
end
end

describe "with enhanced_link_attribution" do
subject { described_class.new(env, tracker: 'happy', enhanced_link_attribution: true).render }

Expand Down