mixpanel 0.5.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.rdoc CHANGED
@@ -1,11 +1,12 @@
1
1
  == What is Mixpanel (the service) ?
2
2
 
3
- *Mixpanel* is a real-time analytics service that helps companies understand how users interact with web applications.
3
+ Mixpanel is a real-time analytics service that helps companies understand how users interact with web applications.
4
4
  http://mixpanel.com
5
5
 
6
6
  == What does this Gem?
7
7
 
8
- * Track events with properties directly from your backend
8
+ * Track events with properties directly from your backend.
9
+ * Track events with properties through javascript using a rack middleware.
9
10
 
10
11
 
11
12
  == How to install?
@@ -13,13 +14,29 @@ http://mixpanel.com
13
14
  gem install mixpanel
14
15
 
15
16
 
16
- == How to use?
17
+ == How to use it with a Rails application?
17
18
 
18
- require 'mixpanel'
19
+ In your application_controller class add a method to instance mixpanel.
19
20
 
20
- mixpanel = Mixpanel.new("your_mixpanel_project_token")
21
+ before_filer :initialize_mixpanel
21
22
 
22
- mixpanel.track("Sign up", {
23
- :referer => "http://example.com",
24
- :ip => "4.4.4.4"
25
- })
23
+ def initialize_mixpanel
24
+ @mixpanel = Mixpanel.new("YOUR_MIXPANEL_API_TOKEN", request.env)
25
+ end
26
+
27
+ Then in each request you want to track some event you can use:
28
+
29
+ To track events directly from your backend...
30
+
31
+ @mixpanel.track_event("Sign in", {:some => "property"})
32
+
33
+ To track events after response with javascript...
34
+
35
+ @mixpanel.append_event("Sign in", {:some => "property"})
36
+
37
+
38
+ == Notes
39
+
40
+ It is strongly recommended to call Mixpanel#track_event using an async lib
41
+ like delayed job or similar, otherwise you will delay your server responses
42
+ with mixpanel responses.
data/lib/mixpanel.rb CHANGED
@@ -1,42 +1,2 @@
1
- require "open-uri"
2
- require 'base64'
3
- require 'json'
4
-
5
- class Mixpanel
6
- attr_reader :events
7
-
8
- def initialize(token, options = {})
9
- @token = token
10
- @events = []
11
- end
12
-
13
- def append_event(event, properties = {})
14
- @events << build_event(event, properties)
15
- end
16
-
17
- def track_event(event, properties = {})
18
- params = build_event(event, properties.merge(:token => @token, :time => Time.now.utc.to_i))
19
- parse_response request(params)
20
- end
21
-
22
- def clean_queue
23
- @events = []
24
- end
25
-
26
- private
27
-
28
- def parse_response(response)
29
- response == "1" ? true : false
30
- end
31
-
32
- def request(params)
33
- data = Base64.encode64(JSON.generate(params)).gsub(/\n/,'')
34
- url = "http://api.mixpanel.com/track/?data=#{data}"
35
-
36
- open(url).read
37
- end
38
-
39
- def build_event(event, properties)
40
- {:event => event, :properties => properties}
41
- end
42
- end
1
+ require 'mixpanel/mixpanel'
2
+ require 'mixpanel/mixpanel_middleware'
@@ -0,0 +1,49 @@
1
+ require "open-uri"
2
+ require 'base64'
3
+ require 'json'
4
+
5
+ class Mixpanel
6
+ def initialize(token, env)
7
+ @token = token
8
+ @env = env
9
+ clear_queue
10
+ end
11
+
12
+ def append_event(event, properties = {})
13
+ queue << build_event(event, properties)
14
+ end
15
+
16
+ def track_event(event, properties = {})
17
+ params = build_event(event, properties.merge(:token => @token, :time => Time.now.utc.to_i, :ip => ip))
18
+ parse_response request(params)
19
+ end
20
+
21
+ def ip
22
+ @env.has_key?("REMOTE_ADDR") ? @env["REMOTE_ADDR"] : ""
23
+ end
24
+
25
+ def queue
26
+ @env["mixpanel_events"]
27
+ end
28
+
29
+ def clear_queue
30
+ @env["mixpanel_events"] = []
31
+ end
32
+
33
+ private
34
+
35
+ def parse_response(response)
36
+ response == "1" ? true : false
37
+ end
38
+
39
+ def request(params)
40
+ data = Base64.encode64(JSON.generate(params)).gsub(/\n/,'')
41
+ url = "http://api.mixpanel.com/track/?data=#{data}"
42
+
43
+ open(url).read
44
+ end
45
+
46
+ def build_event(event, properties)
47
+ {:event => event, :properties => properties}
48
+ end
49
+ end
@@ -0,0 +1,95 @@
1
+ require 'rack'
2
+
3
+ class MixpanelMiddleware
4
+ def initialize(app, mixpanel_token)
5
+ @app = app
6
+ @token = mixpanel_token
7
+ end
8
+
9
+ def call(env)
10
+ @env = env
11
+
12
+ @status, @headers, @response = @app.call(env)
13
+
14
+ update_response!
15
+ update_content_length!
16
+ delete_event_queue!
17
+
18
+ [@status, @headers, @response]
19
+ end
20
+
21
+ private
22
+
23
+ def update_response!
24
+ @response.each do |part|
25
+ if is_regular_request? && is_html_response?
26
+ part.gsub!("</head>", "#{render_mixpanel_scripts}</head>")
27
+ part.gsub!("</head>", "#{render_event_tracking_scripts}</head>")
28
+ elsif is_ajax_request? && is_html_response?
29
+ part.gsub!(part, render_event_tracking_scripts + part)
30
+ elsif is_ajax_request? && is_javascript_response?
31
+ part.gsub!(part, render_event_tracking_scripts(false) + part)
32
+ end
33
+ end
34
+ end
35
+
36
+ def update_content_length!
37
+ new_size = 0
38
+ @response.each{|part| new_size += part.bytesize}
39
+ @headers.merge!("Content-Length" => new_size.to_s)
40
+ end
41
+
42
+ def is_regular_request?
43
+ !is_ajax_request?
44
+ end
45
+
46
+ def is_ajax_request?
47
+ @env.has_key?("HTTP_X_REQUESTED_WITH") && @env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest"
48
+ end
49
+
50
+ def is_html_response?
51
+ @headers["Content-Type"].include?("text/html") if @headers.has_key?("Content-Type")
52
+ end
53
+
54
+ def is_javascript_response?
55
+ @headers["Content-Type"].include?("text/javascript") if @headers.has_key?("Content-Type")
56
+ end
57
+
58
+ def render_mixpanel_scripts
59
+ <<-EOT
60
+ <script type='text/javascript'>
61
+ var mp_protocol = (('https:' == document.location.protocol) ? 'https://' : 'http://');
62
+ document.write(unescape('%3Cscript src="' + mp_protocol + 'api.mixpanel.com/site_media/js/api/mixpanel.js" type="text/javascript"%3E%3C/script%3E'));
63
+ </script>
64
+ <script type='text/javascript'>
65
+ try {
66
+ var mpmetrics = new MixpanelLib('#{@token}');
67
+ } catch(err) {
68
+ null_fn = function () {};
69
+ var mpmetrics = {
70
+ track: null_fn, track_funnel: null_fn, register: null_fn, register_once: null_fn, register_funnel: null_fn
71
+ };
72
+ }
73
+ </script>
74
+ EOT
75
+ end
76
+
77
+ def delete_event_queue!
78
+ @env.delete('mixpanel_events')
79
+ end
80
+
81
+ def queue
82
+ return [] if !@env.has_key?('mixpanel_events') || @env['mixpanel_events'].empty?
83
+ @env['mixpanel_events']
84
+ end
85
+
86
+ def render_event_tracking_scripts(include_script_tag=true)
87
+ return "" if queue.empty?
88
+
89
+ output = queue.map {|event| %(mpmetrics.track("#{event[:event]}", #{event[:properties].to_json});) }.join("\n")
90
+
91
+ output = "try {#{output}} catch(err) {}"
92
+
93
+ include_script_tag ? "<script type='text/javascript'>#{output}</script>" : output
94
+ end
95
+ end
data/mixpanel.gemspec CHANGED
@@ -1,27 +1,23 @@
1
+ files = ['README.rdoc', 'LICENSE', 'Rakefile', 'mixpanel.gemspec', '{spec,lib}/**/*'].map {|f| Dir[f]}.flatten
2
+
1
3
  spec = Gem::Specification.new do |s|
2
4
  s.name = "mixpanel"
3
- s.version = "0.5.1"
5
+ s.version = "0.6.0"
4
6
  s.rubyforge_project = "mixpanel"
5
- s.description = "Simple lib to track events in Mixpanel service."
7
+ s.description = "Simple lib to track events in Mixpanel service. It can be used in any rack based framework."
6
8
  s.author = "Alvaro Gil"
7
9
  s.email = "zevarito@gmail.com"
8
10
  s.homepage = "http://cuboxsa.com"
9
11
  s.platform = Gem::Platform::RUBY
10
- s.summary = "Supports direct request api and javascript requests."
11
- s.files = %w[
12
- .gitignore
13
- README.rdoc
14
- LICENSE
15
- Rakefile
16
- mixpanel.gemspec
17
- lib/mixpanel.rb
18
- spec/spec_helper.rb
19
- spec/mixpanel/mixpanel_spec.rb
20
- ]
12
+ s.summary = "Supports direct request api and javascript requests through a middleware."
13
+ s.files = files
21
14
  s.require_path = "lib"
22
15
  s.has_rdoc = false
23
16
  s.extra_rdoc_files = ["README.rdoc"]
24
17
  s.add_dependency 'json'
18
+ s.add_dependency 'rack'
25
19
  s.add_development_dependency 'rspec'
20
+ s.add_development_dependency 'rack-test'
26
21
  s.add_development_dependency 'fakeweb'
22
+ s.add_development_dependency 'nokogiri'
27
23
  end
@@ -0,0 +1,134 @@
1
+ require 'spec_helper'
2
+
3
+ describe MixpanelMiddleware do
4
+ include Rack::Test::Methods
5
+
6
+ describe "Dummy apps, no text/html" do
7
+ before do
8
+ setup_rack_application(DummyApp, :body => html_document, :headers => {})
9
+ get "/"
10
+ end
11
+
12
+ it "should pass through if the document is not text/html content type" do
13
+ last_response.body.should == html_document
14
+ end
15
+ end
16
+
17
+ describe "Appending mixpanel scripts" do
18
+ describe "With ajax requests" do
19
+ before do
20
+ setup_rack_application(DummyApp, :body => html_document, :headers => {"Content-Type" => "text/html"})
21
+ get "/", {}, {"HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"}
22
+ end
23
+
24
+ it "should not append mixpanel scripts to head element" do
25
+ Nokogiri::HTML(last_response.body).search('script').should be_empty
26
+ end
27
+
28
+ it "should not update Content-Length in headers" do
29
+ last_response.headers["Content-Length"].should == html_document.length.to_s
30
+ end
31
+ end
32
+
33
+ describe "With regular requests" do
34
+ before do
35
+ setup_rack_application(DummyApp, :body => html_document, :headers => {"Content-Type" => "text/html"})
36
+ get "/"
37
+ end
38
+
39
+ it "should append mixpanel scripts to head element" do
40
+ Nokogiri::HTML(last_response.body).search('head script').should_not be_empty
41
+ Nokogiri::HTML(last_response.body).search('body script').should be_empty
42
+ end
43
+
44
+ it "should have 2 included scripts" do
45
+ Nokogiri::HTML(last_response.body).search('script').size.should == 2
46
+ end
47
+
48
+ it "should use the specified token instantiating mixpanel lib" do
49
+ last_response.should =~ /new MixpanelLib\('#{MIX_PANEL_TOKEN}'\)/
50
+ end
51
+
52
+ it "should define Content-Length if not exist" do
53
+ last_response.headers.has_key?("Content-Length").should == true
54
+ end
55
+
56
+ it "should update Content-Length in headers" do
57
+ last_response.headers["Content-Length"].should_not == html_document.length.to_s
58
+ end
59
+ end
60
+ end
61
+
62
+ describe "Tracking appended events" do
63
+ before do
64
+ @mixpanel = Mixpanel.new(MIX_PANEL_TOKEN, {})
65
+ @mixpanel.append_event("Visit", {:article => 1})
66
+ @mixpanel.append_event("Sign in")
67
+ end
68
+
69
+ describe "With ajax requests and text/html response" do
70
+ before do
71
+ setup_rack_application(DummyApp, :body => "<p>response</p>", :headers => {"Content-Type" => "text/html"})
72
+
73
+ get "/", {}, {"mixpanel_events" => @mixpanel.queue, "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"}
74
+ end
75
+
76
+ it "should render only one script tag" do
77
+ Nokogiri::HTML(last_response.body).search('script').size.should == 1
78
+ end
79
+
80
+ it "should be tracking the correct events inside a script tag" do
81
+ script = Nokogiri::HTML(last_response.body).search('script')
82
+ script.inner_html.should =~ /try\s?\{(.*)\}\s?catch/m
83
+ script.inner_html.should =~ /mpmetrics\.track\("Visit",\s?\{"article":1\}\)/
84
+ script.inner_html.should =~ /mpmetrics\.track\("Sign in",\s?\{\}\)/
85
+ end
86
+
87
+ it "should delete events queue after use it" do
88
+ last_request.env.has_key?("mixpanel_events").should == false
89
+ end
90
+ end
91
+
92
+ describe "With ajax requests and text/javascript response" do
93
+ before do
94
+ setup_rack_application(DummyApp, :body => "alert('response')", :headers => {"Content-Type" => "text/javascript"})
95
+ get "/", {}, {"mixpanel_events" => @mixpanel.queue, "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"}
96
+ end
97
+
98
+ it "should not render a script tag" do
99
+ Nokogiri::HTML(last_response.body).search('script').size.should == 0
100
+ end
101
+
102
+ it "should be tracking the correct events inside a try/catch" do
103
+ script = last_response.body.match(/try\s?\{(.*)\}\s?catch/m)[1]
104
+ script.should =~ /mpmetrics\.track\("Visit",\s?\{"article":1\}\)/
105
+ script.should =~ /mpmetrics\.track\("Sign in",\s?\{\}\)/
106
+ end
107
+
108
+ it "should delete events queue after use it" do
109
+ last_request.env.has_key?("mixpanel_events").should == false
110
+ end
111
+ end
112
+
113
+ describe "With regular requests" do
114
+ before do
115
+ setup_rack_application(DummyApp, :body => html_document, :headers => {"Content-Type" => "text/html"})
116
+
117
+ get "/", {}, {"mixpanel_events" => @mixpanel.queue}
118
+ end
119
+
120
+ it "should render 3 script tags" do
121
+ Nokogiri::HTML(last_response.body).search('script').size.should == 3
122
+ end
123
+
124
+ it "should be tracking the correct events" do
125
+ last_response.body.should =~ /mpmetrics\.track\("Visit",\s?\{"article":1\}\)/
126
+ last_response.body.should =~ /mpmetrics\.track\("Sign in",\s?\{\}\)/
127
+ end
128
+
129
+ it "should delete events queue after use it" do
130
+ last_request.env.has_key?("mixpanel_events").should == false
131
+ end
132
+ end
133
+ end
134
+ end
@@ -2,21 +2,21 @@ require 'spec_helper'
2
2
 
3
3
  describe Mixpanel do
4
4
  before do
5
- @mixpanel = Mixpanel.new(MIX_PANEL_TOKEN)
5
+ @mixpanel = Mixpanel.new(MIX_PANEL_TOKEN, @env = {"REMOTE_ADDR" => "127.0.0.1"})
6
6
  end
7
7
 
8
8
  context "Initializing object" do
9
9
  it "should have an instance variable for token and events" do
10
- @mixpanel.instance_variables.should include("@token", "@events")
10
+ @mixpanel.instance_variables.should include("@token", "@env")
11
11
  end
12
12
  end
13
13
 
14
- context "Cleaning events" do
15
- it "should clean the queue" do
14
+ context "Cleaning appended events" do
15
+ it "should clear the queue" do
16
16
  @mixpanel.append_event("Sign up")
17
- @mixpanel.events.size.should == 1
18
- @mixpanel.clean_queue
19
- @mixpanel.events.size.should == 0
17
+ @mixpanel.queue.size.should == 1
18
+ @mixpanel.clear_queue
19
+ @mixpanel.queue.size.should == 0
20
20
  end
21
21
  end
22
22
 
@@ -27,7 +27,7 @@ describe Mixpanel do
27
27
  end
28
28
 
29
29
  it "should call request method with token and time value" do
30
- params = {:event => "Sign up", :properties => {:token => MIX_PANEL_TOKEN, :time => Time.now.utc.to_i}}
30
+ params = {:event => "Sign up", :properties => {:token => MIX_PANEL_TOKEN, :time => Time.now.utc.to_i, :ip => "127.0.0.1"}}
31
31
 
32
32
  @mixpanel.should_receive(:request).with(params).and_return("1")
33
33
  @mixpanel.track_event("Sign up").should == true
@@ -37,19 +37,28 @@ describe Mixpanel do
37
37
 
38
38
  context "Accessing Mixpanel through javascript API" do
39
39
  context "Appending events" do
40
+ it "should store the event under the appropriate key" do
41
+ @mixpanel.append_event("Sign up")
42
+ @env.has_key?("mixpanel_events").should == true
43
+ end
44
+
45
+ it "should be the same the queue than env['mixpanel_events']" do
46
+ @env['mixpanel_events'].object_id.should == @mixpanel.queue.object_id
47
+ end
48
+
40
49
  it "should append simple events" do
41
50
  @mixpanel.append_event("Sign up")
42
- mixpanel_events_should_include(@mixpanel, "Sign up", {})
51
+ mixpanel_queue_should_include(@mixpanel, "Sign up", {})
43
52
  end
44
53
 
45
54
  it "should append events with properties" do
46
55
  @mixpanel.append_event("Sign up", {:referer => 'http://example.com'})
47
- mixpanel_events_should_include(@mixpanel, "Sign up", {:referer => 'http://example.com'})
56
+ mixpanel_queue_should_include(@mixpanel, "Sign up", {:referer => 'http://example.com'})
48
57
  end
49
58
 
50
- it "should give direct access to events" do
59
+ it "should give direct access to queue" do
51
60
  @mixpanel.append_event("Sign up", {:referer => 'http://example.com'})
52
- @mixpanel.events.size.should == 1
61
+ @mixpanel.queue.size.should == 1
53
62
  end
54
63
  end
55
64
  end
data/spec/spec_helper.rb CHANGED
@@ -1,10 +1,14 @@
1
+ require 'ruby-debug'
1
2
  require File.join(File.dirname(__FILE__), "../lib", "mixpanel")
3
+ require 'rack/test'
2
4
  require 'fakeweb'
5
+ require 'nokogiri'
6
+ Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
3
7
 
4
8
  MIX_PANEL_TOKEN = "e2d8b0bea559147844ffab3d607d26a6"
5
9
 
6
- def mixpanel_events_should_include(mixpanel, event, properties)
7
- mixpanel.events.each do |event_hash|
10
+ def mixpanel_queue_should_include(mixpanel, event, properties)
11
+ mixpanel.queue.each do |event_hash|
8
12
  event_hash[:event].should == event
9
13
  event_hash[:properties].should == properties if properties
10
14
  end
@@ -0,0 +1,27 @@
1
+ def setup_rack_application(application, options = {})
2
+ stub!(:app).and_return(MixpanelMiddleware.new(application.new(options), MIX_PANEL_TOKEN))
3
+ end
4
+
5
+ def html_document
6
+ <<-EOT
7
+ <html>
8
+ <head>
9
+ </head>
10
+ <body>
11
+ </body>
12
+ </html>
13
+ EOT
14
+ end
15
+
16
+ class DummyApp
17
+ def initialize(options)
18
+ @response_with = {}
19
+ @response_with[:status] = options[:status] || "200"
20
+ @response_with[:headers] = options[:headers] || {}
21
+ @response_with[:body] = options[:body] || ""
22
+ end
23
+
24
+ def call(env)
25
+ [@response_with[:status], @response_with[:headers], [@response_with[:body]]]
26
+ end
27
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mixpanel
3
3
  version: !ruby/object:Gem::Version
4
- hash: 9
4
+ hash: 7
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 5
9
- - 1
10
- version: 0.5.1
8
+ - 6
9
+ - 0
10
+ version: 0.6.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Alvaro Gil
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-07-05 00:00:00 -03:00
18
+ date: 2010-07-16 00:00:00 -03:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -33,7 +33,7 @@ dependencies:
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
35
  - !ruby/object:Gem::Dependency
36
- name: rspec
36
+ name: rack
37
37
  prerelease: false
38
38
  requirement: &id002 !ruby/object:Gem::Requirement
39
39
  none: false
@@ -44,10 +44,10 @@ dependencies:
44
44
  segments:
45
45
  - 0
46
46
  version: "0"
47
- type: :development
47
+ type: :runtime
48
48
  version_requirements: *id002
49
49
  - !ruby/object:Gem::Dependency
50
- name: fakeweb
50
+ name: rspec
51
51
  prerelease: false
52
52
  requirement: &id003 !ruby/object:Gem::Requirement
53
53
  none: false
@@ -60,7 +60,49 @@ dependencies:
60
60
  version: "0"
61
61
  type: :development
62
62
  version_requirements: *id003
63
- description: Simple lib to track events in Mixpanel service.
63
+ - !ruby/object:Gem::Dependency
64
+ name: rack-test
65
+ prerelease: false
66
+ requirement: &id004 !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ hash: 3
72
+ segments:
73
+ - 0
74
+ version: "0"
75
+ type: :development
76
+ version_requirements: *id004
77
+ - !ruby/object:Gem::Dependency
78
+ name: fakeweb
79
+ prerelease: false
80
+ requirement: &id005 !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ hash: 3
86
+ segments:
87
+ - 0
88
+ version: "0"
89
+ type: :development
90
+ version_requirements: *id005
91
+ - !ruby/object:Gem::Dependency
92
+ name: nokogiri
93
+ prerelease: false
94
+ requirement: &id006 !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ hash: 3
100
+ segments:
101
+ - 0
102
+ version: "0"
103
+ type: :development
104
+ version_requirements: *id006
105
+ description: Simple lib to track events in Mixpanel service. It can be used in any rack based framework.
64
106
  email: zevarito@gmail.com
65
107
  executables: []
66
108
 
@@ -69,14 +111,17 @@ extensions: []
69
111
  extra_rdoc_files:
70
112
  - README.rdoc
71
113
  files:
72
- - .gitignore
73
114
  - README.rdoc
74
115
  - LICENSE
75
116
  - Rakefile
76
117
  - mixpanel.gemspec
77
- - lib/mixpanel.rb
78
- - spec/spec_helper.rb
118
+ - spec/mixpanel/mixpanel_middleware_spec.rb
79
119
  - spec/mixpanel/mixpanel_spec.rb
120
+ - spec/spec_helper.rb
121
+ - spec/support/rack_apps.rb
122
+ - lib/mixpanel/mixpanel.rb
123
+ - lib/mixpanel/mixpanel_middleware.rb
124
+ - lib/mixpanel.rb
80
125
  has_rdoc: true
81
126
  homepage: http://cuboxsa.com
82
127
  licenses: []
@@ -110,6 +155,6 @@ rubyforge_project: mixpanel
110
155
  rubygems_version: 1.3.7
111
156
  signing_key:
112
157
  specification_version: 3
113
- summary: Supports direct request api and javascript requests.
158
+ summary: Supports direct request api and javascript requests through a middleware.
114
159
  test_files: []
115
160
 
data/.gitignore DELETED
@@ -1,2 +0,0 @@
1
- .bundle
2
- mixpanel*.gem