mixpanel-ruby 0.3.2 → 1.0.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.rdoc +10 -4
- data/lib/mixpanel-ruby/consumer.rb +26 -12
- data/lib/mixpanel-ruby/events.rb +48 -2
- data/lib/mixpanel-ruby/people.rb +27 -18
- data/lib/mixpanel-ruby/tracker.rb +37 -4
- data/lib/mixpanel-ruby/version.rb +1 -1
- data/spec/mixpanel-ruby/consumer_spec.rb +31 -9
- data/spec/mixpanel-ruby/events_spec.rb +22 -2
- data/spec/mixpanel-ruby/people_spec.rb +21 -21
- data/spec/mixpanel-ruby/tracker_spec.rb +28 -10
- metadata +2 -2
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
|
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 :
|
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 :
|
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
|
-
|
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(
|
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
|
142
|
-
|
143
|
-
|
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
|
-
|
159
|
-
@consumer.send(type,
|
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
|
data/lib/mixpanel-ruby/events.rb
CHANGED
@@ -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
|
-
|
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
|
data/lib/mixpanel-ruby/people.rb
CHANGED
@@ -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
|
-
#
|
147
|
-
#
|
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
|
-
|
222
|
-
|
223
|
-
|
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
|
-
|
114
|
+
data = {
|
88
115
|
'event' => '$create_alias',
|
89
116
|
'properties' => {
|
90
117
|
'distinct_id' => real_id,
|
91
|
-
'
|
118
|
+
'alias' => alias_id,
|
119
|
+
'token' => @token
|
92
120
|
}
|
93
|
-
}
|
94
|
-
|
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
|
@@ -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' => '
|
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' => '
|
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' => '
|
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' => '
|
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' =>
|
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' =>
|
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' =>
|
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' =>
|
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' =>
|
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' =>
|
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' =>
|
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' =>
|
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' =>
|
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' =>
|
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 => '
|
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' =>
|
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
|
-
|
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' =>
|
68
|
+
'time' => @time_now.to_i
|
68
69
|
}
|
69
70
|
}
|
70
71
|
],
|
71
|
-
[ :
|
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' =>
|
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' =>
|
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.
|
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-
|
12
|
+
date: 2013-07-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|