Permalink
Browse files

initial commit

  • Loading branch information...
0 parents commit af29ab05e24bc5a286ace74a195af988b077494e @jkraemer committed May 11, 2011
@@ -0,0 +1,2 @@
+*.gem
+.rvmrc
No changes.
12 Gemfile
@@ -0,0 +1,12 @@
+source "http://rubygems.org"
+
+# Will automatically pull in this gem and all its
+# dependencies specified in the gemspec
+gem "piwik-tracker", :path => File.expand_path("..", __FILE__)
+
+gem 'test-unit'
+gem 'json'
+gem 'patron'
+
+# These are development dependencies
+gem "rake"
@@ -0,0 +1,22 @@
+PATH
+ remote: .
+ specs:
+ piwik-tracker (0.1.0)
+
+GEM
+ remote: http://rubygems.org/
+ specs:
+ json (1.5.1)
+ patron (0.4.11)
+ rake (0.8.7)
+ test-unit (2.3.0)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ json
+ patron
+ piwik-tracker!
+ rake
+ test-unit
20 LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2011 Jens Krämer
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
No changes.
@@ -0,0 +1,20 @@
+require "bundler"
+Bundler.setup
+
+require 'rake/testtask'
+
+desc 'Test the library.'
+Rake::TestTask.new(:test) do |t|
+ t.libs << 'lib' << 'test'
+ t.pattern = 'test/**/*_test.rb'
+ t.verbose = true
+end
+
+gemspec = eval(File.read("piwik-tracker.gemspec"))
+
+task :build => "#{gemspec.full_name}.gem"
+
+file "#{gemspec.full_name}.gem" => gemspec.files + ["piwik-tracker.gemspec"] do
+ system "gem build piwik-tracker.gemspec"
+ system "gem install piwik-tracker-#{PiwikTracker::VERSION}.gem"
+end
@@ -0,0 +1,2 @@
+require "piwik_tracker/version"
+require "piwik_tracker/piwik"
@@ -0,0 +1,205 @@
+require 'uri'
+require 'json'
+require 'patron'
+
+module PiwikTracker
+
+ # Piwik HTTP client
+ # piwik = Piwik.new('http://yoursite.com/piwik', 6)
+ # piwik.request(auth_token).
+ # url('http://yoursite.com/some-page.html').
+ # custom_variable(:foobar, 'value').
+ # track_page_view('Page Title')
+ class Piwik
+
+ MAX_INT = 2 ** ((['foo'].pack('p').size * 8) - 1) - 1
+
+ HTTP_TIMEOUT = 20
+ USER_AGENT = "piwik-tracker/#{PiwikTracker::VERSION}"
+
+ attr_accessor :debug
+
+ # base_uri - the location of your Piwik installation, i.e. 'http://yoursite.com/piwik'.
+ # site_id - Id of the site to be tracked
+ def initialize(base_uri, site_id)
+ @base_uri = base_uri
+ @site_id = site_id
+ end
+
+ # sends a tracking request
+ def track(params)
+ send_request params.merge( 'idsite' => @site_id,
+ 'rec' => 1,
+ 'rand' => rand(MAX_INT) )
+ end
+
+ protected
+
+ def send_request(params)
+ headers = { 'Accept-Language' => params.delete(:browser_language) }
+ headers['User-Agent'] = params.delete(:user_agent) if params.key?(:user_agent)
+ url = "piwik.php?#{hash_to_querystring(params)}"
+ puts "#{url} / #{headers.inspect}" if @debug
+ http.get url, headers
+ end
+
+ def http
+ @http ||= connect
+ end
+
+ def hash_to_querystring(hash)
+ (keys = hash.keys).inject('') do |query_string, key|
+ query_string << '&' unless key == keys.first
+ query_string << "#{URI.encode(key.to_s)}=#{URI.encode(hash[key].to_s)}"
+ end
+ end
+
+ def connect
+ Patron::Session.new.tap do |session|
+ session.timeout = HTTP_TIMEOUT
+ session.base_url = @base_uri
+ session.headers['User-Agent'] = USER_AGENT
+ end
+ end
+
+
+ public
+
+ class Request
+
+ # Piwik API version
+ VERSION = 1
+
+ # length of Piwik visitor ids
+ VISITOR_ID_LENGTH = 16
+
+ def initialize(piwik, auth_token = nil)
+ @piwik = piwik
+ @custom_variables = []
+ @data = {}
+ @data[:token_auth] = auth_token if auth_token
+ end
+
+ # Chainable attribute setters
+ ###########################
+
+ # Sets the current URL being tracked
+ def url(url)
+ @data[:url] = url
+ self
+ end
+
+ # Sets the URL referrer used to track Referrers details for new visits.
+ def referrer(url)
+ @data[:urlref] = url
+ self
+ end
+
+ # Sets the attribution information to the visit, so that subsequent Goal conversions are
+ # properly attributed to the right Referrer URL, timestamp, Campaign Name & Keyword.
+ # info - 4 element array of [campaign name, campaign keyword, Timestamp at which the referrer was set, Referrer URL]
+ def attribution_info(info)
+ info = JSON.parse(info) if String === info
+ @data[:_rcn], @data[:_rck], @data[:_refts], @data[:_ref] = info
+ self
+ end
+
+ # Sets Visit Custom Variable.
+ # See http://piwik.org/docs/custom-variables/
+ # slot_id - Custom variable slot ID from 1-5
+ # name - Custom variable name
+ # value - Custom variable value
+ def custom_variable(slot_id, name, value)
+ raise "invalid slot id, has to be between 1 and 5" unless (1..5).include?(slot_id)
+ @custom_variables[slot_id - 1] = [name, value]
+ self
+ end
+
+ def browser_language(lang)
+ @data[:browser_language] = lang
+ self
+ end
+
+ def user_agent(name)
+ @data[:user_agent] = name
+ self
+ end
+
+ # Overrides server date and time for the tracking requests.
+ # By default Piwik will track requests for the "current datetime" but this function allows you
+ # to track visits in the past.
+ # time - ruby Time instance
+ def forced_date_time(time)
+ @data[:cdt] = time.utc.to_i
+ self
+ end
+
+ # Overrides IP address
+ # client_ip - IP address string
+ def ip(client_ip)
+ @data[:cip] = client_ip
+ self
+ end
+
+ # Forces the requests to be recorded for the specified Visitor ID
+ # rather than using the heuristics based on IP and other attributes.
+ # id - 16 hexadecimal characters visitor ID, eg. "33c31e01394bdc63"
+ def visitor_id(id)
+ raise "visitor_id must be exactly #{VISITOR_ID_LENGTH} characters long" unless id.to_s.length == VISITOR_ID_LENGTH
+ @data[:cid] = id
+ self
+ end
+
+
+
+ # Tracking functions
+ ###########################
+
+ # Tracks a page view
+ # document_title is the page title as it will appear in the Actions > Page titles report
+ def track_pageview(document_title)
+ @piwik.track request_params.merge(:action_name => document_title)
+ end
+
+ # Records a Goal conversion
+ # goal_id - Id of the goal to record
+ # revenue - revenue for this conversion
+ def track_goal(goal_id, revenue = nil)
+ params = request_params.merge :idgoal => goal_id
+ params[:revenue] = revenue if revenue
+ @piwik.track params
+ end
+
+ # Tracks a download or outlink
+ # action_url - URL of the download or outlink
+ # action_type Type of the action: :download or :link
+ def track_action(action_url, action_type)
+ @piwik.track request_params.merge(action_type => action_url, :redirect => '0')
+ end
+
+ protected
+
+ def request_params
+ @data.dup.tap do |params|
+ params[:_cvar] = @custom_variables.to_json if @custom_variables.any?
+ end
+ end
+
+ end
+
+
+ # generates a new request object.
+ #
+ # Some Tracking API functionnality requires express authentication, using either the
+ # Super User token_auth, or a user with 'admin' access to the website.
+ #
+ # The following features require access:
+ # - force the visitor IP
+ # - force the date & time of the tracking requests rather than track for the current datetime
+ # - force Piwik to track the requests to a specific VisitorId rather than use the standard visitor matching heuristic
+ def request(auth_token = nil)
+ Request.new self, auth_token
+ end
+ end
+
+end
@@ -0,0 +1,3 @@
+module PiwikTracker
+ VERSION = "0.1.0"
+end
@@ -0,0 +1,30 @@
+require File.expand_path("../lib/piwik_tracker/version", __FILE__)
+
+Gem::Specification.new do |s|
+ s.name = "piwik-tracker"
+ s.version = PiwikTracker::VERSION
+ s.platform = Gem::Platform::RUBY
+ s.authors = ["Jens Krämer"]
+ s.email = ["jk@jkraemer.net"]
+ s.homepage = "http://github.com/jkraemer/piwik-tracker"
+ s.summary = "Record visits, page views, Goals, in a Piwik server"
+ s.description = ""
+
+ s.required_rubygems_version = ">= 1.3.6"
+
+ # lol - required for validation
+ s.rubyforge_project = "piwik-tracker"
+
+ # If you have other dependencies, add them here
+ # s.add_dependency "another", "~> 1.2"
+
+ # If you need to check in files that aren't .rb files, add them here
+ s.files = Dir["{lib}/**/*.rb", "bin/*", "LICENSE", "*.md"]
+ s.require_path = 'lib'
+
+ # If you need an executable, add it here
+ # s.executables = ["newgem"]
+
+ # If you have C extensions, uncomment this line
+ # s.extensions = "ext/extconf.rb"
+end
No changes.
@@ -0,0 +1,34 @@
+require 'test_helper'
+require 'piwik_tracker/piwik'
+
+module PiwikTracker
+ class PiwikTest < Test::Unit::TestCase
+
+ # piwik = Piwik.new('http://yoursite.com/piwik', 6)
+ # piwik.request(auth_token).
+ # url('http://yoursite.com/some-page.html').
+ # custom_variable(:foobar, 'value').
+ # track_page_view('Page Title')
+ def setup
+ @piwik = Piwik.new ENV['piwik'], ENV['site']
+ @piwik.debug = true
+ @request = @piwik.request(ENV['auth'])
+ end
+
+ test "should track pageview" do
+ assert resp = @request.url('http://test.com/track_pageview').track_pageview( 'somwhere' )
+ pp resp
+ end
+
+ test "should track action" do
+ assert r = @request.url('http://test.com/track_action').track_action( 'http://targetsite.com/test.html', 'link' )
+ pp r
+ end
+
+ test "should track goal" do
+ assert r = @request.url('http://test.com/track_goal').track_goal( 1, 99 )
+ pp r
+ end
+
+ end
+end
@@ -0,0 +1,4 @@
+require 'test/unit'
+require 'pp'
+
+require 'piwik_tracker'

0 comments on commit af29ab0

Please sign in to comment.