Create a gist now

Instantly share code, notes, and snippets.

A preliminary clicky client example built on api_smith
require 'rubygems'
require 'api_smith'
require 'date'
require 'ipaddr'
module GettinClickyWithIt
class Error < StandardError; end
SMART_NUMBER_TRANSFORMER = lambda { |v| Integer(v) rescue v }
class StatsCollection < APISmith::Smash
property :date
property :items
end
def self.collection_transformers
@collection_transformers ||= Hash.new do |h, k|
h[k] = Class.new(StatsCollection).tap do |klass|
klass.transformer_for :items, k
end
end
end
class TallyStat < APISmith::Smash
property :title
property :value, :transformer => SMART_NUMBER_TRANSFORMER
property :value_percent, :transformer => :to_f
property :url
property :clicky_url
# Goal Information
property :incompleted, :transformer => :to_i
property :conversion, :transformer => :to_f
property :revenue
property :cost
end
class ItemStat < APISmith::Smash
property :time, :transformer => lambda { |v| Time.at(v.to_i) }
property :time_pretty
property :item
property :clicky_url
alias query item
alias link item
end
class VisitStat < APISmith::Smash
property :time, :transformer => lambda { |v| Time.at(v.to_i) }
property :time_pretty
property :time_total, :transformer => :to_i
property :ip_address, :transformer => lambda { |v| IPAddr.new(v) }
property :session_id, :transformer => :to_i
property :actions, :transformer => :to_i
property :web_browser
property :operating_system
property :screen_resolution
property :javascript, :transformer => lambda { |v| v == '1' }
property :language
property :referrer_url
property :referrer_domain
property :referrer_search
property :referrer_type
property :geolocation
property :latitude, :transformer => :to_f
property :longitude, :transformer => :to_f
# These need a premium account fwiw.
property :hostname
property :organization
property :campaign
property :goals_incompleted
property :goals_completed
property :custom
property :clicky_url
alias javascript? javascript
end
class ActionStat < APISmith::Smash
property :time, :transformer => lambda { |v| Time.at(v.to_i) }
property :time_pretty
property :time_total, :transformer => :to_i
property :ip_address, :transformer => lambda { |v| IPAddr.new(v) }
property :session_id, :transformer => :to_i
property :action_type
property :action_title
property :action_url
property :referrer_url
property :referrer_domain
property :referrer_search
property :custom
property :clicky_url
%w(pageview download outbound).each do |v|
define_method(:"#{v}?") { action_type == v }
end
end
POPULAR_METHODS = %w(pages pages-entrance pages-exit downloads clicks links links-domains links-outbound searches searches-keywords searches-engines
goals split-tests campaigns countries cities regions languages web-browsers operating-systems screen-resolutions hostnames organizations
engagement-actions engagement-times visitors-most-active traffic-sources tweets shorturls)
TALLY_METHODS = %w(visitors visitors-unique actions actions-average time-average time-average-pretty bounce-rate visitors-online feedburner-statistics)
ITEM_LISTING_TYPES = %w(searches-recent searches-unique links-recent links-unique)
CUSTOM_METHODS = {
'visitors-list' => collection_transformers[VisitStat],
'actions-list' => collection_transformers[ActionStat]
}
AUTO_TRANSFORMER = lambda do |v|
type = v["type"]
if (transformer = CUSTOM_METHODS[type])
transformer.call v['dates']
elsif POPULAR_METHODS.include?(type) or TALLY_METHODS.include?(type)
collection_transformers[TallyStat].call v['dates']
elsif ITEM_LISTING_TYPES.include?(type)
collection_transformers[ItemStat].call v['dates']
else
v
end
end
class Client
include APISmith::Client
base_uri 'http://api.getclicky.com/'
endpoint 'api/stats/4'
attr_reader :site_id, :site_key
def initialize(site_id, site_key)
@site_key = site_key
@site_id = site_id
add_query_options! :site_id => site_id, :sitekey => site_key
end
(POPULAR_METHODS + ITEM_LISTING_TYPES + TALLY_METHODS + CUSTOM_METHODS.keys).each do |m|
define_method m.tr('-', '_') do |*args|
singular_api_call m, *args
end
end
private
def check_response_errors(response)
if response.first.is_a?(Hash) and (error = response.first['error'])
raise Error.new(error)
end
end
def base_query_options
{:output => 'json'}
end
def singular_api_call(type, options = {})
response = get '/', :extra_query => normalise_options(type, options),
:response_container => [0], :transform => AUTO_TRANSFORMER
extract_item response, options
end
def normalise_options(type, options)
encode_parameters(options).merge 'type' => [*type].join(",")
end
def extract_item(response, options)
if options[:daily] or options[:hourly]
response
else
response.first.items
end
end
def encode_parameters(params)
encoded = {}
params.each_pair do |k, v|
case k.to_s
when 'custom'
v.each_pair do |name, value|
encoded["#{k}[#{name}]"] = value
end
when 'date'
encoded[k] = normalise_value(v) { |t| normalise_date t }
else
encoded[k] = normalise_value v
end
end
encoded
end
def normalise_value(value, &blk)
blk ||= :to_s.to_proc
case value
when Range
[blk.call(value.begin), blk.call(value.end)] * ","
when Array
value.map(&blk) * "|"
when true
'1'
when false
'0'
else
value.to_s
end
end
def normalise_date(date)
if date.respond_to?(:strftime)
date.strftime "%Y-%m-%d"
else
date.to_s
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment