Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

merget chrisle gattica

  • Loading branch information...
commit fbcdaeb5b794a0b33a5d9b1d4fb3a640ff333503 2 parents 0826d69 + a3a4a98
@vgololobov authored
View
3  Gemfile
@@ -1,3 +1,6 @@
source "http://rubygems.org"
gemspec
gem 'test-unit'
+gem 'hpricot' #, 0.8.6
+gem 'test-unit' #, 2.4.5
+gem 'bundler' #, 1.0.21
View
12 Gemfile.lock
@@ -1,7 +1,12 @@
PATH
remote: .
specs:
+<<<<<<< HEAD
gattica (0.5.1)
+=======
+ gattica (0.6.0)
+ gattica
+>>>>>>> upstream/master
hpricot
test-unit
@@ -9,12 +14,19 @@ GEM
remote: http://rubygems.org/
specs:
hpricot (0.8.6)
+<<<<<<< HEAD
rake (0.9.2.2)
+=======
+>>>>>>> upstream/master
test-unit (2.4.5)
PLATFORMS
ruby
DEPENDENCIES
+<<<<<<< HEAD
rake
+=======
+ gattica!
+>>>>>>> upstream/master
test-unit
View
41 README.md
@@ -1,11 +1,3 @@
-This Fork
-=======
-Deviantech's fork of the Gattica gem has the following modifications:
-
-* Authentication by token actually works
-
--------
-
Gattica
=======
Gattica is an easy to use Gem for getting data from the Google Analytics API.
@@ -422,6 +414,37 @@ History
Version history
---------------
+### 0.6.1
+ * Incorporated fixes by vgololobov
+ * Removed circular dependency
+ * Fixed 1.9.3 init exception https://github.com/chrisle/gattica/pull/6
+
+### 0.6.0
+ * Update to use Google Analytics v2.4 management API
+
+ TL;DR: Uses the v2.4 API now because Google deprecated <2.3.
+
+ * :) - Drop-in replacement for you.
+ * :) - Won't timeout anymore.
+ * :) - Accounts method might be faster if you have a few profiles
+ * :( - Accounts method is notably slower if you have >1000 profiles.
+
+ Google has changed the output of the API < 2.3. Most notable changes
+ were the output of what was the /management/accounts/default call. Some
+ of the XML changed, but most notably it didn't return everything all at
+ once. It used to look like this: http://bit.ly/w6Ummj
+
+ * Fixed token [deviantech]
+
+### 0.5.1
+ * Added some tests - needs more work :(
+
+### 0.4.7
+ * Removed version numbers [john mcgrath]
+
+### 0.4.6
+ * Removed monkey patch [mathieuravaux]
+
### 0.4.4
* Added a configuration file to unit tests
* Removed version.rb. Not needed. (thanks John McGrath see: github.com/john)
@@ -480,4 +503,4 @@ Maintainer history
* [Rob Cameron](https://github.com/activenetwork/gattica) (2010)
* [Mike Rumble](https://github.com/rumble/gattica) (2010)
* [Chris Le](https://github.com/chrisle/gattica) (Current)
-
+
View
6 VERSION.yml
@@ -1,5 +1,5 @@
----
+---
:major: 0
-:minor: 5
+:minor: 6
:patch: 1
-:build:
+:build: !!null
View
26 gattica.gemspec
@@ -4,20 +4,21 @@
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
- s.name = %q{gattica}
- s.version = "0.5.1"
+ s.name = "gattica"
+ s.version = "0.6.1"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
- s.authors = [%q{Christopher Le, et all}]
- s.date = %q{2011-06-06}
- s.description = %q{Gattica is a easy to use Ruby Gem for getting data from the Google Analytics API. It supports metrics, dimensions, sort, filters, goals, and segments. It can handle accounts with 1000+ profiles, and can return data in CSV, Hash, or JSON}
- s.email = %q{chrisl@seerinteractive.com}
+ s.authors = ["Christopher Le, et all"]
+ s.date = "2012-01-31"
+ s.description = "Gattica is a easy to use Ruby Gem for getting data from the Google Analytics API. It supports metrics, dimensions, sort, filters, goals, and segments. It can handle accounts with 1000+ profiles, and can return data in CSV, Hash, or JSON"
+ s.email = "chrisl@seerinteractive.com"
s.extra_rdoc_files = [
"LICENSE",
"README.md"
]
s.files = [
"Gemfile",
+ "Gemfile.lock",
"LICENSE",
"README.md",
"Rakefile",
@@ -31,7 +32,9 @@ Gem::Specification.new do |s|
"lib/gattica/data_set.rb",
"lib/gattica/engine.rb",
"lib/gattica/exceptions.rb",
+ "lib/gattica/goals.rb",
"lib/gattica/hash_extensions.rb",
+ "lib/gattica/profiles.rb",
"lib/gattica/segment.rb",
"lib/gattica/settings.rb",
"lib/gattica/user.rb",
@@ -42,26 +45,23 @@ Gem::Specification.new do |s|
"test/test_results.rb",
"test/test_user.rb"
]
- s.homepage = %q{http://github.com/chrisle/gattica}
- s.require_paths = [%q{lib}]
- s.rubygems_version = %q{1.8.4}
- s.summary = %q{Gattica is a easy to use Ruby Gem for getting data from the Google Analytics API.}
+ s.homepage = "http://github.com/chrisle/gattica"
+ s.require_paths = ["lib"]
+ s.rubygems_version = "1.8.10"
+ s.summary = "Gattica is a easy to use Ruby Gem for getting data from the Google Analytics API."
if s.respond_to? :specification_version then
s.specification_version = 3
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
s.add_runtime_dependency(%q<test-unit>, [">= 0"])
- s.add_development_dependency(%q<rake>, [">= 0"])
s.add_runtime_dependency(%q<hpricot>, [">= 0"])
else
s.add_dependency(%q<test-unit>, [">= 0"])
- s.add_dependency(%q<rake>, [">= 0"])
s.add_dependency(%q<hpricot>, [">= 0"])
end
else
s.add_dependency(%q<test-unit>, [">= 0"])
- s.add_dependency(%q<rake>, [">= 0"])
s.add_dependency(%q<hpricot>, [">= 0"])
end
end
View
2  lib/gattica.rb
@@ -25,7 +25,7 @@
# Please see the README for usage docs.
module Gattica
- VERSION = '0.5.1'
+ VERSION = '0.6.1'
# Creates a new instance of Gattica::Engine
def self.new(*args)
View
62 lib/gattica/account.rb
@@ -1,34 +1,54 @@
-require 'rubygems'
-require 'hpricot'
-
module Gattica
-
- # Represents an account that an authenticated user has access to
-
class Account
-
include Convertible
attr_reader :id, :updated, :title, :table_id, :account_id, :account_name,
:profile_id, :web_property_id, :goals
def initialize(xml)
- @id = xml.at(:id).inner_html
+ @id = xml.at("link[@rel='self']").attributes['href']
@updated = DateTime.parse(xml.at(:updated).inner_html)
- @title = xml.at(:title).inner_html
- @table_id = xml.at('dxp:tableid').inner_html
- @account_id = xml.at("dxp:property[@name='ga:accountId']").attributes['value'].to_i
- @account_name = xml.at("dxp:property[@name='ga:accountName']").attributes['value']
- @profile_id = xml.at("dxp:property[@name='ga:profileId']").attributes['value'].to_i
- @web_property_id = xml.at("dxp:property[@name='ga:webPropertyId']").attributes['value']
- @goals = xml.search('ga:goal').collect do |goal| {
- :active => goal.attributes['active'],
- :name => goal.attributes['name'],
- :number => goal.attributes['number'].to_i,
- :value => goal.attributes['value'].to_f,
- }
+ @account_id = find_account_id(xml)
+
+ @title = xpath_value(xml, "dxp:property[@name='ga:profileName']")
+ @table_id = xpath_value(xml, "dxp:property[@name='dxp:tableId']")
+ @profile_id = find_profile_id(xml)
+ @web_property_id = xpath_value(xml, "dxp:property[@name='ga:webPropertyId']")
+ @goals = []
+ end
+
+ def xpath_value(xml, xpath)
+ xml.at(xpath).attributes['value']
+ end
+
+ def find_account_id(xml)
+ xml.at("dxp:property[@name='ga:accountId']").attributes['value'].to_i
+ end
+
+ def find_account_name(xml)
+ xml.at("dxp:property[@name='ga:accountName']").attributes['value']
+ end
+
+ def find_profile_id(xml)
+ xml.at("dxp:property[@name='ga:profileId']").attributes['value'].to_i
+ end
+
+ def set_account_name(account_feed_entry)
+ if @account_id == find_account_id(account_feed_entry)
+ @account_name = find_account_name(account_feed_entry)
end
end
-
+
+ def set_goals(goals_feed_entry)
+ if @profile_id == find_profile_id(goals_feed_entry)
+ goal = goals_feed_entry.search('ga:goal').first
+ @goals.push({
+ :active => goal.attributes['active'],
+ :name => goal.attributes['name'],
+ :number => goal.attributes['number'].to_i,
+ :value => goal.attributes['value'].to_f
+ })
+ end
+ end
end
end
View
7 lib/gattica/auth.rb
@@ -1,12 +1,5 @@
-require 'net/http'
-require 'net/https'
-
module Gattica
-
- # Authenticates a user against the Google Client Login system
-
class Auth
-
include Convertible
SCRIPT_NAME = '/accounts/ClientLogin'
View
60 lib/gattica/engine.rb
@@ -2,7 +2,7 @@ module Gattica
class Engine
attr_reader :user
- attr_accessor :profile_id, :token
+ attr_accessor :profile_id, :token, :user_accounts
# Initialize Gattica using username/password or token.
#
@@ -19,9 +19,8 @@ class Engine
def initialize(options={})
@options = Settings::DEFAULT_OPTIONS.merge(options)
handle_init_options(@options)
- create_http_connection()
+ create_http_connection('www.google.com')
check_init_auth_requirements()
- # TODO: check that the user has access to the specified profile and show an error here rather than wait for Google to respond with a message
end
# Returns the list of accounts the user has access to. A user may have
@@ -43,13 +42,32 @@ def initialize(options={})
# See Gattica::Engine#get to see how to get some data.
def accounts
- # if we haven't retrieved the user's accounts yet, get them now and save them
if @user_accounts.nil?
- data = request_default_account_feed
- xml = Hpricot(data)
- @user_accounts = xml.search(:entry).collect { |entry| Account.new(entry) }
+ create_http_connection('www.googleapis.com')
+
+ # get profiles
+ response = do_http_get("/analytics/v2.4/management/accounts/~all/webproperties/~all/profiles?max-results=10000")
+ xml = Hpricot(response)
+ @user_accounts = xml.search(:entry).collect { |profile_xml|
+ Account.new(profile_xml)
+ }
+
+ # Fill in the goals
+ response = do_http_get("/analytics/v2.4/management/accounts/~all/webproperties/~all/profiles/~all/goals?max-results=10000")
+ xml = Hpricot(response)
+ @user_accounts.each do |ua|
+ xml.search(:entry).each { |e| ua.set_goals(e) }
+ end
+
+ # Fill in the account name
+ response = do_http_get("/analytics/v2.4/management/accounts?max-results=10000")
+ xml = Hpricot(response)
+ @user_accounts.each do |ua|
+ xml.search(:entry).each { |e| ua.set_account_name(e) }
+ end
+
end
- return @user_accounts
+ @user_accounts
end
# Returns the list of segments available to the authenticated user.
@@ -68,9 +86,11 @@ def accounts
def segments
if @user_segments.nil?
- data = request_default_account_feed
- xml = Hpricot(data)
- @user_segments = xml.search("dxp:segment").collect { |s| Segment.new(s) }
+ response = do_http_get("/analytics/v2.4/management/segments?max-results=10000")
+ xml = Hpricot(response)
+ @user_segments = xml.search("dxp:segment").collect { |s|
+ Segment.new(s)
+ }
end
return @user_segments
end
@@ -114,8 +134,8 @@ def get(args={})
args = validate_and_clean(Settings::DEFAULT_ARGS.merge(args))
query_string = build_query_string(args,@profile_id)
@logger.debug(query_string) if @debug
- data = do_http_get("/analytics/feeds/data?#{query_string}")
- #data = do_http_get("/analytics/feeds/data?ids=ga%3A915568&metrics=ga%3Avisits&segment=gaid%3A%3A-7&start-date=2010-03-29&end-date=2010-03-29&max-results=50")
+ create_http_connection('www.googleapis.com')
+ data = do_http_get("/analytics/v2.4/data?#{query_string}")
return DataSet.new(Hpricot.XML(data))
end
@@ -132,14 +152,6 @@ def token=(token)
######################################################################
private
- # Gets the default account feed from Google
- def request_default_account_feed
- if @default_account_feed.nil?
- @default_account_feed = do_http_get('/analytics/feeds/accounts/default')
- end
- return @default_account_feed
- end
-
# Does the work of making HTTP calls and then going through a suite of tests on the response to make
# sure it's valid and not an error
@@ -246,9 +258,9 @@ def validate_and_clean(args)
return args
end
- def create_http_connection
+ def create_http_connection(server)
port = Settings::USE_SSL ? Settings::SSL_PORT : Settings::NON_SSL_PORT
- @http = Net::HTTP.new(Settings::SERVER, port)
+ @http = Net::HTTP.new(server, port)
@http.use_ssl = Settings::USE_SSL
@http.set_debug_output $stdout if @options[:debug]
@http.read_timeout = @options[:timeout] if @options[:timeout]
@@ -268,7 +280,7 @@ def handle_init_options(options)
# If the authorization is a email and password then create User objects
# or if it's a previous token, use that. Else, raise exception.
def check_init_auth_requirements
- if @options[:token].to_s.length > 200 # Not sure actual required length, but mine's 267
+ if @options[:token].to_s.length > 200
self.token = @options[:token]
elsif @options[:email] && @options[:password]
@user = User.new(@options[:email], @options[:password])
View
33 lib/gattica/goals.rb
@@ -0,0 +1,33 @@
+require 'rubygems'
+require 'hpricot'
+
+module Gattica
+ class Goals
+ include Convertible
+
+ attr_reader :id, :updated, :title, :table_id, :account_id, :account_name,
+ :profile_id, :web_property_id, :goals
+
+
+ def initialize(xml)
+ @id = xml.at(:id).inner_html
+ @updated = DateTime.parse(xml.at(:updated).inner_html)
+ @account_id = xml.at("dxp:property[@name='ga:accountId']").attributes['value'].to_i
+ @account_name = xml.at("dxp:property[@name='ga:accountName']").attributes['value']
+
+ @title = xml.at("dxp:property[@name='ga:profileName']").attributes['value']
+ @table_id = xml.at("dxp:property[@name='dxp:tableId']").attributes['value']
+ @profile_id = xml.at("dxp:property[@name='ga:profileId']").attributes['value'].to_i
+ @web_property_id = xml.at("dxp:property[@name='ga:webPropertyId']").attributes['value']
+
+ # @goals = xml.search('ga:goal').collect do |goal| {
+ # :active => goal.attributes['active'],
+ # :name => goal.attributes['name'],
+ # :number => goal.attributes['number'].to_i,
+ # :value => goal.attributes['value'].to_f,
+ # }
+ # end
+ end
+
+ end
+end
View
33 lib/gattica/profiles.rb
@@ -0,0 +1,33 @@
+require 'rubygems'
+require 'hpricot'
+
+module Gattica
+ class Profiles
+ include Convertible
+
+ attr_reader :id, :updated, :title, :table_id, :account_id, :account_name,
+ :profile_id, :web_property_id, :goals
+
+
+ def initialize(xml)
+ @id = xml.at(:id).inner_html
+ @updated = DateTime.parse(xml.at(:updated).inner_html)
+ @account_id = xml.at("dxp:property[@name='ga:accountId']").attributes['value'].to_i
+ @account_name = xml.at("dxp:property[@name='ga:accountName']").attributes['value']
+
+ @title = xml.at("dxp:property[@name='ga:profileName']").attributes['value']
+ @table_id = xml.at("dxp:property[@name='dxp:tableId']").attributes['value']
+ @profile_id = xml.at("dxp:property[@name='ga:profileId']").attributes['value'].to_i
+ @web_property_id = xml.at("dxp:property[@name='ga:webPropertyId']").attributes['value']
+
+ # @goals = xml.search('ga:goal').collect do |goal| {
+ # :active => goal.attributes['active'],
+ # :name => goal.attributes['name'],
+ # :number => goal.attributes['number'].to_i,
+ # :value => goal.attributes['value'].to_f,
+ # }
+ # end
+ end
+
+ end
+end
View
21 lib/gattica/settings.rb
@@ -1,28 +1,10 @@
module Gattica
module Settings
- # Google server to connect to
- #
- # You may need to change this if you use a proxy server. However, I have not
- # tested using a proxy.... YMMV
- SERVER = 'www.google.com'
-
- # Use a secure connection?
- #
- # If set to true, Gattica will use SSL_PORT or else it will use NON_SSL_PORT.
- #
- # === Example:
- # +USE_SSL = true+:: # Always use a secure connection
USE_SSL = true
SSL_PORT = 443
NON_SSL_PORT = 80
- # Net::HTTP timeout in seconds
- #
- # Increase the timeout setting if you have over 100 profiles.
- #
- # === Example:
- # +TIMEOUT = 300+:: # Increase timeout to 5 minutes.
TIMEOUT = 100
DEFAULT_ARGS = {
@@ -47,5 +29,6 @@ module Settings
FILTER_METRIC_OPERATORS = %w{ == != > < >= <= }
FILTER_DIMENSION_OPERATORS = %w{ == != =~ !~ =@ ~@ }
+
end
-end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.