mixpanel 3.1.0 → 3.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +116 -101
- data/lib/mixpanel/event.rb +15 -17
- data/lib/mixpanel/person.rb +29 -15
- data/lib/mixpanel/tracker.rb +16 -12
- data/mixpanel.gemspec +1 -5
- data/spec/mixpanel/middleware_spec.rb +2 -1
- data/spec/mixpanel/tracker_spec.rb +9 -5
- data/spec/spec_helper.rb +0 -2
- metadata +85 -156
data/README.md
CHANGED
@@ -8,11 +8,11 @@
|
|
8
8
|
- [Rack Middleware] (#rack-middleware)
|
9
9
|
- [Usage] (#usage)
|
10
10
|
- [Initialize Mixpanel] (#initialize-mixpanel)
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
- [Track Events Directly](#track-events-directly)
|
12
|
+
- [Pixel Based Event Tracking](#pixel-based-event-tracking)
|
13
|
+
- [Import Events](#import-events)
|
14
|
+
- [Set Person Attributes Directly](#set-person-attributes-directly)
|
15
|
+
- [Increment Person Attributes Directly](#increment-person-attributes-directly)
|
16
16
|
- [Examples] (#examples)
|
17
17
|
- [How to use it from Rails controllers] (#how-to-use-it-from-rails-controllers)
|
18
18
|
- [How to track events using Resque and Rails] (#how-to-track-events-using-resque-and-rails)
|
@@ -59,7 +59,7 @@ Where **options** is a hash that accepts the following keys:
|
|
59
59
|
By default the scripts are inserted into the head of the HTML response. If you'd prefer the scripts to run after
|
60
60
|
all rendering has completed, set the insert_js_last flag to true and they'll be added at the end of the body tag.
|
61
61
|
This will work whether or not you opt for the aynchronous version of the API. However, this will have no effect
|
62
|
-
|
62
|
+
when inserting JS into an AJAX response.
|
63
63
|
|
64
64
|
* **persist** : boolean
|
65
65
|
|
@@ -74,8 +74,7 @@ Where **options** is a hash that accepts the following keys:
|
|
74
74
|
This allows you to use a before_filter to set these variables, redirect, and still have them only transmitted
|
75
75
|
once.
|
76
76
|
|
77
|
-
*To enable persistence*, you must set the flag twice: here when instantiating Middleware and again when you initialize
|
78
|
-
the Mixpanel class.
|
77
|
+
*To enable persistence*, you must set the flag twice: here when instantiating Middleware and again when you initialize the Mixpanel class.
|
79
78
|
|
80
79
|
* **config** : hash
|
81
80
|
|
@@ -93,24 +92,24 @@ Where **options** is a hash that accepts the following keys:
|
|
93
92
|
Where **options** is a hash that accepts the following keys:
|
94
93
|
|
95
94
|
* **async** : boolean
|
96
|
-
|
95
|
+
|
97
96
|
*Default: false*
|
98
97
|
|
99
98
|
Built in async feature. Events are sent to a subprocess via a pipe and the sub process asynchronously send events to Mixpanel.
|
100
99
|
This value can be overwritten on subsequent method calls. I.e., this setting represents the default for your Mixpanel object,
|
101
|
-
|
102
|
-
|
103
|
-
|
100
|
+
but each call can overwrite this default setting.
|
101
|
+
|
102
|
+
This process uses a single thread to upload events, and may start dropping events if your application generates
|
104
103
|
them at a very high rate. While this is a simple way to have asynchronous interaction with Mixpanel, more robust solutions are
|
105
|
-
|
104
|
+
available. Specifically, see the [Resque example](#how-to-track-events-using-resque-and-rails) below.
|
106
105
|
|
107
106
|
* **persist** : boolean
|
108
107
|
|
109
108
|
*Default: false*
|
110
109
|
|
111
|
-
|
112
|
-
|
113
|
-
|
110
|
+
This is used in connection with the [Rack Middleware section](#rack-middleware) above. If you are not going to use Middleware
|
111
|
+
to send requests to Mixpanel through JavaScript, you don't need to worry about this option.
|
112
|
+
|
114
113
|
If you would like, the Mixpanel gem may be configured to store its queue in a Rack session. This allows events
|
115
114
|
to be stored through redirects, which can be helpful if you sign in and redirect but want to associate an event with that
|
116
115
|
action. The Mixpanel gem will also remove duplicate events from your queue for information that should only be
|
@@ -121,39 +120,40 @@ Where **options** is a hash that accepts the following keys:
|
|
121
120
|
once.
|
122
121
|
|
123
122
|
*To enable persistence*, you must set the flag twice: here when instantiating Middleware and again when you initialize
|
124
|
-
|
123
|
+
the Mixpanel class.
|
125
124
|
|
126
125
|
* **api_key** : string
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
126
|
+
|
127
|
+
*Default: nil*
|
128
|
+
|
129
|
+
When using the [import functionality](#import-events), you must set an API key to go along with your token. If not set when the
|
130
|
+
class is instantiated, you will be required to send the api key in the options hash of the import method.
|
131
|
+
|
133
132
|
* **env** : hash
|
134
133
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
134
|
+
*Default: {}*
|
135
|
+
|
136
|
+
This is used by the gem to append information from your request environment to your Mixpanel request. If you are calling this
|
137
|
+
directly from a controller, simply passing in `request.env` will be sufficient. However, as explained in the Resque example,
|
138
|
+
your environment might choke if it tries to convert that hash to JSON (not to mention how large that hash can be). You can just pass
|
139
|
+
in a subset of the full environment:
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
env = {
|
143
|
+
'REMOTE_ADDR' => request.env['REMOTE_ADDR'],
|
144
|
+
'HTTP_X_FORWARDED_FOR' => request.env['HTTP_X_FORWARDED_FOR'],
|
145
|
+
'rack.session' => request.env['rack.session'],
|
146
|
+
'mixpanel_events' => request.env['mixpanel_events']
|
147
|
+
}
|
148
|
+
|
149
|
+
@mixpanel = Mixpanel::Tracker.new MIXPANEL_TOKEN, { :env => env }
|
150
|
+
```
|
151
|
+
|
152
|
+
Basically, this information is being used to: set the default IP address associated with the request, and grab any session variables
|
153
|
+
needed to run the Middleware stuff.
|
154
|
+
|
155
|
+
Additional information contained in your environment (e.g., http_referer) can simply be sent in as attributes where appropriate
|
156
|
+
for your use case.
|
157
157
|
|
158
158
|
### Track Events Directly
|
159
159
|
|
@@ -171,18 +171,18 @@ it will automatically be converted to the correct form (e.g., `{ :os => 'Mac' }`
|
|
171
171
|
|
172
172
|
* **async** : boolean
|
173
173
|
|
174
|
-
|
175
|
-
|
174
|
+
*Default: the async value from when the class was instantiated*
|
175
|
+
|
176
176
|
* **api_key**: string
|
177
177
|
|
178
|
-
|
178
|
+
*Default: the api_key value from when the class was instantiated*
|
179
179
|
|
180
180
|
* **url**: string
|
181
181
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
182
|
+
*Default: `http://api.mixpanel.com/track/`*
|
183
|
+
|
184
|
+
This can be used to proxy Mixpanel API requests.
|
185
|
+
|
186
186
|
Example:
|
187
187
|
|
188
188
|
```ruby
|
@@ -226,10 +226,13 @@ Example:
|
|
226
226
|
### Set Person Attributes Directly
|
227
227
|
|
228
228
|
```ruby
|
229
|
-
@mixpanel.set
|
229
|
+
@mixpanel.set distinct_id_or_request_properties, properties, options
|
230
230
|
```
|
231
231
|
|
232
|
-
**
|
232
|
+
**distinct_id_or_request_properties** is whatever is used to identify the user to Mixpanel or a hash of
|
233
|
+
properties of the [engage event](https://mixpanel.com/docs/people-analytics/people-http-specification-insert-data) that exist
|
234
|
+
outside of the `$set`. Special properties will be automatically converted to the correct form (e.g., `{ :ip => '127.0.0.1' }` will be
|
235
|
+
converted to `{ :$ip => '127.0.0.1' }`
|
233
236
|
|
234
237
|
**properties** is a hash of properties to be set. The keys in the properties can either be strings
|
235
238
|
or symbols. If you send in a key that matches a [special property](https://mixpanel.com/docs/people-analytics/special-properties),
|
@@ -239,20 +242,26 @@ it will automatically be converted to the correct form (e.g., `{ :first_name =>
|
|
239
242
|
|
240
243
|
* **async**: boolean
|
241
244
|
|
242
|
-
|
245
|
+
*Default: the async value from when the class was instantiated*
|
243
246
|
|
244
247
|
* **url**: string
|
245
248
|
|
246
|
-
|
247
|
-
|
248
|
-
This can be used to proxy Mixpanel API requests
|
249
|
+
*Default: `http://api.mixpanel.com/engage/`*
|
249
250
|
|
250
|
-
|
251
|
+
This can be used to proxy Mixpanel API requests
|
252
|
+
|
253
|
+
Example using `distinct_id` to identify the user:
|
251
254
|
|
252
255
|
```ruby
|
253
256
|
@mixpanel.set 'john-doe', { :age => 31, :email => 'john@doe.com' }
|
254
257
|
```
|
255
258
|
|
259
|
+
Example using request properties, telling mixpanel to [ignore the time](https://groups.google.com/forum/#!msg/mp-dev/Ao4f8D0IKms/6MVhQqFDzL8J):
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
@mixpanel.set { :distinct_id => 'john-doe', :ignore_time => true }, { :age => 31, :email => 'john@doe.com' }
|
263
|
+
```
|
264
|
+
|
256
265
|
### Increment Person Attributes Directly
|
257
266
|
|
258
267
|
```ruby
|
@@ -301,35 +310,39 @@ you identify the user, the change will not be immediately sent to Mixpanel. Mixp
|
|
301
310
|
Occasionally you may need to send a request for HTML that you don't want the middleware to alter. In your AJAX request include the header "SKIP_MIXPANEL_MIDDLEWARE" to prevent the mixpanel code from being inserted.
|
302
311
|
|
303
312
|
```javascript
|
304
|
-
$.ajax("/path/to/api/endpoint", {
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
});
|
313
|
+
$.ajax("/path/to/api/endpoint", {
|
314
|
+
headers: {"Skip-Mixpanel-Middleware": true}, // valid http headers don't allow underscores and get filtered by some webservers
|
315
|
+
success: function(data) {
|
316
|
+
// Process data here
|
317
|
+
}
|
318
|
+
});
|
310
319
|
```
|
311
320
|
|
312
321
|
## Examples
|
313
322
|
|
314
323
|
### How to use it from Rails controllers?
|
315
|
-
|
324
|
+
|
316
325
|
In your ApplicationController class add a method to keep track of a Mixpanel instance.
|
317
326
|
|
318
327
|
```ruby
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
end
|
328
|
+
def mixpanel
|
329
|
+
@mixpanel ||= Mixpanel::Tracker.new YOUR_MIXPANEL_API_TOKEN, { :env => request.env }
|
330
|
+
end
|
323
331
|
```
|
324
332
|
|
325
333
|
Then you can call against this method where it makes sense in your controller. For example, in the users#create method:
|
326
334
|
|
327
335
|
```ruby
|
328
|
-
def create
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
336
|
+
def create
|
337
|
+
@user = User.create( :name => 'Jane Doe', :gender => 'female', :mixpanel_identifer => 'asdf' )
|
338
|
+
mixpanel.track 'User Created', {
|
339
|
+
:gender => @user.gender,
|
340
|
+
:distinct_id => @user.mixpanel_identifier,
|
341
|
+
:time => @user.created_at
|
342
|
+
} # Note that passing the time key overwrites the default value of Time.now
|
343
|
+
|
344
|
+
mixpanel.set @user.mixpanel_identifer, { :gender => @user.gender, :created => @user.created_at, :name => @user.name }
|
345
|
+
end
|
333
346
|
```
|
334
347
|
|
335
348
|
## How to track events using Resque and Rails
|
@@ -339,38 +352,39 @@ might be done with [Resque](https://github.com/defunkt/resque), but the same con
|
|
339
352
|
|
340
353
|
```ruby
|
341
354
|
class MixpanelTrackEventJob
|
342
|
-
|
355
|
+
@queue = :slow
|
343
356
|
|
344
|
-
|
345
|
-
|
346
|
-
|
357
|
+
def self.mixpanel env
|
358
|
+
Mixpanel::Tracker.new MIXPANEL_TOKEN, { :env => env }
|
359
|
+
end
|
347
360
|
|
348
|
-
|
349
|
-
|
350
|
-
|
361
|
+
def self.perform name, properties, env
|
362
|
+
mixpanel(env).track name, properties
|
363
|
+
end
|
351
364
|
end
|
352
365
|
```
|
353
366
|
|
354
367
|
```ruby
|
355
|
-
class UsersController < ApplicationController
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
end
|
368
|
+
class UsersController < ApplicationController
|
369
|
+
def create
|
370
|
+
@user = User.new(params[:user])
|
371
|
+
|
372
|
+
if @user.save
|
373
|
+
env = {
|
374
|
+
'REMOTE_ADDR' => request.env['REMOTE_ADDR'],
|
375
|
+
'HTTP_X_FORWARDED_FOR' => request.env['HTTP_X_FORWARDED_FOR'],
|
376
|
+
'rack.session' => request.env['rack.session'],
|
377
|
+
'mixpanel_events' => request.env['mixpanel_events']
|
378
|
+
} # Trying to pass request.env to Resque is going to fail (it chokes when trying to conver it to JSON, but no worries...)
|
379
|
+
|
380
|
+
Resque.enqueue MixpanelTrackEventJob, 'Sign up', { :invited => params[:invited] }, env
|
381
|
+
|
382
|
+
redirect_to user_root_path
|
383
|
+
else
|
384
|
+
render :new
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
374
388
|
```
|
375
389
|
|
376
390
|
## Supported Ruby Platforms
|
@@ -398,3 +412,4 @@ end
|
|
398
412
|
* [Goalee](https://github.com/Goalee)
|
399
413
|
* [Ahmed Belal](https://github.com/AhmedBelal)
|
400
414
|
* [Esteban Pastorino](https://github.com/kitop)
|
415
|
+
* [Jeffrey Chu](https://github.com/jochu)
|
data/lib/mixpanel/event.rb
CHANGED
@@ -2,7 +2,7 @@ module Mixpanel::Event
|
|
2
2
|
EVENT_PROPERTIES = %w{initial_referrer initial_referring_domain search_engine os browser referrer referring_domain}
|
3
3
|
TRACK_URL = 'http://api.mixpanel.com/track/'
|
4
4
|
IMPORT_URL = 'http://api.mixpanel.com/import/'
|
5
|
-
|
5
|
+
|
6
6
|
def track(event, properties={}, options={})
|
7
7
|
track_event event, properties, options, TRACK_URL
|
8
8
|
end
|
@@ -10,33 +10,31 @@ module Mixpanel::Event
|
|
10
10
|
def tracking_pixel(event, properties={}, options={})
|
11
11
|
build_url event, properties, options.merge(:url => TRACK_URL, :img => true)
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def import(event, properties={}, options={})
|
15
15
|
track_event event, properties, options, IMPORT_URL
|
16
16
|
end
|
17
|
-
|
17
|
+
|
18
18
|
def append_track(event, properties={})
|
19
19
|
append 'track', event, track_properties(properties, false)
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
protected
|
23
|
-
|
23
|
+
|
24
24
|
def track_event(event, properties, options, default_url)
|
25
|
-
|
26
|
-
url = build_url
|
25
|
+
default = {:url => default_url, :async => @async, :api_key => @api_key}
|
26
|
+
url = build_url(event, properties, default.merge(options))
|
27
27
|
parse_response request(url, options[:async])
|
28
28
|
end
|
29
|
-
|
30
|
-
def ip
|
31
|
-
(@env['HTTP_X_FORWARDED_FOR'] || @env['REMOTE_ADDR'] || '').split(',').last
|
32
|
-
end
|
33
|
-
|
29
|
+
|
34
30
|
def track_properties(properties, include_token=true)
|
35
|
-
|
36
|
-
properties
|
37
|
-
|
31
|
+
default = {:time => Time.now, :ip => ip}
|
32
|
+
properties = default.merge(properties)
|
33
|
+
|
34
|
+
properties.merge!(:token => @token) if include_token
|
35
|
+
properties_hash(properties, EVENT_PROPERTIES)
|
38
36
|
end
|
39
|
-
|
37
|
+
|
40
38
|
def build_event(event, properties)
|
41
39
|
{ :event => event, :properties => properties_hash(properties, EVENT_PROPERTIES) }
|
42
40
|
end
|
@@ -44,7 +42,7 @@ module Mixpanel::Event
|
|
44
42
|
def build_url event, properties, options
|
45
43
|
data = build_event event, track_properties(properties)
|
46
44
|
url = "#{options[:url]}?data=#{encoded_data(data)}"
|
47
|
-
url << "&api_key=#{options[:api_key]}" if options
|
45
|
+
url << "&api_key=#{options[:api_key]}" if options.fetch(:api_key, nil)
|
48
46
|
url << "&img=1" if options[:img]
|
49
47
|
url
|
50
48
|
end
|
data/lib/mixpanel/person.rb
CHANGED
@@ -1,27 +1,28 @@
|
|
1
1
|
module Mixpanel::Person
|
2
2
|
PERSON_PROPERTIES = %w{email created first_name last_name name last_login username country_code}
|
3
|
+
PERSON_REQUEST_PROPERTIES = %w{token distinct_id ip ignore_time}
|
3
4
|
PERSON_URL = 'http://api.mixpanel.com/engage/'
|
4
|
-
|
5
|
+
|
5
6
|
def set(distinct_id, properties={}, options={})
|
6
7
|
engage :set, distinct_id, properties, options
|
7
8
|
end
|
8
|
-
|
9
|
+
|
9
10
|
def increment(distinct_id, properties={}, options={})
|
10
11
|
engage :add, distinct_id, properties, options
|
11
12
|
end
|
12
|
-
|
13
|
+
|
13
14
|
def append_set(properties={})
|
14
15
|
append 'people.set', properties_hash(properties, PERSON_PROPERTIES)
|
15
16
|
end
|
16
|
-
|
17
|
+
|
17
18
|
def append_increment(property, increment=1)
|
18
19
|
append 'people.increment', property, increment
|
19
20
|
end
|
20
|
-
|
21
|
+
|
21
22
|
def append_register(properties={})
|
22
23
|
append 'register', properties_hash(properties, PERSON_PROPERTIES)
|
23
24
|
end
|
24
|
-
|
25
|
+
|
25
26
|
def append_identify(distinct_id)
|
26
27
|
append 'identify', distinct_id
|
27
28
|
end
|
@@ -29,17 +30,30 @@ module Mixpanel::Person
|
|
29
30
|
def append_people_identify(distinct_id)
|
30
31
|
append 'people.identify', distinct_id
|
31
32
|
end
|
32
|
-
|
33
|
+
|
33
34
|
protected
|
34
|
-
|
35
|
-
def engage(action,
|
36
|
-
|
37
|
-
|
35
|
+
|
36
|
+
def engage(action, request_properties_or_distinct_id, properties, options)
|
37
|
+
default = {:async => @async, :url => PERSON_URL}
|
38
|
+
options = default.merge(options)
|
39
|
+
|
40
|
+
request_properties = person_request_properties(request_properties_or_distinct_id)
|
41
|
+
|
42
|
+
data = build_person action, request_properties, properties
|
38
43
|
url = "#{options[:url]}?data=#{encoded_data(data)}"
|
39
44
|
parse_response request(url, options[:async])
|
40
45
|
end
|
41
|
-
|
42
|
-
def
|
43
|
-
|
46
|
+
|
47
|
+
def person_request_properties(request_properties_or_distinct_id)
|
48
|
+
default = {:token => @token, :ip => ip}
|
49
|
+
if request_properties_or_distinct_id.respond_to? :to_hash
|
50
|
+
default.merge(request_properties_or_distinct_id)
|
51
|
+
else
|
52
|
+
default.merge({ :distinct_id => request_properties_or_distinct_id })
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def build_person(action, request_properties, person_properties)
|
57
|
+
properties_hash(request_properties, PERSON_REQUEST_PROPERTIES).merge({ "$#{action}".to_sym => properties_hash(person_properties, PERSON_PROPERTIES) })
|
44
58
|
end
|
45
|
-
end
|
59
|
+
end
|
data/lib/mixpanel/tracker.rb
CHANGED
@@ -8,18 +8,18 @@ module Mixpanel
|
|
8
8
|
require 'mixpanel/async'
|
9
9
|
require 'mixpanel/event'
|
10
10
|
require 'mixpanel/person'
|
11
|
-
|
11
|
+
|
12
12
|
extend Mixpanel::Async
|
13
13
|
include Mixpanel::Event
|
14
14
|
include Mixpanel::Person
|
15
|
-
|
15
|
+
|
16
16
|
def initialize(token, options={})
|
17
17
|
@token = token
|
18
18
|
@async = !!options.fetch(:async, false)
|
19
19
|
@persist = !!options.fetch(:persist, false)
|
20
20
|
@env = options.fetch :env, {}
|
21
21
|
@api_key = options.fetch :api_key, nil
|
22
|
-
|
22
|
+
|
23
23
|
# Make sure queue object is instantiated to an array. If not persisted, set queue object to empty array.
|
24
24
|
if @persist
|
25
25
|
@env['rack.session'] ||= {}
|
@@ -28,17 +28,21 @@ module Mixpanel
|
|
28
28
|
@env['mixpanel_events'] = []
|
29
29
|
end
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
def queue
|
33
33
|
@persist ? @env['rack.session']['mixpanel_events'] : @env['mixpanel_events']
|
34
34
|
end
|
35
|
-
|
35
|
+
|
36
36
|
def append(type, *args)
|
37
37
|
queue << [type, args.collect {|arg| arg.to_json}]
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
protected
|
41
|
-
|
41
|
+
|
42
|
+
def ip
|
43
|
+
(@env['HTTP_X_FORWARDED_FOR'] || @env['REMOTE_ADDR'] || '').split(',').last
|
44
|
+
end
|
45
|
+
|
42
46
|
# Walk through each property and see if it is in the special_properties. If so, change the key to have a $ in front of it.
|
43
47
|
def properties_hash(properties, special_properties)
|
44
48
|
properties.inject({}) do |props, (key, value)|
|
@@ -47,19 +51,19 @@ module Mixpanel
|
|
47
51
|
props
|
48
52
|
end
|
49
53
|
end
|
50
|
-
|
54
|
+
|
51
55
|
def encoded_data(parameters)
|
52
56
|
Base64.encode64(JSON.generate(parameters)).gsub(/\n/,'')
|
53
57
|
end
|
54
|
-
|
58
|
+
|
55
59
|
def request(url, async)
|
56
60
|
async ? send_async(url) : open(url).read
|
57
61
|
end
|
58
|
-
|
62
|
+
|
59
63
|
def parse_response(response)
|
60
64
|
response.to_i == 1
|
61
65
|
end
|
62
|
-
|
66
|
+
|
63
67
|
def send_async(url)
|
64
68
|
w = Mixpanel::Tracker.worker
|
65
69
|
begin
|
@@ -72,4 +76,4 @@ module Mixpanel
|
|
72
76
|
end
|
73
77
|
end
|
74
78
|
end
|
75
|
-
end
|
79
|
+
end
|
data/mixpanel.gemspec
CHANGED
@@ -2,7 +2,7 @@ files = ['README.md', 'LICENSE', 'Rakefile', 'mixpanel.gemspec', '{spec,lib}/**/
|
|
2
2
|
|
3
3
|
spec = Gem::Specification.new do |s|
|
4
4
|
s.name = "mixpanel"
|
5
|
-
s.version = "3.
|
5
|
+
s.version = "3.4.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"
|
@@ -17,13 +17,9 @@ spec = Gem::Specification.new do |s|
|
|
17
17
|
s.add_dependency 'json'
|
18
18
|
s.add_dependency 'rack'
|
19
19
|
s.add_dependency 'escape'
|
20
|
-
s.add_development_dependency 'active_support'
|
21
20
|
s.add_development_dependency 'rspec'
|
22
21
|
s.add_development_dependency 'rack-test'
|
23
22
|
s.add_development_dependency 'fakeweb'
|
24
23
|
s.add_development_dependency 'nokogiri'
|
25
24
|
s.add_development_dependency 'rake'
|
26
|
-
s.add_development_dependency 'debugger' if RUBY_VERSION =~ /^1\.9\.3/
|
27
|
-
s.add_development_dependency 'ruby-debug19' if RUBY_VERSION =~ /^1\.9\.2/
|
28
|
-
s.add_development_dependency 'ruby-debug' if RUBY_VERSION =~ /^1\.8/
|
29
25
|
end
|
@@ -8,7 +8,8 @@ def exec_default_appends_on(mixpanel)
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def check_for_default_appends_on(txt)
|
11
|
-
|
11
|
+
|
12
|
+
txt.should =~ /mixpanel\.track\("Visit",\s?\{.*"article":1/
|
12
13
|
txt.should =~ /mixpanel\.track\("Sign in",\s?\{.*"time":.*\}/
|
13
14
|
txt.should =~ /mixpanel\.people\.set\(.*\);\nmixpanel.people.increment\(\"sign_in_rate\",\s?1\);/
|
14
15
|
match = txt.match(/mixpanel\.people\.set\((.*\));/)
|
@@ -25,7 +25,7 @@ describe Mixpanel::Tracker do
|
|
25
25
|
it "should track simple events" do
|
26
26
|
@mixpanel.track("Sign up").should == true
|
27
27
|
end
|
28
|
-
|
28
|
+
|
29
29
|
it "should track events with properties" do
|
30
30
|
@mixpanel.track('Sign up', { :likeable => true }, { :api_key => 'asdf' }).should == true
|
31
31
|
end
|
@@ -40,22 +40,26 @@ describe Mixpanel::Tracker do
|
|
40
40
|
@mixpanel.tracking_pixel("Sign up").should match(/&img=1/)
|
41
41
|
end
|
42
42
|
end
|
43
|
-
|
43
|
+
|
44
44
|
context "Importing events" do
|
45
45
|
it "should import simple events" do
|
46
46
|
@mixpanel.import('Sign up').should == true
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
it "should import events with properties" do
|
50
50
|
@mixpanel.import('Sign up', { :likeable => true }, { :api_key => 'asdf' }).should == true
|
51
51
|
end
|
52
52
|
end
|
53
|
-
|
53
|
+
|
54
54
|
context "Engaging people" do
|
55
55
|
it "should set attributes" do
|
56
56
|
@mixpanel.set('person-a', { :email => 'me@domain.com', :likeable => false }).should == true
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
|
+
it "should set attributes with request properties" do
|
60
|
+
@mixpanel.set({ :distinct_id => 'person-a', :ignore_time => true }, { :email => 'me@domain.com', :likeable => false }).should == true
|
61
|
+
end
|
62
|
+
|
59
63
|
it "should increment attributes" do
|
60
64
|
@mixpanel.increment('person-a', { :tokens => 3, :money => -1 }).should == true
|
61
65
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,9 +1,7 @@
|
|
1
|
-
require 'ruby-debug'
|
2
1
|
require File.join(File.dirname(__FILE__), "../lib", "mixpanel")
|
3
2
|
require 'rack/test'
|
4
3
|
require 'fakeweb'
|
5
4
|
require 'nokogiri'
|
6
|
-
require 'active_support/core_ext/hash'
|
7
5
|
|
8
6
|
Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
|
9
7
|
|
metadata
CHANGED
@@ -1,172 +1,112 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixpanel
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 3
|
8
|
-
- 1
|
9
|
-
- 0
|
10
|
-
version: 3.1.0
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 3.4.0
|
5
|
+
prerelease:
|
11
6
|
platform: ruby
|
12
|
-
authors:
|
7
|
+
authors:
|
13
8
|
- Alvaro Gil
|
14
9
|
autorequire:
|
15
10
|
bindir: bin
|
16
11
|
cert_chain: []
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
dependencies:
|
21
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-12-23 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
22
15
|
name: json
|
23
|
-
|
24
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &2153080840 !ruby/object:Gem::Requirement
|
25
17
|
none: false
|
26
|
-
requirements:
|
27
|
-
- -
|
28
|
-
- !ruby/object:Gem::Version
|
29
|
-
|
30
|
-
segments:
|
31
|
-
- 0
|
32
|
-
version: "0"
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
33
22
|
type: :runtime
|
34
|
-
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: rack
|
37
23
|
prerelease: false
|
38
|
-
|
24
|
+
version_requirements: *2153080840
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rack
|
27
|
+
requirement: &2153080400 !ruby/object:Gem::Requirement
|
39
28
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
44
|
-
segments:
|
45
|
-
- 0
|
46
|
-
version: "0"
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
47
33
|
type: :runtime
|
48
|
-
version_requirements: *id002
|
49
|
-
- !ruby/object:Gem::Dependency
|
50
|
-
name: escape
|
51
34
|
prerelease: false
|
52
|
-
|
35
|
+
version_requirements: *2153080400
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: escape
|
38
|
+
requirement: &2153079980 !ruby/object:Gem::Requirement
|
53
39
|
none: false
|
54
|
-
requirements:
|
55
|
-
- -
|
56
|
-
- !ruby/object:Gem::Version
|
57
|
-
|
58
|
-
segments:
|
59
|
-
- 0
|
60
|
-
version: "0"
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
61
44
|
type: :runtime
|
62
|
-
version_requirements: *id003
|
63
|
-
- !ruby/object:Gem::Dependency
|
64
|
-
name: active_support
|
65
45
|
prerelease: false
|
66
|
-
|
67
|
-
|
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
|
46
|
+
version_requirements: *2153079980
|
47
|
+
- !ruby/object:Gem::Dependency
|
78
48
|
name: rspec
|
79
|
-
|
80
|
-
requirement: &id005 !ruby/object:Gem::Requirement
|
49
|
+
requirement: &2153079560 !ruby/object:Gem::Requirement
|
81
50
|
none: false
|
82
|
-
requirements:
|
83
|
-
- -
|
84
|
-
- !ruby/object:Gem::Version
|
85
|
-
|
86
|
-
segments:
|
87
|
-
- 0
|
88
|
-
version: "0"
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
89
55
|
type: :development
|
90
|
-
version_requirements: *id005
|
91
|
-
- !ruby/object:Gem::Dependency
|
92
|
-
name: rack-test
|
93
56
|
prerelease: false
|
94
|
-
|
57
|
+
version_requirements: *2153079560
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rack-test
|
60
|
+
requirement: &2153079140 !ruby/object:Gem::Requirement
|
95
61
|
none: false
|
96
|
-
requirements:
|
97
|
-
- -
|
98
|
-
- !ruby/object:Gem::Version
|
99
|
-
|
100
|
-
segments:
|
101
|
-
- 0
|
102
|
-
version: "0"
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
103
66
|
type: :development
|
104
|
-
version_requirements: *id006
|
105
|
-
- !ruby/object:Gem::Dependency
|
106
|
-
name: fakeweb
|
107
67
|
prerelease: false
|
108
|
-
|
68
|
+
version_requirements: *2153079140
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: fakeweb
|
71
|
+
requirement: &2153078720 !ruby/object:Gem::Requirement
|
109
72
|
none: false
|
110
|
-
requirements:
|
111
|
-
- -
|
112
|
-
- !ruby/object:Gem::Version
|
113
|
-
|
114
|
-
segments:
|
115
|
-
- 0
|
116
|
-
version: "0"
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
117
77
|
type: :development
|
118
|
-
version_requirements: *id007
|
119
|
-
- !ruby/object:Gem::Dependency
|
120
|
-
name: nokogiri
|
121
78
|
prerelease: false
|
122
|
-
|
79
|
+
version_requirements: *2153078720
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: nokogiri
|
82
|
+
requirement: &2153078300 !ruby/object:Gem::Requirement
|
123
83
|
none: false
|
124
|
-
requirements:
|
125
|
-
- -
|
126
|
-
- !ruby/object:Gem::Version
|
127
|
-
|
128
|
-
segments:
|
129
|
-
- 0
|
130
|
-
version: "0"
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
131
88
|
type: :development
|
132
|
-
version_requirements: *id008
|
133
|
-
- !ruby/object:Gem::Dependency
|
134
|
-
name: rake
|
135
89
|
prerelease: false
|
136
|
-
|
90
|
+
version_requirements: *2153078300
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: rake
|
93
|
+
requirement: &2153104240 !ruby/object:Gem::Requirement
|
137
94
|
none: false
|
138
|
-
requirements:
|
139
|
-
- -
|
140
|
-
- !ruby/object:Gem::Version
|
141
|
-
|
142
|
-
segments:
|
143
|
-
- 0
|
144
|
-
version: "0"
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
145
99
|
type: :development
|
146
|
-
version_requirements: *id009
|
147
|
-
- !ruby/object:Gem::Dependency
|
148
|
-
name: ruby-debug
|
149
100
|
prerelease: false
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
- - ">="
|
154
|
-
- !ruby/object:Gem::Version
|
155
|
-
hash: 3
|
156
|
-
segments:
|
157
|
-
- 0
|
158
|
-
version: "0"
|
159
|
-
type: :development
|
160
|
-
version_requirements: *id010
|
161
|
-
description: Simple lib to track events in Mixpanel service. It can be used in any rack based framework.
|
101
|
+
version_requirements: *2153104240
|
102
|
+
description: Simple lib to track events in Mixpanel service. It can be used in any
|
103
|
+
rack based framework.
|
162
104
|
email: zevarito@gmail.com
|
163
105
|
executables: []
|
164
|
-
|
165
106
|
extensions: []
|
166
|
-
|
167
|
-
extra_rdoc_files:
|
107
|
+
extra_rdoc_files:
|
168
108
|
- README.md
|
169
|
-
files:
|
109
|
+
files:
|
170
110
|
- README.md
|
171
111
|
- LICENSE
|
172
112
|
- Rakefile
|
@@ -182,39 +122,28 @@ files:
|
|
182
122
|
- lib/mixpanel/subprocess.rb
|
183
123
|
- lib/mixpanel/tracker.rb
|
184
124
|
- lib/mixpanel.rb
|
185
|
-
has_rdoc: true
|
186
125
|
homepage: http://github.com/zevarito/mixpanel
|
187
126
|
licenses: []
|
188
|
-
|
189
127
|
post_install_message:
|
190
128
|
rdoc_options: []
|
191
|
-
|
192
|
-
require_paths:
|
129
|
+
require_paths:
|
193
130
|
- lib
|
194
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
131
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
195
132
|
none: false
|
196
|
-
requirements:
|
197
|
-
- -
|
198
|
-
- !ruby/object:Gem::Version
|
199
|
-
|
200
|
-
|
201
|
-
- 0
|
202
|
-
version: "0"
|
203
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - ! '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
204
138
|
none: false
|
205
|
-
requirements:
|
206
|
-
- -
|
207
|
-
- !ruby/object:Gem::Version
|
208
|
-
|
209
|
-
segments:
|
210
|
-
- 0
|
211
|
-
version: "0"
|
139
|
+
requirements:
|
140
|
+
- - ! '>='
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
212
143
|
requirements: []
|
213
|
-
|
214
144
|
rubyforge_project: mixpanel
|
215
|
-
rubygems_version: 1.
|
145
|
+
rubygems_version: 1.8.15
|
216
146
|
signing_key:
|
217
147
|
specification_version: 3
|
218
148
|
summary: Supports direct request api and javascript requests through a middleware.
|
219
149
|
test_files: []
|
220
|
-
|