pushpop-mixpanel 0.1.1

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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a8d3ba15e9deadfad48828151d9125ce21ba2c22
4
+ data.tar.gz: 7445263059c8d122ffc90f223d81acffd97cfecf
5
+ SHA512:
6
+ metadata.gz: 3a2215952a98ba15628eab98749cc40be9e27d709302b5af2f4f6fff4badd9168af0123e9b8dd3091542c0a03498e57d4fa8826a5723eb81f7782cf3b58cdd28
7
+ data.tar.gz: 3ecff53f78ff4c6e450d4868ef713ade684633f6d16dceb399e7191e17eaff264917e9de711d897d52ffb65f8d34d250b296d24c2cbabc07afa5039ed820d3a4
@@ -0,0 +1 @@
1
+ Gemfile.lock
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ bundler_args: --without development
3
+
4
+ rvm:
5
+ - 2.1.1
6
+
7
+ script:
8
+ - bundle exec rake spec
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'pushpop'
4
+ gem 'mixpanel-ruby', '~>2.1.0'
5
+
6
+ group :development, :test do
7
+ gem 'rake'
8
+ gem 'rspec'
9
+ end
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ Author Joe Wegner
2
+ Copyright (c) 2015 Keen Labs
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining
5
+ a copy of this software and associated documentation files (the
6
+ "Software"), to deal in the Software without restriction, including
7
+ without limitation the rights to use, copy, modify, merge, publish,
8
+ distribute, sublicense, and/or sell copies of the Software, and to
9
+ permit persons to whom the Software is furnished to do so, subject to
10
+ the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,141 @@
1
+ # pushpop-mixpanel
2
+
3
+ Mixpanel plugin for [Pushpop](https://github.com/pushpop-project/pushpop).
4
+
5
+ - [Installation](#installation)
6
+ - [Usage](#usage)
7
+ - [Global Functions](#global-functions)
8
+ - [Tracking Functions](#tracking-functions)
9
+ - [User Functions](#user-functions)
10
+ - [Analysis Functions](#analysis-functions)
11
+ - [Contributing](#contributing)
12
+
13
+ ## Installation
14
+
15
+ Add `pushpop-mixpanel` to your Gemfile:
16
+
17
+ ```ruby
18
+ gem 'pushpop-mixpanel'
19
+ ```
20
+
21
+ or install it as a gem
22
+
23
+ ```bash
24
+ $ gem install pushpop-mixpanel
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ The mixpanel plugin gives you a simple interface for tracking information to Mixpanel. You can very simply do all sorts of things with Mixpanel, including creating/deleting users, updating their properties, tracking events, or deleting users altogether.
30
+
31
+ Here's a quick preview of what a mixpanel job might do
32
+
33
+ ``` ruby
34
+
35
+ job 'track support users in mixpanel' do
36
+
37
+ step 'receive users' do
38
+ # Pretend that this step checks for new support emails,
39
+ # and looks up some information based on that email
40
+ end
41
+
42
+ mixpanel do |response|
43
+ # Set the user you want to interact with
44
+ user response.email
45
+
46
+ # Update the user with some basic information
47
+ set({
48
+ name: response.name,
49
+ age: response.age
50
+ })
51
+
52
+ # Increment the support request count
53
+ # Values that aren't currently set will be treated as 0, and then incremented
54
+ increment({support_requests: 1})
55
+
56
+ # Track a charge of $10 (your support fee)
57
+ charge(10, {type: 'support charge'})
58
+ end
59
+ end
60
+ ```
61
+
62
+ In order to track things with `pushpop-mixpanel` you will need to drop your project token in the `MIXPANEL_PROJECT_TOKEN` environment variable.
63
+
64
+ ### Global Functions
65
+
66
+ **user(id, [properties])**
67
+
68
+ This sets the user context for the rest of the step. All functions run after this will be run with the user `id` specified here. If this user does not already exist in Mixpanel, it will be created.
69
+
70
+ You can also pass in a hash of `properties` that will be set on the user. If the user already exists, the values in `properties` **will overwrite** existing properties.
71
+
72
+ ### Tracking Functions
73
+
74
+ **track(name, [properties])**
75
+
76
+ This will track an event for the currently set user. You can optionally pass in a hash of metadata for this event.
77
+
78
+ ### User Functions
79
+
80
+ **set(properties)**
81
+
82
+ Accepts a hash of properties that should be set for the current user. Any properties that already exist on that user will be overwritten by the new values in the hash.
83
+
84
+ **create_alias(new_id, previous_id)**
85
+
86
+ Creates a user id alias inside of Mixpanel. Any events/updates made with either `new_id` or `previous_id` going forward will now affect the same user inside of Mixpanel.
87
+
88
+ _This will also update the current user context to be `new_id`._
89
+
90
+ **increment(properties)**
91
+
92
+ This will increment/decrement numeric properties based on the values provided in the hash. For example:
93
+
94
+ ``` ruby
95
+ increment({
96
+ support_tickets: 1, # Increase ticket count by 1
97
+ available_balance: -10 # Decrease balance by 10
98
+ })
99
+ ```
100
+
101
+ Incrementing properties that don't currently exist on the user will preset the property to 0, and then do the increment. So incrementing a new property by `10` will set that property to `10`.
102
+
103
+ **append(properties)**
104
+
105
+ This will push a value on to the end of a list property. For instance, say your user currently has a property, `{devices: ['android']}`. Then you ran:
106
+
107
+ ``` ruby
108
+ append({
109
+ devices: 'Mac'
110
+ })
111
+ ```
112
+
113
+ Their `devices` property would now be `['android', 'Mac']`.
114
+
115
+ **charge(amount, [properties])**
116
+
117
+ This will add a charge associated with the current user. `amount` should be a dollar value. You can optionally pass in a hash of `properties` that describe the charge.
118
+
119
+ **delete([ignore_alias])**
120
+
121
+ This deletes the current user from Mixpanel. **This is a destructive action, and cannot be undone**.
122
+
123
+ To delete a user and ignore alias, pass `true` in to this function.
124
+
125
+ ### Analysis Functions
126
+
127
+ For now we are just using [mixpanel_client](https://github.com/keolo/mixpanel_client) internally, so the syntax for doing analysis queries pretty directly matches that. Check out that README for details, but a basic query might look like:
128
+
129
+ ``` ruby
130
+ mixpanel do
131
+ query 'events/properties',
132
+ event: 'Support Ticket',
133
+ type: 'unique',
134
+ unit: 'day',
135
+ interval: 5
136
+ end
137
+ ```
138
+
139
+ ## Contributing
140
+
141
+ Code and documentation issues and pull requests are definitely welcome!
@@ -0,0 +1,16 @@
1
+ $stdout.sync = true
2
+
3
+ $: << File.join(File.dirname(__FILE__), './lib')
4
+
5
+ begin
6
+ require 'rspec/core/rake_task'
7
+ desc 'Run Rspec unit tests'
8
+ RSpec::Core::RakeTask.new(:spec) do |t|
9
+ t.pattern = 'spec/**/*_spec.rb'
10
+ end
11
+
12
+ task default: :spec
13
+ rescue LoadError
14
+ end
15
+
16
+
@@ -0,0 +1,144 @@
1
+ require 'pushpop'
2
+ require 'mixpanel-ruby'
3
+ require 'mixpanel_client'
4
+
5
+ module Pushpop
6
+
7
+ class Mixpanel < Step
8
+
9
+ PLUGIN_NAME = 'mixpanel'
10
+
11
+ Pushpop::Job.register_plugin(PLUGIN_NAME, self)
12
+
13
+ attr_accessor :_user
14
+ attr_accessor :_endpoint
15
+ attr_accessor :_query_properties
16
+ attr_accessor :_user_created
17
+
18
+ ## Setup Functions
19
+
20
+ def run(last_response=nil, step_responses=nil)
21
+ ret = self.configure(last_response, step_responses)
22
+
23
+ unless self._user_created || self._user.nil?
24
+ set({})
25
+ end
26
+
27
+ if self._endpoint
28
+ Pushpop::Mixpanel.querent.request(self._endpoint, self._query_properties)
29
+ else
30
+ ret
31
+ end
32
+ end
33
+
34
+ def configure(last_response=nil, step_responses=nil)
35
+ self.instance_exec(last_response, step_responses, &block)
36
+ end
37
+
38
+ def user(id, properties = nil)
39
+ self._user = id
40
+
41
+ if properties.nil?
42
+ self._user_created = false
43
+ else
44
+ self._user_created = true
45
+ Pushpop::Mixpanel.tracker.people.set(id, properties)
46
+ end
47
+ end
48
+
49
+ ### Querying Functions
50
+
51
+ def query(endpoint, properties = {})
52
+ self._endpoint = endpoint
53
+ self._query_properties = properties
54
+ end
55
+
56
+ ## Tracking Functions
57
+
58
+ def track(name, properties = nil)
59
+ raise 'You have to set the user before tracking mixpanel events' unless self._user
60
+
61
+ if properties.nil?
62
+ Pushpop::Mixpanel.tracker.track(self._user, name)
63
+ else
64
+ Pushpop::Mixpanel.tracker.track(self._user, name, properties)
65
+ end
66
+ end
67
+
68
+ ## User Functions
69
+
70
+ def set(properties)
71
+ raise 'You have to set the user before updating properties' unless self._user
72
+ self._user_created = true
73
+
74
+ Pushpop::Mixpanel.tracker.people.set(self._user, properties)
75
+ end
76
+
77
+ def create_alias(new_id, previous_id)
78
+ Pushpop::Mixpanel.tracker.alias(new_id, previous_id)
79
+ self._user = new_id
80
+ end
81
+
82
+ def increment(properties)
83
+ raise 'You have to set the user before incrementing' unless self._user
84
+ Pushpop::Mixpanel.tracker.people.increment(self._user, properties)
85
+ end
86
+
87
+ def append(properties)
88
+ raise 'You have to set the user before appending proeprties to it' unless self._user
89
+ Pushpop::Mixpanel.tracker.people.append(self._user, properties)
90
+ end
91
+
92
+ def charge(amount, properties = nil)
93
+ raise 'You have to set the user before charging them' unless self._user
94
+
95
+ if properties.nil?
96
+ Pushpop::Mixpanel.tracker.people.track_charge(self._user, amount)
97
+ else
98
+ Pushpop::Mixpanel.tracker.people.track_charge(self._user, amount, properties)
99
+ end
100
+ end
101
+
102
+ def delete(ignore_alias = false)
103
+ raise 'You have to set the user to delete' unless self._user
104
+
105
+ if ignore_alias
106
+ Pushpop::Mixpanel.tracker.people.delete_user(self._user, {"$ignore_alias" => true})
107
+ else
108
+ Pushpop::Mixpanel.tracker.people.delete_user(self._user)
109
+ end
110
+ end
111
+
112
+
113
+ class << self
114
+ def tracker
115
+ if @tracker
116
+ @tracker
117
+ else
118
+ if !ENV['MIXPANEL_PROJECT_TOKEN'].nil? && !ENV['MIXPANEL_PROJECT_TOKEN'].empty?
119
+ @tracker = ::Mixpanel::Tracker.new(ENV['MIXPANEL_PROJECT_TOKEN'])
120
+ else
121
+ raise 'You must provide a mixpanel project token'
122
+ end
123
+ end
124
+ end
125
+
126
+ def querent
127
+ if @querent
128
+ @querent
129
+ else
130
+ if ENV['MIXPANEL_API_KEY'].nil? || ENV['MIXPANEL_API_KEY'].empty?
131
+ raise 'You must provide a mixpanel api key'
132
+ elsif ENV['MIXPANEL_API_SECRET'].nil? || ENV['MIXPANEL_API_SECRET'].empty?
133
+ raise 'Ypu must provide a mixpanel api secret'
134
+ else
135
+ @querent = ::Mixpanel::Client.new(
136
+ api_key: ENV['MIXPANEL_API_KEY'],
137
+ api_secret: ENV['MIXPANEL_API_SECRET']
138
+ )
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+
6
+ s.name = "pushpop-mixpanel"
7
+ s.version = '0.1.1'
8
+ s.authors = ["Joe Wegner"]
9
+ s.email = "joe@keen.io"
10
+ s.homepage = "https://github.com/pushpop-project/pushpop-mixpanel"
11
+ s.summary = "Pushpop Mixpanel plugin for querying and recording events"
12
+
13
+ s.add_dependency "pushpop"
14
+ s.add_dependency "mixpanel-ruby", '~>2.1.0'
15
+ s.add_dependency "mixpanel_client"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ end
22
+
@@ -0,0 +1,213 @@
1
+ require 'spec_helper'
2
+
3
+ ENV['MIXPANEL_PROJECT_TOKEN'] = '0987654321'
4
+ ENV['MIXPANEL_API_KEY'] = '0987654321'
5
+ ENV['MIXPANEL_API_SECRET'] = '0987654321'
6
+
7
+ describe Pushpop::Mixpanel do
8
+ describe 'track' do
9
+ it 'tracks events' do
10
+ step = Pushpop::Mixpanel.new do
11
+ user '12345'
12
+ track 'An Event'
13
+ end
14
+
15
+ expect(Pushpop::Mixpanel.tracker).to receive(:track).with('12345', 'An Event')
16
+ step.run
17
+ end
18
+
19
+ it 'tracks events with properties' do
20
+ step = Pushpop::Mixpanel.new do
21
+ user '12345'
22
+ track 'An Event', {browser: 'Chrome'}
23
+ end
24
+
25
+ expect(Pushpop::Mixpanel.tracker).to receive(:track).with('12345', 'An Event', {
26
+ browser: 'Chrome'
27
+ })
28
+ step.run
29
+ end
30
+
31
+ it 'raises an error if the user is not set' do
32
+ step = Pushpop::Mixpanel.new do
33
+ track 'An Event'
34
+ end
35
+
36
+ expect{step.run}.to raise_error
37
+ end
38
+ end
39
+
40
+ describe 'query' do
41
+ it 'performs queries to an endpoint' do
42
+ step = Pushpop::Mixpanel.new do
43
+ query 'a/thing'
44
+ end
45
+
46
+ expect(Pushpop::Mixpanel.querent).to receive(:request).with('a/thing', {})
47
+ step.run
48
+ expect(step._endpoint).to eq('a/thing')
49
+ end
50
+
51
+ it 'performs queries with properties' do
52
+ step = Pushpop::Mixpanel.new do
53
+ query 'a/thing', age: 23
54
+ end
55
+
56
+ expect(Pushpop::Mixpanel.querent).to receive(:request).with('a/thing', {age: 23})
57
+ step.run
58
+ expect(step._endpoint).to eq('a/thing')
59
+ end
60
+ end
61
+
62
+ describe 'user' do
63
+ it 'sets the user to do work with' do
64
+ step = Pushpop::Mixpanel.new do
65
+ user '12345'
66
+ end
67
+
68
+ step.run
69
+ expect(step._user).to eq('12345')
70
+ end
71
+
72
+ it 'creates the user with blank properties if no other set is called' do
73
+ step = Pushpop::Mixpanel.new do
74
+ user '12345'
75
+ end
76
+
77
+ expect(Pushpop::Mixpanel.tracker.people).to receive(:set).with('12345', {})
78
+ step.run
79
+ end
80
+
81
+ it 'updates the user if properties are passed' do
82
+ step = Pushpop::Mixpanel.new do
83
+ user '12345', {name: 'Bob'}
84
+ end
85
+
86
+ expect(Pushpop::Mixpanel.tracker.people).to receive(:set).with('12345', {name: 'Bob'})
87
+ step.run
88
+ end
89
+
90
+ it 'updates a user' do
91
+ step = Pushpop::Mixpanel.new do
92
+ user '12345'
93
+ set({coolness: 1})
94
+ end
95
+
96
+ expect(Pushpop::Mixpanel.tracker.people).to receive(:set).with('12345', {coolness: 1})
97
+ step.run
98
+ end
99
+
100
+ describe 'alias' do
101
+ it 'should create aliases' do
102
+ step = Pushpop::Mixpanel.new do
103
+ create_alias '12345', '54321'
104
+ end
105
+
106
+ expect(Pushpop::Mixpanel.tracker).to receive(:alias).with('12345', '54321')
107
+ step.run
108
+ end
109
+
110
+ it 'set the user to the new alias' do
111
+ step = Pushpop::Mixpanel.new do
112
+ create_alias '12345', '54321'
113
+ end
114
+
115
+ step.run
116
+ expect(step._user).to eq('12345')
117
+ end
118
+ end
119
+
120
+ it 'increments a user property' do
121
+ step = Pushpop::Mixpanel.new do
122
+ user '12345'
123
+ increment({coolness: 1})
124
+ end
125
+
126
+ expect(Pushpop::Mixpanel.tracker.people).to receive(:increment).with('12345', {coolness: 1})
127
+ step.run
128
+ end
129
+
130
+ it 'appends a user property' do
131
+ step = Pushpop::Mixpanel.new do
132
+ user '12345'
133
+ append({hair_color: 'red'})
134
+ end
135
+
136
+ expect(Pushpop::Mixpanel.tracker.people).to receive(:append).with('12345', {hair_color: 'red'})
137
+ step.run
138
+ end
139
+
140
+ describe 'charge' do
141
+ it 'adds a charge to a user' do
142
+ step = Pushpop::Mixpanel.new do
143
+ user '12345'
144
+ charge 100
145
+ end
146
+
147
+ expect(Pushpop::Mixpanel.tracker.people).to receive(:track_charge).with('12345', 100)
148
+ step.run
149
+ end
150
+
151
+ it 'passes properties if they are provided' do
152
+ step = Pushpop::Mixpanel.new do
153
+ user '12345'
154
+ charge 100, {item: 'Hot Dog'}
155
+ end
156
+
157
+ expect(Pushpop::Mixpanel.tracker.people).to receive(:track_charge).with('12345', 100, {
158
+ item: 'Hot Dog'
159
+ })
160
+
161
+ step.run
162
+ end
163
+ end
164
+
165
+ describe 'delete' do
166
+ it 'deletes a user' do
167
+ step = Pushpop::Mixpanel.new do
168
+ user '12345'
169
+ delete
170
+ end
171
+
172
+ expect(Pushpop::Mixpanel.tracker.people).to receive(:delete_user).with('12345')
173
+ step.run
174
+ end
175
+
176
+ it 'ignores aliases when deleting' do
177
+ step = Pushpop::Mixpanel.new do
178
+ user '12345'
179
+ delete true
180
+ end
181
+
182
+ expect(Pushpop::Mixpanel.tracker.people).to receive(:delete_user).with('12345', {'$ignore_alias' => true})
183
+ step.run
184
+ end
185
+ end
186
+
187
+ describe 'errors' do
188
+ it "can't increment withour a user" do
189
+ step = Pushpop::Mixpanel.new do
190
+ increment '54321'
191
+ end
192
+
193
+ expect{step.run}.to raise_error
194
+ end
195
+
196
+ it "can't append withour a user" do
197
+ step = Pushpop::Mixpanel.new do
198
+ append '12345'
199
+ end
200
+
201
+ expect{step.run}.to raise_error
202
+ end
203
+
204
+ it "can't charge withour a user" do
205
+ step = Pushpop::Mixpanel.new do
206
+ charge '100'
207
+ end
208
+
209
+ expect{step.run}.to raise_error
210
+ end
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,11 @@
1
+ $: << File.join(File.dirname(__FILE__), '../lib')
2
+
3
+ require 'pushpop'
4
+ require 'pushpop-mixpanel'
5
+
6
+ RSpec.configure do |config|
7
+ config.before :each do
8
+ Pushpop.jobs.clear
9
+ end
10
+ end
11
+
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pushpop-mixpanel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Joe Wegner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pushpop
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: mixpanel-ruby
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: 2.1.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 2.1.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: mixpanel_client
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description:
56
+ email: joe@keen.io
57
+ executables: []
58
+ extensions: []
59
+ extra_rdoc_files: []
60
+ files:
61
+ - .gitignore
62
+ - .travis.yml
63
+ - Gemfile
64
+ - LICENSE
65
+ - README.md
66
+ - Rakefile
67
+ - lib/pushpop-mixpanel.rb
68
+ - pushpop-plugin.gemspec
69
+ - spec/pushpop-mixpanel_spec.rb
70
+ - spec/spec_helper.rb
71
+ homepage: https://github.com/pushpop-project/pushpop-mixpanel
72
+ licenses: []
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 2.0.14
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Pushpop Mixpanel plugin for querying and recording events
94
+ test_files:
95
+ - spec/pushpop-mixpanel_spec.rb
96
+ - spec/spec_helper.rb