require 'rack' class MixpanelMiddleware def initialize(app, mixpanel_token, options={}) @app = app @token = mixpanel_token @options = { :async => false }.merge(options) end def call(env) @env = env @status, @headers, @response = @app.call(env) update_response! update_content_length! delete_event_queue! [@status, @headers, @response] end private def update_response! @response.each do |part| if is_regular_request? && is_html_response? insert_at = part.index(' new_size.to_s) end def is_regular_request? !is_ajax_request? end def is_ajax_request? @env.has_key?("HTTP_X_REQUESTED_WITH") && @env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" end def is_html_response? @headers["Content-Type"].include?("text/html") if @headers.has_key?("Content-Type") end def is_javascript_response? @headers["Content-Type"].include?("text/javascript") if @headers.has_key?("Content-Type") end def render_mixpanel_scripts if @options[:async] <<-EOT EOT else <<-EOT EOT end end def delete_event_queue! @env.delete('mixpanel_events') end def queue return [] if !@env.has_key?('mixpanel_events') || @env['mixpanel_events'].empty? @env['mixpanel_events'] end def render_event_tracking_scripts(include_script_tag=true) return "" if queue.empty? if @options[:async] output = queue.map {|type, arguments| %(mpq.push(["#{type}", #{arguments.join(', ')}]);) }.join("\n") else output = queue.map {|type, arguments| %(mpmetrics.#{type}(#{arguments.join(', ')});) }.join("\n") end output = "try {#{output}} catch(err) {}" include_script_tag ? "" : output end end