mixpanel-ruby 0.3.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Readme.rdoc CHANGED
@@ -11,12 +11,12 @@ get started sending your first events and updates:
11
11
  == Getting Started
12
12
 
13
13
  require 'mixpanel-ruby'
14
-
14
+
15
15
  tracker = Mixpanel::Tracker.new(YOUR_TOKEN)
16
-
16
+
17
17
  # Track an event on behalf of user "User1"
18
18
  tracker.track('User1', 'A Mixpanel Event')
19
-
19
+
20
20
  # Send an update to User1's profile
21
21
  tracker.people.set('User1', {
22
22
  '$first_name' => 'David',
@@ -34,5 +34,11 @@ For more information please visit:
34
34
 
35
35
  * Our Ruby API Integration page[https://mixpanel.com/help/reference/ruby#introduction]
36
36
  * The usage demo[https://github.com/mixpanel/mixpanel-ruby/tree/master/demo]
37
- * The docuemntation[http://mixpanel.github.io/mixpanel-ruby/]
37
+ * The documentation[http://mixpanel.github.io/mixpanel-ruby/]
38
+
39
+ == Changes
38
40
 
41
+ === 1.0.0 (Proposed)
42
+ * tracker#import added
43
+ * Change to internal tracking message format. Messages written
44
+ by earlier versions of the library will not work with 1.0.0 consumer classes.
@@ -34,7 +34,7 @@ module Mixpanel
34
34
  # the tracker, or just passing a block to Mixpanel::Tracker.new
35
35
  #
36
36
  # tracker = Mixpanel::Tracker.new(MY_TOKEN) do |type, message|
37
- # # type will be one of :event or :profile_update
37
+ # # type will be one of :event, :profile_update or :import
38
38
  # @kestrel.set(ANALYTICS_QUEUE, [ type, message ].to_json)
39
39
  # end
40
40
  #
@@ -56,13 +56,14 @@ module Mixpanel
56
56
  # they will be used instead of the default Mixpanel endpoints.
57
57
  # This can be useful for proxying, debugging, or if you prefer
58
58
  # not to use SSL for your events.
59
- def initialize(events_endpoint=nil, update_endpoint=nil)
59
+ def initialize(events_endpoint=nil, update_endpoint=nil, import_endpoint=nil)
60
60
  @events_endpoint = events_endpoint || 'https://api.mixpanel.com/track'
61
61
  @update_endpoint = update_endpoint || 'https://api.mixpanel.com/engage'
62
+ @import_endpoint = import_endpoint || 'https://api.mixpanel.com/import'
62
63
  end
63
64
 
64
65
  # Send the given string message to Mixpanel. Type should be
65
- # one of :event or :profile_update, which will determine the endpoint.
66
+ # one of :event, :profile_update or :import, which will determine the endpoint.
66
67
  #
67
68
  # Mixpanel::Consumer#send sends messages to Mixpanel immediately on
68
69
  # each call. To reduce the overall bandwidth you use when communicating
@@ -72,16 +73,22 @@ module Mixpanel
72
73
  endpoint = {
73
74
  :event => @events_endpoint,
74
75
  :profile_update => @update_endpoint,
76
+ :import => @import_endpoint
75
77
  }[ type ]
76
- data = Base64.strict_encode64(message)
78
+
79
+ decoded_message = JSON.load(message)
80
+ api_key = decoded_message["api_key"]
81
+ data = Base64.strict_encode64(decoded_message["data"].to_json)
77
82
  uri = URI(endpoint)
78
83
 
79
84
  client = Net::HTTP.new(uri.host, uri.port)
80
85
  client.use_ssl = true
81
86
  Mixpanel.with_http(client)
82
87
 
88
+ form_data = { "data" => data }
89
+ form_data.merge!("api_key" => api_key) if api_key
83
90
  request = Net::HTTP::Post.new(uri.request_uri)
84
- request.set_form_data({"data" => data })
91
+ request.set_form_data(form_data)
85
92
  response = client.request(request)
86
93
 
87
94
  if response.code == '200' and response.body == '1'
@@ -124,9 +131,9 @@ module Mixpanel
124
131
  # consumer automatically sends its buffered events. The Mixpanel
125
132
  # endpoints have a limit of 50 events per HTTP request, but
126
133
  # you can lower the limit if your individual events are very large.
127
- def initialize(events_endpoint=nil, update_endpoint=nil, max_buffer_length=MAX_LENGTH)
134
+ def initialize(events_endpoint=nil, update_endpoint=nil, import_endpoint=nil, max_buffer_length=MAX_LENGTH)
128
135
  @max_length = [ max_buffer_length, MAX_LENGTH ].min
129
- @consumer = Consumer.new(events_endpoint, update_endpoint)
136
+ @consumer = Consumer.new(events_endpoint, update_endpoint, import_endpoint)
130
137
  @buffers = {
131
138
  :event => [],
132
139
  :profile_update => [],
@@ -136,11 +143,18 @@ module Mixpanel
136
143
  # Stores a message for Mixpanel in memory. When the buffer
137
144
  # hits a maximum length, the consumer will flush automatically.
138
145
  # Flushes are synchronous when they occur.
146
+ #
147
+ # Currently, only :event and :profile_update messages are buffered,
148
+ # :import messages will be send immediately on call.
139
149
  def send(type, message)
140
150
  type = type.to_sym
141
- @buffers[type] << message
142
- if @buffers[type].length >= @max_length
143
- flush_type(type)
151
+ if @buffers.has_key? type
152
+ @buffers[type] << message
153
+ if @buffers[type].length >= @max_length
154
+ flush_type(type)
155
+ end
156
+ else
157
+ @consumer.send(type, message)
144
158
  end
145
159
  end
146
160
 
@@ -155,8 +169,8 @@ module Mixpanel
155
169
 
156
170
  def flush_type(type)
157
171
  @buffers[type].each_slice(@max_length) do |chunk|
158
- message = "[ #{chunk.join(',')} ]"
159
- @consumer.send(type, message)
172
+ data = chunk.map {|message| JSON.load(message)['data'] }
173
+ @consumer.send(type, {'data' => data}.to_json)
160
174
  end
161
175
  @buffers[type] = []
162
176
  end
@@ -59,12 +59,58 @@ module Mixpanel
59
59
  properties['ip'] = ip
60
60
  end
61
61
 
62
+ data = {
63
+ 'event' => event,
64
+ 'properties' => properties
65
+ }
66
+
62
67
  message = {
63
- 'event' => event,
64
- 'properties' => properties
68
+ 'data' => data
65
69
  }
66
70
 
67
71
  @sink.call(:event, message.to_json)
68
72
  end
73
+
74
+ # Imports an event that has occurred in the past, along with a distinct_id
75
+ # representing the source of that event (for example, a user id),
76
+ # an event name describing the event and a set of properties
77
+ # describing that event. Properties are provided as a Hash with
78
+ # string keys and strings, numbers or booleans as values.
79
+ #
80
+ # tracker = Mixpanel::Tracker.new
81
+ #
82
+ # # Track that user "12345"'s credit card was declined
83
+ # tracker.import("API_KEY", "12345", "Credit Card Declined")
84
+ #
85
+ # # Properties describe the circumstances of the event,
86
+ # # or aspects of the source or user associated with the event
87
+ # tracker.import("API_KEY", "12345", "Welcome Email Sent", {
88
+ # 'Email Template' => 'Pretty Pink Welcome',
89
+ # 'User Sign-up Cohort' => 'July 2013'
90
+ # })
91
+ def import(api_key, distinct_id, event, properties={}, ip=nil)
92
+ properties = {
93
+ 'distinct_id' => distinct_id,
94
+ 'token' => @token,
95
+ 'time' => Time.now.to_i,
96
+ 'mp_lib' => 'ruby',
97
+ '$lib_version' => Mixpanel::VERSION
98
+ }.merge(properties)
99
+ if ip
100
+ properties['ip'] = ip
101
+ end
102
+
103
+ data = {
104
+ 'event' => event,
105
+ 'properties' => properties
106
+ }
107
+
108
+ message = {
109
+ 'data' => data,
110
+ 'api_key' => api_key
111
+ }
112
+
113
+ @sink.call(:import, message.to_json)
114
+ end
69
115
  end
70
116
  end
@@ -22,6 +22,7 @@ module Mixpanel
22
22
  #
23
23
  def initialize(token, &block)
24
24
  @token = token
25
+
25
26
  if block
26
27
  @sink = block
27
28
  else
@@ -44,12 +45,12 @@ module Mixpanel
44
45
  #
45
46
  # If you provide an ip argument, \Mixpanel will use that
46
47
  # ip address for geolocation (rather than the ip of your server)
47
- def set(distinct_id, properties, ip=nil)
48
+ def set(distinct_id, properties, ip=nil, optional_params={})
48
49
  properties = fix_property_dates(properties)
49
50
  message = {
50
51
  '$distinct_id' => distinct_id,
51
52
  '$set' => properties,
52
- }
53
+ }.merge(optional_params)
53
54
 
54
55
  if ip
55
56
  message['$ip'] = ip
@@ -68,12 +69,12 @@ module Mixpanel
68
69
  # 'First Login Date': DateTime.now
69
70
  # });
70
71
  #
71
- def set_once(distinct_id, properties, ip=nil)
72
+ def set_once(distinct_id, properties, ip=nil, optional_params={})
72
73
  properties = fix_property_dates(properties)
73
74
  message = {
74
75
  '$distinct_id' => distinct_id,
75
76
  '$set_once' => properties,
76
- }
77
+ }.merge(optional_params)
77
78
 
78
79
  if ip
79
80
  message['$ip'] = ip
@@ -94,12 +95,12 @@ module Mixpanel
94
95
  # 'Coins Earned' => -7, # Use a negative number to subtract
95
96
  # });
96
97
  #
97
- def increment(distinct_id, properties, ip=nil)
98
+ def increment(distinct_id, properties, ip=nil, optional_params={})
98
99
  properties = fix_property_dates(properties)
99
100
  message = {
100
101
  '$distinct_id' => distinct_id,
101
102
  '$add' => properties,
102
- }
103
+ }.merge(optional_params)
103
104
 
104
105
  if ip
105
106
  message['$ip'] = ip
@@ -129,12 +130,12 @@ module Mixpanel
129
130
  # 'Alter Ego Names' => 'Ziggy Stardust'
130
131
  # });
131
132
  #
132
- def append(distinct_id, properties, ip=nil)
133
+ def append(distinct_id, properties, ip=nil, optional_params={})
133
134
  properties = fix_property_dates(properties)
134
135
  message = {
135
136
  '$distinct_id' => distinct_id,
136
137
  '$append' => properties,
137
- }
138
+ }.merge(optional_params)
138
139
 
139
140
  if ip
140
141
  message['$ip'] = ip
@@ -143,20 +144,23 @@ module Mixpanel
143
144
  update(message)
144
145
  end
145
146
 
146
- # Appends a value to the end of list-valued properties,
147
- # only if the given value is not already present in the list.
147
+ # Set union on list valued properties.
148
+ # Associates a list containing all elements of a given list,
149
+ # and all elements currently in a list associated with the given
150
+ # property. After a union, every element in the list associated
151
+ # with a property will be unique.
148
152
  #
149
153
  # tracker = Mixpanel::Tracker.new
150
154
  # tracker.people.union("12345", {
151
- # 'Levels Completed' => 'Suffragette City'
155
+ # 'Levels Completed' => ['Suffragette City']
152
156
  # });
153
157
  #
154
- def union(distinct_id, properties, ip=nil)
158
+ def union(distinct_id, properties, ip=nil, optional_params={})
155
159
  properties = fix_property_dates(properties)
156
160
  message = {
157
161
  '$distinct_id' => distinct_id,
158
162
  '$union' => properties,
159
- }
163
+ }.merge(optional_params)
160
164
 
161
165
  if ip
162
166
  message['$ip'] = ip
@@ -190,10 +194,10 @@ module Mixpanel
190
194
  # '$time' => DateTime.parse("Jan 2 2013")
191
195
  # })
192
196
  #
193
- def track_charge(distinct_id, amount, properties={}, ip=nil)
197
+ def track_charge(distinct_id, amount, properties={}, ip=nil, optional_params={})
194
198
  properties = fix_property_dates(properties)
195
199
  charge_properties = properties.merge({ '$amount' => amount })
196
- append(distinct_id, { '$transactions' => charge_properties }, ip)
200
+ append(distinct_id, { '$transactions' => charge_properties }, ip, optional_params)
197
201
  end
198
202
 
199
203
  # Clear all charges from a \Mixpanel people profile
@@ -218,10 +222,15 @@ module Mixpanel
218
222
  # The \Mixpanel HTTP tracking API is documented at
219
223
  # https://mixpanel.com/help/reference/http
220
224
  def update(message)
221
- message = {
222
- '$token' => @token,
223
- '$time' => ((Time.now.to_f) * 1000.0).to_i
225
+ data = {
226
+ '$token' => @token,
227
+ '$time' => ((Time.now.to_f) * 1000.0).to_i
224
228
  }.merge(message)
229
+
230
+ message = {
231
+ 'data' => data
232
+ }
233
+
225
234
  @sink.call(:profile_update, message.to_json)
226
235
  end
227
236
 
@@ -72,6 +72,33 @@ module Mixpanel
72
72
  super
73
73
  end
74
74
 
75
+ # A call to #import is to import an event occurred in the past. #import
76
+ # takes a distinct_id representing the source of that event (for
77
+ # example, a user id), an event name describing the event, and a
78
+ # set of properties describing that event. Properties are provided
79
+ # as a Hash with string keys and strings, numbers or booleans as
80
+ # values.
81
+ #
82
+ # tracker = Mixpanel::Tracker.new
83
+ #
84
+ # # Import event that user "12345"'s credit card was declined
85
+ # tracker.import("12345", "Credit Card Declined", {
86
+ # 'time' => 1310111365
87
+ # })
88
+ #
89
+ # # Properties describe the circumstances of the event,
90
+ # # or aspects of the source or user associated with the event
91
+ # tracker.import("API_KEY", "12345", "Welcome Email Sent", {
92
+ # 'Email Template' => 'Pretty Pink Welcome',
93
+ # 'User Sign-up Cohort' => 'July 2013',
94
+ # 'time' => 1310111365
95
+ # })
96
+ def import(api_key, distinct_id, event, properties={}, ip=nil)
97
+ # This is here strictly to allow rdoc to include the relevant
98
+ # documentation
99
+ super
100
+ end
101
+
75
102
  # Creates a distinct_id alias. \Events and updates with an alias
76
103
  # will be considered by mixpanel to have the same source, and
77
104
  # refer to the same profile.
@@ -84,14 +111,20 @@ module Mixpanel
84
111
  # the \Mixpanel service, regardless of how the tracker is configured.
85
112
  def alias(alias_id, real_id, events_endpoint=nil)
86
113
  consumer = Mixpanel::Consumer.new(events_endpoint)
87
- message = {
114
+ data = {
88
115
  'event' => '$create_alias',
89
116
  'properties' => {
90
117
  'distinct_id' => real_id,
91
- 'token' => @token,
118
+ 'alias' => alias_id,
119
+ 'token' => @token
92
120
  }
93
- }.to_json
94
- consumer.send(:event, message)
121
+ }
122
+
123
+ message = {
124
+ 'data' => data
125
+ }
126
+
127
+ consumer.send(:event, message.to_json)
95
128
  end
96
129
  end
97
130
  end
@@ -1,3 +1,3 @@
1
1
  module Mixpanel
2
- VERSION = '0.3.2'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -11,16 +11,23 @@ describe Mixpanel::Consumer do
11
11
 
12
12
  it 'should send a request to api.mixpanel.com/track on events' do
13
13
  stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => "1" })
14
- @consumer.send(:event, 'TEST EVENT MESSAGE')
14
+ @consumer.send(:event, {'data' => 'TEST EVENT MESSAGE'}.to_json)
15
15
  WebMock.should have_requested(:post, 'https://api.mixpanel.com/track').
16
- with(:body => {'data' => 'VEVTVCBFVkVOVCBNRVNTQUdF' })
16
+ with(:body => {'data' => 'IlRFU1QgRVZFTlQgTUVTU0FHRSI=' })
17
17
  end
18
18
 
19
19
  it 'should send a request to api.mixpanel.com/people on profile updates' do
20
20
  stub_request(:any, 'https://api.mixpanel.com/engage').to_return({ :body => "1" })
21
- @consumer.send(:profile_update, 'TEST EVENT MESSAGE')
21
+ @consumer.send(:profile_update, {'data' => 'TEST EVENT MESSAGE'}.to_json)
22
22
  WebMock.should have_requested(:post, 'https://api.mixpanel.com/engage').
23
- with(:body => {'data' => 'VEVTVCBFVkVOVCBNRVNTQUdF' })
23
+ with(:body => {'data' => 'IlRFU1QgRVZFTlQgTUVTU0FHRSI=' })
24
+ end
25
+
26
+ it 'should send a request to api.mixpanel.com/import on event imports' do
27
+ stub_request(:any, 'https://api.mixpanel.com/import').to_return({ :body => "1" })
28
+ @consumer.send(:import, {'data' => 'TEST EVENT MESSAGE', 'api_key' => 'API_KEY'}.to_json)
29
+ WebMock.should have_requested(:post, 'https://api.mixpanel.com/import').
30
+ with(:body => {'data' => 'IlRFU1QgRVZFTlQgTUVTU0FHRSI=', 'api_key' => 'API_KEY' })
24
31
  end
25
32
  end
26
33
 
@@ -28,27 +35,42 @@ describe Mixpanel::BufferedConsumer do
28
35
  before(:each) do
29
36
  WebMock.reset!
30
37
  @max_length = 10
31
- @consumer = Mixpanel::BufferedConsumer.new(nil, nil, @max_length)
38
+ @consumer = Mixpanel::BufferedConsumer.new(nil, nil, nil, @max_length)
32
39
  end
33
40
 
34
41
  it 'should not send a request for a single message until flush is called' do
35
42
  stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => "1" })
