mixpanel 2.1.0 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -90,10 +90,10 @@ Where **options** is a Hash that accepts the following keys:
90
90
 
91
91
  * **url** : String
92
92
 
93
- *Default: http://api.mixpanel.com/track/?data=*.
93
+ *Default: http://api.mixpanel.com*.
94
94
  If you are proxying Mixpanel API requests then you can set a custom url and additionally stop the token from
95
95
  being sent by marking it as false if you're going to let the proxy add it.
96
- Example: { url: "http://localhost:8000/mixpanelproxy?data=" }.
96
+ Example: { url: "http://localhost:8000/mixpanelproxy" }.
97
97
 
98
98
  * **persist** : true | false
99
99
 
@@ -117,6 +117,13 @@ Where **options** is a Hash that accepts the following keys:
117
117
  @mixpanel.track_event("Sign in", {:some => "property"})
118
118
  ```
119
119
 
120
+ ### Interface with People management directly
121
+
122
+ ```ruby
123
+ @mixpanel.engage_set(@user.id, {:username => @user.username, :email => @user.email})
124
+ @mixpanel.engage_add(@user.id, {:monkeys_punched => 12})
125
+ ```
126
+
120
127
  ### Append events to be tracked with Javascript.
121
128
 
122
129
  *Note*: You should setup the [Rack Middleware](#rack-middleware).
@@ -134,6 +141,20 @@ Where **options** is a Hash that accepts the following keys:
134
141
  @mixpanel.append_api("identify", "Unique Identifier")
135
142
  ```
136
143
 
