You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用服务账号授权Ruby REST请求访问GA4 API?报错排查

GA4 API REST请求认证报错及数据差异排查

问题背景

我已经通过Ruby的google-analytics-data gem实现了从GA4 API获取指定页面路径的浏览量数据,但发现GA4查询资源管理器和我的Ruby代码返回结果存在显著差异——部分路径数据一致,但多数不一致。为了对比结果,我尝试用基础REST请求调用API,却持续遇到认证错误。

报错信息

触发的错误如下:

/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)
      # GA4 Reporting API 端点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 1小时后过期
         }
        
      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}"
      }
             
      # 准备Net::HTTP请求对象
      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) 适用于较新版本Ruby
      headers.each do |key, value|
        request.add_field(key, value)
      end

      request.body = body.to_json

      # 发送请求并处理响应
      response = https.request(request)
      if response.is_a?(Net::HTTPSuccess)
        JSON.parse(response.body)
      else
        error_message = "GA4请求出错: #{response.code} - #{response.message}"  
        puts "错误信息: #{error_message}"
        puts "响应内容: #{response.body}"
      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}], 
    }
  ]
}

内容的提问来源于stack exchange,提问作者markhorrocks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 12:53:19