36
- @consumer.send(:event, 'TEST EVENT 1')
43
+ @consumer.send(:event, {'data' => 'TEST EVENT 1'}.to_json)
37
44
  WebMock.should have_not_requested(:post, 'https://api.mixpanel.com/track')
38
45
 
39
46
  @consumer.flush()
40
47
  WebMock.should have_requested(:post, 'https://api.mixpanel.com/track').
41
- with(:body => {'data' => 'WyBURVNUIEVWRU5UIDEgXQ==' })
48
+ with(:body => {'data' => 'WyJURVNUIEVWRU5UIDEiXQ==' })
42
49
  end
43
50
 
44
51
  it 'should send one message when max_length events are tracked' do
45
52
  stub_request(:any, 'https://api.mixpanel.com/track').to_return({ :body => "1" })
46
53
 
47
54
  @max_length.times do |i|
48
- @consumer.send(:event, "x #{i}")
55
+ @consumer.send(:event, {'data' => "x #{i}"}.to_json)
49
56
  end
50
57
 
51
58
  WebMock.should have_requested(:post, 'https://api.mixpanel.com/track').
52
- with(:body => {'data' => 'WyB4IDAseCAxLHggMix4IDMseCA0LHggNSx4IDYseCA3LHggOCx4IDkgXQ==' })
59
+ with(:body => {'data' => 'WyJ4IDAiLCJ4IDEiLCJ4IDIiLCJ4IDMiLCJ4IDQiLCJ4IDUiLCJ4IDYiLCJ4IDciLCJ4IDgiLCJ4IDkiXQ==' })
60
+ end
61
+
62
+ it 'should send one message per api key on import' do
63
+ stub_request(:any, 'https://api.mixpanel.com/import').to_return({ :body => "1" })
64
+ @consumer.send(:import, {'data' => 'TEST EVENT 1', 'api_key' => 'KEY 1'}.to_json)
65
+ @consumer.send(:import, {'data' => 'TEST EVENT 1', 'api_key' => 'KEY 2'}.to_json)
66
+ @consumer.send(:import, {'data' => 'TEST EVENT 2', 'api_key' => 'KEY 1'}.to_json)
67
+ @consumer.send(:import, {'data' => 'TEST EVENT 2', 'api_key' => 'KEY 2'}.to_json)
68
+ @consumer.flush
69
+
70
+ WebMock.should have_requested(:post, 'https://api.mixpanel.com/import').
71
+ with(:body => {'data' => 'IlRFU1QgRVZFTlQgMSI=', 'api_key' => 'KEY 1' })
72
+
73
+ WebMock.should have_requested(:post, 'https://api.mixpanel.com/import').
74
+ with(:body => {'data' => 'IlRFU1QgRVZFTlQgMSI=', 'api_key' => 'KEY 2' })
53
75
  end
54
76
  end
@@ -18,7 +18,7 @@ describe Mixpanel::Events do
18
18
  @events.track('TEST ID', 'Test Event', {
19
19
  'Circumstances' => 'During a test'
20
20
  })
21
- @log.should eq([[ :event, {
21
+ @log.should eq([[ :event, 'data' => {
22
22
  'event' => 'Test Event',
23
23
  'properties' => {
24
24
  'Circumstances' => 'During a test',
@@ -26,9 +26,29 @@ describe Mixpanel::Events do
26
26
  'mp_lib' => 'ruby',
27
27
  '$lib_version' => Mixpanel::VERSION,
28
28
  'token' => 'TEST TOKEN',
29
- 'time' => 76695784
29
+ 'time' => @time_now.to_i
30
30
  }
31
31
  }]])
32
32
  end
33
+
34
+ it 'should send a well formed import/ message' do
35
+ @events.import('API_KEY', 'TEST ID', 'Test Event', {
36
+ 'Circumstances' => 'During a test'
37
+ })
38
+ @log.should eq([[ :import, {
39
+ 'api_key' => 'API_KEY',
40
+ 'data' => {
41
+ 'event' => 'Test Event',
42
+ 'properties' => {
43
+ 'Circumstances' => 'During a test',
44
+ 'distinct_id' => 'TEST ID',
45
+ 'mp_lib' => 'ruby',
46
+ '$lib_version' => Mixpanel::VERSION,
47
+ 'token' => 'TEST TOKEN',
48
+ 'time' => @time_now.to_i
49
+ }
50
+ }
51
+ } ]])
52
+ end
33
53
  end
34
54
 
@@ -19,10 +19,10 @@ describe Mixpanel::People do
19
19
  '$firstname' => 'David',
20
20
  '$lastname' => 'Bowie',
21
21
  })
22
- @log.should eq([[ :profile_update, {
22
+ @log.should eq([[ :profile_update, 'data' => {
23
23
  '$token' => 'TEST TOKEN',
24
24
  '$distinct_id' => 'TEST ID',
25
- '$time' => 76695784000,
25
+ '$time' => @time_now.to_i * 1000,
26
26
  '$set' => {
27
27
  '$firstname' => 'David',
28
28
  '$lastname' => 'Bowie'
@@ -35,10 +35,10 @@ describe Mixpanel::People do
35
35
  '$firstname' => 'David',
36
36
  '$lastname' => 'Bowie',
37
37
  })
38
- @log.should eq([[ :profile_update, {
38
+ @log.should eq([[ :profile_update, 'data' => {
39
39
  '$token' => 'TEST TOKEN',
40
40
  '$distinct_id' => 'TEST ID',
41
- '$time' => 76695784000,
41
+ '$time' => @time_now.to_i * 1000,
42
42
  '$set_once' => {
43
43
  '$firstname' => 'David',
44
44
  '$lastname' => 'Bowie'
@@ -48,10 +48,10 @@ describe Mixpanel::People do
48
48
 
49
49
  it 'should send a well formed engage/add message' do
50
50
  @people.increment("TEST ID", { 'Albums Released' => 10 })
51
- @log.should eq([[ :profile_update, {
51
+ @log.should eq([[ :profile_update, 'data' => {
52
52
  '$token' => 'TEST TOKEN',
53
53
  '$distinct_id' => 'TEST ID',
54
- '$time' => 76695784000,
54
+ '$time' => @time_now.to_i * 1000,
55
55
  '$add' => {
56
56
  'Albums Released' => 10
57
57
  }
@@ -60,7 +60,7 @@ describe Mixpanel::People do
60
60
 
61
61
  it 'should send an engage/add message with a value of 1' do
62
62
  @people.plus_one("TEST ID", 'Albums Released')
63
- @log.should eq([[ :profile_update, {
63
+ @log.should eq([[ :profile_update, 'data' => {
64
64
  '$token' => 'TEST TOKEN',
65
65
  '$distinct_id' => 'TEST ID',
66
66
  '$time' => 76695784000,
@@ -72,10 +72,10 @@ describe Mixpanel::People do
72
72
 
73
73
  it 'should send a well formed engage/append message' do
74
74
  @people.append("TEST ID", { 'Albums' => 'Diamond Dogs' })
75
- @log.should eq([[ :profile_update, {
75
+ @log.should eq([[ :profile_update, 'data' => {
76
76
  '$token' => 'TEST TOKEN',
77
77
  '$distinct_id' => 'TEST ID',
78
- '$time' => 76695784000,
78
+ '$time' => @time_now.to_i * 1000,
79
79
  '$append' => {
80
80
  'Albums' => 'Diamond Dogs'
81
81
  }
@@ -83,23 +83,23 @@ describe Mixpanel::People do
83
83
  end
84
84
 
85
85
  it 'should send a well formed engage/union message' do
86
- @people.union("TEST ID", { 'Albums' => 'Diamond Dogs' })
87
- @log.should eq([[ :profile_update, {
86
+ @people.union("TEST ID", { 'Albums' => ['Diamond Dogs'] })
87
+ @log.should eq([[ :profile_update, 'data' => {
88
88
  '$token' => 'TEST TOKEN',
89
89
  '$distinct_id' => 'TEST ID',
90
- '$time' => 76695784000,
90
+ '$time' => @time_now.to_i * 1000,
91
91
  '$union' => {
92
- 'Albums' => 'Diamond Dogs'
92
+ 'Albums' => ['Diamond Dogs']
93
93
  }
94
94
  }]])
95
95
  end
96
96
 
97
97
  it 'should send a well formed unset message' do
98
98
  @people.unset('TEST ID', 'Albums')
99
- @log.should eq([[ :profile_update, {
99
+ @log.should eq([[ :profile_update, 'data' => {
100
100
  '$token' => 'TEST TOKEN',
101
101
  '$distinct_id' => 'TEST ID',
102
- '$time' => 76695784000,
102
+ '$time' => @time_now.to_i * 1000,
103
103
  '$unset' => [ 'Albums' ]
104
104
  }]])
105
105
  end
@@ -109,10 +109,10 @@ describe Mixpanel::People do
109
109
  '$time' => DateTime.new(1999,12,24,14, 02, 53),
110
110
  'SKU' => '1234567'
111
111
  })
112
- @log.should eq([[ :profile_update, {
112
+ @log.should eq([[ :profile_update, 'data' => {
113
113
  '$token' => 'TEST TOKEN',
114
114
  '$distinct_id' => 'TEST ID',
115
- '$time' => 76695784000,
115
+ '$time' => @time_now.to_i * 1000,
116
116
  '$append' => {
117
117
  '$transactions' => {
118
118
  '$time' => '1999-12-24T14:02:53',
@@ -125,20 +125,20 @@ describe Mixpanel::People do
125
125
 
126
126
  it 'should send a well formed engage/unset message for $transaction' do
127
127
  @people.clear_charges("TEST ID")
128
- @log.should eq([[ :profile_update, {
128
+ @log.should eq([[ :profile_update, 'data' => {
129
129
  '$token' => 'TEST TOKEN',
130
130
  '$distinct_id' => 'TEST ID',
131
- '$time' => 76695784000,
131
+ '$time' => @time_now.to_i * 1000,
132
132
  '$unset' => [ '$transactions' ]
133
133
  }]])
134
134
  end
135
135
 
136
136
  it 'should send a well formed engage/delete message' do
137
137
  @people.delete_user("TEST ID")
138
- @log.should eq([[ :profile_update, {
138
+ @log.should eq([[ :profile_update, 'data' => {
139
139
  '$token' => 'TEST TOKEN',
140
140
  '$distinct_id' => 'TEST ID',
141
- '$time' => 76695784000,
141
+ '$time' => @time_now.to_i * 1000,
142
142
  '$delete' => ''
143
143
  }]])
144
144
  end
@@ -16,7 +16,7 @@ describe Mixpanel::Tracker do
16
16
  mixpanel.alias('TEST ALIAS', 'TEST ID')
17
17
 
18
18
  WebMock.should have_requested(:post, 'https://api.mixpanel.com/track').
19
- with(:body => { :data => 'eyJldmVudCI6IiRjcmVhdGVfYWxpYXMiLCJwcm9wZXJ0aWVzIjp7ImRpc3RpbmN0X2lkIjoiVEVTVCBJRCIsInRva2VuIjoiVEVTVCBUT0tFTiJ9fQ==' })
19
+ with(:body => { :data => 'eyJldmVudCI6IiRjcmVhdGVfYWxpYXMiLCJwcm9wZXJ0aWVzIjp7ImRpc3RpbmN0X2lkIjoiVEVTVCBJRCIsImFsaWFzIjoiVEVTVCBBTElBUyIsInRva2VuIjoiVEVTVCBUT0tFTiJ9fQ==' })
20
20
  end
21
21
 
22
22
  it 'should send a request to the track api with the default consumer' do
@@ -42,7 +42,7 @@ describe Mixpanel::Tracker do
42
42
  'mp_lib' => 'ruby',
43
43
  '$lib_version' => Mixpanel::VERSION,
44
44
  'token' => 'TEST TOKEN',
45
- 'time' => 76695784
45
+ 'time' => @time_now.to_i
46
46
  }
47
47
  })
48
48
  end
@@ -53,35 +53,53 @@ describe Mixpanel::Tracker do
53
53
  messages << [ type, JSON.load(message) ]
54
54
  end
55
55
  mixpanel.track('ID', 'Event')
56
+ mixpanel.import('API_KEY', 'ID', 'Import')
56
57
  mixpanel.people.set('ID', { 'k' => 'v' })
57
58
  mixpanel.people.append('ID', { 'k' => 'v' })
58
59
 
59
- messages.should eq([
60
- [ :event,
60
+ expect = [
61
+ [ :event, 'data' =>
61
62
  { 'event' => 'Event',
62
63
  'properties' => {
63
64
  'distinct_id' => 'ID',
64
65
  'mp_lib' => 'ruby',
65
66
  '$lib_version' => Mixpanel::VERSION,
66
67
  'token' => 'TEST TOKEN',
67
- 'time' => 76695784
68
+ 'time' => @time_now.to_i
68
69
  }
69
70
  }
70
71
  ],
71
- [ :profile_update,
72
+ [ :import, {
73
+ 'data' => {
74
+ 'event' => 'Import',
75
+ 'properties' => {
76
+ 'distinct_id' => 'ID',
77
+ 'mp_lib' => 'ruby',
78
+ '$lib_version' => Mixpanel::VERSION,
79
+ 'token' => 'TEST TOKEN',
80
+ 'time' => @time_now.to_i
81
+ }
82
+ },
83
+ 'api_key' => 'API_KEY',
84
+ }
85
+ ],
86
+ [ :profile_update, 'data' =>
72
87
  { '$token' => 'TEST TOKEN',
73
88
  '$distinct_id' => 'ID',
74
- '$time' => 76695784000,
89
+ '$time' => @time_now.to_i * 1000,
75
90
  '$set' => { 'k' => 'v' }
76
91
  }
77
92
  ],
78
- [ :profile_update,
93
+ [ :profile_update, 'data' =>
79
94
  { '$token' => 'TEST TOKEN',
80
95
  '$distinct_id' => 'ID',
81
- '$time' => 76695784000,
96
+ '$time' => @time_now.to_i * 1000,
82
97
  '$append' => { 'k' => 'v' }
83
98
  }
84
99
  ]
85
- ])
100
+ ]
101
+ expect.zip(messages).each do |expect, found|
102
+ expect.should eq(found)
103
+ end
86
104
  end
87
105
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mixpanel-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-07-09 00:00:00.000000000 Z
12
+ date: 2013-07-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake