mixpanel 3.1.0 → 3.4.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.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
|
-
|