mixpanel-ruby-with-pixel-tracking 1.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.
@@ -0,0 +1,116 @@
1
+ require 'mixpanel-ruby/consumer'
2
+ require 'time'
3
+
4
+ module Mixpanel
5
+
6
+ # Handles formatting Mixpanel event tracking messages
7
+ # and sending them to the consumer. Mixpanel::Tracker
8
+ # is a subclass of this class, and the best way to
9
+ # track events is to instantiate a Mixpanel::Tracker
10
+ #
11
+ # tracker = Mixpanel::Tracker.new # Has all of the methods of Mixpanel::Event
12
+ # tracker.track(...)
13
+ #
14
+ class Events
15
+
16
+ # You likely won't need to instantiate an instance of
17
+ # Mixpanel::Events directly. The best way to get an instance
18
+ # is to use Mixpanel::Tracker
19
+ #
20
+ # # tracker has all of the methods of Mixpanel::Events
21
+ # tracker = Mixpanel::Tracker.new(...)
22
+ #
23
+ def initialize(token, &block)
24
+ @token = token
25
+ if block
26
+ @sink = block
27
+ else
28
+ consumer = Consumer.new
29
+ @sink = consumer.method(:send)
30
+ end
31
+ end
32
+
33
+ # Notes that an event has occurred, along with a distinct_id
34
+ # representing the source of that event (for example, a user id),
35
+ # an event name describing the event and a set of properties
36
+ # describing that event. Properties are provided as a Hash with
37
+ # string keys and strings, numbers or booleans as values.
38
+ #
39
+ # tracker = Mixpanel::Tracker.new
40
+ #
41
+ # # Track that user "12345"'s credit card was declined
42
+ # tracker.track("12345", "Credit Card Declined")
43
+ #
44
+ # # Properties describe the circumstances of the event,
45
+ # # or aspects of the source or user associated with the event
46
+ # tracker.track("12345", "Welcome Email Sent", {
47
+ # 'Email Template' => 'Pretty Pink Welcome',
48
+ # 'User Sign-up Cohort' => 'July 2013'
49
+ # })
50
+ def track(distinct_id, event, properties={}, ip=nil, as_pixel=nil)
51
+ properties = {
52
+ 'distinct_id' => distinct_id,
53
+ 'token' => @token,
54
+ 'time' => Time.now.to_i,
55
+ 'mp_lib' => 'ruby',
56
+ '$lib_version' => Mixpanel::VERSION
57
+ }.merge(properties)
58
+ if ip
59
+ properties['ip'] = ip
60
+ end
61
+
62
+ data = {
63
+ 'event' => event,
64
+ 'properties' => properties
65
+ }
66
+
67
+ message = {
68
+ 'data' => data
69
+ }
70
+
71
+ @sink.call(:event, message.to_json, as_pixel)
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
115
+ end
116
+ end
@@ -0,0 +1,258 @@
1
+ require 'mixpanel-ruby/consumer'
2
+ require 'json'
3
+ require 'date'
4
+ require 'time'
5
+
6
+ module Mixpanel
7
+
8
+ # Handles formatting Mixpanel profile updates and
9
+ # sending them to the consumer. You will rarely need
10
+ # to instantiate this class directly- to send
11
+ # profile updates, use Mixpanel::Tracker#people
12
+ #
13
+ # tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
14
+ # tracker.people.set(...) # Or .append(..), or track_charge(...) etc.
15
+ class People
16
+
17
+ # You likely won't need to instantiate instances of Mixpanel::People
18
+ # directly. The best way to get an instance of Mixpanel::People is
19
+ #
20
+ # tracker = Mixpanel::Tracker.new(...)
21
+ # tracker.people # An instance of Mixpanel::People
22
+ #
23
+ def initialize(token, &block)
24
+ @token = token
25
+
26
+ if block
27
+ @sink = block
28
+ else
29
+ consumer = Consumer.new
30
+ @sink = consumer.method(:send)
31
+ end
32
+ end
33
+
34
+ # Sets properties on a user record. Takes a Hash with string
35
+ # keys, and values that are strings, numbers, booleans, or
36
+ # DateTimes
37
+ #
38
+ # tracker = Mixpanel::Tracker.new
39
+ # # Sets properties on profile with id "1234"
40
+ # tracker.people.set("1234", {
41
+ # 'company' => 'Acme',
42
+ # 'plan' => 'Premium',
43
+ # 'Sign-Up Date' => DateTime.now
44
+ # });
45
+ #
46
+ # If you provide an ip argument, \Mixpanel will use that
47
+ # ip address for geolocation (rather than the ip of your server)
48
+ def set(distinct_id, properties, ip=nil, optional_params={})
49
+ properties = fix_property_dates(properties)
50
+ message = {
51
+ '$distinct_id' => distinct_id,
52
+ '$set' => properties,
53
+ }.merge(optional_params)
54
+
55
+ if ip
56
+ message['$ip'] = ip
57
+ end
58
+
59
+ update(message)
60
+ end
61
+
62
+ # set_once works just like #set, but will only change the
63
+ # value of properties if they are not already present
64
+ # in the profile. That means you can call set_once many times
65
+ # without changing an original value.
66
+ #
67
+ # tracker = Mixpanel::Tracker.new
68
+ # tracker.people.set_once("12345", {
69
+ # 'First Login Date': DateTime.now
70
+ # });
71
+ #
72
+ def set_once(distinct_id, properties, ip=nil, optional_params={})
73
+ properties = fix_property_dates(properties)
74
+ message = {
75
+ '$distinct_id' => distinct_id,
76
+ '$set_once' => properties,
77
+ }.merge(optional_params)
78
+
79
+ if ip
80
+ message['$ip'] = ip
81
+ end
82
+
83
+ update(message)
84
+ end
85
+
86
+ # Changes the value of properties by a numeric amount. Takes a
87
+ # hash with string keys and numeric properties. \Mixpanel will add
88
+ # the given amount to whatever value is currently assigned to the
89
+ # property. If no property exists with a given name, the value
90
+ # will be added to zero.
91
+ #
92
+ # tracker = Mixpanel::Tracker.new
93
+ # tracker.people.increment("12345", {
94
+ # 'Coins Spent' => 7,
95
+ # 'Coins Earned' => -7, # Use a negative number to subtract
96
+ # });
97
+ #
98
+ def increment(distinct_id, properties, ip=nil, optional_params={})
99
+ properties = fix_property_dates(properties)
100
+ message = {
101
+ '$distinct_id' => distinct_id,
102
+ '$add' => properties,
103
+ }.merge(optional_params)
104
+
105
+ if ip
106
+ message['$ip'] = ip
107
+ end
108
+
109
+ update(message)
110
+ end
111
+
112
+ # Convenience method- increases the value of a numeric property
113
+ # by one. Calling #plus_one(distinct_id, property_name) is the same as calling
114
+ # #increment(distinct_id, {property_name => 1})
115
+ #
116
+ # tracker = Mixpanel::Tracker.new
117
+ # tracker.people.plus_one("12345", "Albums Released")
118
+ #
119
+ def plus_one(distinct_id, property_name, ip=nil, optional_params={})
120
+ increment(distinct_id, {property_name => 1}, ip, optional_params)
121
+ end
122
+
123
+ # Appends a values to the end of list-valued properties.
124
+ # If the given properties don't exist, a new list-valued
125
+ # property will be created.
126
+ #
127
+ # tracker = Mixpanel::Tracker.new
128
+ # tracker.people.append("12345", {
129
+ # 'Login Dates' => DateTime.now,
130
+ # 'Alter Ego Names' => 'Ziggy Stardust'
131
+ # });
132
+ #
133
+ def append(distinct_id, properties, ip=nil, optional_params={})
134
+ properties = fix_property_dates(properties)
135
+ message = {
136
+ '$distinct_id' => distinct_id,
137
+ '$append' => properties,
138
+ }.merge(optional_params)
139
+
140
+ if ip
141
+ message['$ip'] = ip
142
+ end
143
+
144
+ update(message)
145
+ end
146
+
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.
152
+ #
153
+ # tracker = Mixpanel::Tracker.new
154
+ # tracker.people.union("12345", {
155
+ # 'Levels Completed' => ['Suffragette City']
156
+ # });
157
+ #
158
+ def union(distinct_id, properties, ip=nil, optional_params={})
159
+ properties = fix_property_dates(properties)
160
+ message = {
161
+ '$distinct_id' => distinct_id,
162
+ '$union' => properties,
163
+ }.merge(optional_params)
164
+
165
+ if ip
166
+ message['$ip'] = ip
167
+ end
168
+
169
+ update(message)
170
+ end
171
+
172
+ # Removes properties and their values from a profile.
173
+ #
174
+ # tracker = Mixpanel::Tracker.new
175
+ #
176
+ # # removes a single property and its value from a profile
177
+ # tracker.people.unset("12345", "Overdue Since")
178
+ #
179
+ # # removes multiple properties and their values from a profile
180
+ # tracker.people.unset("12345", ["Overdue Since", "Paid Date"])
181
+ #
182
+ def unset(distinct_id, properties, ip=nil, optional_params={})
183
+ properties = [properties] unless properties.is_a?(Array)
184
+ message = {
185
+ '$distinct_id' => distinct_id,
186
+ '$unset' => properties
187
+ }.merge(optional_params)
188
+
189
+ if ip
190
+ message['$ip'] = ip
191
+ end
192
+
193
+ update(message)
194
+ end
195
+
196
+ # Records a payment to you to a profile. Charges recorded with
197
+ # #track_charge will appear in the \Mixpanel revenue report.
198
+ #
199
+ # tracker = Mixpanel::Tracker.new
200
+ #
201
+ # # records a charge of $25.32 from user 12345
202
+ # tracker.people.track_charge("12345", 25.32)
203
+ #
204
+ # # records a charge of $30.50 on the 2nd of January,
205
+ # mixpanel.people.track_charge("12345", 30.50, {
206
+ # '$time' => DateTime.parse("Jan 2 2013")
207
+ # })
208
+ #
209
+ def track_charge(distinct_id, amount, properties={}, ip=nil, optional_params={})
210
+ properties = fix_property_dates(properties)
211
+ charge_properties = properties.merge({'$amount' => amount})
212
+ append(distinct_id, {'$transactions' => charge_properties}, ip, optional_params)
213
+ end
214
+
215
+ # Clear all charges from a \Mixpanel people profile
216
+ def clear_charges(distinct_id, ip=nil, optional_params={})
217
+ unset(distinct_id, '$transactions', ip, optional_params)
218
+ end
219
+
220
+ # Permanently delete a profile from \Mixpanel people analytics
221
+ def delete_user(distinct_id)
222
+ update({
223
+ '$distinct_id' => distinct_id,
224
+ '$delete' => ''
225
+ })
226
+ end
227
+
228
+ # Send a generic update to \Mixpanel people analytics.
229
+ # Caller is responsible for formatting the update message, as
230
+ # documented in the \Mixpanel HTTP specification, and passing
231
+ # the message as a dict to #update. This
232
+ # method might be useful if you want to use very new
233
+ # or experimental features of people analytics from Ruby
234
+ # The \Mixpanel HTTP tracking API is documented at
235
+ # https://mixpanel.com/help/reference/http
236
+ def update(message)
237
+ data = {
238
+ '$token' => @token,
239
+ '$time' => ((Time.now.to_f) * 1000.0).to_i
240
+ }.merge(message)
241
+
242
+ message = {
243
+ 'data' => data
244
+ }
245
+
246
+ @sink.call(:profile_update, message.to_json)
247
+ end
248
+
249
+ private
250
+
251
+ def fix_property_dates(h)
252
+ h.inject({}) do |ret,(k,v)|
253
+ ret[k] = v.respond_to?(:strftime) ? v.strftime('%Y-%m-%dT%H:%M:%S') : v
254
+ ret
255
+ end
256
+ end
257
+ end
258
+ end
@@ -0,0 +1,137 @@
1
+ require 'mixpanel-ruby/events.rb'
2
+ require 'mixpanel-ruby/people.rb'
3
+
4
+ module Mixpanel
5
+ # Use Mixpanel::Tracker to track events and profile updates in your application.
6
+ # To track an event, call
7
+ #
8
+ # tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
9
+ # Mixpanel::Tracker.track(a_distinct_id, an_event_name, {properties})
10
+ #
11
+ # To send people updates, call
12
+ #
13
+ # tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
14
+ # tracker.people.set(a_distinct_id, {properties})
15
+ #
16
+ # You can find your project token in the settings dialog for your
17
+ # project, inside of the Mixpanel web application.
18
+ #
19
+ # Mixpanel::Tracker is a subclass of Mixpanel::Events, and exposes
20
+ # an instance of Mixpanel::People as Tracker#people
21
+ class Tracker < Events
22
+ # An instance of Mixpanel::People. Use this to
23
+ # send profile updates
24
+ attr_reader :people
25
+
26
+ # Takes your Mixpanel project token, as a string.
27
+ #
28
+ # tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN)
29
+ #
30
+ # By default, the tracker will send an message to Mixpanel
31
+ # synchronously with each call, using an instance of Mixpanel::Consumer.
32
+ #
33
+ # You can also provide a block to the constructor
34
+ # to specify particular consumer behaviors (for
35
+ # example, if you wanted to write your messages to
36
+ # a queue instead of sending them directly to Mixpanel)
37
+ #
38
+ # tracker = Mixpanel::Tracker.new(YOUR_MIXPANEL_TOKEN) do |type, message|
39
+ # @kestrel.set(MY_MIXPANEL_QUEUE, [type,message].to_json)
40
+ # end
41
+ #
42
+ # If a block is provided, it is passed a type (one of :event or :profile_update)
43
+ # and a string message. This same format is accepted by Mixpanel::Consumer#send
44
+ # and Mixpanel::BufferedConsumer#send
45
+ def initialize(token, &block)
46
+ super(token, &block)
47
+ @token = token
48
+ @people = People.new(token, &block)
49
+ end
50
+
51
+ # A call to #track is a report that an event has occurred. #track
52
+ # takes a distinct_id representing the source of that event (for
53
+ # example, a user id), an event name describing the event, and a
54
+ # set of properties describing that event. Properties are provided
55
+ # as a Hash with string keys and strings, numbers or booleans as
56
+ # values.
57
+ #
58
+ # tracker = Mixpanel::Tracker.new
59
+ #
60
+ # # Track that user "12345"'s credit card was declined
61
+ # tracker.track("12345", "Credit Card Declined")
62
+ #
63
+ # # Properties describe the circumstances of the event,
64
+ # # or aspects of the source or user associated with the event
65
+ # tracker.track("12345", "Welcome Email Sent", {
66
+ # 'Email Template' => 'Pretty Pink Welcome',
67
+ # 'User Sign-up Cohort' => 'July 2013'
68
+ # })
69
+ #
70
+ # Optionallly, #track can be used to generate a pixel tracking url
71
+ # by setting "as_pixel" to true. In this case, a call to #track will not
72
+ # report the event, but instead return the string representation of a URL
73
+ # that will report the event when requested. For more information, see:
74
+ # https://mixpanel.com/docs/api-documentation/pixel-based-event-tracking
75
+
76
+ def track(distinct_id, event, properties={}, ip=nil, as_pixel=nil)
77
+ # This is here strictly to allow rdoc to include the relevant
78
+ # documentation
79
+ super
80
+ end
81
+
82
+ # A call to #import is to import an event occurred in the past. #import
83
+ # takes a distinct_id representing the source of that event (for
84
+ # example, a user id), an event name describing the event, and a
85
+ # set of properties describing that event. Properties are provided
86
+ # as a Hash with string keys and strings, numbers or booleans as
87
+ # values.
88
+ #
89
+ # tracker = Mixpanel::Tracker.new
90
+ #
91
+ # # Import event that user "12345"'s credit card was declined
92
+ # tracker.import("12345", "Credit Card Declined", {
93
+ # 'time' => 1310111365
94
+ # })
95
+ #
96
+ # # Properties describe the circumstances of the event,
97
+ # # or aspects of the source or user associated with the event
98
+ # tracker.import("API_KEY", "12345", "Welcome Email Sent", {
99
+ # 'Email Template' => 'Pretty Pink Welcome',
100
+ # 'User Sign-up Cohort' => 'July 2013',
101
+ # 'time' => 1310111365
102
+ # })
103
+ def import(api_key, distinct_id, event, properties={}, ip=nil)
104
+ # This is here strictly to allow rdoc to include the relevant
105
+ # documentation
106
+ super
107
+ end
108
+
109
+ # Creates a distinct_id alias. \Events and updates with an alias
110
+ # will be considered by mixpanel to have the same source, and
111
+ # refer to the same profile.
112
+ #
113
+ # Multiple aliases can map to the same real_id, once a real_id is
114
+ # used to track events or send updates, it should never be used as
115
+ # an alias itself.
116
+ #
117
+ # Alias requests are always sent synchronously, directly to
118
+ # the \Mixpanel service, regardless of how the tracker is configured.
119
+ def alias(alias_id, real_id, events_endpoint=nil)
120
+ consumer = Mixpanel::Consumer.new(events_endpoint)
121
+ data = {
122
+ 'event' => '$create_alias',
123
+ 'properties' => {
124
+ 'distinct_id' => real_id,
125
+ 'alias' => alias_id,
126
+ 'token' => @token
127
+ }
128
+ }
129
+
130
+ message = {
131
+ 'data' => data
132
+ }
133
+
134
+ consumer.send(:event, message.to_json)
135
+ end
136
+ end
137
+ end