mixpanel 1.1.3 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +213 -0
- data/lib/mixpanel.rb +0 -4
- data/lib/mixpanel/tracker.rb +37 -6
- data/lib/mixpanel/tracker/middleware.rb +52 -36
- data/mixpanel.gemspec +5 -4
- data/spec/mixpanel/mixpanel_spec.rb +4 -3
- data/spec/mixpanel/tracker/middleware_spec.rb +39 -31
- metadata +151 -140
- data/README.rdoc +0 -120
data/README.md
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
[![Build Status](https://secure.travis-ci.org/zevarito/mixpanel.png)](http://travis-ci.org/zevarito/mixpanel)
|
2
|
+
|
3
|
+
## Table of Contents
|
4
|
+
|
5
|
+
- [What is Mixpanel] (#what-is-mixpanel)
|
6
|
+
- [What does this Gem do?] (#what-does-this-gem-do)
|
7
|
+
- [Install] (#install)
|
8
|
+
- [Rack Middleware] (#rack-middleware)
|
9
|
+
- [Usage] (#usage)
|
10
|
+
- [Initialize Mixpanel class] (#initialize-mixpanel-class)
|
11
|
+
- [Examples] (#examples)
|
12
|
+
- [How to use it from Rails controllers] (#how-to-use-it-from-rails-controllers)
|
13
|
+
- [How to track events using Resque and Rails] (#how-to-track-events-using-resque-and-rails)
|
14
|
+
- [Supported Platforms] (#supported-platforms)
|
15
|
+
- [Deprecation Notes] (#deprecation-notes)
|
16
|
+
- [Collaborators and Maintainers] (#collaborators-and-maintainers)
|
17
|
+
|
18
|
+
## What is Mixpanel
|
19
|
+
|
20
|
+
Mixpanel is a real-time analytics service that helps companies understand how users interact with web applications.
|
21
|
+
http://mixpanel.com
|
22
|
+
|
23
|
+
## What does this Gem do?
|
24
|
+
|
25
|
+
- Track events with properties directly from your backend.
|
26
|
+
- Track events with properties through javascript using a rack middleware.
|
27
|
+
|
28
|
+
## Install
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
gem install mixpanel
|
32
|
+
```
|
33
|
+
|
34
|
+
### Rack Middleware
|
35
|
+
|
36
|
+
*Only need if you want to track events from Javascript.*
|
37
|
+
|
38
|
+
If you are using Rails you can add this to your specific environment configuration file (located in config/environments/) or create a new
|
39
|
+
initializer for it:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
config.middleware.use "Mixpanel::Tracker::Middleware", "YOUR_MIXPANEL_API_TOKEN", options
|
43
|
+
```
|
44
|
+
|
45
|
+
Where **options** is a Hash that accepts the following keys:
|
46
|
+
|
47
|
+
* **insert_js_last** : true | false
|
48
|
+
|
49
|
+
*Default: false*.
|
50
|
+
By default the scripts are inserted into the head of the html response. If you'd prefer the scripts to run after
|
51
|
+
all rendering has completed you can set the insert_js_last flag and they'll be added at the end of the body tag.
|
52
|
+
This will work whether or not you opt for the aynchronous version of the API. However, when inserting js into an
|
53
|
+
ajax response it will have no effect.
|
54
|
+
|
55
|
+
* **persist** : true | false
|
56
|
+
|
57
|
+
*Default: false*.
|
58
|
+
If you would like, the Mixpanel gem may be configured to store its queue in a Rack session. This allows events
|
59
|
+
to be stored through redirects, helpful if you sign in and redirect but want to associate an event with that
|
60
|
+
action. The mixpanel gem will also remove duplicate events from your queue for information that should only be
|
61
|
+
trasmitted to the API once, such as `mixpanel.identify`, `mixpanel.name_tag`, `mixpanel.people.set`, and
|
62
|
+
`mixpanel.register`.
|
63
|
+
This allows you to use a before filter to set these variables, redirect, and still have them only transmitted
|
64
|
+
once.
|
65
|
+
*To enable persistence*, you must set it in both places, Middleware and when you initialize Mixpanel class.
|
66
|
+
|
67
|
+
* **config** : a Hash
|
68
|
+
|
69
|
+
*Default: {}*.
|
70
|
+
You can also pass Mixpanel configuration details as seen here
|
71
|
+
(https://mixpanel.com/docs/integration-libraries/javascript-full-api#set_config)
|
72
|
+
|
73
|
+
## Usage
|
74
|
+
|
75
|
+
### Initialize Mixpanel class
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
@mixpanel = Mixpanel::Tracker.new("YOUR_MIXPANEL_API_TOKEN", request.env, true, options)
|
79
|
+
```
|
80
|
+
Where **options** is a Hash that accepts the following keys:
|
81
|
+
|
82
|
+
* **async** : true | false
|
83
|
+
|
84
|
+
*Default: false*.
|
85
|
+
Built in async feature. Events are sent to a subprocess via a pipe and the sub process which asynchronously send events to Mixpanel.
|
86
|
+
This process uses a single thread to upload events, and may start dropping events if your application generates
|
87
|
+
them at a very high rate.
|
88
|
+
If you like for a more robust async behavior take a look at Resque example.
|
89
|
+
|
90
|
+
* **url** : String
|
91
|
+
|
92
|
+
*Default: http://api.mixpanel.com/track/?data=*.
|
93
|
+
If you are proxying Mixpanel API requests then you can set a custom url and additionally stop the token from
|
94
|
+
being sent by marking it as false if you're going to let the proxy add it.
|
95
|
+
Example: { url: "http://localhost:8000/mixpanelproxy?data=" }.
|
96
|
+
|
97
|
+
* **persist** : true | false
|
98
|
+
|
99
|
+
*Default: false*.
|
100
|
+
If you would like, the Mixpanel gem may be configured to store its queue in a Rack session. This allows events
|
101
|
+
to be stored through redirects, helpful if you sign in and redirect but want to associate an event with that
|
102
|
+
action. The mixpanel gem will also remove duplicate events from your queue for information that should only be
|
103
|
+
trasmitted to the API once, such as `mixpanel.identify`, `mixpanel.name_tag`, `mixpanel.people.set`, and
|
104
|
+
`mixpanel.register`.
|
105
|
+
This allows you to use a before filter to set these variables, redirect, and still have them only transmitted
|
106
|
+
once.
|
107
|
+
*To enable persistence*, you must set it in both places, Middleware and when you initialize Mixpanel class.
|
108
|
+
|
109
|
+
### Track events directly.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
@mixpanel.track_event("Sign in", {:some => "property"})
|
113
|
+
```
|
114
|
+
|
115
|
+
### Append events to be tracked with Javascript.
|
116
|
+
|
117
|
+
*Note*: You should setup the [Rack Middleware](#rack-middleware).
|
118
|
+
|
119
|
+
```ruby
|
120
|
+
@mixpanel.append_event("Sign in", {:some => "property"})
|
121
|
+
```
|
122
|
+
|
123
|
+
### Execute Javascript API call
|
124
|
+
|
125
|
+
*Note*: You should setup the [Rack Middleware](#rack-middleware).
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
@mixpanel.append_api("register", {:some => "property"})
|
129
|
+
@mixpanel.append_api("identify", "Unique Identifier")
|
130
|
+
```
|
131
|
+
|
132
|
+
## Examples
|
133
|
+
|
134
|
+
### How to use it from Rails controllers?
|
135
|
+
|
136
|
+
In your ApplicationController class add a method to instantiate mixpanel.
|
137
|
+
|
138
|
+
```ruby
|
139
|
+
before_filter :initialize_mixpanel
|
140
|
+
|
141
|
+
def initialize_mixpanel
|
142
|
+
@mixpanel = Mixpanel::Tracker.new("YOUR_MIXPANEL_API_TOKEN", request.env, options)
|
143
|
+
end
|
144
|
+
```
|
145
|
+
## How to track events using Resque and Rails
|
146
|
+
|
147
|
+
If you don't want to use the built in Mixpanel Gem async feature bellow there is an example about how to make
|
148
|
+
async calls using Resque.
|
149
|
+
|
150
|
+
[Resque is a Redis-backed Ruby library for creating background jobs](https://github.com/defunkt/resque)
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
class MixpanelTrackEventJob
|
154
|
+
@queue = :slow
|
155
|
+
|
156
|
+
def mixpanel(request_env)
|
157
|
+
Mixpanel::Tracker.new(MIXPANEL_TOKEN, request_env)
|
158
|
+
end
|
159
|
+
|
160
|
+
def perform(name, params, request_env)
|
161
|
+
mixpanel(request_env).track_event(name, params)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
```
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
class UsersController < ApplicationController
|
168
|
+
def create
|
169
|
+
@user = User.new(params[:user])
|
170
|
+
|
171
|
+
if @user.save
|
172
|
+
MixpanelTrackEventJob.enqueue("Sign up", {:invited => params[:invited]}, request.env)
|
173
|
+
redirect_to user_root_path
|
174
|
+
else
|
175
|
+
render :new
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
```
|
180
|
+
|
181
|
+
## Supported Platforms
|
182
|
+
|
183
|
+
- 1.8.7
|
184
|
+
- 1.9.2
|
185
|
+
- 1.9.3
|
186
|
+
- JRuby 1.8 Mode
|
187
|
+
|
188
|
+
## Deprecation Notes
|
189
|
+
|
190
|
+
This way to initialize Mixpanel gem is not longer allowed.
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
Mixpanel.new
|
194
|
+
```
|
195
|
+
|
196
|
+
Use this instead:
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
Mixpanel::Tracker.new
|
200
|
+
```
|
201
|
+
|
202
|
+
## Collaborators and Maintainers
|
203
|
+
|
204
|
+
* [Alvaro Gil](https://github.com/zevarito) (Author)
|
205
|
+
* [Nathan Baxter](https://github.com/LogicWolfe)
|
206
|
+
* [Jake Mallory](https://github.com/tinomen)
|
207
|
+
* [Logan Bowers](https://github.com/loganb)
|
208
|
+
* [jakemack](https://github.com/jakemack)
|
209
|
+
* [James Ferguson](https://github.com/JamesFerguson)
|
210
|
+
* [Brad Wilson](https://github.com/bradx3)
|
211
|
+
* [Mark Cheverton](https://github.com/ennui2342)
|
212
|
+
* [Jamie Quint](https://github.com/jamiequint)
|
213
|
+
* [Ryan Schmukler](https://github.com/rschmukler)
|
data/lib/mixpanel.rb
CHANGED
data/lib/mixpanel/tracker.rb
CHANGED
@@ -6,18 +6,41 @@ require 'mixpanel/tracker/middleware'
|
|
6
6
|
|
7
7
|
module Mixpanel
|
8
8
|
class Tracker
|
9
|
-
def initialize(token, env,
|
9
|
+
def initialize(token, env, options={})
|
10
10
|
@token = token
|
11
11
|
@env = env
|
12
|
-
@async = async
|
13
|
-
@url = url
|
14
|
-
|
12
|
+
@async = options.fetch(:async, false)
|
13
|
+
@url = options.fetch(:url, 'http://api.mixpanel.com/track/?data=')
|
14
|
+
@persist = options.fetch(:persist, false)
|
15
|
+
|
16
|
+
if @persist
|
17
|
+
@env["rack.session"]["mixpanel_events"] ||= []
|
18
|
+
else
|
19
|
+
clear_queue
|
20
|
+
end
|
15
21
|
end
|
16
22
|
|
17
23
|
def append_event(event, properties = {})
|
18
24
|
append_api('track', event, properties)
|
19
25
|
end
|
20
26
|
|
27
|
+
def append_person_event(properties = {})
|
28
|
+
# evaluate symbols and rewrite
|
29
|
+
special_properties = %w{email created first_name last_name last_login username country_code}
|
30
|
+
special_properties.each do |key|
|
31
|
+
symbolized_key = key.to_sym
|
32
|
+
if properties.has_key?(symbolized_key)
|
33
|
+
properties["$#{key}"] = properties[symbolized_key]
|
34
|
+
properties.delete(symbolized_key)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
append_api('people.set', properties)
|
38
|
+
end
|
39
|
+
|
40
|
+
def append_person_increment_event(property, increment=1)
|
41
|
+
append_api('people.increment', property, increment)
|
42
|
+
end
|
43
|
+
|
21
44
|
def append_api(type, *args)
|
22
45
|
queue << [type, args.map {|arg| arg.to_json}]
|
23
46
|
end
|
@@ -41,11 +64,19 @@ module Mixpanel
|
|
41
64
|
end
|
42
65
|
|
43
66
|
def queue
|
44
|
-
@
|
67
|
+
if @persist
|
68
|
+
return @env["rack.session"]["mixpanel_events"]
|
69
|
+
else
|
70
|
+
return @env["mixpanel_events"]
|
71
|
+
end
|
45
72
|
end
|
46
73
|
|
47
74
|
def clear_queue
|
48
|
-
@
|
75
|
+
if @persist
|
76
|
+
@env["rack.session"]["mixpanel_events"] = []
|
77
|
+
else
|
78
|
+
@env["mixpanel_events"] = []
|
79
|
+
end
|
49
80
|
end
|
50
81
|
|
51
82
|
class <<self
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'rack'
|
2
|
+
require 'json'
|
2
3
|
|
3
4
|
module Mixpanel
|
4
5
|
class Tracker
|
@@ -7,8 +8,9 @@ module Mixpanel
|
|
7
8
|
@app = app
|
8
9
|
@token = mixpanel_token
|
9
10
|
@options = {
|
10
|
-
:
|
11
|
-
:
|
11
|
+
:insert_js_last => false,
|
12
|
+
:persist => false,
|
13
|
+
:config => {}
|
12
14
|
}.merge(options)
|
13
15
|
end
|
14
16
|
|
@@ -18,6 +20,7 @@ module Mixpanel
|
|
18
20
|
@status, @headers, @response = @app.call(env)
|
19
21
|
|
20
22
|
if is_trackable_response?
|
23
|
+
merge_queue! if @options[:persist]
|
21
24
|
update_response!
|
22
25
|
update_content_length!
|
23
26
|
delete_event_queue!
|
@@ -67,56 +70,69 @@ module Mixpanel
|
|
67
70
|
end
|
68
71
|
|
69
72
|
def is_trackable_response?
|
73
|
+
return false if @status == 302
|
70
74
|
is_html_response? || is_javascript_response?
|
71
75
|
end
|
72
76
|
|
73
77
|
def render_mixpanel_scripts
|
74
|
-
|
75
|
-
|
76
|
-
<script type=
|
77
|
-
var
|
78
|
-
|
79
|
-
|
78
|
+
<<-EOT
|
79
|
+
<!-- start Mixpanel -->
|
80
|
+
<script type="text/javascript">
|
81
|
+
(function(c,a){var b,d,h,e;b=c.createElement("script");b.type="text/javascript";
|
82
|
+
b.async=!0;b.src=("https:"===c.location.protocol?"https:":"http:")+
|
83
|
+
'//api.mixpanel.com/site_media/js/api/mixpanel.2.js';d=c.getElementsByTagName("script")[0];
|
84
|
+
d.parentNode.insertBefore(b,d);a._i=[];a.init=function(b,c,f){function d(a,b){
|
85
|
+
var c=b.split(".");2==c.length&&(a=a[c[0]],b=c[1]);a[b]=function(){a.push([b].concat(
|
86
|
+
Array.prototype.slice.call(arguments,0)))}}var g=a;"undefined"!==typeof f?g=a[f]=[]:
|
87
|
+
f="mixpanel";g.people=g.people||[];h=['disable','track','track_pageview','track_links',
|
88
|
+
'track_forms','register','register_once','unregister','identify','name_tag',
|
89
|
+
'set_config','people.set','people.increment'];for(e=0;e<h.length;e++)d(g,h[e]);
|
90
|
+
a._i.push([b,c,f])};a.__SV=1.1;window.mixpanel=a})(document,window.mixpanel||[]);
|
91
|
+
|
92
|
+
mixpanel.init("#{@token}");
|
93
|
+
mixpanel.set_config(#{@options[:config].to_json});
|
80
94
|
</script>
|
81
|
-
|
82
|
-
|
83
|
-
<<-EOT
|
84
|
-
<script type='text/javascript'>
|
85
|
-
var mp_protocol = (('https:' == document.location.protocol) ? 'https://' : 'http://');
|
86
|
-
document.write(unescape('%3Cscript src="' + mp_protocol + 'api.mixpanel.com/site_media/js/api/mixpanel.js" type="text/javascript"%3E%3C/script%3E'));
|
87
|
-
</script>
|
88
|
-
<script type='text/javascript'>
|
89
|
-
try {
|
90
|
-
var mpmetrics = new MixpanelLib('#{@token}');
|
91
|
-
} catch(err) {
|
92
|
-
null_fn = function () {};
|
93
|
-
var mpmetrics = {
|
94
|
-
track: null_fn, track_funnel: null_fn, register: null_fn, register_once: null_fn, register_funnel: null_fn
|
95
|
-
};
|
96
|
-
}
|
97
|
-
</script>
|
98
|
-
EOT
|
99
|
-
end
|
95
|
+
<!-- end Mixpanel -->
|
96
|
+
EOT
|
100
97
|
end
|
101
98
|
|
102
99
|
def delete_event_queue!
|
103
|
-
@
|
100
|
+
if @options[:persist]
|
101
|
+
(@env['rack.session']).delete('mixpanel_events')
|
102
|
+
else
|
103
|
+
@env.delete('mixpanel_events')
|
104
|
+
end
|
104
105
|
end
|
105
106
|
|
106
107
|
def queue
|
107
|
-
|
108
|
-
|
108
|
+
if @options[:persist]
|
109
|
+
return [] if !(@env['rack.session']).has_key?('mixpanel_events') || @env['rack.session']['mixpanel_events'].empty?
|
110
|
+
@env['rack.session']['mixpanel_events']
|
111
|
+
else
|
112
|
+
return [] if !@env.has_key?('mixpanel_events') || @env['mixpanel_events'].empty?
|
113
|
+
@env['mixpanel_events']
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def merge_queue!
|
118
|
+
present_hash = {}
|
119
|
+
special_events = ['identify', 'name_tag', 'people.set', 'register']
|
120
|
+
queue.uniq!
|
121
|
+
|
122
|
+
queue.reverse_each do |item|
|
123
|
+
is_special = special_events.include?(item[0])
|
124
|
+
if present_hash[item[0]] and is_special
|
125
|
+
queue.delete(item)
|
126
|
+
else
|
127
|
+
present_hash[item[0]] = true if is_special
|
128
|
+
end
|
129
|
+
end
|
109
130
|
end
|
110
131
|
|
111
132
|
def render_event_tracking_scripts(include_script_tag=true)
|
112
133
|
return "" if queue.empty?
|
113
134
|
|
114
|
-
|
115
|
-
output = queue.map {|type, arguments| %(mpq.push(["#{type}", #{arguments.join(', ')}]);) }.join("\n")
|
116
|
-
else
|
117
|
-
output = queue.map {|type, arguments| %(mpmetrics.#{type}(#{arguments.join(', ')});) }.join("\n")
|
118
|
-
end
|
119
|
-
|
135
|
+
output = queue.map {|type, arguments| %(mixpanel.#{type}(#{arguments.join(', ')});) }.join("\n")
|
120
136
|
output = "try {#{output}} catch(err) {}"
|
121
137
|
|
122
138
|
include_script_tag ? "<script type='text/javascript'>#{output}</script>" : output
|
data/mixpanel.gemspec
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
files = ['README.
|
1
|
+
files = ['README.md', 'LICENSE', 'Rakefile', 'mixpanel.gemspec', '{spec,lib}/**/*'].map {|f| Dir[f]}.flatten
|
2
2
|
|
3
3
|
spec = Gem::Specification.new do |s|
|
4
4
|
s.name = "mixpanel"
|
5
|
-
s.version = "
|
5
|
+
s.version = "2.0.0"
|
6
6
|
s.rubyforge_project = "mixpanel"
|
7
7
|
s.description = "Simple lib to track events in Mixpanel service. It can be used in any rack based framework."
|
8
8
|
s.author = "Alvaro Gil"
|
@@ -13,7 +13,7 @@ spec = Gem::Specification.new do |s|
|
|
13
13
|
s.files = files
|
14
14
|
s.require_path = "lib"
|
15
15
|
s.has_rdoc = false
|
16
|
-
s.extra_rdoc_files = ["README.
|
16
|
+
s.extra_rdoc_files = ["README.md"]
|
17
17
|
s.add_dependency 'json'
|
18
18
|
s.add_dependency 'rack'
|
19
19
|
s.add_dependency 'escape'
|
@@ -22,6 +22,7 @@ spec = Gem::Specification.new do |s|
|
|
22
22
|
s.add_development_dependency 'fakeweb'
|
23
23
|
s.add_development_dependency 'nokogiri'
|
24
24
|
s.add_development_dependency 'rake'
|
25
|
-
s.add_development_dependency '
|
25
|
+
s.add_development_dependency 'debugger' if RUBY_VERSION =~ /^1\.9\.3/
|
26
|
+
s.add_development_dependency 'ruby-debug19' if RUBY_VERSION =~ /^1\.9\.2/
|
26
27
|
s.add_development_dependency 'ruby-debug' if RUBY_VERSION =~ /^1\.8/
|
27
28
|
end
|
@@ -2,9 +2,10 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Mixpanel do
|
4
4
|
context "Deprecated initialization mode" do
|
5
|
-
it "should
|
6
|
-
|
7
|
-
|
5
|
+
it "should not allow to initialize the class as the old way" do
|
6
|
+
lambda do
|
7
|
+
mixpanel = Mixpanel.new(MIX_PANEL_TOKEN, @env = {"REMOTE_ADDR" => "127.0.0.1"})
|
8
|
+
end.should raise_error(NoMethodError)
|
8
9
|
end
|
9
10
|
end
|
10
11
|
end
|
@@ -1,5 +1,23 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
+
def exec_default_appends_on(mixpanel)
|
4
|
+
mixpanel.append_event("Visit", {:article => 1})
|
5
|
+
mixpanel.append_event("Sign in")
|
6
|
+
mixpanel.append_person_event(:first_name => "foo", :last_name => "bar", :username => "foobar")
|
7
|
+
mixpanel.append_person_increment_event(:sign_in_rate)
|
8
|
+
end
|
9
|
+
|
10
|
+
def check_for_default_appends_on(txt)
|
11
|
+
txt.should =~ /mixpanel\.track\("Visit",\s?\{"article":1\}\)/
|
12
|
+
txt.should =~ /mixpanel\.track\("Sign in",\s?\{\}\)/
|
13
|
+
txt.should =~ /mixpanel\.people\.set\(.*\);\nmixpanel.people.increment\(\"sign_in_rate\",\s?1\);/
|
14
|
+
match = txt.match(/mixpanel\.people\.set\((.*\));/)
|
15
|
+
match[1].should =~ /\"\$first_name\":\"foo\"/
|
16
|
+
match[1].should =~ /\"\$username\":\"foobar\"/
|
17
|
+
match[1].should =~ /\"\$last_name\":\"bar\"/
|
18
|
+
txt.should =~ /mixpanel\.people\.increment\(\"sign_in_rate\"\s?,\s?1\)/
|
19
|
+
end
|
20
|
+
|
3
21
|
describe Mixpanel::Tracker::Middleware do
|
4
22
|
include Rack::Test::Methods
|
5
23
|
|
@@ -17,7 +35,7 @@ describe Mixpanel::Tracker::Middleware do
|
|
17
35
|
describe "Appending async mixpanel scripts" do
|
18
36
|
describe "With ajax requests" do
|
19
37
|
before do
|
20
|
-
setup_rack_application(DummyApp, {:body => html_document, :headers => {"Content-Type" => "text/html"}}
|
38
|
+
setup_rack_application(DummyApp, {:body => html_document, :headers => {"Content-Type" => "text/html"}})
|
21
39
|
get "/", {}, {"HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"}
|
22
40
|
end
|
23
41
|
|
@@ -32,7 +50,7 @@ describe Mixpanel::Tracker::Middleware do
|
|
32
50
|
|
33
51
|
describe "With large ajax response" do
|
34
52
|
before do
|
35
|
-
setup_rack_application(DummyApp, {:body => large_script, :headers => {"Content-Type" => "text/html"}}
|
53
|
+
setup_rack_application(DummyApp, {:body => large_script, :headers => {"Content-Type" => "text/html"}})
|
36
54
|
get "/", {}, {"HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"}
|
37
55
|
end
|
38
56
|
|
@@ -48,7 +66,7 @@ describe Mixpanel::Tracker::Middleware do
|
|
48
66
|
describe "With regular requests" do
|
49
67
|
describe "With js in head" do
|
50
68
|
before do
|
51
|
-
setup_rack_application(DummyApp, {:body => html_document, :headers => {"Content-Type" => "text/html"}}, {:
|
69
|
+
setup_rack_application(DummyApp, {:body => html_document, :headers => {"Content-Type" => "text/html"}}, {:insert_js_last => false})
|
52
70
|
get "/"
|
53
71
|
end
|
54
72
|
|
@@ -62,7 +80,7 @@ describe Mixpanel::Tracker::Middleware do
|
|
62
80
|
end
|
63
81
|
|
64
82
|
it "should use the specified token instantiating mixpanel lib" do
|
65
|
-
last_response.should =~ /
|
83
|
+
last_response.body.should =~ /mixpanel\.init\("#{MIX_PANEL_TOKEN}"\)/
|
66
84
|
end
|
67
85
|
|
68
86
|
it "should define Content-Length if not exist" do
|
@@ -76,7 +94,7 @@ describe Mixpanel::Tracker::Middleware do
|
|
76
94
|
|
77
95
|
describe "With js last" do
|
78
96
|
before do
|
79
|
-
setup_rack_application(DummyApp, {:body => html_document, :headers => {"Content-Type" => "text/html"}}, {:
|
97
|
+
setup_rack_application(DummyApp, {:body => html_document, :headers => {"Content-Type" => "text/html"}}, {:insert_js_last => true})
|
80
98
|
get "/"
|
81
99
|
end
|
82
100
|
|
@@ -131,12 +149,12 @@ describe Mixpanel::Tracker::Middleware do
|
|
131
149
|
Nokogiri::HTML(last_response.body).search('body script').should be_empty
|
132
150
|
end
|
133
151
|
|
134
|
-
it "should have
|
135
|
-
Nokogiri::HTML(last_response.body).search('script').size.should ==
|
152
|
+
it "should have 1 included script" do
|
153
|
+
Nokogiri::HTML(last_response.body).search('script').size.should == 1
|
136
154
|
end
|
137
155
|
|
138
156
|
it "should use the specified token instantiating mixpanel lib" do
|
139
|
-
last_response.should =~ /
|
157
|
+
last_response.body.should =~ /mixpanel\.init\("#{MIX_PANEL_TOKEN}"\)/
|
140
158
|
end
|
141
159
|
|
142
160
|
it "should define Content-Length if not exist" do
|
@@ -165,13 +183,12 @@ describe Mixpanel::Tracker::Middleware do
|
|
165
183
|
describe "Tracking async appended events" do
|
166
184
|
before do
|
167
185
|
@mixpanel = Mixpanel::Tracker.new(MIX_PANEL_TOKEN, {})
|
168
|
-
@mixpanel
|
169
|
-
@mixpanel.append_event("Sign in")
|
186
|
+
exec_default_appends_on @mixpanel
|
170
187
|
end
|
171
188
|
|
172
189
|
describe "With ajax requests and text/html response" do
|
173
190
|
before do
|
174
|
-
setup_rack_application(DummyApp, {:body => "<p>response</p>", :headers => {"Content-Type" => "text/html"}}
|
191
|
+
setup_rack_application(DummyApp, {:body => "<p>response</p>", :headers => {"Content-Type" => "text/html"}})
|
175
192
|
|
176
193
|
get "/", {}, {"mixpanel_events" => @mixpanel.queue, "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"}
|
177
194
|
end
|
@@ -182,9 +199,7 @@ describe Mixpanel::Tracker::Middleware do
|
|
182
199
|
|
183
200
|
it "should be tracking the correct events inside a script tag" do
|
184
201
|
script = Nokogiri::HTML(last_response.body).search('script')
|
185
|
-
script.inner_html
|
186
|
-
script.inner_html.should =~ /mpq\.push\(\["track",\s?"Visit",\s?\{"article":1\}\]\)/
|
187
|
-
script.inner_html.should =~ /mpq\.push\(\["track",\s?"Sign in",\s?\{\}\]\)/
|
202
|
+
check_for_default_appends_on script.inner_html
|
188
203
|
end
|
189
204
|
|
190
205
|
it "should delete events queue after use it" do
|
@@ -194,7 +209,7 @@ describe Mixpanel::Tracker::Middleware do
|
|
194
209
|
|
195
210
|
describe "With ajax requests and text/javascript response" do
|
196
211
|
before do
|
197
|
-
setup_rack_application(DummyApp, {:body => "alert('response')", :headers => {"Content-Type" => "text/javascript"}}
|
212
|
+
setup_rack_application(DummyApp, {:body => "alert('response')", :headers => {"Content-Type" => "text/javascript"}})
|
198
213
|
get "/", {}, {"mixpanel_events" => @mixpanel.queue, "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest"}
|
199
214
|
end
|
200
215
|
|
@@ -204,8 +219,7 @@ describe Mixpanel::Tracker::Middleware do
|
|
204
219
|
|
205
220
|
it "should be tracking the correct events inside a try/catch" do
|
206
221
|
script = last_response.body.match(/try\s?\{(.*)\}\s?catch/m)[1]
|
207
|
-
script
|
208
|
-
script.should =~ /mpq\.push\(\["track",\s?"Sign in",\s?\{\}\]\)/
|
222
|
+
check_for_default_appends_on script
|
209
223
|
end
|
210
224
|
|
211
225
|
it "should delete events queue after use it" do
|
@@ -215,7 +229,7 @@ describe Mixpanel::Tracker::Middleware do
|
|
215
229
|
|
216
230
|
describe "With regular requests" do
|
217
231
|
before do
|
218
|
-
setup_rack_application(DummyApp, {:body => html_document, :headers => {"Content-Type" => "text/html"}}
|
232
|
+
setup_rack_application(DummyApp, {:body => html_document, :headers => {"Content-Type" => "text/html"}})
|
219
233
|
|
220
234
|
get "/", {}, {"mixpanel_events" => @mixpanel.queue}
|
221
235
|
end
|
@@ -225,8 +239,7 @@ describe Mixpanel::Tracker::Middleware do
|
|
225
239
|
end
|
226
240
|
|
227
241
|
it "should be tracking the correct events" do
|
228
|
-
last_response.body
|
229
|
-
last_response.body.should =~ /mpq\.push\(\["track",\s?"Sign in",\s?\{\}\]\)/
|
242
|
+
check_for_default_appends_on last_response.body
|
230
243
|
end
|
231
244
|
|
232
245
|
it "should delete events queue after use it" do
|
@@ -238,8 +251,7 @@ describe Mixpanel::Tracker::Middleware do
|
|
238
251
|
describe "Tracking appended events" do
|
239
252
|
before do
|
240
253
|
@mixpanel = Mixpanel::Tracker.new(MIX_PANEL_TOKEN, {})
|
241
|
-
@mixpanel
|
242
|
-
@mixpanel.append_event("Sign in")
|
254
|
+
exec_default_appends_on @mixpanel
|
243
255
|
end
|
244
256
|
|
245
257
|
describe "With ajax requests and text/html response" do
|
@@ -255,9 +267,7 @@ describe Mixpanel::Tracker::Middleware do
|
|
255
267
|
|
256
268
|
it "should be tracking the correct events inside a script tag" do
|
257
269
|
script = Nokogiri::HTML(last_response.body).search('script')
|
258
|
-
script.inner_html
|
259
|
-
script.inner_html.should =~ /mpmetrics\.track\("Visit",\s?\{"article":1\}\)/
|
260
|
-
script.inner_html.should =~ /mpmetrics\.track\("Sign in",\s?\{\}\)/
|
270
|
+
check_for_default_appends_on script.inner_html
|
261
271
|
end
|
262
272
|
|
263
273
|
it "should delete events queue after use it" do
|
@@ -277,8 +287,7 @@ describe Mixpanel::Tracker::Middleware do
|
|
277
287
|
|
278
288
|
it "should be tracking the correct events inside a try/catch" do
|
279
289
|
script = last_response.body.match(/try\s?\{(.*)\}\s?catch/m)[1]
|
280
|
-
script
|
281
|
-
script.should =~ /mpmetrics\.track\("Sign in",\s?\{\}\)/
|
290
|
+
check_for_default_appends_on script
|
282
291
|
end
|
283
292
|
|
284
293
|
it "should delete events queue after use it" do
|
@@ -293,13 +302,12 @@ describe Mixpanel::Tracker::Middleware do
|
|
293
302
|
get "/", {}, {"mixpanel_events" => @mixpanel.queue}
|
294
303
|
end
|
295
304
|
|
296
|
-
it "should render
|
297
|
-
Nokogiri::HTML(last_response.body).search('script').size.should ==
|
305
|
+
it "should render 2 script tags" do
|
306
|
+
Nokogiri::HTML(last_response.body).search('script').size.should == 2
|
298
307
|
end
|
299
308
|
|
300
309
|
it "should be tracking the correct events" do
|
301
|
-
last_response.body
|
302
|
-
last_response.body.should =~ /mpmetrics\.track\("Sign in",\s?\{\}\)/
|
310
|
+
check_for_default_appends_on last_response.body
|
303
311
|
end
|
304
312
|
|
305
313
|
it "should delete events queue after use it" do
|
metadata
CHANGED
@@ -1,149 +1,169 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixpanel
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 1
|
7
|
-
- 1
|
8
|
-
- 3
|
9
|
-
version: 1.1.3
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.0.0
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Alvaro Gil
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
dependencies:
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-08-09 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: json
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
segments:
|
29
|
-
- 0
|
30
|
-
version: "0"
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
31
22
|
type: :runtime
|
32
|
-
version_requirements: *id001
|
33
|
-
- !ruby/object:Gem::Dependency
|
34
|
-
name: rack
|
35
23
|
prerelease: false
|
36
|
-
|
37
|
-
none: false
|
38
|
-
requirements:
|
39
|
-
- -
|
40
|
-
- !ruby/object:Gem::Version
|
41
|
-
|
42
|
-
|
43
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rack
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
44
38
|
type: :runtime
|
45
|
-
version_requirements: *id002
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name: escape
|
48
39
|
prerelease: false
|
49
|
-
|
50
|
-
none: false
|
51
|
-
requirements:
|
52
|
-
- -
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
|
55
|
-
|
56
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: escape
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
57
54
|
type: :runtime
|
58
|
-
version_requirements: *id003
|
59
|
-
- !ruby/object:Gem::Dependency
|
60
|
-
name: rspec
|
61
55
|
prerelease: false
|
62
|
-
|
63
|
-
none: false
|
64
|
-
requirements:
|
65
|
-
- -
|
66
|
-
- !ruby/object:Gem::Version
|
67
|
-
|
68
|
-
|
69
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rspec
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
70
|
type: :development
|
71
|
-
version_requirements: *id004
|
72
|
-
- !ruby/object:Gem::Dependency
|
73
|
-
name: rack-test
|
74
71
|
prerelease: false
|
75
|
-
|
76
|
-
none: false
|
77
|
-
requirements:
|
78
|
-
- -
|
79
|
-
- !ruby/object:Gem::Version
|
80
|
-
|
81
|
-
|
82
|
-
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: rack-test
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
83
86
|
type: :development
|
84
|
-
version_requirements: *id005
|
85
|
-
- !ruby/object:Gem::Dependency
|
86
|
-
name: fakeweb
|
87
87
|
prerelease: false
|
88
|
-
|
89
|
-
none: false
|
90
|
-
requirements:
|
91
|
-
- -
|
92
|
-
- !ruby/object:Gem::Version
|
93
|
-
|
94
|
-
|
95
|
-
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: fakeweb
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
96
102
|
type: :development
|
97
|
-
version_requirements: *id006
|
98
|
-
- !ruby/object:Gem::Dependency
|
99
|
-
name: nokogiri
|
100
103
|
prerelease: false
|
101
|
-
|
102
|
-
none: false
|
103
|
-
requirements:
|
104
|
-
- -
|
105
|
-
- !ruby/object:Gem::Version
|
106
|
-
|
107
|
-
|
108
|
-
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
- !ruby/object:Gem::Dependency
|
111
|
+
name: nokogiri
|
112
|
+
requirement: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
109
118
|
type: :development
|
110
|
-
version_requirements: *id007
|
111
|
-
- !ruby/object:Gem::Dependency
|
112
|
-
name: rake
|
113
119
|
prerelease: false
|
114
|
-
|
115
|
-
none: false
|
116
|
-
requirements:
|
117
|
-
- -
|
118
|
-
- !ruby/object:Gem::Version
|
119
|
-
|
120
|
-
|
121
|
-
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
none: false
|
122
|
+
requirements:
|
123
|
+
- - ! '>='
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: rake
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
122
134
|
type: :development
|
123
|
-
version_requirements: *id008
|
124
|
-
- !ruby/object:Gem::Dependency
|
125
|
-
name: ruby-debug19
|
126
135
|
prerelease: false
|
127
|
-
|
128
|
-
none: false
|
129
|
-
requirements:
|
130
|
-
- -
|
131
|
-
- !ruby/object:Gem::Version
|
132
|
-
|
133
|
-
|
134
|
-
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: debugger
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
135
150
|
type: :development
|
136
|
-
|
137
|
-
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
description: Simple lib to track events in Mixpanel service. It can be used in any
|
159
|
+
rack based framework.
|
138
160
|
email: zevarito@gmail.com
|
139
161
|
executables: []
|
140
|
-
|
141
162
|
extensions: []
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
- README.rdoc
|
163
|
+
extra_rdoc_files:
|
164
|
+
- README.md
|
165
|
+
files:
|
166
|
+
- README.md
|
147
167
|
- LICENSE
|
148
168
|
- Rakefile
|
149
169
|
- mixpanel.gemspec
|
@@ -156,37 +176,28 @@ files:
|
|
156
176
|
- lib/mixpanel/tracker/subprocess.rb
|
157
177
|
- lib/mixpanel/tracker.rb
|
158
178
|
- lib/mixpanel.rb
|
159
|
-
has_rdoc: true
|
160
179
|
homepage: http://github.com/zevarito/mixpanel
|
161
180
|
licenses: []
|
162
|
-
|
163
181
|
post_install_message:
|
164
182
|
rdoc_options: []
|
165
|
-
|
166
|
-
require_paths:
|
183
|
+
require_paths:
|
167
184
|
- lib
|
168
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
185
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
169
186
|
none: false
|
170
|
-
requirements:
|
171
|
-
- -
|
172
|
-
- !ruby/object:Gem::Version
|
173
|
-
|
174
|
-
|
175
|
-
version: "0"
|
176
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
187
|
+
requirements:
|
188
|
+
- - ! '>='
|
189
|
+
- !ruby/object:Gem::Version
|
190
|
+
version: '0'
|
191
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
177
192
|
none: false
|
178
|
-
requirements:
|
179
|
-
- -
|
180
|
-
- !ruby/object:Gem::Version
|
181
|
-
|
182
|
-
- 0
|
183
|
-
version: "0"
|
193
|
+
requirements:
|
194
|
+
- - ! '>='
|
195
|
+
- !ruby/object:Gem::Version
|
196
|
+
version: '0'
|
184
197
|
requirements: []
|
185
|
-
|
186
198
|
rubyforge_project: mixpanel
|
187
|
-
rubygems_version: 1.
|
199
|
+
rubygems_version: 1.8.21
|
188
200
|
signing_key:
|
189
201
|
specification_version: 3
|
190
202
|
summary: Supports direct request api and javascript requests through a middleware.
|
191
203
|
test_files: []
|
192
|
-
|
data/README.rdoc
DELETED
@@ -1,120 +0,0 @@
|
|
1
|
-
== What is Mixpanel (the service) ?
|
2
|
-
|
3
|
-
Mixpanel is a real-time analytics service that helps companies understand how users interact with web applications.
|
4
|
-
http://mixpanel.com
|
5
|
-
|
6
|
-
== What does this Gem do?
|
7
|
-
|
8
|
-
* Track events with properties directly from your backend.
|
9
|
-
* Track events with properties through javascript using a rack middleware.
|
10
|
-
|
11
|
-
|
12
|
-
== How to install?
|
13
|
-
|
14
|
-
gem install mixpanel
|
15
|
-
|
16
|
-
|
17
|
-
== How to use it with a Rails application?
|
18
|
-
|
19
|
-
In your environment config file add this.
|
20
|
-
|
21
|
-
Rails::Initializer.run do |config|
|
22
|
-
|
23
|
-
config.middleware.use "Mixpanel::Tracker::Middleware", "YOUR_MIXPANEL_API_TOKEN"
|
24
|
-
|
25
|
-
If you want to use the asynchronous version of Mixpanel's javascript API
|
26
|
-
|
27
|
-
Rails::Initializer.run do |config|
|
28
|
-
|
29
|
-
config.middleware.use "Mixpanel::Tracker::Middleware", "YOUR_MIXPANEL_API_TOKEN", :async => true
|
30
|
-
|
31
|
-
By default the scripts are inserted into the head of the html response. If you'd prefer the scripts to run after all rendering has completed you can set the insert_js_last flag and they'll be added at the end of the body tag. This will work whether or not you opt for the aynchronous version of the API. However, when inserting js into an ajax response it will have no effect:
|
32
|
-
|
33
|
-
Rails::Initializer.run do |config|
|
34
|
-
|
35
|
-
config.middleware.use "Mixpanel::Tracker::Middleware", "YOUR_MIXPANEL_API_TOKEN", :async => true, :insert_js_last => true
|
36
|
-
|
37
|
-
In your application_controller class add a method to instance mixpanel.
|
38
|
-
|
39
|
-
before_filter :initialize_mixpanel
|
40
|
-
|
41
|
-
def initialize_mixpanel
|
42
|
-
@mixpanel = Mixpanel::Tracker.new("YOUR_MIXPANEL_API_TOKEN", request.env, true)
|
43
|
-
end
|
44
|
-
|
45
|
-
Then in each request you want to track some event you can use:
|
46
|
-
|
47
|
-
To track events directly from your backend...
|
48
|
-
|
49
|
-
@mixpanel.track_event("Sign in", {:some => "property"})
|
50
|
-
|
51
|
-
To track events after response with javascript...
|
52
|
-
|
53
|
-
@mixpanel.append_event("Sign in", {:some => "property"})
|
54
|
-
|
55
|
-
To execute any javascript API call
|
56
|
-
|
57
|
-
@mixpanel.append_api("register", {:some => "property"})
|
58
|
-
@mixpanel.append_api("identify", "Unique Identifier")
|
59
|
-
|
60
|
-
If you are proxying Mixpanel API requests then you can set a custom url and additionally stop the token from being sent by marking it as false if you're going to let the proxy add it...
|
61
|
-
|
62
|
-
@mixpanel = Mixpanel::Tracker.new(flase, request.env, true, 'http://localhost:8000/mixpanelproxy?data=')
|
63
|
-
|
64
|
-
== Resque and Rails example
|
65
|
-
|
66
|
-
If you don't want to use the built in Mixpanel Gem async feature bellow there is an example about how to make async calls using Resque.
|
67
|
-
|
68
|
-
{Resque is a Redis-backed Ruby library for creating background jobs}[https://github.com/defunkt/resque]
|
69
|
-
|
70
|
-
class MixpanelTrackEventJob
|
71
|
-
@queue = :slow
|
72
|
-
|
73
|
-
def mixpanel(request_env)
|
74
|
-
Mixpanel.new(MIXPANEL_TOKEN, request_env)
|
75
|
-
end
|
76
|
-
|
77
|
-
def perform(name, params, request_env)
|
78
|
-
mixpanel(request_env).track_event(name, params)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
class UsersController < ApplicationController
|
83
|
-
def create
|
84
|
-
@user = User.new(params[:user])
|
85
|
-
|
86
|
-
if @user.save
|
87
|
-
MixpanelTrackEventJob.enqueue("Sign up", {:invited => params[:invited]}, request.env)
|
88
|
-
redirect_to user_root_path
|
89
|
-
else
|
90
|
-
render :new
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
== Notes
|
96
|
-
|
97
|
-
There are two forms of async operation:
|
98
|
-
* Using MixpanelMiddleware, events are queued via Mixpanel#append_event and inserted into a JavaScript block within the HTML response.
|
99
|
-
* Using Mixpanel.new(…, …, true), events are sent to a subprocess via a pipe and the sub process which asynchronously send events to Mixpanel. This process uses a single thread to upload events, and may start dropping events if your application generates them at a very high rate.
|
100
|
-
|
101
|
-
== Deprecation Notes
|
102
|
-
|
103
|
-
For a short term this method will be accepted but it will be deprecated soon.
|
104
|
-
|
105
|
-
Mixpanel.new
|
106
|
-
|
107
|
-
== Collaborations
|
108
|
-
|
109
|
-
All collaborations are welcome to this project, please fork and make a pull request.
|
110
|
-
|
111
|
-
== Collaborators and Maintainers
|
112
|
-
|
113
|
-
* {Alvaro Gil}[https://github.com/zevarito] (Author)
|
114
|
-
* {Nathan Baxter}[https://github.com/LogicWolfe]
|
115
|
-
* {Jake Mallory}[https://github.com/tinomen]
|
116
|
-
* {Logan Bowers}[https://github.com/loganb]
|
117
|
-
* {jakemack}[https://github.com/jakemack]
|
118
|
-
* {James Ferguson}[https://github.com/JamesFerguson]
|
119
|
-
* {Brad Wilson}[https://github.com/bradx3]
|
120
|
-
* {Mark Cheverton}[https://github.com/ennui2342]
|