pushpop-mixpanel 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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