mixpanel 2.1.0 → 2.2.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 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
-