Permalink
Browse files

Add google analytics, so we know roughly how many folks are using thi…

…s plugin.
  • Loading branch information...
1 parent 34bac3a commit 64e90292508959ce6ee0b7bbcbca90fc5c5c17cc @philc committed Mar 17, 2011
Showing with 131 additions and 3 deletions.
  1. +4 −0 TextMateVim.xcodeproj/project.pbxproj
  2. +1 −1 lib/activesupport_json.rb
  3. +114 −0 lib/google_analytics.rb
  4. +12 −2 src/event_handler.rb
@@ -14,6 +14,7 @@
0A4347AC132CB1C0007C2EBF /* SBJsonWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = 0A4347A7132CB1C0007C2EBF /* SBJsonWriter.m */; };
0A77BE8F111FF5B2006F0625 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A77BE8E111FF5B2006F0625 /* Cocoa.framework */; };
0A77BEB3111FFA4D006F0625 /* RubyCocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0A77BEB2111FFA4D006F0625 /* RubyCocoa.framework */; };
+ 6A36EFC7133289ED00F9CC6D /* google_analytics.rb in Resources */ = {isa = PBXBuildFile; fileRef = 6A36EFC6133289ED00F9CC6D /* google_analytics.rb */; };
6A3CD22913308F74001A7161 /* TextMateVimPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A3CD22613308F74001A7161 /* TextMateVimPlugin.m */; };
6A3CD22A13308F74001A7161 /* TextMateVimWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 6A3CD22813308F74001A7161 /* TextMateVimWindow.m */; };
6A3CD2361330A6EA001A7161 /* json_implementation.rb in Resources */ = {isa = PBXBuildFile; fileRef = 6A3CD2351330A6EA001A7161 /* json_implementation.rb */; };
@@ -46,6 +47,7 @@
0A77BE8E111FF5B2006F0625 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
0A77BEB2111FFA4D006F0625 /* RubyCocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RubyCocoa.framework; path = System/Library/Frameworks/RubyCocoa.framework; sourceTree = SDKROOT; };
0AA1909FFE8422F4C02AAC07 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
+ 6A36EFC6133289ED00F9CC6D /* google_analytics.rb */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.ruby; name = google_analytics.rb; path = lib/google_analytics.rb; sourceTree = SOURCE_ROOT; };
6A3CD22513308F74001A7161 /* TextMateVimPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TextMateVimPlugin.h; path = src/TextMateVimPlugin.h; sourceTree = "<group>"; };
6A3CD22613308F74001A7161 /* TextMateVimPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TextMateVimPlugin.m; path = src/TextMateVimPlugin.m; sourceTree = "<group>"; };
6A3CD22713308F74001A7161 /* TextMateVimWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TextMateVimWindow.h; path = src/TextMateVimWindow.h; sourceTree = "<group>"; };
@@ -165,6 +167,7 @@
6ABE41051313B263001CA6B4 /* src */ = {
isa = PBXGroup;
children = (
+ 6A36EFC6133289ED00F9CC6D /* google_analytics.rb */,
6A3CD23B13315554001A7161 /* activesupport_json.rb */,
6A3CD2351330A6EA001A7161 /* json_implementation.rb */,
6A8618E71324CDD7001A5360 /* editor_commands.rb */,
@@ -236,6 +239,7 @@
6A8618E81324CDD7001A5360 /* editor_commands.rb in Resources */,
6A3CD2361330A6EA001A7161 /* json_implementation.rb in Resources */,
6A3CD23C13315554001A7161 /* activesupport_json.rb in Resources */,
+ 6A36EFC7133289ED00F9CC6D /* google_analytics.rb in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -8,7 +8,7 @@
# has macports installed, then the gem environment TextMateVim uses will not contain the gem they installed
# via the terminal. If we require gems in the future, we should bundle them with TextMateVim.
#
-# We're not bundling the JSON gem with TextMateVim because it's GPL.
+# We're not bundling the JSON gem with TextMateVim because it's GPL. Argh!
require "yaml"
#
View
@@ -0,0 +1,114 @@
+#
+# Taken from https://github.com/hybridgroup/gabba and slightly modified to make the HTTP request in a
+# separate thread, and to have a more intelligible namespace.
+#
+
+require "uri"
+require "net/http"
+require "cgi"
+
+module GoogleAnalytics
+ class NoGoogleAnalyticsAccountError < RuntimeError; end
+ class NoGoogleAnalyticsDomainError < RuntimeError; end
+ class GoogleAnalyticsNetworkError < RuntimeError; end
+
+ class GoogleAnalytics
+ GOOGLE_HOST = "www.google-analytics.com"
+ BEACON_PATH = "/__utm.gif"
+ USER_AGENT = "TextMateVim"
+
+ attr_accessor :utmwv, :utmn, :utmhn, :utmcs, :utmul, :utmdt, :utmp, :utmac, :utmt, :utmcc, :user_agent
+
+ def initialize(ga_acct, domain, agent = USER_AGENT)
+ @utmwv = "4.4sh" # GA version
+ @utmcs = "UTF-8" # charset
+ @utmul = "en-us" # language
+
+ @utmn = rand(8999999999) + 1000000000
+ @utmhid = rand(8999999999) + 1000000000
+
+ @utmac = ga_acct
+ @utmhn = domain
+ @user_agent = agent
+ end
+
+ def page_view(title, page, utmhid = rand(8999999999) + 1000000000)
+ check_account_params
+ hey(page_view_params(title, page, utmhid))
+ end
+
+ def event(category, action, label = nil, value = nil, utmhid = rand(8999999999) + 1000000000)
+ check_account_params
+ hey(event_params(category, action, label, value, utmhid))
+ end
+
+ def page_view_params(title, page, utmhid = rand(8999999999) + 1000000000)
+ {
+ :utmwv => @utmwv,
+ :utmn => @utmn,
+ :utmhn => @utmhn,
+ :utmcs => @utmcs,
+ :utmul => @utmul,
+ :utmdt => title,
+ :utmhid => utmhid,
+ :utmp => page,
+ :utmac => @utmac,
+ :utmcc => @utmcc || cookie_params
+ }
+ end
+
+ def event_params(category, action, label = nil, value = nil, utmhid = rand(8999999999) + 1000000000)
+ {
+ :utmwv => @utmwv,
+ :utmn => @utmn,
+ :utmhn => @utmhn,
+ :utmt => 'event',
+ :utme => event_data(category, action, label, value),
+ :utmcs => @utmcs,
+ :utmul => @utmul,
+ :utmhid => utmhid,
+ :utmac => @utmac,
+ :utmcc => @utmcc || cookie_params
+ }
+ end
+
+ def event_data(category, action, label = nil, value = nil)
+ data = "5(#{category}*#{action}" + (label ? "*#{label})" : ")")
+ data += "(#{value})" if value
+ data
+ end
+
+ # create magical cookie params used by GA for its own nefarious purposes
+ def cookie_params(utma1 = rand(89999999) + 10000000, utma2 = rand(1147483647) + 1000000000, today = Time.now)
+ "__utma=1.#{utma1}00145214523.#{utma2}.#{today.to_i}.#{today.to_i}.15;+__utmz=1.#{today.to_i}.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none);"
+ end
+
+ # sanity check that we have needed params to even call GA
+ def check_account_params
+ raise NoGoogleAnalyticsAccountError unless @utmac
+ raise NoGoogleAnalyticsDomainError unless @utmhn
+ end
+
+ # makes the tracking call to Google Analytics
+ def hey(params)
+ Thread.new do
+ begin
+ query = params.map {|k,v| "#{k}=#{CGI.escape(v.to_s)}" }.join('&')
+ response = Net::HTTP.start(GOOGLE_HOST) do |http|
+ request = Net::HTTP::Get.new("#{BEACON_PATH}?#{query}")
+ request["User-Agent"] = URI.escape(user_agent)
+ request["Accept"] = "*/*"
+ http.request(request)
+ end
+ raise GoogleAnalyticsNetworkError unless response.code == "200"
+ response
+ rescue => e
+ # NOTE(philc): Ignoring exceptions for now.
+ # log e.inspect
+ end
+ Thread.current.kill
+ end
+ end
+ end
+
+end
View
@@ -17,6 +17,7 @@
require "ui_helper"
require "editor_commands"
require "json_implementation"
+require "google_analytics"
class EventHandler
include EditorCommands
@@ -184,9 +185,18 @@ def log(str)
# Use for more verbose logging during development.
def debug_log(str) log(str) if ENABLE_DEBUG_LOGGING end
+# We'd like to roughly know how many folks are using TextMateVim. We ping google analytics whenever TextMate
+# first starts up with this plugin installed.
+def ping_google_analytics
+ machine_unique_id = "unknown" # TODO(philc): do we need this?
+ google_analytics_id = "UA-22129017-1"
+ GoogleAnalytics::GoogleAnalytics.new(google_analytics_id, "github.com").event("AppEvents", "Launch",
+ machine_unique_id, 1)
+end
+
if $0 == __FILE__
log "TextMateVim event_handler.rb coprocess has been started."
-
+ ping_google_analytics()
load "default_config.rb"
load_user_config_file
event_handler = EventHandler.new
@@ -199,4 +209,4 @@ def debug_log(str) log(str) if ENABLE_DEBUG_LOGGING end
log error.backtrace.join("\n")
end
end
-end
+end

0 comments on commit 64e9029

Please sign in to comment.