-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
initial commit; working on google analytics adapter
- Loading branch information
Maik Vlcek
committed
Aug 24, 2011
1 parent
fb29844
commit c62106c
Showing
9 changed files
with
494 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,7 +27,13 @@ pkg | |
# | ||
# For MacOS: | ||
# | ||
#.DS_Store | ||
.DS_Store | ||
|
||
# RubyMine | ||
.idea | ||
|
||
# RVM | ||
.rvmrc | ||
|
||
# For TextMate | ||
#*.tmproj | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
GEM | ||
remote: http://rubygems.org/ | ||
specs: | ||
git (1.2.5) | ||
jeweler (1.6.4) | ||
bundler (~> 1.0) | ||
git (>= 1.2.5) | ||
rake | ||
rake (0.9.2) | ||
rcov (0.9.10) | ||
shoulda (2.11.3) | ||
|
||
PLATFORMS | ||
ruby | ||
|
||
DEPENDENCIES | ||
bundler (~> 1.0.0) | ||
jeweler (~> 1.6.4) | ||
rcov | ||
shoulda |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
require 'open-uri' | ||
|
||
# load string helpers | ||
unless Object.const_defined?("ActiveSupport") | ||
Dir.glob(File.dirname(__FILE__) + '/support/*') { |file| require file } | ||
end | ||
|
||
# load adapters | ||
Dir.glob(File.dirname(__FILE__) + '/satellite/adapters/*') { |file| require file } | ||
|
||
module Satellite | ||
|
||
class NoAdapterError < NameError | ||
end | ||
|
||
class TrackerInterface | ||
def initialize(adapter) | ||
@adapter = adapter | ||
end | ||
|
||
def track_page_view(path=nil) | ||
@adapter.track_page_view(path) | ||
end | ||
|
||
def track_event(category, action, label=nil, value=nil) | ||
@adapter.track_event(category, action, label, value) | ||
end | ||
|
||
def set_custom_variable(slot, name, value, scope=nil) | ||
@adapter.set_custom_variable(slot, name, value, scope) | ||
end | ||
|
||
def unset_custom_variable(slot) | ||
@adapter.unset_custom_variable(slot) | ||
end | ||
|
||
def []=(key, value) | ||
@adapter[key] = value | ||
end | ||
|
||
def [](key) | ||
@adapter[key] | ||
end | ||
end | ||
|
||
def self.get_tracker(type, params = { }) | ||
begin | ||
tracker_klass = "Satellite::Adapters::#{type.to_s.camelcase}".constantize | ||
rescue | ||
raise NoAdapterError, "There is no such adapter like 'Satellite::Adapters::#{type.to_s.camelcase}'" | ||
end | ||
|
||
TrackerInterface.new(tracker_klass.new(params)) | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,265 @@ | ||
module Satellite | ||
module Adapters | ||
class GoogleAnalytics | ||
|
||
def initialize(params, use_ssl=false) | ||
self.utm_params = extend_with_default_params(params) | ||
self.utm_location = (use_ssl ? 'https://ssl' : 'http://www') + UTM_GIF_LOCATION | ||
end | ||
|
||
def track | ||
puts utm_params.inspect | ||
|
||
utm_url = utm_location + "?" + utm_params.to_query | ||
|
||
puts "--------sending request to GA-----------------------" | ||
puts utm_url | ||
#open(utm_url) | ||
|
||
# reset events / custom variables here | ||
utm_params.delete(:utme) | ||
end | ||
|
||
def track_event(category, action, label=nil, value=nil) | ||
utm_params[:utme].set_event(category, action, label, value) | ||
track | ||
end | ||
|
||
def track_page_view(path=nil) | ||
utm_params.merge({ :utmp => path }) if path | ||
track | ||
end | ||
|
||
def set_custom_variable(index, name, value, scope=nil) | ||
utm_params[:utme].set_custom_variable(index, name, value, scope) | ||
end | ||
|
||
def unset_custom_variable(index) | ||
utm_params[:utme].unset_custom_variable(index) | ||
end | ||
|
||
def []=(key, value) | ||
value = Utme.parse(value) if key.to_s == 'utme' | ||
utm_params[key] = value | ||
end | ||
|
||
def [](key) | ||
utm_params[key] | ||
end | ||
|
||
class << self | ||
attr_accessor :account_id | ||
end | ||
|
||
protected | ||
|
||
attr_accessor :utm_params, :utm_location | ||
|
||
private | ||
|
||
# seems to be the current version | ||
# search for 'utmwv' in http://www.google-analytics.com/ga.js | ||
VERSION = "5.1.5" | ||
UTM_GIF_LOCATION = ".google-analytics.com/__utm.gif" | ||
|
||
# adds default params | ||
def extend_with_default_params(params) | ||
{ | ||
:utme => Utme.parse(params[:utme]), | ||
:utmwv => VERSION, | ||
:utmn => rand(0x7fffffff).to_s, | ||
:utmac => self.class.account_id | ||
}.merge(params) | ||
end | ||
|
||
end | ||
end | ||
end | ||
|
||
module Satellite | ||
module Adapters | ||
class GoogleAnalytics::Utme | ||
|
||
def initialize | ||
@custom_variables = CustomVariables.new | ||
end | ||
|
||
def set_event(category, action, label=nil, value=nil) | ||
@event = Event.new(category, action, label, value) | ||
self | ||
end | ||
|
||
def set_custom_variable(slot, name, value, scope=nil) | ||
@custom_variables.set_custom_variable(slot, CustomVariable.new(name, value, scope)) | ||
self | ||
end | ||
|
||
def unset_custom_variable(slot) | ||
@custom_variables.unset_custom_variable(slot) | ||
self | ||
end | ||
|
||
def to_s | ||
@event.to_s + @custom_variables.to_s | ||
end | ||
|
||
alias_method :to_param, :to_s | ||
|
||
class << self | ||
|
||
@@regex_event = /5\((\w+)\*(\w+)(\*(\w+))?\)(\((\d+)\))?/ | ||
@@regex_custom_variables = /8\(([^\)]*)\)9\(([^\)]*)\)(11\(([^\)]*)\))?/ | ||
@@regex_custom_variable_value = /((\d)!)?(\w+)/ | ||
|
||
def parse(args) | ||
return self.new if args.nil? | ||
case args | ||
when String | ||
return self.from_string(args) | ||
when self | ||
return args | ||
else | ||
raise ArgumentError, "Could parse argument neither as String nor GATracker::Utme" | ||
end | ||
end | ||
|
||
def from_string(str) | ||
utme = self.new | ||
|
||
# parse event | ||
str.gsub!(@@regex_event) do |match| | ||
utme.set_event($1, $2, $4, $6) | ||
'' | ||
end | ||
|
||
# parse custom variables | ||
str.gsub!(@@regex_custom_variables) do |match| | ||
custom_vars = { } | ||
match_names, match_values, match_scopes = $1, $2, $4 | ||
|
||
names = match_names.to_s.split('*') | ||
values = match_values.to_s.split('*') | ||
scopes = match_scopes.to_s.split('*') | ||
|
||
raise ArgumentError, "Each custom variable must have a value defined." if names.length != values.length | ||
|
||
names.each_with_index do |raw_name, i| | ||
match_data = raw_name.match(@@regex_custom_variable_value) | ||
slot, name = (match_data[2] || i+1).to_i, match_data[3] | ||
custom_vars[slot] = { :name => name } | ||
end | ||
|
||
values.each_with_index do |raw_value, i| | ||
match_data = raw_value.match(@@regex_custom_variable_value) | ||
slot, value = (match_data[2] || i+1).to_i, match_data[3] | ||
custom_vars[slot][:value] = value | ||
end | ||
|
||
scopes.each_with_index do |raw_scope, i| | ||
match_data = raw_scope.match(@@regex_custom_variable_value) | ||
slot, scope = (match_data[2] || i+1).to_i, match_data[3] | ||
# silently ignore scope if there's no corresponding custom variable | ||
custom_vars[slot][:scope] = scope if custom_vars[slot] | ||
end | ||
|
||
# finally set all the gathered custom vars | ||
custom_vars.each do |key, custom_var| | ||
utme.set_custom_variable(key, custom_var[:name], custom_var[:value], custom_var[:scope]) | ||
end | ||
'' | ||
end | ||
|
||
utme | ||
end | ||
end | ||
|
||
private | ||
|
||
Event = Struct.new(:category, :action, :opt_label, :opt_value) do | ||
def to_s | ||
output = "5(#{category}*#{action}" | ||
output += "*#{opt_label}" if opt_label | ||
output += ")" | ||
output += "(#{opt_value})" if opt_value | ||
output | ||
end | ||
end | ||
|
||
CustomVariable = Struct.new(:name, :value, :opt_scope) | ||
|
||
class CustomVariables | ||
|
||
@@valid_keys = 1..5 | ||
|
||
def initialize | ||
@contents = { } | ||
end | ||
|
||
def set_custom_variable(slot, custom_variable) | ||
raise ArgumentError, "Cannot set a slot other than #{@@valid_keys}. Given #{slot}" if not @@valid_keys.include?(slot) | ||
@contents[slot] = custom_variable | ||
end | ||
|
||
def unset_custom_variable(slot) | ||
raise ArgumentError, "Cannot unset a slot other than #{@@valid_keys}. Given #{slot}" if not @@valid_keys.include?(slot) | ||
@contents.delete(slot) | ||
end | ||
|
||
# follows google custom variable format | ||
# | ||
# 8(NAMES)9(VALUES)11(SCOPES) | ||
# | ||
# best explained by examples | ||
# | ||
# 1) | ||
# pageTracker._setCustomVar(1,"foo", "val", 1) | ||
# ==> 8(foo)9(bar)11(1) | ||
# | ||
# 2) | ||
# pageTracker._setCustomVar(1,"foo", "val", 1) | ||
# pageTracker._setCustomVar(2,"bar", "vok", 3) | ||
# ==> 8(foo*bar)9(val*vok)11(1*3) | ||
# | ||
# 3) | ||
# pageTracker._setCustomVar(1,"foo", "val", 1) | ||
# pageTracker._setCustomVar(2,"bar", "vok", 3) | ||
# pageTracker._setCustomVar(4,"baz", "vol", 1) | ||
# ==> 8(foo*bar*4!baz)9(val*vak*4!vol)11(1*3*4!1) | ||
# | ||
# 4) | ||
# pageTracker._setCustomVar(4,"foo", "bar", 1) | ||
# ==> 8(4!foo)9(4!bar)11(4!1) | ||
# | ||
def to_s | ||
return '' if @contents.empty? | ||
|
||
ordered_keys = @contents.keys.sort | ||
names = values = scopes = '' | ||
|
||
ordered_keys.each do |slot| | ||
custom_variable = @contents[slot] | ||
predecessor = @contents[slot-1] | ||
|
||
has_predecessor = !!predecessor | ||
has_scoped_predecessor = !!predecessor.try(:opt_scope) | ||
|
||
star = names.empty? ? '' : '*' | ||
bang = (slot == 1 || has_predecessor) ? '' : "#{slot}!" | ||
|
||
scope_star = scopes.empty? ? '' : '*' | ||
scope_bang = (slot == 1 || has_scoped_predecessor) ? '' : "#{slot}!" | ||
|
||
names += "#{star}#{bang}#{custom_variable.name}" | ||
values += "#{star}#{bang}#{custom_variable.value}" | ||
scopes += "#{scope_star}#{scope_bang}#{custom_variable.opt_scope}" if custom_variable.opt_scope | ||
end | ||
|
||
output = "8(#{names})9(#{values})" | ||
output += "11(#{scopes})" if not scopes.empty? | ||
output | ||
end | ||
|
||
end | ||
end | ||
end | ||
end |
Oops, something went wrong.