mixpal 0.0.5 → 0.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.
- checksums.yaml +5 -5
- data/.rubocop.yml +24 -0
- data/.travis.yml +7 -0
- data/Dockerfile +6 -0
- data/README.md +51 -11
- data/Rakefile +10 -1
- data/docker-compose.yml +14 -0
- data/lib/mixpal.rb +27 -7
- data/lib/mixpal/event.rb +4 -4
- data/lib/mixpal/integration.rb +12 -8
- data/lib/mixpal/revenue.rb +32 -0
- data/lib/mixpal/tracker.rb +44 -27
- data/lib/mixpal/user.rb +9 -7
- data/lib/mixpal/util.rb +3 -3
- data/lib/mixpal/version.rb +1 -1
- data/mixpanel_assistant.gemspec +8 -7
- data/spec/lib/mixpal/event_spec.rb +20 -18
- data/spec/lib/mixpal/revenue_spec.rb +60 -0
- data/spec/lib/mixpal/tracker_spec.rb +181 -153
- data/spec/lib/mixpal/user_spec.rb +37 -31
- data/spec/lib/mixpal/util_spec.rb +15 -14
- data/spec/lib/mixpal_spec.rb +13 -2
- data/spec/spec_helper.rb +4 -7
- data/spec/support/custom_events_module.rb +5 -0
- data/spec/support/matchers/element_matchers.rb +2 -2
- data/test_app/.gitignore +18 -0
- data/test_app/Gemfile +11 -0
- data/test_app/README.rdoc +28 -0
- data/test_app/Rakefile +6 -0
- data/test_app/app/assets/images/.keep +0 -0
- data/test_app/app/assets/javascripts/application.js +16 -0
- data/test_app/app/assets/stylesheets/application.css +15 -0
- data/test_app/app/controllers/application_controller.rb +12 -0
- data/test_app/app/controllers/concerns/.keep +0 -0
- data/test_app/app/controllers/redirects_controller.rb +10 -0
- data/test_app/app/helpers/application_helper.rb +2 -0
- data/test_app/app/mailers/.keep +0 -0
- data/test_app/app/models/.keep +0 -0
- data/test_app/app/models/concerns/.keep +0 -0
- data/test_app/app/views/layouts/application.html.erb +16 -0
- data/test_app/app/views/redirects/new.html.erb +1 -0
- data/test_app/bin/bundle +3 -0
- data/test_app/bin/rails +8 -0
- data/test_app/bin/rake +8 -0
- data/test_app/bin/spring +18 -0
- data/test_app/config.ru +4 -0
- data/test_app/config/application.rb +30 -0
- data/test_app/config/boot.rb +4 -0
- data/test_app/config/environment.rb +5 -0
- data/test_app/config/environments/development.rb +37 -0
- data/test_app/config/environments/production.rb +82 -0
- data/test_app/config/environments/test.rb +39 -0
- data/test_app/config/initializers/assets.rb +8 -0
- data/test_app/config/initializers/backtrace_silencers.rb +7 -0
- data/test_app/config/initializers/cookies_serializer.rb +3 -0
- data/test_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/test_app/config/initializers/inflections.rb +16 -0
- data/test_app/config/initializers/mime_types.rb +4 -0
- data/test_app/config/initializers/session_store.rb +3 -0
- data/test_app/config/initializers/wrap_parameters.rb +14 -0
- data/test_app/config/locales/en.yml +23 -0
- data/test_app/config/routes.rb +4 -0
- data/test_app/config/secrets.yml +22 -0
- data/test_app/db/seeds.rb +7 -0
- data/test_app/lib/assets/.keep +0 -0
- data/test_app/lib/tasks/.keep +0 -0
- data/test_app/log/.keep +0 -0
- data/test_app/public/404.html +67 -0
- data/test_app/public/422.html +67 -0
- data/test_app/public/500.html +66 -0
- data/test_app/public/favicon.ico +0 -0
- data/test_app/public/robots.txt +5 -0
- data/test_app/vendor/assets/javascripts/.keep +0 -0
- data/test_app/vendor/assets/stylesheets/.keep +0 -0
- metadata +112 -44
- data/spec/support/mock_rails.rb +0 -6
- data/spec/support/mock_storage.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 70923329c62f76ee4d6b0796547cdd2e367038940c30d8f5ccb10b044f506d36
|
4
|
+
data.tar.gz: 492801097fa1ac2fb85f4600273b2db3fc6e0e8383c9b17112e0302100fc9020
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8dbd5bd3051e8edf9ab7b130c0cd6a5af876d52c8fb6992e82c4ae3b22b58eeb726591bffc67368c9cc3c40e60faa2a1f5d5090a3392fe5fc96f374dde1af6e
|
7
|
+
data.tar.gz: e32c5e8e487ea31dc875df217e26f962c634978cd07b1d036b97a10f3e7eaa0fb8d446b0e8c00d89c4a5eacce591012400d01e3b541bd98238114a4ea1785aaf
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
Encoding:
|
2
|
+
Enabled: false
|
3
|
+
|
4
|
+
Documentation:
|
5
|
+
Enabled: false
|
6
|
+
|
7
|
+
ClassAndModuleChildren:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
ClassLength:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
MethodLength:
|
14
|
+
Enabled: false
|
15
|
+
|
16
|
+
DoubleNegation:
|
17
|
+
Enabled: false
|
18
|
+
|
19
|
+
AllCops:
|
20
|
+
NewCops: enable
|
21
|
+
Include:
|
22
|
+
- "Rakefile"
|
23
|
+
Exclude:
|
24
|
+
- "test_app/**/*"
|
data/.travis.yml
ADDED
data/Dockerfile
ADDED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Mixpal
|
1
|
+
# Mixpal [](https://travis-ci.org/philosophie/mixpal)
|
2
2
|
|
3
3
|
As the JavaScript library is Mixpanel's preferred method of usage,
|
4
4
|
Mixpal aims to make it easier to work with from your Rails backend.
|
@@ -78,9 +78,41 @@ mixpanel.update_user email: "mynewemail@example.com"
|
|
78
78
|
|
79
79
|
As with `register_user`, this method will also identify "special properties".
|
80
80
|
|
81
|
+
### Custom Events
|
82
|
+
|
83
|
+
Mixpal allows you to define custom mixpal methods to use in your controllers/views
|
84
|
+
|
85
|
+
1. create a custom module and define your mixpal events
|
86
|
+
```ruby
|
87
|
+
module YourCustomEventsModule
|
88
|
+
def sign_up(user)
|
89
|
+
register_user user.attributes.slice('name', 'email')
|
90
|
+
track 'User signed up'
|
91
|
+
end
|
92
|
+
end
|
93
|
+
```
|
94
|
+
|
95
|
+
2. create a mixpal.rb initializer and configure mixpal to use your module
|
96
|
+
```ruby
|
97
|
+
Mixpal.configure do |config|
|
98
|
+
config.helper_module = YourCustomEventsModule
|
99
|
+
end
|
100
|
+
```
|
101
|
+
|
102
|
+
3. use in controllers/views
|
103
|
+
```ruby
|
104
|
+
class UserController < ActionController::Base
|
105
|
+
def create
|
106
|
+
# ... do cool stuff ...
|
107
|
+
mixpal.sign_up(user)
|
108
|
+
redirect_to root_path
|
109
|
+
end
|
110
|
+
end
|
111
|
+
```
|
112
|
+
|
81
113
|
### Persistance Across Redirects
|
82
114
|
|
83
|
-
Mixpal stores any tracked events or user data in
|
115
|
+
Mixpal stores any tracked events or user data in the session when
|
84
116
|
it detects a redirect so it can output the appropriate Mixpanel JS integration
|
85
117
|
code to the client on the following render. This enables us to do cool things
|
86
118
|
like:
|
@@ -104,16 +136,12 @@ class UsersController < ActionController::Base
|
|
104
136
|
end
|
105
137
|
```
|
106
138
|
|
107
|
-
####
|
108
|
-
|
109
|
-
You can specify a custom persistence storage adapter like so:
|
110
|
-
|
111
|
-
```ruby
|
112
|
-
Mixpal::Tracker.storage = MyCustomAdapter.new
|
113
|
-
```
|
139
|
+
#### A note about `CookieStore` size limit
|
114
140
|
|
115
|
-
|
116
|
-
|
141
|
+
When using Rails' default `ActionDispatch::Session::CookieStore`, a 4K cookie
|
142
|
+
size limit is enforced. This cookie is shared by anything using the session.
|
143
|
+
If you anticipate tracking many events or large data sets to Mixpal,
|
144
|
+
[consider a different session store](http://guides.rubyonrails.org/action_controller_overview.html#session).
|
117
145
|
|
118
146
|
## Contributing
|
119
147
|
|
@@ -124,3 +152,15 @@ Storage adapters must implement the following API: `write(key, value)`,
|
|
124
152
|
1. Commit your changes (`git commit -am 'Add some feature'`)
|
125
153
|
1. Push to the branch (`git push origin feature/my-new-feature`)
|
126
154
|
1. Create new Pull Request
|
155
|
+
|
156
|
+
## Releasing
|
157
|
+
|
158
|
+
Bump `lib/mixpal/version.rb` then build + release with docker-compose. If you
|
159
|
+
prefer local development, inspect the Dockerfile to get your local env built.
|
160
|
+
|
161
|
+
```
|
162
|
+
docker-compose build \
|
163
|
+
--build-arg USER_ID=$(id -u) \
|
164
|
+
--build-arg GROUP_ID=$(id -g)
|
165
|
+
docker-compose run rake release
|
166
|
+
```
|
data/Rakefile
CHANGED
data/docker-compose.yml
ADDED
data/lib/mixpal.rb
CHANGED
@@ -1,10 +1,30 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require 'mixpal/version'
|
2
|
+
require 'active_support'
|
3
|
+
require 'active_support/core_ext'
|
3
4
|
|
4
5
|
module Mixpal
|
5
|
-
autoload :Util,
|
6
|
-
autoload :Tracker,
|
7
|
-
autoload :Event,
|
8
|
-
autoload :User,
|
9
|
-
autoload :
|
6
|
+
autoload :Util, 'mixpal/util'
|
7
|
+
autoload :Tracker, 'mixpal/tracker'
|
8
|
+
autoload :Event, 'mixpal/event'
|
9
|
+
autoload :User, 'mixpal/user'
|
10
|
+
autoload :Revenue, 'mixpal/revenue'
|
11
|
+
autoload :Integration, 'mixpal/integration'
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def configuration
|
15
|
+
@configuration ||= Configuration.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def configure
|
19
|
+
yield(configuration)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class Configuration
|
24
|
+
attr_writer :helper_module
|
25
|
+
|
26
|
+
def helper_module
|
27
|
+
@helper_module ||= Module.new
|
28
|
+
end
|
29
|
+
end
|
10
30
|
end
|
data/lib/mixpal/event.rb
CHANGED
@@ -14,13 +14,13 @@ module Mixpal
|
|
14
14
|
|
15
15
|
def to_store
|
16
16
|
{
|
17
|
-
name
|
18
|
-
properties
|
17
|
+
'name' => name,
|
18
|
+
'properties' => properties
|
19
19
|
}
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.from_store(data)
|
23
|
-
new(data[
|
23
|
+
new(data['name'], data['properties'])
|
24
24
|
end
|
25
25
|
end
|
26
|
-
end
|
26
|
+
end
|
data/lib/mixpal/integration.rb
CHANGED
@@ -4,31 +4,35 @@ module Mixpal
|
|
4
4
|
|
5
5
|
included do
|
6
6
|
helper_method :mixpanel
|
7
|
-
|
7
|
+
if Rails::VERSION::MAJOR >= 4
|
8
|
+
after_action :store_mixpanel_if_redirecting
|
9
|
+
else
|
10
|
+
after_filter :store_mixpanel_if_redirecting
|
11
|
+
end
|
8
12
|
|
9
13
|
class_attribute :mixpanel_identity_data
|
10
14
|
def self.mixpanel_identity(object_method, attribute_method)
|
11
15
|
self.mixpanel_identity_data = {
|
12
16
|
object_method: object_method,
|
13
|
-
attribute_method: attribute_method
|
17
|
+
attribute_method: attribute_method
|
14
18
|
}
|
15
19
|
end
|
16
20
|
end
|
17
21
|
|
18
22
|
def mixpanel
|
19
23
|
@mixpanel ||= begin
|
20
|
-
identity = if data = self.class.mixpanel_identity_data
|
21
|
-
|
22
|
-
|
24
|
+
identity = if (data = self.class.mixpanel_identity_data)
|
25
|
+
send(data[:object_method]).try(data[:attribute_method])
|
26
|
+
end
|
23
27
|
|
24
|
-
Mixpal::Tracker.new(identity: identity)
|
28
|
+
Mixpal::Tracker.new(identity: identity).tap { |t| t.restore!(session) }
|
25
29
|
end
|
26
30
|
end
|
27
31
|
|
28
32
|
private
|
29
33
|
|
30
34
|
def store_mixpanel_if_redirecting
|
31
|
-
mixpanel.store! if status == 302
|
35
|
+
mixpanel.store!(session) if status == 302
|
32
36
|
end
|
33
37
|
end
|
34
|
-
end
|
38
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Mixpal
|
2
|
+
class Revenue
|
3
|
+
attr_reader :amount, :properties
|
4
|
+
|
5
|
+
def initialize(amount, properties)
|
6
|
+
@amount = amount
|
7
|
+
@properties = properties
|
8
|
+
end
|
9
|
+
|
10
|
+
def render
|
11
|
+
args = "#{amount}, #{properties_as_js_object_for_mixpanel}"
|
12
|
+
"mixpanel.people.track_charge(#{args});".html_safe
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_store
|
16
|
+
{
|
17
|
+
'amount' => amount,
|
18
|
+
'properties' => properties
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.from_store(data)
|
23
|
+
new(data['amount'], data['properties'])
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def properties_as_js_object_for_mixpanel
|
29
|
+
Mixpal::Util.hash_to_js_object_string(properties)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/mixpal/tracker.rb
CHANGED
@@ -1,16 +1,15 @@
|
|
1
1
|
module Mixpal
|
2
2
|
class Tracker
|
3
|
-
attr_reader :events, :user_updates, :identity, :alias_user
|
3
|
+
attr_reader :events, :user_updates, :revenue_updates, :identity, :alias_user
|
4
4
|
|
5
|
-
STORAGE_KEY =
|
6
|
-
|
7
|
-
|
5
|
+
STORAGE_KEY = 'mixpal'
|
6
|
+
|
7
|
+
def initialize(args = {})
|
8
|
+
extend Mixpal.configuration.helper_module
|
8
9
|
|
9
|
-
def initialize(args={})
|
10
10
|
@events = []
|
11
11
|
@user_updates = []
|
12
|
-
|
13
|
-
restore!
|
12
|
+
@revenue_updates = []
|
14
13
|
|
15
14
|
@identity = args[:identity]
|
16
15
|
end
|
@@ -24,44 +23,62 @@ module Mixpal
|
|
24
23
|
user_updates << Mixpal::User.new(properties)
|
25
24
|
end
|
26
25
|
|
27
|
-
def track(name, properties={})
|
26
|
+
def track(name, properties = {})
|
28
27
|
events << Mixpal::Event.new(name, properties)
|
29
28
|
end
|
30
29
|
|
30
|
+
def track_charge(amount, properties = {})
|
31
|
+
revenue_updates << Mixpal::Revenue.new(amount, properties)
|
32
|
+
end
|
33
|
+
|
31
34
|
def render
|
32
|
-
|
33
|
-
html <<
|
35
|
+
''.tap do |html|
|
36
|
+
html << '<script type="text/javascript">'
|
34
37
|
html << "mixpanel.alias(\"#{identity}\");" if alias_user
|
35
38
|
html << "mixpanel.identify(\"#{identity}\");" if identity
|
36
|
-
html << events.map(&:render).join(
|
37
|
-
html << user_updates.map(&:render).join(
|
38
|
-
html <<
|
39
|
+
html << events.map(&:render).join('')
|
40
|
+
html << user_updates.map(&:render).join('')
|
41
|
+
html << revenue_updates.map(&:render).join('')
|
42
|
+
html << '</script>'
|
39
43
|
end.html_safe
|
40
44
|
end
|
41
45
|
|
42
|
-
def store!
|
43
|
-
|
46
|
+
def store!(session)
|
47
|
+
session[STORAGE_KEY] = to_store
|
44
48
|
end
|
45
49
|
|
46
|
-
|
50
|
+
def restore!(session)
|
51
|
+
data = session[STORAGE_KEY] || {}
|
47
52
|
|
48
|
-
|
49
|
-
|
53
|
+
@alias_user = data['alias_user']
|
54
|
+
@identity ||= data['identity']
|
50
55
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
@user_updates = data[:user_updates].map { |u| Mixpal::User.from_store(u) } if data[:user_updates]
|
56
|
+
if data['events']
|
57
|
+
@events = data['events'].map { |e| Mixpal::Event.from_store(e) }
|
58
|
+
end
|
55
59
|
|
56
|
-
|
60
|
+
if data['user_updates']
|
61
|
+
@user_updates =
|
62
|
+
data['user_updates'].map { |u| Mixpal::User.from_store(u) }
|
63
|
+
end
|
64
|
+
|
65
|
+
if data['revenue_updates']
|
66
|
+
@revenue_updates =
|
67
|
+
data['revenue_updates'].map { |u| Mixpal::Revenue.from_store(u) }
|
68
|
+
end
|
69
|
+
|
70
|
+
session.delete(STORAGE_KEY)
|
57
71
|
end
|
58
72
|
|
73
|
+
private
|
74
|
+
|
59
75
|
def to_store
|
60
76
|
{
|
61
|
-
alias_user
|
62
|
-
identity
|
63
|
-
events
|
64
|
-
user_updates
|
77
|
+
'alias_user' => alias_user,
|
78
|
+
'identity' => identity,
|
79
|
+
'events' => events.map(&:to_store),
|
80
|
+
'user_updates' => user_updates.map(&:to_store),
|
81
|
+
'revenue_updates' => revenue_updates.map(&:to_store)
|
65
82
|
}
|
66
83
|
end
|
67
84
|
end
|
data/lib/mixpal/user.rb
CHANGED
@@ -12,12 +12,12 @@ module Mixpal
|
|
12
12
|
|
13
13
|
def to_store
|
14
14
|
{
|
15
|
-
properties
|
15
|
+
'properties' => properties
|
16
16
|
}
|
17
17
|
end
|
18
18
|
|
19
19
|
def self.from_store(data)
|
20
|
-
new(data[
|
20
|
+
new(data['properties'])
|
21
21
|
end
|
22
22
|
|
23
23
|
private
|
@@ -29,15 +29,17 @@ module Mixpal
|
|
29
29
|
# Isolate special properties and rename their keys to align with
|
30
30
|
# Mixpanel's naming.
|
31
31
|
def properties_for_mixpanel
|
32
|
-
Hash[
|
32
|
+
Hash[
|
33
|
+
properties.map { |k, v| [mixpanel_special_properties_map[k] || k, v] }
|
34
|
+
]
|
33
35
|
end
|
34
36
|
|
35
37
|
def mixpanel_special_properties_map
|
36
38
|
{
|
37
|
-
name:
|
38
|
-
email:
|
39
|
-
created_at:
|
39
|
+
name: '$name',
|
40
|
+
email: '$email',
|
41
|
+
created_at: '$created'
|
40
42
|
}.with_indifferent_access
|
41
43
|
end
|
42
44
|
end
|
43
|
-
end
|
45
|
+
end
|