diff --git a/.gitignore b/.gitignore index 9f30a35..60bd284 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ pkg/* *.gem .bundle +Guardfile diff --git a/Gemfile.lock b/Gemfile.lock index ef11b50..0ed9b69 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - gabba (0.0.1) + gabba (0.1.1) GEM remote: http://rubygems.org/ diff --git a/README b/README index cf376a4..f707bdf 100644 --- a/README +++ b/README @@ -1,12 +1,42 @@ -== Simple class to send custom server-side events to Google Analytics +Simple class to send custom server-side events to Google Analytics +================================================================== Heavily influenced by the http://code.google.com/p/serversidegoogleanalytics HOW TO USE: +----------- - Track page views Gabba::Gabba.new("UT-1234", "mydomain.com").page_view("something", "track/me") - Track custom events Gabba::Gabba.new("UT-1234", "mydomain.com").event("Videos", "Play", "ID", "123") + +IN THIS FORK: +------------- + +* Setting custom vars + + # Index: 1 through 5 + index = 1 + + # Scope: VISITOR, SESSION or PAGE + scope = Gabba::Gabba::VISITOR + + # Set var + gabba.set_custom_var(index, 'Name', 'Value', scope) + + # Track the event (all vars will be included) + gabba.event(...) + + # Track the page view (all vars will be included) + gabba.page_view(...) + +* Removing custom vars + + # Index: 1 through 5 + index = 1 + + # Delete var with this index + gabba.delete_custom_var index \ No newline at end of file diff --git a/lib/gabba/gabba.rb b/lib/gabba/gabba.rb index 9a3d0c5..3f81d30 100644 --- a/lib/gabba/gabba.rb +++ b/lib/gabba/gabba.rb @@ -14,6 +14,13 @@ class Gabba GOOGLE_HOST = "www.google-analytics.com" BEACON_PATH = "/__utm.gif" USER_AGENT = "Gabba #{VERSION} Agent" + + # Custom var levels + VISITOR = 1 + SESSION = 2 + PAGE = 3 + + ESCAPES = %w{ ' ! * ) } attr_accessor :utmwv, :utmn, :utmhn, :utmcs, :utmul, :utmdt, :utmp, :utmac, :utmt, :utmcc, :user_agent @@ -28,15 +35,48 @@ def initialize(ga_acct, domain, agent = Gabba::USER_AGENT) @utmac = ga_acct @utmhn = domain @user_agent = agent + + @custom_vars = [] end + def set_custom_var(index, name, value, scope) + raise "Index must be between 1 and 5" unless (1..5).include?(index) + raise "Scope must be 1 (VISITOR), 2 (SESSION) or 3 (PAGE)" unless (1..3).include?(scope) + + @custom_vars[index] = [ name, value, scope ] + end + + def delete_custom_var(index) + raise "Index must be between 1 and 5" unless (1..5).include?(index) + + @custom_vars.delete_at(index) + end + + def custom_var_data + names = [] + values = [] + scopes = [] + + idx = 1 + @custom_vars.each_with_index do |(n, v, s), i| + next if !n || !v || (/\w/ !~ n) || (/\w/ !~ v) + prefix = "#{i}!" if idx != i + names << "#{prefix}#{escape(n)}" + values << "#{prefix}#{escape(v)}" + scopes << "#{prefix}#{escape(s)}" + idx = i + 1 + end + + names.empty? ? "" : "8(#{names.join('*')})9(#{values.join('*')})11(#{scopes.join('*')})" + end + def page_view(title, page, utmhid = random_id) check_account_params hey(page_view_params(title, page, utmhid)) end def page_view_params(title, page, utmhid = random_id) - { + options = { :utmwv => @utmwv, :utmn => @utmn, :utmhn => @utmhn, @@ -48,6 +88,12 @@ def page_view_params(title, page, utmhid = random_id) :utmac => @utmac, :utmcc => @utmcc || cookie_params } + + # Add custom vars if present + cvd = custom_var_data + options[:utme] = cvd if /\w/ =~ cvd + + options end def event(category, action, label = nil, value = nil, utmhid = random_id) @@ -61,7 +107,7 @@ def event_params(category, action, label = nil, value = nil, utmhid = nil) :utmn => @utmn, :utmhn => @utmhn, :utmt => 'event', - :utme => event_data(category, action, label, value), + :utme => "#{event_data(category, action, label, value)}#{custom_var_data}", :utmcs => @utmcs, :utmul => @utmul, :utmhid => utmhid, @@ -171,6 +217,14 @@ def random_id rand 8999999999 + 1000000000 end + def escape(t) + return t if !t || (/\w/ !~ t.to_s) + + URI.escape(t.to_s).gsub(/[\*'!\)]/) do |m| + "'#{ESCAPES.index(m)}" + end + end + end # Gabba Class end \ No newline at end of file diff --git a/spec/gabba_spec.rb b/spec/gabba_spec.rb index 483f703..7b19a12 100644 --- a/spec/gabba_spec.rb +++ b/spec/gabba_spec.rb @@ -99,6 +99,67 @@ end end + describe "setting a custom var" do + before do + @gabba = Gabba::Gabba.new("abc", "123") + @gabba.utmn = "1009731272" + @gabba.utmcc = '' + end + + it "must return data for a valid var" do + @gabba.set_custom_var 1, 'A (B*\'!)', 'Yes', Gabba::Gabba::SESSION + @gabba.custom_var_data.must_equal "8(A%20(B'2'0'1'3)9(Yes)11(2)" + end + + it "must return data for several valid vards" do + @gabba.set_custom_var 1, 'A', 'Yes', Gabba::Gabba::SESSION + @gabba.set_custom_var 2, 'B', 'No', Gabba::Gabba::VISITOR + @gabba.custom_var_data.must_equal "8(A*B)9(Yes*No)11(2*1)" + end + + it "must return an empty string if vars aren't set" do + @gabba.custom_var_data.must_equal "" + end + + it "must not include var with an empty value" do + @gabba.set_custom_var 1, 'A', 'Yes', Gabba::Gabba::SESSION + @gabba.set_custom_var 2, 'B', '', Gabba::Gabba::VISITOR + @gabba.set_custom_var 3, 'C', ' ', Gabba::Gabba::VISITOR + @gabba.set_custom_var 4, 'D', nil, Gabba::Gabba::VISITOR + @gabba.custom_var_data.must_equal "8(A)9(Yes)11(2)" + end + + it "must mention index of the var if non sequential" do + @gabba.set_custom_var 2, 'A', 'Y', Gabba::Gabba::SESSION + @gabba.set_custom_var 4, 'D', 'N', Gabba::Gabba::VISITOR + @gabba.custom_var_data.must_equal "8(2!A*4!D)9(2!Y*4!N)11(2!2*4!1)" + end + + it "must raise an error if index is outside the 1-5 (incl) range" do + lambda { @gabba.set_custom_var(0, 'A', 'B', 1) }.must_raise(RuntimeError) + lambda { @gabba.set_custom_var(6, 'A', 'B', 1) }.must_raise(RuntimeError) + end + + it "must raise an error if scope is outside the 1-3 (incl) range" do + lambda { @gabba.set_custom_var(1, 'A', 'B', 0) }.must_raise(RuntimeError) + lambda { @gabba.set_custom_var(1, 'A', 'B', 4) }.must_raise(RuntimeError) + end + end + + describe 'delete custom var' do + before do + @gabba = Gabba::Gabba.new("abc", "123") + @gabba.utmn = "1009731272" + @gabba.utmcc = '' + end + + it "must return data for a valid var" do + @gabba.set_custom_var 1, 'A (B*\'!)', 'Yes', Gabba::Gabba::SESSION + @gabba.delete_custom_var 1 + @gabba.custom_var_data.must_equal "" + end + end + def stub_analytics(expected_params) s = stub_request(:get, /www.google-analytics.com\/__utm.gif\?utmac=#{expected_params[:utmac]}&.*/). to_return(:status => 200, :body => "", :headers => {})