google_analytics_v4_api 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 00e78b59df928bfa8edea30095716394a73902e8b49e67dbf80d43a50bd0abae
4
- data.tar.gz: ebb7c0c7726fcfd28692959614d11d5e47c5b35f468f353df1b157e6c6516023
3
+ metadata.gz: 516d5859258748f1f4749df54b064cc3caf1b9707028041fd0db0084a75d719d
4
+ data.tar.gz: 0030de2106fff16d2ad13e7feb9c98af718fa0c55b04c30a9eecd462ff8df08a
5
5
  SHA512:
6
- metadata.gz: 9cf3584d6552e6c46849ad878dc3a987d5b835d198f138a4f8125722e5c50b47466adc337999235adf8c1ec8ba4a5fa3ae70b454209b838e860da2c9e156938f
7
- data.tar.gz: f12a6255bda5ce39749cd152f515d8fbc6e3fa99c3b5ae087dd356f582fdcff45b73ac49c278ec184dc7933df208e84353166bd2dec019d8cd812bb614af5f53
6
+ metadata.gz: 3bee4ad056696d0829191e46f6187c0d5a29cfeaebc5ad7fba3ea3b0766aa7d004b1b99ec26f854f4f7cf6d636c94f1f3b097e2ad5991413e7507be3e545443c
7
+ data.tar.gz: 060b03b7c94203270e627dcc35ae8e1262ccbb467040b5221c86518c4815b16a5239d3c77699ea43a8b5b511160d948143a4069aaa3b67b8af8d398e14ef4be6
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- google_analytics_v4_api (0.0.1)
4
+ google_analytics_v4_api (0.0.3)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Google Analytics v4 API Ruby Gem
2
2
  This is a simple wrapper to interact with the Google Analytics v4 API (currently in beta) with Ruby.
3
- It's based on the [API guide](https://developers.google.com/analytics/devguides/config/admin/v1/rest/v1beta)
3
+ It's based on the [Admin API guide](https://developers.google.com/analytics/devguides/config/admin/v1/rest) and the
4
+ [Reports API guide](https://developers.google.com/analytics/devguides/reporting/data/v1/basics?authuser=1#report_response)
4
5
 
5
6
  ## Usage
6
7
  Add this gem to your Gemfile:
@@ -10,21 +11,79 @@ gem 'google_analytics_v4_api'
10
11
 
11
12
  You will need a way to get a user's valid (and fresh) token (I personally use the `gem omnioauth`), and then:
12
13
 
14
+ ### Management API
13
15
  ```rb
14
16
  client = GoogleAnalyticsV4Api::Client.new(token)
15
17
  # List all the accounts
16
- client.accounts
18
+ accounts = client.accounts
17
19
  # Or get one particular account
18
- client.account("account/24696xxx")
20
+ account = client.account("accounts/24696xxx")
19
21
 
20
22
  # List all the properties for a particular account
21
- client.properties("accounts/24596xxx")
23
+ properties = client.properties("accounts/24596xxx")
22
24
  # Or get one particular property
23
- client.property("properties/33783xxx")
25
+ property = client.property("properties/33783xxx")
26
+
27
+ # Or simply call the properties for an Account object
28
+ properties = account.properties
29
+ # Or one particular property
30
+ property = account.property("properties/33783xxx")
24
31
  ```
25
32
 
26
- The rest is still being defined.
33
+ ### Data API
34
+ ```rb
35
+ filter = {
36
+ "andGroup": {
37
+ "expressions": [
38
+ {
39
+ "filter": {
40
+ "fieldName": "countryId",
41
+ "stringFilter": {
42
+ "value": "CL"
43
+ }
44
+ }
45
+ },
46
+ {
47
+ "filter": {
48
+ "fieldName": "pagePath",
49
+ "stringFilter": {
50
+ "matchType": "CONTAINS",
51
+ "value": "events",
52
+ "caseSensitive": false
53
+ }
54
+ }
55
+ }
56
+ ]
57
+ }
58
+ }
59
+ report = GoogleAnalyticsV4Api::Report.new(
60
+ dimensions: ['pagePath', 'countryId'],
61
+ metrics: ['sessions', 'screenPageViews'],
62
+ dimension_filter: filter,
63
+ start_date: Date.today - 30, #optional, 30 days ago by default
64
+ end_date: Date.today - 1) #optional, today by default
65
+
66
+ response = property.run_report(report)
67
+
68
+ # Get raw data from the response
69
+ response.raw_dimension_headers
70
+ => [{"name"=>"pagePath"}, {"name"=>"countryId"}]
71
+ response.raw_metric_headers
72
+ => [{"name"=>"sessions", "type"=>"TYPE_INTEGER"}, {"name"=>"screenPageViews", "type"=>"TYPE_INTEGER"}]
73
+ response.rows.first
74
+ => {"dimensionValues"=>[{"value"=>"/events"}, {"value"=>"CL"}], "metricValues"=>[{"value"=>"58"}, {"value"=>"78"}]}
75
+
76
+ # Or get a simplified version of the response
77
+ response.dimension_headers
78
+ => ["pagePath", "countryId"]
79
+ response.metric_headers
80
+ => ["sessions", "screenPageViews"]
81
+ response.parsed_rows.first.data
82
+ => {"pagePath"=>"/events", "countryId"=>"CL", "sessions"=>58, "screenPageViews"=>78}
27
83
 
84
+ ```
85
+ Dimensions and Metrics are available [here](https://developers.google.com/analytics/devguides/reporting/data/v1/api-schema)
86
+ Information about Filters is available [here](https://developers.google.com/analytics/devguides/reporting/data/v1/basics#dimension_filters)
28
87
 
29
88
  ## Development
30
89
 
@@ -6,19 +6,24 @@ module GoogleAnalyticsV4Api
6
6
  class Account
7
7
  attr_accessor :name, :createTime, :updateTime, :displayName, :regionCode
8
8
 
9
- def initialize(attributes = {})
9
+ def initialize(client, attributes = {})
10
+ @client = client
10
11
  attributes.each do |k, v|
11
12
  self.send("#{k}=", v)
12
13
  end
13
14
  end
14
15
 
15
16
  def properties
17
+ @client.properties(name)
18
+ end
16
19
 
20
+ def property(property_name)
21
+ @client.property(property_name)
17
22
  end
18
23
 
19
- def self.parse_list(body)
24
+ def self.parse_list(client, body)
20
25
  JSON.parse(body)["accounts"].map do |attrs|
21
- GoogleAnalyticsV4Api::Account.new(attrs)
26
+ GoogleAnalyticsV4Api::Account.new(client, attrs)
22
27
  end
23
28
  end
24
29
  end
@@ -1,20 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'json'
4
- require "net/http"
5
- require "uri"
6
-
7
3
  module GoogleAnalyticsV4Api
8
4
  class Client
9
5
 
10
- BASE_URL = "https://analyticsadmin.googleapis.com/v1beta"
6
+ attr_accessor :access_token
11
7
 
12
8
  def initialize(access_token)
13
9
  @access_token = access_token
14
10
  end
15
11
 
16
12
  def accounts
17
- @accounts ||= GoogleAnalyticsV4Api::Account.parse_list get("/accounts").body
13
+ @accounts ||= GoogleAnalyticsV4Api::Account.parse_list(self, get("/accounts"))
18
14
  end
19
15
 
20
16
  def account(account_name)
@@ -22,7 +18,10 @@ module GoogleAnalyticsV4Api
22
18
  end
23
19
 
24
20
  def properties(account_name)
25
- @properties ||= GoogleAnalyticsV4Api::Property.parse_list get("/properties", { filter: "parent:#{account_name}"}).body
21
+ @properties ||= Hash.new do |h, key|
22
+ h[key] = GoogleAnalyticsV4Api::Property.parse_list(self, get("/properties", { filter: "parent:#{key}"}))
23
+ end
24
+ @properties[account_name]
26
25
  end
27
26
 
28
27
  def property(property_name)
@@ -31,25 +30,13 @@ module GoogleAnalyticsV4Api
31
30
  return property unless property.nil?
32
31
  end
33
32
 
34
- GoogleAnalyticsV4Api::Property.parse get("/#{property_name}").body
33
+ GoogleAnalyticsV4Api::Property.parse(self, get("/#{property_name}"))
35
34
  end
36
35
 
37
36
  private
38
37
  def get(path, params = {})
39
- url = "#{BASE_URL}#{path}"
40
- url += "?#{URI.encode_www_form params}" unless params.empty?
41
- uri = URI(url)
42
-
43
- response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
44
- request = Net::HTTP::Get.new uri
45
- request["Authorization"] = "Bearer #{@access_token}"
46
- request["Content-Type"] = "application/json"
47
-
48
- http.request request
49
- end
50
- raise GoogleAnalyticsV4Api::Error.new(response) unless response.is_a?(Net::HTTPSuccess)
51
-
52
- response
38
+ Request.get(access_token: @access_token, path: path, params: params).body
53
39
  end
40
+
54
41
  end
55
42
  end
@@ -6,21 +6,30 @@ module GoogleAnalyticsV4Api
6
6
  class Property
7
7
  attr_accessor :name, :propertyType, :createTime, :updateTime, :parent, :displayName, :industryCategory, :timeZone, :currencyCode, :serviceLevel, :deleteTime, :expireTime, :account
8
8
 
9
- def initialize(attributes = {})
9
+ def initialize(client, attributes = {})
10
+ @client = client
10
11
  attributes.each do |k, v|
11
12
  self.send("#{k}=", v)
12
13
  end
13
14
  end
14
15
 
15
- def self.parse_list(body)
16
+ def account
17
+ @client.account(parent)
18
+ end
19
+
20
+ def run_report(report)
21
+ response = Request.post(access_token: @client.access_token, path: "/#{name}:runReport", payload: report.to_json)
22
+ ReportResponse.new(response)
23
+ end
24
+
25
+ def self.parse_list(client, body)
16
26
  JSON.parse(body)["properties"].map do |attrs|
17
- GoogleAnalyticsV4Api::Property.new(attrs)
27
+ GoogleAnalyticsV4Api::Property.new(client, attrs)
18
28
  end
19
29
  end
20
30
 
21
- def self.parse(body)
22
- GoogleAnalyticsV4Api::Property.new(JSON.parse(body))
31
+ def self.parse(client, body)
32
+ GoogleAnalyticsV4Api::Property.new(client, JSON.parse(body))
23
33
  end
24
-
25
34
  end
26
35
  end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'date'
5
+
6
+ module GoogleAnalyticsV4Api
7
+ class Report
8
+ attr_accessor :date_ranges, :dimensions, :metrics, :dimension_filter
9
+
10
+ def initialize(start_date: nil, end_date: nil, dimensions: [], metrics: [], dimension_filter: {})
11
+ @date_ranges = [{ "startDate": start_date || (Date.today - 30), "endDate": end_date || Date.today }]
12
+ @dimensions = dimensions.map { |dimension| { "name": dimension } }
13
+ @metrics = metrics.map { |metric| { "name": metric } }
14
+ @dimension_filter = dimension_filter
15
+ end
16
+
17
+ def to_json
18
+ {
19
+ "dateRanges": @date_ranges,
20
+ "dimensions": @dimensions,
21
+ "metrics": @metrics,
22
+ "dimensionFilter": @dimension_filter
23
+ }.to_json
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'date'
5
+
6
+ module GoogleAnalyticsV4Api
7
+ class ReportResponse
8
+
9
+ attr_accessor :body, :raw_dimension_headers, :raw_metric_headers, :rows, :row_count, :metadata, :kind
10
+
11
+ def initialize(body)
12
+ @body = JSON.parse body
13
+ @raw_dimension_headers = @body["dimensionHeaders"]
14
+ @raw_metric_headers = @body["metricHeaders"]
15
+ @rows = @body["rows"]
16
+ @row_cont = @body["rowCount"]
17
+ @metadata = @body["metadata"]
18
+ @kind = @body["kind"]
19
+ end
20
+
21
+ def dimension_headers
22
+ @dimension_headers ||= @raw_dimension_headers.map { |header| header["name"] }
23
+ end
24
+
25
+ def metric_headers
26
+ @metric_headers ||= @raw_metric_headers.map { |header| header["name"] }
27
+ end
28
+
29
+ def parsed_rows
30
+ @rows.map do |row|
31
+ ReportResponseRow.new(row, @raw_dimension_headers, @raw_metric_headers)
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'date'
5
+
6
+ module GoogleAnalyticsV4Api
7
+ class ReportResponseRow
8
+
9
+ attr_accessor :data
10
+
11
+ def initialize(row, raw_dimension_headers, raw_metric_headers)
12
+ # "dimensionHeaders"=>[{"name"=>"pagePath"}, {"name"=>"countryId"}],
13
+ # "metricHeaders"=>[{"name"=>"sessions", "type"=>"TYPE_INTEGER"}, {"name"=>"screenPageViews", "type"=>"TYPE_INTEGER"}],
14
+ # a row: {"dimensionValues"=>[{"value"=>"/events"}, {"value"=>"CL"}], "metricValues"=>[{"value"=>"62"}, {"value"=>"82"}]}
15
+ @raw_row = row
16
+ @data = {}
17
+ raw_dimension_headers.each_with_index do |dimension_header, index|
18
+ @data[dimension_header["name"]] = row["dimensionValues"][index]["value"]
19
+ end
20
+ raw_metric_headers.each_with_index do |metric_header, index|
21
+ @data[metric_header["name"]] = cast(row["metricValues"][index]["value"], metric_header["type"])
22
+ end
23
+ end
24
+
25
+ def cast(value, type)
26
+ words = type.split("_")
27
+ return value unless words[0] == 'TYPE'
28
+ return value.to_i if words[1] == "INTEGER"
29
+ return value.to_f if words[1].in? %w(FLOAT SECONDS MILLISECONDS MINUTES HOURS STANDARD CURRENCY FEET MILES METERS KILOMETERS)
30
+
31
+ value
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "uri"
5
+
6
+ module GoogleAnalyticsV4Api
7
+ class Request
8
+
9
+ ADMIN_URL = "https://analyticsadmin.googleapis.com/v1beta"
10
+ DATA_URL = "https://analyticsdata.googleapis.com/v1beta"
11
+
12
+ def self.get(access_token:, url: ADMIN_URL, path:, params: {})
13
+ url = "#{url}#{path}"
14
+ url += "?#{URI.encode_www_form params}" unless params.empty?
15
+ uri = URI(url)
16
+
17
+ response = Net::HTTP.start(uri.host, uri.port, :use_ssl => true) do |http|
18
+ request = Net::HTTP::Get.new uri
19
+ request["Authorization"] = "Bearer #{access_token}"
20
+ request["Content-Type"] = "application/json"
21
+
22
+ http.request request
23
+ end
24
+ raise GoogleAnalyticsV4Api::Error.new(response) unless response.is_a?(Net::HTTPSuccess)
25
+
26
+ response
27
+ end
28
+
29
+ def self.post(access_token:, url: DATA_URL, path:, payload: nil)
30
+ url = URI("#{url}#{path}")
31
+
32
+ https = Net::HTTP.new(url.host, url.port)
33
+ https.use_ssl = true
34
+
35
+ request = Net::HTTP::Post.new(url)
36
+ request["Authorization"] = "Bearer #{access_token}"
37
+ request["Content-Type"] = "application/javascript"
38
+ request.body = payload
39
+
40
+ response = https.request(request)
41
+ response.read_body
42
+ end
43
+
44
+ end
45
+ end
@@ -1,3 +1,3 @@
1
1
  module GoogleAnalyticsV4Api
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -4,5 +4,9 @@ module GoogleAnalyticsV4Api
4
4
  autoload :Client, "google_analytics_v4_api/client"
5
5
  autoload :Account, "google_analytics_v4_api/account"
6
6
  autoload :Property, "google_analytics_v4_api/property"
7
+ autoload :Request, "google_analytics_v4_api/request"
8
+ autoload :Report, "google_analytics_v4_api/report"
9
+ autoload :ReportResponse, "google_analytics_v4_api/report_response"
10
+ autoload :ReportResponseRow, "google_analytics_v4_api/report_response_row"
7
11
  autoload :Error, "google_analytics_v4_api/error"
8
12
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google_analytics_v4_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gustavo Garcia
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-12-20 00:00:00.000000000 Z
11
+ date: 2023-01-09 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: A very humble wrapper for the Google Analytics V4 API to be used in conjuntion
14
14
  with OAuth2
@@ -33,6 +33,10 @@ files:
33
33
  - lib/google_analytics_v4_api/client.rb
34
34
  - lib/google_analytics_v4_api/error.rb
35
35
  - lib/google_analytics_v4_api/property.rb
36
+ - lib/google_analytics_v4_api/report.rb
37
+ - lib/google_analytics_v4_api/report_response.rb
38
+ - lib/google_analytics_v4_api/report_response_row.rb
39
+ - lib/google_analytics_v4_api/request.rb
36
40
  - lib/google_analytics_v4_api/version.rb
37
41
  homepage: https://github.com/dailytics/google_analytics_v4_api
38
42
  licenses: