isc_analytics 0.5

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :test, :development do
6
+ gem "rspec-rails"
7
+ gem "sqlite3"
8
+ #gem "capybara"
9
+ #gem 'ruby-debug19'
10
+ end
data/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # ISC Analytics
2
+ A simple client-side & server-side analytics library for Rails
3
+
4
+ ## Installation
5
+
6
+ Just add the `isc_analytics` gem into your Gemfile
7
+
8
+ ```ruby
9
+ gem 'isc_analytics'
10
+ ```
11
+
12
+ Then create an initializer file in your `config/initialize` directory containing the initial config of your analytics.
13
+
14
+ ## Configuration
15
+
16
+ ISC Analytics current supports the following configurations:
17
+
18
+
19
+ ```ruby
20
+ IscAnalytics.config.accounts = ANALYTIC_ACCOUNTS # an accounts objects (preferably using ConfigReader)
21
+ IscAnalytics.config.namespace = 'App' # an alias which will gain all the analytics behivour in the clientside.
22
+ ```
23
+
24
+ We recommend our other gem [ConfigReader](https://github.com/TheGiftsProject/configreader) to load the analytics_accounts data from a YML.
25
+
26
+ The analytics accounts should contain the following sub keys:
27
+
28
+ ```yml
29
+ kissmetrics_key: "KEY"
30
+ google_analytics_key: "KEY"
31
+ ipinfodb_key: "KEY"
32
+ optimizely_key: "KEY"
33
+ ```
34
+
35
+ Currently only the KISSMetrics and Google Analytics keys are mandatory although the gem isn't fully tested without the ipinfodb and optimizely options.
36
+
37
+ ## Usage
38
+
39
+ There are three points of usage for the isc_analytics gem, the first is including and starting to use the gem in your app. The second is Client side analytics events and the third is server side analytics events.
40
+
41
+ ### Including
42
+
43
+ To include isc_analytics in your app, after you install the gem.
44
+ Add the following line inside your ApplicationController:
45
+
46
+ ```ruby
47
+ include IscAnalytics::ControllerSupport
48
+ ```
49
+ This will enable you to use the analytics object from your controllers and views.
50
+
51
+ And the following line to your main application layout
52
+
53
+ ```erb
54
+ <%= add_analytics %>
55
+ ```
56
+
57
+ This will embed all the needed html for the analytics to run (including the code for all the required services.)
58
+
59
+ ### Client Side
60
+
61
+ After your install and include the isc_gem you can use the following functions in your client side javascript.
62
+
63
+ ```js
64
+ Analytics.trackEvent(<event name>, [<properties_hash>]);
65
+ Analytics.setProperty(<property_key>, <property_value>);
66
+ Analytics.setProperties(<properties_hash>);
67
+ Analytics.identify(<identity>, [<properties_hash>]);
68
+ Analytics.clearIdentity()
69
+ ```
70
+
71
+ #### Namespacing
72
+ The cool thing is that if you configure a Namespace in the configuration then we'll automatically alias all the functions to the Namespace of your choice for easy access.
73
+ For example if I set my namespace as `App` then I'll be able to access the trackEvent function from `App.trackEvent`
74
+
75
+ ### Server Side
76
+
77
+ All the **client side event tracking is available from the server side** as well. Once you inlcude isc_analytics you can access the `analytics` object which will have methods identical to the client-side analytics methods.
78
+ For example you can call `analytics.trackEvent('user-visit')` and it will be persisted in the current user session and flushed into the users browser next time he visits a page (via add_analytics). This mechanism is similar in behaivour to Rails' flash object.
79
+
80
+ ### Opt out
81
+
82
+ One very cool feature **isc_analytics** has is a built in opt_out feature to be used when testing the system or when doing admin actions.
83
+ To enter opt_out for the current browsing session just call `analytics.opt_out!` from the controller.
84
+ Once opt-ted out, a dummy implementation of the analytics js will be sent to the client meaning that no calls will actually be sent to the analytics service.
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # encoding: UTF-8
2
+ require 'rubygems'
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rake'
10
+
11
+ require 'rspec/core'
12
+ require 'rspec/core/rake_task'
13
+
14
+ RSpec::Core::RakeTask.new(:spec)
15
+
16
+ task :default => :spec
@@ -0,0 +1,2 @@
1
+ #= require ./isc_analytics
2
+ #= require ./visitor_analytics
@@ -0,0 +1,77 @@
1
+ class window.Analytics
2
+
3
+ # check if the Kissmetrics async queue is loaded
4
+ @isLoaded: ->
5
+ window._kmq?
6
+
7
+ ###
8
+ Push a call asynchronously to Kissmetrics API
9
+ @param callData - array to push
10
+ ###
11
+ @push: (callData) ->
12
+ if _.isArray(callData) and @isLoaded()
13
+ _kmq.push callData
14
+
15
+ ###
16
+ Track Event
17
+ @param eventName - event name string
18
+ @param properties - JSON with custom data
19
+ ###
20
+ @trackEvent: (eventName, properties) ->
21
+ if @isValid eventName
22
+ properties = properties or {}
23
+ @push ["record", eventName, properties]
24
+
25
+ ###
26
+ Set properties
27
+ @param properties - JSON with custom data
28
+ ###
29
+ @setProperties: (properties) ->
30
+ unless _.isEmpty(properties)
31
+ @push ["set", properties]
32
+
33
+
34
+ ###
35
+ Set a single property
36
+ @param property
37
+ @param value
38
+ ###
39
+ @setProperty: (property, value) ->
40
+ if @isValid property
41
+ properties = {}
42
+ properties[property] = value
43
+ @setProperties properties
44
+
45
+
46
+ ###
47
+ Identify a user with a unique id
48
+ @param identifier - could be either username or email (currently email)
49
+ @param properties - JSON with custom data
50
+ ###
51
+ @identify: (identifier, properties) ->
52
+ if @isValid identifier
53
+ @push ["identify", identifier]
54
+ @setProperties(properties)
55
+
56
+
57
+ ###
58
+ Clear the user's identity
59
+ @see http://support.kissmetrics.com/advanced/identity-management
60
+ ###
61
+ @clearIdentity: ->
62
+ @push ["clearIdentity"]
63
+
64
+
65
+ ###
66
+ alias simply takes two arguments which are the two identities that you need
67
+ to tie together. So if you call alias with the identities bob and bob@bob.com
68
+ KISSmetrics will tie together the two records and will treat the identities bob
69
+ and bob@bob.com as the same person.
70
+ @param name
71
+ ###
72
+ @setAlias: (name, identifier) ->
73
+ if @isValid(identifier) and @isValid(name)
74
+ @push ["alias", name, identifier]
75
+
76
+ @isValid: (str)->
77
+ !_.isEmpty(str) and _.isString(str)
@@ -0,0 +1,19 @@
1
+ class window.Analytics
2
+
3
+ @isLoaded: ->
4
+
5
+ @push: (callData) ->
6
+
7
+ @trackEvent: (eventName, properties) ->
8
+
9
+ @setProperties: (properties) ->
10
+
11
+ @setProperty: (property, value) ->
12
+
13
+ @identify: (identifier, properties) ->
14
+
15
+ @clearIdentity: ->
16
+
17
+ @setAlias: (name, identifier) ->
18
+
19
+ @isValid: (str)->
@@ -0,0 +1,66 @@
1
+ #= require isc_analytics/yepnope
2
+
3
+ class window.VisitorAnalytics
4
+
5
+ ###
6
+ Save visitor data
7
+ @param {Object} sessionData - session data from session.js
8
+ ###
9
+ @save: (sessionData) ->
10
+ @sessionData = sessionData
11
+ @_saveAnalyticsData sessionData
12
+
13
+
14
+ ###
15
+ Has Location Data - checks to see the call to IPInfoDB didn't fail
16
+ @return {Boolean}
17
+ ###
18
+ @hasLocationData: ->
19
+ @sessionData.location and (@sessionData.location.statusCode is "OK")
20
+
21
+
22
+ ###
23
+ Save Analytics Data
24
+ ###
25
+ @_saveAnalyticsData: ->
26
+ if @sessionData
27
+ data = @sessionData
28
+ properties = {}
29
+ properties["Locale"] = data.locale.country + " " + data.locale.lang if data.locale
30
+ if data.browser
31
+ properties["Browser"] = data.browser.browser + " " + data.browser.version
32
+ properties["OS"] = data.browser.os
33
+ if data.device
34
+ properties["Resolution"] = data.device.screen.width + " " + data.device.screen.height
35
+ properties["Is Tablet"] = data.device.is_tablet
36
+ properties["Is Phone"] = data.device.is_phone
37
+ properties["Is Mobile"] = data.device.is_mobile
38
+ if @hasLocationData()
39
+ properties["Country"] = @niceName(data.location.countryName)
40
+ properties["Region"] = @niceName(data.location.regionName)
41
+ properties["City"] = @niceName(data.location.cityName)
42
+ properties["Latitude"] = data.location.latitude
43
+ properties["Longitude"] = data.location.longitude
44
+ Analytics.setProperties properties
45
+
46
+ #niceName("one_two") //-> "One Two"
47
+ @niceName: (s) ->
48
+ parts = s.split(/_|-/)
49
+ for i in [0..parts.length-1]
50
+ parts[i] = @capitalize(parts[i])
51
+
52
+ parts.join(' ')
53
+
54
+ @capitalize: (str)->
55
+ str.charAt(0).toUpperCase() + str.slice(1).toLowerCase()
56
+
57
+ window.session =
58
+ options:
59
+ use_html5_location: false
60
+ gapi_location: false
61
+ ipinfodb_key: window.IPINFODB_KEY
62
+ location_cookie: ""
63
+ session_cookie: ""
64
+ start: (sessionData)->
65
+ VisitorAnalytics.save(sessionData)
66
+ yepnope("<%= javascript_path("isc_analytics/session") %>")
@@ -0,0 +1,17 @@
1
+ require "#{File.dirname(__FILE__)}/isc_analytics/engine"
2
+ require "#{File.dirname(__FILE__)}/isc_analytics/config"
3
+ require "#{File.dirname(__FILE__)}/isc_analytics/client_api"
4
+ require "#{File.dirname(__FILE__)}/isc_analytics/exceptions"
5
+ require "#{File.dirname(__FILE__)}/isc_analytics/bootstrap"
6
+ require "#{File.dirname(__FILE__)}/isc_analytics/controller_support"
7
+
8
+ module IscAnalytics
9
+
10
+ mattr_accessor :app
11
+
12
+ def self.config
13
+ @configuration ||= IscAnalytics::Config.default
14
+ end
15
+
16
+ end
17
+
@@ -0,0 +1,83 @@
1
+ require 'isc_analytics/tags'
2
+ require 'isc_analytics/services'
3
+
4
+ module IscAnalytics
5
+ class Bootstrap
6
+ include KISSMetricsClientAPI
7
+
8
+ def initialize(options = {})
9
+ validate_accounts_config
10
+ @session = options[:session] || {}
11
+ @opt_out = false
12
+ end
13
+
14
+ def opt_out?
15
+ !!@opt_out
16
+ end
17
+
18
+ def opt_out!
19
+ @opt_out = true
20
+ end
21
+
22
+ def analytics_script_tags
23
+ Tags.scripts(analytics_scripts)
24
+ end
25
+
26
+ private
27
+
28
+ def analytics_scripts
29
+ scripts = []
30
+ scripts.concat Services.scripts(config.accounts) unless opt_out?
31
+ scripts << isc_analytics_tag
32
+ scripts << extend_analytics(config.namespace)
33
+ scripts << queued_events unless opt_out?
34
+ scripts
35
+ end
36
+
37
+ def config
38
+ IscAnalytics.config
39
+ end
40
+
41
+ def validate_accounts_config
42
+ raise IscAnalytics::NoConfigSpecified.new('You have specified a nil config, you must specify an EnvConfigReader of your Analytics Accounts keys') if config.accounts.nil?
43
+
44
+ if config.accounts.kissmetrics_key.nil?
45
+ raise IscAnalytics::MissingConfigParams.new('KISSMetrics configuration key isn\'t specified in your config.')
46
+ elsif config.accounts.google_analytics_key.nil?
47
+ raise IscAnalytics::MissingConfigParams.new('Google Analytics configuration key isn\'t specified in your config.')
48
+ end
49
+ end
50
+
51
+ def queued_events
52
+ queue_js = generate_queue_js
53
+ return nil if queue_js.blank?
54
+ Tags.script_tag(queue_js)
55
+ end
56
+
57
+ def extend_analytics(namespace)
58
+ return nil if namespace.nil?
59
+ Tags.script_tag <<-SCRIPT
60
+ (function() {
61
+ _.extend(window.#{namespace}, window.Analytics)
62
+ })();
63
+ SCRIPT
64
+ end
65
+
66
+ def isc_analytics_tag
67
+ prefix = ''
68
+ if IscAnalytics.app.config.assets.prefix.present?
69
+ prefix = IscAnalytics.app.config.assets.prefix + '/'
70
+ end
71
+ Tags.script_link_tag(prefix + isc_analytics_asset + '.js')
72
+ end
73
+
74
+ def isc_analytics_asset
75
+ if opt_out?
76
+ 'isc_analytics/opt_out_analytics'
77
+ else
78
+ 'isc_analytics'
79
+ end
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,79 @@
1
+ module IscAnalytics
2
+ module KISSMetricsClientAPI
3
+
4
+ def identify(identifier, properties = {})
5
+ unless identifier.blank? || is_identified(identifier)
6
+ remove_duplicated_identify
7
+ if properties.blank?
8
+ enqueue 'identify', identifier
9
+ else
10
+ enqueue 'identify', identifier, properties
11
+ end
12
+ set_identity(identifier)
13
+ end
14
+ end
15
+
16
+ def clear_identify
17
+ set_identity(nil) # removed identity from session
18
+ enqueue 'clearIdentity'
19
+ end
20
+
21
+ def track_event(name, properties = {})
22
+ unless name.blank?
23
+ if properties.blank?
24
+ enqueue 'trackEvent', name
25
+ else
26
+ enqueue 'trackEvent', name, properties
27
+ end
28
+ end
29
+ end
30
+
31
+ def set_properties(properties = {})
32
+ enqueue('setProperties', properties) unless properties.blank?
33
+ end
34
+
35
+ def set_property(property, value = nil)
36
+ enqueue('setProperty', property, value) unless property.blank?
37
+ end
38
+
39
+ # reset_queue makes sure that subsequent calls will not send events that have already been sent.
40
+ def generate_queue_js(reset_queue = true)
41
+ buffer = get_parsed_queue_string
42
+ queue.clear if reset_queue
43
+ buffer
44
+ end
45
+
46
+ private
47
+
48
+ def enqueue(name, *args)
49
+ call = "#{name}(#{args.map(&:as_json).map(&:to_json).join(',')});"
50
+ queue << call unless queue.include?(call)
51
+ end
52
+
53
+ def queue
54
+ session[:analytics_queue] ||= []
55
+ end
56
+
57
+ def session
58
+ @session
59
+ end
60
+
61
+ # Parse the queue by adding the JS class name and newlines to each call
62
+ def get_parsed_queue_string
63
+ queue.map{ |api_call| "Analytics.#{api_call}" }.join("\n")
64
+ end
65
+
66
+ def is_identified(identifier)
67
+ session[:analytics_identity] == identifier
68
+ end
69
+
70
+ def set_identity(identifier)
71
+ session[:analytics_identity] = identifier
72
+ end
73
+
74
+ def remove_duplicated_identify
75
+ queue.delete_if { |api_call| !(/identify/ =~ api_call).nil? }
76
+ end
77
+
78
+ end
79
+ end
@@ -0,0 +1,15 @@
1
+ module IscAnalytics
2
+ class Config
3
+
4
+ attr_accessor :accounts, :namespace
5
+
6
+ def self.default
7
+ new.instance_eval {
8
+ @accounts = nil
9
+ @namespace = nil
10
+
11
+ self
12
+ }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,36 @@
1
+ require 'controller_support/base'
2
+
3
+ module IscAnalytics
4
+ ## A mixin that provides access to isc_analytics API in the controller.
5
+ module ControllerSupport
6
+ extend ::ControllerSupport::Base
7
+
8
+ helper_method :add_analytics, :analytics, :opt_out!, :opt_out?
9
+
10
+ ##Is the analytics tracking disabled for the current page?
11
+ def opt_opt?
12
+ analytics.opt_out?
13
+ end
14
+
15
+ ##This method will disable the analytics tracking of the user
16
+ def opt_out!
17
+ analytics.opt_out!
18
+ end
19
+
20
+ ##This method will generate all the javascript needed for client-side analytics tracking.
21
+ ##This also includes server-side analytics events that were queued to the client during the current request.
22
+ def add_analytics
23
+ analytics.analytics_script_tags
24
+ end
25
+
26
+ def analytics
27
+ isc_analytics
28
+ end
29
+
30
+ private
31
+
32
+ def isc_analytics
33
+ @isc_analytics_bootstrap ||= IscAnalytics::Bootstrap.new(:session => session)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,12 @@
1
+ if defined?(::Rails::Engine)
2
+ module IscAnalytics
3
+ module Rails
4
+ class Engine < ::Rails::Engine
5
+ initializer :assets do |app|
6
+ IscAnalytics.app = app
7
+ app.config.assets.precompile += %w(isc_analytics isc_analytics/session isc_analytics/opt_out_analytics)
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ module IscAnalytics
2
+ class ConfigReaderNotDefined < StandardError; end
3
+ class NoConfigSpecified < StandardError; end
4
+ class MissingConfigParams < StandardError; end
5
+ end
@@ -0,0 +1,59 @@
1
+ require 'isc_analytics/tags'
2
+ require 'active_support/core_ext/object/blank'
3
+
4
+ module IscAnalytics
5
+ class Services
6
+
7
+ def self.scripts(accounts)
8
+ [
9
+ kissmetrics_tag(accounts.kissmetrics_key),
10
+ google_tag(accounts.google_analytics_key),
11
+ optimizely_tag(accounts.optimizely_key),
12
+ ipinfodb_tag(accounts.ipinfodb_key)
13
+ ]
14
+ end
15
+
16
+ def self.kissmetrics_tag(key)
17
+ Tags.script_tag <<-SCRIPT
18
+ var _kmq = _kmq || [];
19
+ function _kms(u){
20
+ setTimeout(function(){
21
+ var s = document.createElement('script'); var f = document.getElementsByTagName('script')[0];
22
+ s.type = 'text/javascript'; s.async = true;
23
+ s.src = u; f.parentNode.insertBefore(s, f);
24
+ }, 1);
25
+ }
26
+ _kms('//i.kissmetrics.com/i.js');
27
+ _kms('//doug1izaerwt3.cloudfront.net/#{key}.1.js');
28
+ SCRIPT
29
+ end
30
+
31
+ def self.google_tag(key)
32
+ Tags.script_tag <<-SCRIPT
33
+ var _gaq = _gaq || [];
34
+ _gaq.push(['_setAccount', '#{key}']);
35
+ (function() {
36
+ var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
37
+ ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
38
+ var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
39
+ })();
40
+ SCRIPT
41
+ end
42
+
43
+ def self.optimizely_tag(key)
44
+ return nil if key.blank?
45
+ <<-HTML
46
+ <script src='//cdn.optimizely.com/js/#{key}.js\'></script>
47
+ <script type="text/javascript">
48
+ window['optimizely'] = optimizely || [];
49
+ </script>
50
+ HTML
51
+ end
52
+
53
+ def self.ipinfodb_tag(key)
54
+ return nil if key.blank?
55
+ Tags.script_tag "window.IPINFODB_KEY = '#{key}';"
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,18 @@
1
+ require 'active_support/core_ext/string/output_safety'
2
+
3
+ module IscAnalytics
4
+ module Tags
5
+
6
+ def self.scripts(scripts_array)
7
+ scripts_array.compact.join().html_safe
8
+ end
9
+
10
+ def self.script_tag(script)
11
+ "<script type='text/javascript'>#{script}</script>"
12
+ end
13
+
14
+ def self.script_link_tag(link)
15
+ "<script type='text/javascript' src='#{link}'></script>"
16
+ end
17
+ end
18
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: isc_analytics
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.5'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Itay Adler
9
+ - Yonatan Bergman
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-12-24 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: controller_support
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ - !ruby/object:Gem::Dependency
32
+ name: configreader
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ - !ruby/object:Gem::Dependency
48
+ name: activesupport
49
+ requirement: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :runtime
56
+ prerelease: false
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ description: A simple client-side & server-side analytics library
64
+ email:
65
+ - itayadler@gmail.com
66
+ - yonbergman@gmail.com
67
+ executables: []
68
+ extensions: []
69
+ extra_rdoc_files: []
70
+ files:
71
+ - lib/assets/javascripts/isc_analytics/index.js.coffee
72
+ - lib/assets/javascripts/isc_analytics/isc_analytics.js.coffee
73
+ - lib/assets/javascripts/isc_analytics/opt_out_analytics.js.coffee
74
+ - lib/assets/javascripts/isc_analytics/visitor_analytics.coffee.erb
75
+ - lib/isc_analytics/bootstrap.rb
76
+ - lib/isc_analytics/client_api.rb
77
+ - lib/isc_analytics/config.rb
78
+ - lib/isc_analytics/controller_support.rb
79
+ - lib/isc_analytics/engine.rb
80
+ - lib/isc_analytics/exceptions.rb
81
+ - lib/isc_analytics/services.rb
82
+ - lib/isc_analytics/tags.rb
83
+ - lib/isc_analytics.rb
84
+ - Rakefile
85
+ - Gemfile
86
+ - README.md
87
+ homepage: https://github.com/TheGiftsProject/isc_analytics
88
+ licenses: []
89
+ post_install_message:
90
+ rdoc_options: []
91
+ require_paths:
92
+ - lib
93
+ required_ruby_version: !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 1.8.24
108
+ signing_key:
109
+ specification_version: 3
110
+ summary: A simple Analytics Library
111
+ test_files: []