mixpanel 2.2.0 → 3.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +233 -105
- data/lib/mixpanel/async.rb +31 -0
- data/lib/mixpanel/event.rb +41 -0
- data/lib/mixpanel/middleware.rb +142 -0
- data/lib/mixpanel/person.rb +41 -0
- data/lib/mixpanel/subprocess.rb +27 -0
- data/lib/mixpanel/tracker.rb +54 -151
- data/lib/mixpanel.rb +1 -0
- data/mixpanel.gemspec +2 -1
- data/spec/mixpanel/{tracker/middleware_spec.rb → middleware_spec.rb} +10 -10
- data/spec/mixpanel/tracker_spec.rb +33 -90
- data/spec/spec_helper.rb +13 -3
- data/spec/support/rack_apps.rb +1 -1
- metadata +37 -24
- data/lib/mixpanel/tracker/middleware.rb +0 -144
- data/lib/mixpanel/tracker/subprocess.rb +0 -29
- data/spec/mixpanel/mixpanel_spec.rb +0 -11
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mixpanel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 3.0.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-12 00:00:00.000000000Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: json
|
16
|
-
requirement: &
|
16
|
+
requirement: &2158058640 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *2158058640
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rack
|
27
|
-
requirement: &
|
27
|
+
requirement: &2158058200 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *2158058200
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: escape
|
38
|
-
requirement: &
|
38
|
+
requirement: &2158057780 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,21 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *2158057780
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: active_support
|
49
|
+
requirement: &2158057360 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2158057360
|
47
58
|
- !ruby/object:Gem::Dependency
|
48
59
|
name: rspec
|
49
|
-
requirement: &
|
60
|
+
requirement: &2158056940 !ruby/object:Gem::Requirement
|
50
61
|
none: false
|
51
62
|
requirements:
|
52
63
|
- - ! '>='
|
@@ -54,10 +65,10 @@ dependencies:
|
|
54
65
|
version: '0'
|
55
66
|
type: :development
|
56
67
|
prerelease: false
|
57
|
-
version_requirements: *
|
68
|
+
version_requirements: *2158056940
|
58
69
|
- !ruby/object:Gem::Dependency
|
59
70
|
name: rack-test
|
60
|
-
requirement: &
|
71
|
+
requirement: &2158056520 !ruby/object:Gem::Requirement
|
61
72
|
none: false
|
62
73
|
requirements:
|
63
74
|
- - ! '>='
|
@@ -65,10 +76,10 @@ dependencies:
|
|
65
76
|
version: '0'
|
66
77
|
type: :development
|
67
78
|
prerelease: false
|
68
|
-
version_requirements: *
|
79
|
+
version_requirements: *2158056520
|
69
80
|
- !ruby/object:Gem::Dependency
|
70
81
|
name: fakeweb
|
71
|
-
requirement: &
|
82
|
+
requirement: &2158056100 !ruby/object:Gem::Requirement
|
72
83
|
none: false
|
73
84
|
requirements:
|
74
85
|
- - ! '>='
|
@@ -76,10 +87,10 @@ dependencies:
|
|
76
87
|
version: '0'
|
77
88
|
type: :development
|
78
89
|
prerelease: false
|
79
|
-
version_requirements: *
|
90
|
+
version_requirements: *2158056100
|
80
91
|
- !ruby/object:Gem::Dependency
|
81
92
|
name: nokogiri
|
82
|
-
requirement: &
|
93
|
+
requirement: &2158055680 !ruby/object:Gem::Requirement
|
83
94
|
none: false
|
84
95
|
requirements:
|
85
96
|
- - ! '>='
|
@@ -87,10 +98,10 @@ dependencies:
|
|
87
98
|
version: '0'
|
88
99
|
type: :development
|
89
100
|
prerelease: false
|
90
|
-
version_requirements: *
|
101
|
+
version_requirements: *2158055680
|
91
102
|
- !ruby/object:Gem::Dependency
|
92
103
|
name: rake
|
93
|
-
requirement: &
|
104
|
+
requirement: &2158055260 !ruby/object:Gem::Requirement
|
94
105
|
none: false
|
95
106
|
requirements:
|
96
107
|
- - ! '>='
|
@@ -98,10 +109,10 @@ dependencies:
|
|
98
109
|
version: '0'
|
99
110
|
type: :development
|
100
111
|
prerelease: false
|
101
|
-
version_requirements: *
|
112
|
+
version_requirements: *2158055260
|
102
113
|
- !ruby/object:Gem::Dependency
|
103
114
|
name: ruby-debug19
|
104
|
-
requirement: &
|
115
|
+
requirement: &2158054800 !ruby/object:Gem::Requirement
|
105
116
|
none: false
|
106
117
|
requirements:
|
107
118
|
- - ! '>='
|
@@ -109,7 +120,7 @@ dependencies:
|
|
109
120
|
version: '0'
|
110
121
|
type: :development
|
111
122
|
prerelease: false
|
112
|
-
version_requirements: *
|
123
|
+
version_requirements: *2158054800
|
113
124
|
description: Simple lib to track events in Mixpanel service. It can be used in any
|
114
125
|
rack based framework.
|
115
126
|
email: zevarito@gmail.com
|
@@ -122,13 +133,15 @@ files:
|
|
122
133
|
- LICENSE
|
123
134
|
- Rakefile
|
124
135
|
- mixpanel.gemspec
|
125
|
-
- spec/mixpanel/
|
126
|
-
- spec/mixpanel/tracker/middleware_spec.rb
|
136
|
+
- spec/mixpanel/middleware_spec.rb
|
127
137
|
- spec/mixpanel/tracker_spec.rb
|
128
138
|
- spec/spec_helper.rb
|
129
139
|
- spec/support/rack_apps.rb
|
130
|
-
- lib/mixpanel/
|
131
|
-
- lib/mixpanel/
|
140
|
+
- lib/mixpanel/async.rb
|
141
|
+
- lib/mixpanel/event.rb
|
142
|
+
- lib/mixpanel/middleware.rb
|
143
|
+
- lib/mixpanel/person.rb
|
144
|
+
- lib/mixpanel/subprocess.rb
|
132
145
|
- lib/mixpanel/tracker.rb
|
133
146
|
- lib/mixpanel.rb
|
134
147
|
homepage: http://github.com/zevarito/mixpanel
|
@@ -1,144 +0,0 @@
|
|
1
|
-
require 'rack'
|
2
|
-
require 'json'
|
3
|
-
|
4
|
-
module Mixpanel
|
5
|
-
class Tracker
|
6
|
-
class Middleware
|
7
|
-
def initialize(app, mixpanel_token, options={})
|
8
|
-
@app = app
|
9
|
-
@token = mixpanel_token
|
10
|
-
@options = {
|
11
|
-
:insert_js_last => false,
|
12
|
-
:persist => false,
|
13
|
-
:config => {}
|
14
|
-
}.merge(options)
|
15
|
-
end
|
16
|
-
|
17
|
-
def call(env)
|
18
|
-
@env = env
|
19
|
-
|
20
|
-
@status, @headers, @response = @app.call(env)
|
21
|
-
|
22
|
-
if is_trackable_response?
|
23
|
-
merge_queue! if @options[:persist]
|
24
|
-
update_response!
|
25
|
-
update_content_length!
|
26
|
-
delete_event_queue!
|
27
|
-
end
|
28
|
-
|
29
|
-
[@status, @headers, @response]
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def update_response!
|
35
|
-
@response.each do |part|
|
36
|
-
if is_regular_request? && is_html_response?
|
37
|
-
insert_at = part.index(@options[:insert_js_last] ? '</body' : '</head')
|
38
|
-
unless insert_at.nil?
|
39
|
-
part.insert(insert_at, render_event_tracking_scripts) unless queue.empty?
|
40
|
-
part.insert(insert_at, render_mixpanel_scripts) #This will insert the mixpanel initialization code before the queue of tracking events.
|
41
|
-
end
|
42
|
-
elsif is_ajax_request? && is_html_response?
|
43
|
-
part.insert(0, render_event_tracking_scripts) unless queue.empty?
|
44
|
-
elsif is_ajax_request? && is_javascript_response?
|
45
|
-
part.insert(0, render_event_tracking_scripts(false)) unless queue.empty?
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def update_content_length!
|
51
|
-
new_size = 0
|
52
|
-
@response.each{|part| new_size += part.bytesize}
|
53
|
-
@headers.merge!("Content-Length" => new_size.to_s)
|
54
|
-
end
|
55
|
-
|
56
|
-
def is_regular_request?
|
57
|
-
!is_ajax_request?
|
58
|
-
end
|
59
|
-
|
60
|
-
def is_ajax_request?
|
61
|
-
@env.has_key?("HTTP_X_REQUESTED_WITH") && @env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest"
|
62
|
-
end
|
63
|
-
|
64
|
-
def is_html_response?
|
65
|
-
@headers["Content-Type"].include?("text/html") if @headers.has_key?("Content-Type")
|
66
|
-
end
|
67
|
-
|
68
|
-
def is_javascript_response?
|
69
|
-
@headers["Content-Type"].include?("text/javascript") if @headers.has_key?("Content-Type")
|
70
|
-
end
|
71
|
-
|
72
|
-
def is_trackable_response?
|
73
|
-
return false if @status == 302
|
74
|
-
return false if @env.has_key?("HTTP_SKIP_MIXPANEL_MIDDLEWARE")
|
75
|
-
is_html_response? || is_javascript_response?
|
76
|
-
end
|
77
|
-
|
78
|
-
def render_mixpanel_scripts
|
79
|
-
<<-EOT
|
80
|
-
<!-- start Mixpanel -->
|
81
|
-
<script type="text/javascript">
|
82
|
-
(function(c,a){window.mixpanel=a;var b,d,h,e;b=c.createElement("script");
|
83
|
-
b.type="text/javascript";b.async=!0;b.src=("https:"===c.location.protocol?"https:":"http:")+
|
84
|
-
'//cdn.mxpnl.com/libs/mixpanel-2.1.min.js';d=c.getElementsByTagName("script")[0];
|
85
|
-
d.parentNode.insertBefore(b,d);a._i=[];a.init=function(b,c,f){function d(a,b){
|
86
|
-
var c=b.split(".");2==c.length&&(a=a[c[0]],b=c[1]);a[b]=function(){a.push([b].concat(
|
87
|
-
Array.prototype.slice.call(arguments,0)))}}var g=a;"undefined"!==typeof f?g=a[f]=[]:
|
88
|
-
f="mixpanel";g.people=g.people||[];h=['disable','track','track_pageview','track_links',
|
89
|
-
'track_forms','register','register_once','unregister','identify','name_tag',
|
90
|
-
'set_config','people.identify','people.set','people.increment'];for(e=0;e<h.length;e++)d(g,h[e]);
|
91
|
-
a._i.push([b,c,f])};a.__SV=1.1;})(document,window.mixpanel||[]);
|
92
|
-
|
93
|
-
mixpanel.init("#{@token}");
|
94
|
-
mixpanel.set_config(#{@options[:config].to_json});
|
95
|
-
</script>
|
96
|
-
<!-- end Mixpanel -->
|
97
|
-
EOT
|
98
|
-
end
|
99
|
-
|
100
|
-
def delete_event_queue!
|
101
|
-
if @options[:persist]
|
102
|
-
(@env['rack.session']).delete('mixpanel_events')
|
103
|
-
else
|
104
|
-
@env.delete('mixpanel_events')
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
def queue
|
109
|
-
if @options[:persist]
|
110
|
-
return [] if !(@env['rack.session']).has_key?('mixpanel_events') || @env['rack.session']['mixpanel_events'].empty?
|
111
|
-
@env['rack.session']['mixpanel_events']
|
112
|
-
else
|
113
|
-
return [] if !@env.has_key?('mixpanel_events') || @env['mixpanel_events'].empty?
|
114
|
-
@env['mixpanel_events']
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def merge_queue!
|
119
|
-
present_hash = {}
|
120
|
-
special_events = ['identify', 'name_tag', 'people.set', 'register']
|
121
|
-
queue.uniq!
|
122
|
-
|
123
|
-
queue.reverse_each do |item|
|
124
|
-
is_special = special_events.include?(item[0])
|
125
|
-
if present_hash[item[0]] and is_special
|
126
|
-
queue.delete(item)
|
127
|
-
else
|
128
|
-
present_hash[item[0]] = true if is_special
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def render_event_tracking_scripts(include_script_tag=true)
|
134
|
-
return "" if queue.empty?
|
135
|
-
|
136
|
-
output = queue.map {|type, arguments| %(mixpanel.#{type}(#{arguments.join(', ')});) }.join("\n")
|
137
|
-
output = "try {#{output}} catch(err) {}"
|
138
|
-
|
139
|
-
include_script_tag ? "<script type='text/javascript'>#{output}</script>" : output
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
@@ -1,29 +0,0 @@
|
|
1
|
-
require 'open-uri'
|
2
|
-
require 'thread'
|
3
|
-
|
4
|
-
module Mixpanel
|
5
|
-
class Tracker
|
6
|
-
class Subprocess
|
7
|
-
Q = Queue.new
|
8
|
-
ENDMARKER = Object.new
|
9
|
-
|
10
|
-
Thread.abort_on_exception = true
|
11
|
-
producer = Thread.new do
|
12
|
-
STDIN.each_line() do |url|
|
13
|
-
STDERR.puts("Dropped: #{url}") && next if Q.length > 10000
|
14
|
-
Q << url
|
15
|
-
end
|
16
|
-
Q << ENDMARKER
|
17
|
-
end
|
18
|
-
|
19
|
-
loop do
|
20
|
-
url = Q.pop
|
21
|
-
break if(url == ENDMARKER)
|
22
|
-
url.chomp!
|
23
|
-
next if(url.empty?) #for testing
|
24
|
-
open(url).read
|
25
|
-
end
|
26
|
-
producer.join
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,11 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Mixpanel do
|
4
|
-
context "Deprecated initialization mode" do
|
5
|
-
it "should not allow to initialize the class as the old way" do
|
6
|
-
lambda do
|
7
|
-
mixpanel = Mixpanel.new(MIX_PANEL_TOKEN, @env = {"REMOTE_ADDR" => "127.0.0.1"})
|
8
|
-
end.should raise_error(NoMethodError)
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|