144
+ ### Prevent middleware from inserting code
145
+ *Note*: Only applies when [Rack Middleware](#rack-middleware) is setup.
146
+
147
+ 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.
148
+
149
+ ```javascript
150
+ $.ajax("/path/to/api/endpoint", {
151
+ headers: {"SKIP_MIXPANEL_MIDDLEWARE": true},
152
+ success: function(data) {
153
+ // Process data here
154
+ }
155
+ });
156
+ ```
157
+
137
158
  ## Examples
138
159
 
139
160
  ### How to use it from Rails controllers?
@@ -218,3 +239,4 @@ Use this instead:
218
239
  * [Ryan Schmukler](https://github.com/rschmukler)
219
240
  * [Travis Pew](https://github.com/travisp)
220
241
  * [Sylvain Niles](https://github.com/sylvainsf)
242
+ * [GBH](https://github.com/GBH)
@@ -6,14 +6,22 @@ require 'mixpanel/tracker/middleware'
6
6
 
7
7
  module Mixpanel
8
8
  class Tracker
9
- def initialize(token, env, options={})
10
- @token = token
11
- @api_key = options.fetch(:api_key, "")
12
- @env = env
13
- @async = options.fetch(:async, false)
14
- @import = options.fetch(:import, false)
15
- @url = @import ? 'http://api.mixpanel.com/import/?data' : options.fetch(:url, 'http://api.mixpanel.com/track/?data=')
16
- @persist = options.fetch(:persist, false)
9
+
10
+ MIXPANEL_API_URL = 'http://api.mixpanel.com'.freeze
11
+ TRACK_ENDPOINT = '/track/?data='.freeze
12
+ ENGAGE_ENDPOINT = '/engage/?data='.freeze
13
+ IMPORT_ENDPOINT = '/import/?data='.freeze
14
+
15
+ PERSON_PROPERTIES = %w(email first_name last_name created last_login username country_code).freeze
16
+
17
+ def initialize(token, env, options = {})
18
+ @token = token
19
+ @api_key = options.fetch(:api_key, "")
20
+ @env = env
21
+ @async = options.fetch(:async, false)
22
+ @import = options.fetch(:import, false)
23
+ @url = options.fetch(:url, MIXPANEL_API_URL)
24
+ @persist = options.fetch(:persist, false)
17
25
 
18
26
  if @persist
19
27
  @env["rack.session"]["mixpanel_events"] ||= []
@@ -27,16 +35,7 @@ module Mixpanel
27
35
  end
28
36
 
29
37
  def append_person_event(properties = {})
30
- # evaluate symbols and rewrite
31
- special_properties = %w{email created first_name last_name last_login username country_code}
32
- special_properties.each do |key|
33
- symbolized_key = key.to_sym
34
- if properties.has_key?(symbolized_key)
35
- properties["$#{key}"] = properties[symbolized_key]
36
- properties.delete(symbolized_key)
37
- end
38
- end
39
- append_api('people.set', properties)
38
+ append_api('people.set', person_properties(properties))
40
39
  end
41
40
 
42
41
  def append_person_increment_event(property, increment=1)
@@ -50,11 +49,29 @@ module Mixpanel
50
49
  def track_event(event, properties = {})
51
50
  options = { :time => Time.now.utc.to_i, :ip => ip }
52
51
  options.merge!( :token => @token ) if @token
53
- options.merge!(properties)
54
- params = build_event(event, options)
55
- parse_response request(params)
52
+ parse_response request(:track,
53
+ :event => event,
54
+ :properties => options.merge(properties)
55
+ )
56
56
  end
57
-
57
+
58
+ def engage(action, distinct_id, properties = {})
59
+ options = { }
60
+ options.merge!( :$token => @token ) if @token
61
+ parse_response request(:engage, options.merge(
62
+ :$distinct_id => distinct_id,
63
+ "$#{action}".to_sym => person_properties(properties)
64
+ ))
65
+ end
66
+
67
+ def engage_set(distinct_id, properties = {})
68
+ engage(:set, distinct_id, properties)
69
+ end
70
+
71
+ def engage_add(distinct_id, properties = {})
72
+ engage(:add, distinct_id, properties)
73
+ end
74
+
58
75
  def ip
59
76
  if @env.has_key?("HTTP_X_FORWARDED_FOR")
60
77
  @env["HTTP_X_FORWARDED_FOR"].split(",").last
@@ -81,7 +98,7 @@ module Mixpanel
81
98
  end
82
99
  end
83
100
 
84
- class <<self
101
+ class << self
85
102
  WORKER_MUTEX = Mutex.new
86
103
 
87
104
  def worker
@@ -111,15 +128,34 @@ module Mixpanel
111
128
  end
112
129
 
113
130
  private
131
+
132
+ def person_properties(properties = {})
133
+ properties.inject({}) do |out, (k, v)|
134
+ if PERSON_PROPERTIES.member?(k.to_s)
135
+ out["$#{k}".to_sym] = v
136
+ else
137
+ out[k] = v
138
+ end
139
+ out
140
+ end
141
+ end
114
142
 
115
143
  def parse_response(response)
116
144
  response == "1" ? true : false
117
145
  end
118
146
 
119
- def request(params)
147
+ def request(mode, params)
120
148
  data = Base64.encode64(JSON.generate(params)).gsub(/\n/,'')
121
- url = @import ? @url + "=" + data + '&api_key=' + @api_key : @url + data
122
-
149
+
150
+ mode = :import if @import
151
+ endpoint = case mode
152
+ when :track then TRACK_ENDPOINT
153
+ when :engage then ENGAGE_ENDPOINT
154
+ when :import then IMPORT_ENDPOINT
155
+ end
156
+ url = "#{@url}#{endpoint}#{data}"
157
+ url += "&api_key=#{@api_key}" if mode == :import
158
+
123
159
  if(@async)
124
160
  w = Tracker.worker
125
161
  begin
@@ -132,9 +168,5 @@ module Mixpanel
132
168
  open(url).read
133
169
  end
134
170
  end
135
-
136
- def build_event(event, properties)
137
- {:event => event, :properties => properties}
138
- end
139
171
  end
140
172
  end
@@ -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 = "2.1.0"
5
+ s.version = "2.2.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"
@@ -29,7 +29,7 @@ describe Mixpanel::Tracker do
29
29
  it "should call request method with token, time value and ip address" do
30
30
  params = {:event => "Sign up", :properties => {:token => MIX_PANEL_TOKEN, :time => Time.now.utc.to_i, :ip => "127.0.0.1"}}
31
31
 
32
- @mixpanel.should_receive(:request).with(params).and_return("1")
32
+ @mixpanel.should_receive(:request).with(:track, params).and_return("1")
33
33
  @mixpanel.track_event("Sign up").should == true
34
34
  end
35
35
 
@@ -38,10 +38,47 @@ describe Mixpanel::Tracker do
38
38
 
39
39
  params = {:event => "Sign up", :properties => {:token => MIX_PANEL_TOKEN, :time => Time.now.utc.to_i, :ip => "10.1.0.2"}}
40
40
 
41
- @mixpanel.should_receive(:request).with(params).and_return("1")
41
+ @mixpanel.should_receive(:request).with(:track, params).and_return("1")
42
42
  @mixpanel.track_event("Sign up")
43
43
  end
44
44
  end
45
+
46
+ context "Managing People" do
47
+ it "should set person data" do
48
+ @mixpanel.engage_set(DISTINCT_ID, :$email => 'test@example.com').should == true
49
+ end
50
+
51
+ it "should add person data" do
52
+ @mixpanel.engage_add(DISTINCT_ID, :custom => 99).should == true
53
+ end
54
+
55
+ it "should be able to call engage method directly" do
56
+ @mixpanel.engage(:set, DISTINCT_ID, :$email => 'test@example.com').should == true
57
+ end
58
+
59
+ it "should call request method for setting" do
60
+ params = {
61
+ :$token => MIX_PANEL_TOKEN,
62
+ :$distinct_id => DISTINCT_ID,
63
+ :$set => {
64
+ :$email => 'test@example.com',
65
+ :custom => 'test'
66
+ }}
67
+ @mixpanel.should_receive(:request).with(:engage, params).and_return("1")
68
+ @mixpanel.engage(:set, DISTINCT_ID, :email => 'test@example.com', :custom => 'test')
69
+ end
70
+
71
+ it "should call request method for adding" do
72
+ params = {
73
+ :$token => MIX_PANEL_TOKEN,
74
+ :$distinct_id => DISTINCT_ID,
75
+ :$add => {
76
+ :custom => 99
77
+ }}
78
+ @mixpanel.should_receive(:request).with(:engage, params).and_return("1")
79
+ @mixpanel.engage(:add, DISTINCT_ID, :custom => 99)
80
+ end
81
+ end
45
82
  end
46
83
 
47
84
  context "Accessing Mixpanel through javascript API" do
@@ -120,10 +157,23 @@ describe Mixpanel::Tracker do
120
157
  end
121
158
  end
122
159
 
123
- context "Import mode" do
160
+ context "Request modes" do
161
+ it "should use the track URL" do
162
+ @mixpanel.track_event("Sign up")
163
+ FakeWeb.last_request.path.to_s.include?(Mixpanel::Tracker::TRACK_ENDPOINT).should == true
164
+ end
165
+
166
+ it "should use the engage URL" do
167
+ @mixpanel.engage(:set, DISTINCT_ID, :email => 'test@example.com')
168
+ FakeWeb.last_request.path.to_s.include?(Mixpanel::Tracker::ENGAGE_ENDPOINT).should == true
169
+ end
170
+
124
171
  it "should use the import URL" do
125
172
  @mixpanel = Mixpanel::Tracker.new(MIX_PANEL_TOKEN, @env = {"REMOTE_ADDR" => "127.0.0.1"}, { :import => true, :api_key => "ABCDEFG" })
126
- @mixpanel.inspect.to_s.include?("import/?data").should == true
173
+ @mixpanel.track_event("Sign up")
174
+ path = FakeWeb.last_request.path.to_s
175
+ path.include?(Mixpanel::Tracker::IMPORT_ENDPOINT).should == true
176
+ path.include?("&api_key=ABCDEFG").should == true
127
177
  end
128
178
  end
129
179
  end
@@ -6,7 +6,7 @@ require 'nokogiri'
6
6
  Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
7
7
 
8
8
  MIX_PANEL_TOKEN = "e2d8b0bea559147844ffab3d607d26a6"
9
-
9
+ DISTINCT_ID = "abcd1234"
10
10
 
11
11
  def mixpanel_queue_should_include(mixpanel, type, *arguments)
12
12
  mixpanel.queue.each do |event_type, event_arguments|
metadata CHANGED
@@ -1,158 +1,123 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: mixpanel
3
- version: !ruby/object:Gem::Version
4
- hash: 11
5
- prerelease: false
6
- segments:
7
- - 2
8
- - 1
9
- - 0
10
- version: 2.1.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.2.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
- date: 2012-09-17 00:00:00 -03:00
19
- default_executable:
20
- dependencies:
21
- - !ruby/object:Gem::Dependency
12
+ date: 2012-10-07 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
22
15
  name: json
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &2160572700 !ruby/object:Gem::Requirement
25
17
  none: false
26
- requirements:
27
- - - ">="
28
- - !ruby/object:Gem::Version
29
- hash: 3
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
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *2160572700
25
+ - !ruby/object:Gem::Dependency
26
+ name: rack
27
+ requirement: &2160572260 !ruby/object:Gem::Requirement
39
28
  none: false
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- hash: 3
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
- requirement: &id003 !ruby/object:Gem::Requirement
35
+ version_requirements: *2160572260
36
+ - !ruby/object:Gem::Dependency
37
+ name: escape
38
+ requirement: &2153622720 !ruby/object:Gem::Requirement
53
39
  none: false
54
- requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
57
- hash: 3
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: rspec
65
45
  prerelease: false
66
- requirement: &id004 !ruby/object:Gem::Requirement
46
+ version_requirements: *2153622720
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec
49
+ requirement: &2153622300 !ruby/object:Gem::Requirement
67
50
  none: false
68
- requirements:
69
- - - ">="
70
- - !ruby/object:Gem::Version
71
- hash: 3
72
- segments:
73
- - 0
74
- version: "0"
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
75
55
  type: :development
76
- version_requirements: *id004
77
- - !ruby/object:Gem::Dependency
78
- name: rack-test
79
56
  prerelease: false
80
- requirement: &id005 !ruby/object:Gem::Requirement
57
+ version_requirements: *2153622300
58
+ - !ruby/object:Gem::Dependency
59
+ name: rack-test
60
+ requirement: &2153621880 !ruby/object:Gem::Requirement
81
61
  none: false
82
- requirements:
83
- - - ">="
84
- - !ruby/object:Gem::Version
85
- hash: 3
86
- segments:
87
- - 0
88
- version: "0"
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
89
66
  type: :development
90
- version_requirements: *id005
91
- - !ruby/object:Gem::Dependency
92
- name: fakeweb
93
67
  prerelease: false
94
- requirement: &id006 !ruby/object:Gem::Requirement
68
+ version_requirements: *2153621880
69
+ - !ruby/object:Gem::Dependency
70
+ name: fakeweb
71
+ requirement: &2153621460 !ruby/object:Gem::Requirement
95
72
  none: false
96
- requirements:
97
- - - ">="
98
- - !ruby/object:Gem::Version
99
- hash: 3
100
- segments:
101
- - 0
102
- version: "0"
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
103
77
  type: :development
104
- version_requirements: *id006
105
- - !ruby/object:Gem::Dependency
106
- name: nokogiri
107
78
  prerelease: false
108
- requirement: &id007 !ruby/object:Gem::Requirement
79
+ version_requirements: *2153621460
80
+ - !ruby/object:Gem::Dependency
81
+ name: nokogiri
82
+ requirement: &2153621040 !ruby/object:Gem::Requirement
109
83
  none: false
110
- requirements:
111
- - - ">="
112
- - !ruby/object:Gem::Version
113
- hash: 3
114
- segments:
115
- - 0
116
- version: "0"
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
117
88
  type: :development
118
- version_requirements: *id007
119
- - !ruby/object:Gem::Dependency
120
- name: rake
121
89
  prerelease: false
122
- requirement: &id008 !ruby/object:Gem::Requirement
90
+ version_requirements: *2153621040
91
+ - !ruby/object:Gem::Dependency
92
+ name: rake
93
+ requirement: &2153620620 !ruby/object:Gem::Requirement
123
94
  none: false
124
- requirements:
125
- - - ">="
126
- - !ruby/object:Gem::Version
127
- hash: 3
128
- segments:
129
- - 0
130
- version: "0"
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
131
99
  type: :development
132
- version_requirements: *id008
133
- - !ruby/object:Gem::Dependency
134
- name: ruby-debug
135
100
  prerelease: false
136
- requirement: &id009 !ruby/object:Gem::Requirement
101
+ version_requirements: *2153620620
102
+ - !ruby/object:Gem::Dependency
103
+ name: ruby-debug19
104
+ requirement: &2153620160 !ruby/object:Gem::Requirement
137
105
  none: false
138
- requirements:
139
- - - ">="
140
- - !ruby/object:Gem::Version
141
- hash: 3
142
- segments:
143
- - 0
144
- version: "0"
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
145
110
  type: :development
146
- version_requirements: *id009
147
- description: Simple lib to track events in Mixpanel service. It can be used in any rack based framework.
111
+ prerelease: false
112
+ version_requirements: *2153620160
113
+ description: Simple lib to track events in Mixpanel service. It can be used in any
114
+ rack based framework.
148
115
  email: zevarito@gmail.com
149
116
  executables: []
150
-
151
117
  extensions: []
152
-
153
- extra_rdoc_files:
118
+ extra_rdoc_files:
154
119
  - README.md
155
- files:
120
+ files:
156
121
  - README.md
157
122
  - LICENSE
158
123
  - Rakefile
@@ -166,39 +131,28 @@ files:
166
131
  - lib/mixpanel/tracker/subprocess.rb
167
132
  - lib/mixpanel/tracker.rb
168
133
  - lib/mixpanel.rb
169
- has_rdoc: true
170
134
  homepage: http://github.com/zevarito/mixpanel
171
135
  licenses: []
172
-
173
136
  post_install_message:
174
137
  rdoc_options: []
175
-
176
- require_paths:
138
+ require_paths:
177
139
  - lib
178
- required_ruby_version: !ruby/object:Gem::Requirement
140
+ required_ruby_version: !ruby/object:Gem::Requirement
179
141
  none: false
180
- requirements:
181
- - - ">="
182
- - !ruby/object:Gem::Version
183
- hash: 3
184
- segments:
185
- - 0
186
- version: "0"
187
- required_rubygems_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ! '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
188
147
  none: false
189
- requirements:
190
- - - ">="
191
- - !ruby/object:Gem::Version
192
- hash: 3
193
- segments:
194
- - 0
195
- version: "0"
148
+ requirements:
149
+ - - ! '>='
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
196
152
  requirements: []
197
-
198
153
  rubyforge_project: mixpanel
199
- rubygems_version: 1.3.7
154
+ rubygems_version: 1.8.15
200
155
  signing_key:
201
156
  specification_version: 3
202
157
  summary: Supports direct request api and javascript requests through a middleware.
203
158
  test_files: []
204
-