サービス アカウントを使用して GA4 API への Ruby REST リクエストを承認するにはどうすればよいですか?
概要
GA4 API ライブラリから特定のページ パスのビュー数を取得しようとしています。 Ruby GA4 API クライアント gem google-analytics-data を使用してこれを行うことができましたが、GA4 Query Explorer と Ruby API コードの間では結果が大きく異なるため、基本的な REST リクエストを使用して結果を比較したいと考えています。一部のパスでは同じカウントが生成されますが、ほとんどのパスでは同じカウントが生成されません。
エラーが発生し続けます
/var/lib/gems/2.7.0/gems/googleauth-1.11.0/lib/googleauth/service_account.rb:87:in `unescape': undefined method `gsub' for nil:NilClass (NoMethodError)
このエラーは次の行によって生成されます。
credentials = Google::Auth::ServiceAccountCredentials.make_creds(
scope: claims[:scope],
json_key: private_key
)
gsub を削除してもエラーが生成されるため、コード内の gsub 行は関係ありません。
これが私の完全なコードです。
#!/usr/bin/ruby
require 'googleauth'
require 'net/http'
require 'json'
require 'time'
require './environment'
error_message = nil
module GoogleAnalytics
def self.make_ga4_rest_request(body)
# Define GA4 Reporting API endpoint URL
endpoint = "https://analyticsreporting.googleapis.com/v4/reports:batchGet"
key_data = JSON.parse(File.read(SERVICE_ACCOUNT_KEY_FILE))
private_key = key_data['private_key'].gsub("\n", "")
puts private_key.inspect
claims = {
iss: SERVICE_ACCOUNT_EMAIL,
scope: AUDIENCE,
aud: AUDIENCE,
exp: (Time.now + 60 * 60).to_i # JWT expires in 1 hour
}
credentials = Google::Auth::ServiceAccountCredentials.make_creds(
scope: claims[:scope],
json_key: private_key
)
jwt = credentials.authorization.id_token
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer #{jwt}"
}
# Prepare the Net::HTTP request object
uri = URI(endpoint)
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
request = Net::HTTP::Post.new(uri)
# request.set_header!(*headers) newer ruby versions
headers.each do |key, value|
request.add_field(key, value)
end
request.body = body.to_json
# Send the request and handle response
response = https.request(request)
if response.is_a?(Net::HTTPSuccess)
JSON.parse(response.body)
else
error_message = "Error making GA4 request: #{response.code} - #{response.message}"
puts "Error message: #{error_message}"
puts "Response object: #{response.body}" # Print thend
end
end
end
完全を期すために含めたクエリの本文は次のとおりです
body = {
"reportRequests": [
{
"property": "properties/#{PROPERTY_ID}",
"dateRanges": [{"startDate": report_start_date, "endDate": report_end_date}],
"metrics": [{"expression": "ga:screenPageViews"}],
"dimensions": [{"name": "ga:pagePath"}],
"filters": [{"field": "ga:pagePath", "operator": "REGEXP_CONTAINS", "value": page}],
}
]
}
解決策
require 'googleauth'
require 'net/http'
require 'json'
require 'time'
require './environment' # Make sure you've defined SERVICE_ACCOUNT_KEY_FILE, SERVICE_ACCOUNT_EMAIL, AUDIENCE, PROPERTY_ID, etc.
module GoogleAnalytics
def self.make_ga4_rest_request(body)
# Define GA4 Reporting API endpoint URL
endpoint = "https://analyticsreporting.googleapis.com/v4/reports:batchGet"
key_data = JSON.parse(File.read(SERVICE_ACCOUNT_KEY_FILE))
private_key = key_data['private_key'].gsub("\n", '')
claims = {
iss: SERVICE_ACCOUNT_EMAIL,
scope: AUDIENCE,
aud: AUDIENCE,
exp: (Time.now + 60 * 60).to_i # JWT expires in 1 hour
}
credentials = Google::Auth::ServiceAccountCredentials.make_creds(
scope: claims[:scope],
json_key: private_key
)
jwt = credentials.authorization.id_token
headers = {
'Content-Type': 'application/json',
'Authorization': "Bearer #{jwt}"
}
# Prepare the Net::HTTP request object
uri = URI(endpoint)
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
request = Net::HTTP::Post.new(uri)
headers.each do |key, value|
request.add_field(key, value)
end
request.body = body.to_json
# Send the request and handle response
response = https.request(request)
if response.is_a?(Net::HTTPSuccess)
JSON.parse(response.body)
else
error_message = "Error making GA4 request: #{response.code} - #{response.message}"
puts "Error message: #{error_message}"
puts "Response object: #{response.body}"
end
end
end
# Example usage:
body = {
"reportRequests": [
{
"property": "properties/#{PROPERTY_ID}",
"dateRanges": [{"startDate": report_start_date, "endDate": report_end_date}],
"metrics": [{"expression": "ga:screenPageViews"}],
"dimensions": [{"name": "ga:pagePath"}],
"filters": [{"field": "ga:pagePath", "operator": "REGEXP_CONTAINS", "value": page}]
}
]
}
result = GoogleAnalytics.make_ga4_rest_request(body)
puts result
プレースホルダー (SERVICE_ACCOUNT_KEY_FILE、SERVICE_ACCOUNT_EMAIL、AUDIENCE、PROPERTY_ID など) を実際の値に置き換えてください。この変更されたコードは、サービス アカウントの資格情報を使用して GA4 API への REST リクエストを正しく承認する必要があります。