google_analytics_v4_api 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: