Hướng dẫn di chuyển

Hướng dẫn này cung cấp các nguyên tắc để di chuyển API Báo cáo chính phiên bản 3 sang API Báo cáo Analytics phiên bản 4.

Giới thiệu

Để tận dụng các tính năng mới được ra mắt trong API Báo cáo Analytics phiên bản 4, hãy di chuyển mã của bạn để sử dụng API này. Hướng dẫn này hiển thị các yêu cầu trong API Báo cáo chính phiên bản 3 và các yêu cầu tương đương trong API Báo cáo Analytics phiên bản 4 để giúp bạn di chuyển dễ dàng hơn.

Di chuyển Python

Nếu bạn là nhà phát triển Python, hãy sử dụng thư viện trình trợ giúp GAV4 trên GitHub để chuyển đổi các yêu cầu API Báo cáo chính của Google Analytics phiên bản 3 thành các yêu cầu API Báo cáo Analytics phiên bản 4

Thiết bị đầu cuối

API Báo cáo chính phiên bản 3 và API Báo cáo Analytics phiên bản 4 có các điểm cuối và phương thức HTTP khác nhau:

Thiết bị đầu cuối phiên bản 3

GET https://www.googleapis.com/analytics/v3/data/ga

Thiết bị đầu cuối phiên bản 4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet

Dưới đây là ví dụ so sánh một yêu cầu trong phiên bản 3 và yêu cầu tương đương trong phiên bản 4:

v3

Tài liệu tham khảo phiên bản 3

GET https://www.googleapis.com/analytics/v3/data/ga?ids=ga:XXXX \
    &start-date=2015-11-01&end-date=2015-11-06 \
    &metrics=ga:users&dimensions=ga:pagePath

v4

Tài liệu tham khảo phiên bản 4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
  "reportRequests":[
  {
    "viewId":"XXXX",
    "dateRanges":[
    {
      "startDate":"2015-11-01",
      "endDate":"2015-11-06"
    }],
    "metrics":[
    {
      "expression":"ga:users"
    }],
    "dimensions": [
    {
      "name":"ga:pagePath"
    }]
  }]
}

Dịch vụ khám phá và thư viện ứng dụng

Nếu sử dụng Python, JavaScript hoặc thư viện ứng dụng khác dựa trên Google Discovery Service, bạn cần cung cấp vị trí của tài liệu khám phá cho API Báo cáo phiên bản 4.

Python

from apiclient import discovery

...

# Build the Analytics Reporting API v4 authorized service object.
analyticsReporting = discovery.build(
  'analyticsreporting',
  'v4',
  http=http,
  discoveryServiceUrl='https://analyticsreporting.googleapis.com/$discovery/rest')

JavaScript

gapi.client.load(
  'https://analyticsreporting.googleapis.com/$discovery/rest',
  'v4'
).then(...)

Thư viện ứng dụng Java và PHP được tạo sẵn, nhưng bạn cũng có thể sử dụng dịch vụ khám phá và trình tạo API của Google để tạo các thư viện đó.

Yêu cầu

Tài liệu tham khảo API v4 mô tả chi tiết cấu trúc của nội dung yêu cầu. Các phần sau đây mô tả cách di chuyển tham số yêu cầu v3 sang tham số yêu cầu v4.

Mã chế độ xem

Trong phiên bản 3, tham số ids chấp nhận "mã bảng" có định dạng ga:XXXX, trong đó XXXX là mã chế độ xem (hồ sơ). Trong phiên bản 4, mã chế độ xem (hồ sơ) được chỉ định trong trường viewId trong nội dung yêu cầu.

Các ví dụ sau đây so sánh tham số ids trong yêu cầu v3 và trường viewId trong yêu cầu v4:

v3

GET https://www.googleapis.com/analytics/v3/data/ga?ids=ga:XXXX

v4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
  "reportRequests":[
  {
    "viewId":"XXXX",
    ...
  }]
}

Phạm vi ngày

API Báo cáo Analytics phiên bản 4 cho phép bạn chỉ định nhiều phạm vi ngày trong một yêu cầu. Trường dateRanges sẽ lấy danh sách các đối tượng DateRange. Trong phiên bản 3, bạn sử dụng các tham số start-dateend-date để chỉ định phạm vi ngày trong một yêu cầu.

Các ví dụ sau đây so sánh các tham số start-dateend-date trong yêu cầu v3 và trường dateRanges trong yêu cầu v4:

v3

GET https://www.googleapis.com/analytics/v3/data/ga?ids=ga:XXXX \
    &start-date=2015-11-01&end-date=2015-11-06 \
    ...

v4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
  "reportRequests":[
  {
    "viewId":"XXXX",
    "dateRanges":[
    {
      "startDate":"2015-11-01",
      "endDate":"2015-11-06"
    }],
    ....
  }]
}

Chỉ số

Tham số metrics của v3 tương ứng với trường metrics của v4. Trường này chứa danh sách các đối tượng Chỉ số.

Các ví dụ sau đây so sánh các tham số metrics trong yêu cầu v3 và trường metrics trong yêu cầu v4:

v3

GET https://www.googleapis.com/analytics/v3/data/ga?ids=ga:XXXX \
    &start-date=2015-11-01&end-date=2015-11-06 \
    &metrics=ga:users,ga:sessions \
    ...

v4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
  "reportRequests":[
  {
    "viewId":"XXXX",
    "dateRanges":[
    {
      "startDate":"2015-11-01",
      "endDate":"2015-11-06"
    }],
    "metrics":[
    {
      "expression":"ga:users"
    },{
      "expression":"ga:sessions"
    }],
    ...
  }]
}

Kích thước

Thông số dimensions của v3 tương ứng với trường dimensions của phiên bản 4. Trường này chứa danh sách các đối tượng Thứ nguyên.

Các ví dụ sau đây so sánh các tham số dimensions trong yêu cầu v3 và trường dimensions trong yêu cầu v4:

v3

GET https://www.googleapis.com/analytics/v3/data/ga?ids=ga:XXXX \
  &dimensions=ga:country,ga:browser&... \

v4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
  "reportRequests":[
  {
    ...
    "dimensions": [
    {
      "name":"ga:country"
    },{
      "name":"ga:browser"
    }],
    ...
  }]
}

Sắp xếp

Tham số sort của v3 tương đương với trường orderBys của v4. Trường này chứa danh sách các đối tượng OrderBy (Đơn đặt hàng).

Trong phiên bản 4, cách sắp xếp kết quả theo giá trị phương diện hoặc chỉ số:

  • Cung cấp tên hoặc email đại diện thông qua trường fieldName.
  • Hãy chỉ định thứ tự sắp xếp (ASCENDING hoặc DESCENDING) thông qua trường sortOrder.

Các ví dụ sau đây so sánh tham số sort trong yêu cầu v3 và trường orderBy trong yêu cầu v4; cả hai đều sắp xếp người dùng theo thứ tự giảm dần và nguồn theo thứ tự bảng chữ cái:

v3

GET https://www.googleapis.com/analytics/v3/data/ga?ids=ga:XXXX \
  &sort=-ga:users,ga:source

v4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
  "reportRequests":[
  {
    ...
    "orderBys": [
    {
      "fieldName": "ga:users",
      "sortOrder": "DESCENDING"
    },{
      "fieldName": "ga:source"
    }],
  }]
}

Mức lấy mẫu

Tham số samplingLevel của v3 tương ứng với trường samplingLevel của v4. Ở phiên bản 3, các giá trị samplingLevel được chấp nhận là FASTER, HIGHER_PRECISIONDEFAULT; còn trong phiên bản 4, các giá trị samplingLevel được chấp nhận là SMALL, LARGEDEFAULT. Xin lưu ý FASTER trong phiên bản 3 đã được thay đổi thành SMALL trong phiên bản 4, HIGHER_PRECISION thành LARGE.

Các ví dụ sau đây so sánh tham số samplingLevel trong yêu cầu v3 và trường samplingLevel trong yêu cầu v4:

v3

https://www.googleapis.com/analytics/v3/data/ga?ids=ga:XXXX ...\
samplingLevel=HIGHER_PRECISION

v4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
  "reportRequests":[
  {
    ...
    "samplingLevel": "LARGE"
  }]
}

Phân đoạn

Tham số segment của v3 tương ứng với trường segments của v4. Trường này lấy danh sách các đối tượng Segment (Phân đoạn).

Mã phân đoạn

Trong phiên bản 4, để yêu cầu một phân khúc theo mã phân khúc, hãy tạo đối tượng Phân khúc và cung cấp mã của phân khúc đó thông qua trường segmentId.

Các ví dụ sau đây so sánh tham số segment trong yêu cầu v3 và trường segments trong yêu cầu v4:

v3

GET https://www.googleapis.com/analytics/v3/data/ga?ids=ga:XXXX \
&segment=gaid::-11

v4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
  "reportRequests": [{
    ...
    "viewId": "XXXX",
    "segments": [{
      "segmentId": "gaid::-11"
    }]
  }]
}

Phân đoạn động

Trong phiên bản 4, để thể hiện các định nghĩa phân đoạn phức tạp hơn, hãy sử dụng trường segments bao gồm đối tượng DynamicSegment (Phân đoạn động).

Các ví dụ sau đây so sánh tham số segment trong yêu cầu v3 và trường segments chứa đối tượng DynamicSegment trong yêu cầu v4:

v3

GET https://www.googleapis.com/analytics/v3/data/ga?ids=ga:XXXX \
&segment=sessions::condition::ga:medium==referral

v4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
  "reportRequests": [{
    ...
    "segments": [{
      "dynamicSegment": {
        "name": "segment_name",
        "sessionSegment": {
          "segmentFilters": [{
            "simpleSegment": {
              "orFiltersForSegment": [{
                "segmentFilterClauses": [{
                  "dimensionFilter": {
                    "dimensionName": "ga:medium",
                    "operator": "EXACT",
                    "expressions": [ "referral" ]
                  }
                }]
              }]
            }
          }]
        }
      }
    }]
  }]
}

Bạn có thể kết hợp các điều kiện và chuỗi trong một phân đoạn:

v3

GET https://www.googleapis.com/analytics/v3/data/ga?ids=ga:XXXX \
&segment=users::condition::ga:revenue>10;sequence::ga:deviceCategory==desktop->>ga:deviceCategory==mobile

v4

  "reportRequests": [{
      "dateRanges": [
            { "endDate": "2014-11-30", "startDate": "2014-11-01" }
      ],
      "metrics": [
          {"expression": "ga:pageviews"},
          {"expression": "ga:sessions"}
      ],
      "viewId": "XXXX",
      "dimensions":[{"name":"ga:medium"}, {"name":"ga:segment"}],
      "segments": [{
        "dynamicSegment": {
        "name": "segment_name",
        "userSegment": {
          "segmentFilters": [{
            "simpleSegment": {
              "orFiltersForSegment": [{
                "segmentFilterClauses": [{
                  "metricFilter": {
                    "metricName": "ga:sessions",
                    "operator": "GREATER_THAN",
                    "comparisonValue": "10"
                  }
                }]
              }]
            }
          },
          {
            "sequenceSegment": {
              "segmentSequenceSteps": [{
                "orFiltersForSegment": [{
                  "segmentFilterClauses": [{
                    "dimensionFilter": {
                      "dimensionName": "ga:deviceCategory",
                      "operator": "EXACT",
                      "expressions": ["desktop"]
                    }
                  }]
                }],
                "matchType": "PRECEDES"
              },{
                "orFiltersForSegment": [{
                  "segmentFilterClauses": [{
                    "dimensionFilter": {
                      "dimensionName": "ga:deviceCategory",
                      "operator": "EXACT",
                      "expressions": ["mobile"]
                    }
                  }]
                }]
              }]
            }
          }]
        }
      }
    }]
  }]

Cú pháp phân đoạn trong v3

Trường segmentId trong API v4 hỗ trợ cú pháp phân đoạn trong API v3.

Các ví dụ sau đây cho thấy cách trường segmentId hỗ trợ tham số segment trong một yêu cầu v3 trong yêu cầu tương đương trong v4:

v3

GET https://www.googleapis.com/analytics/v3/data/ga?ids=ga:XXXX \
&segment=sessions::condition::ga:medium==referral

v4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
  "reportRequests": [{
    ...
    "viewId": "XXXX",
    "segments": [{
      "segmentId": "sessions::condition::ga:medium==referral"
    }]
  }]
}

Bộ lọc

Phiên bản 4 sử dụng dimensionFilterClauses để lọc phương diện và metricFilterClauses để lọc chỉ số. dimensionFilterClauses chứa danh sách đối tượng DimensionFilter; và metricFilterClauses chứa danh sách đối tượng MetricFilter.

Các ví dụ sau đây so sánh tham số filters trong yêu cầu v3 và trường dimensionFilterClauses trong yêu cầu v4:

v3

GET https://www.googleapis.com/analytics/v3/data/ga?ids=ga:XXXX \
  &start-date=2015-06-01&end-date=2015-07-31&metrics=ga:users& \
  dimensions=ga:browser&filters=ga:browser==Firefox

v4

  "reportRequests": [{
      "dateRanges": [
            { "endDate": "2014-11-30", "startDate": "2014-11-01" }
      ],
      "metrics": [
          {"expression": "ga:pageviews"},
          {"expression": "ga:sessions"}
      ],
      "viewId": "XXXX",
      "dimensions":[{"name":"ga:browser"}, {"name":"ga:country"}],
      "dimensionFilterClauses": [{
           "filters": [{
                "dimension_name": "ga:browser",
                "operator": "EXACT",
                "expressions": ["Firefox"]
            }]
      }]
  }]

Cú pháp bộ lọc v3 trong v4

Mặc dù trường filtersExpression (bộ lọc) trong v4 hỗ trợ cú pháp filters trong v3, nhưng hãy sử dụng dimensionFilterClausesmetricFilterClauses để lọc các phương diện và chỉ số.

Các ví dụ sau đây cho thấy cách trường filtersExpression hỗ trợ tham số filters trong một yêu cầu v3 trong yêu cầu tương đương trong v4:

v3

GET https://www.googleapis.com/analytics/v3/data/ga?ids=ga%XXXX \
&filters=ga:browser==Firefox

v4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
  "reportRequests": [{
    ...
    "filtersExpression": "ga:browser==Firefox"
  }]
}

Hàng trống

Tham số include-empty-rows của v3 tương ứng với trường includeEmptyRows trong v4. Tham số v3 mặc định là true, còn trong v4, trường mặc định là false. Nếu chưa đặt giá trị trong v3, bạn cần đặt giá trị thành true trong v4.

Các ví dụ sau đây so sánh tham số include-empty-rows trong yêu cầu v3 với trường includeEmptyRows trong yêu cầu v4:

v3

https://www.googleapis.com/analytics/v3/data/ga? ...\
    &include-empty-rows=true

v4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
  "reportRequests":[
  {
    ...
    "includeEmptyRows": "true",
  }]
}

Phân trang

v4 sử dụng các trường pageTokenpageSize để phân trang thông qua một số lượng lớn kết quả. pageToken được lấy từ thuộc tính nextPageToken của đối tượng phản hồi.

Các ví dụ sau đây so sánh các tham số start-indexmax-results trong yêu cầu v3 với các trường pageTokenpageSize trong yêu cầu v4:

v3

https://www.googleapis.com/analytics/v3/data/ga? ...\
    &start-index=10001&max-results=10000

v4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
  "reportRequests":[
  {
    ...
    # Taken from `nextPageToken` of a previous response.
    "pageToken": "10000",
    "pageSize": "10000",
  }]
}

Thông số tiêu chuẩn

API Báo cáo Analytics phiên bản 4 hỗ trợ hầu hết các tham số truy vấn chuẩn trong API phiên bản 3, ngoại trừ các tham số userIpcallback.

Các ví dụ sau đây so sánh tham số quotaUser trong yêu cầu v3 với tham số trong yêu cầu v4:

Thiết bị đầu cuối phiên bản 3

GET https://www.googleapis.com/analytics/v3/data/ga?quotaUser=1X3F2F2

Thiết bị đầu cuối phiên bản 4

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet?quotaUser=1X3F2F2

Phản hồi

Vì v4 cho phép bạn gửi nhiều đối tượng ReportRequest trong một yêu cầu HTTP, nên bạn sẽ nhận được một loạt các đối tượng báo cáo trong phản hồi. Đối với mỗi ReportRequest được gửi, bạn sẽ nhận được một Báo cáo tương ứng trong phản hồi.

Báo cáo

Báo cáo phiên bản 4 có 3 trường cấp cao nhất: columnHeader, datanextPageToken.

Do nội dung phản hồi v4 không bao gồm các phản hồi cho mọi tham số truy vấn như phản hồi v3, nên để nhận được phản hồi cho một tham số truy vấn cụ thể, ứng dụng khách phải thêm tham số đó vào ReportRequest.

Chúng tôi đã giải quyết nextPageToken trong phần Phân trang, vì vậy, trước tiên hãy xem đối tượng columnHeader.

Tiêu đề cột

Tiêu đề cột chứa danh sách các phương diện được đặt tên và đối tượng MetricHeader. Các đối tượng này chứa danh sách các đối tượng MetricHeaderEntry. Mỗi đối tượng MetricHeaderEntry chỉ định chỉ số nametype của chỉ số đó (đơn vị tiền tệ, phần trăm, v.v.) để giúp bạn định dạng đầu ra.

Các ví dụ sau đây so sánh trường columnHeaders trong phản hồi v3 với trường columnHeader trong phản hồi v4:

v3

"columnHeaders": [
    {
        "name":"ga:source",
        "columnType":"DIMENSION",
        "dataType":"STRING"
    },{
        "name":"ga:city",
        "columnType":"DIMENSION",
        "dataType":"STRING"
    },{
        "name":"ga:sessions",
        "columnType":"METRIC",
        "dataType":"INTEGER"
    },{
        "name":"ga:pageviews",
        "columnType":
        "METRIC",
        "dataType":"INTEGER"
    }
]

v4

"columnHeader": {
    "dimensions": [
        "ga:source",
        "ga:city"
    ],
    "metricHeader": {
        "metricHeaderEntries": [
            {
                "name": "ga:pageviews",
                "type": "INTEGER"
            },
            {
                "name": "ga:sessions",
                "type": "INTEGER"
            }
        ]
    }
},

Hàng báo cáo

API Báo cáo chính phiên bản 3 sẽ trả về dữ liệu báo cáo trong mảng rows (hàng), chứa các phương diện và chỉ số được yêu cầu.

API Báo cáo Analytics phiên bản 4 sẽ trả về dữ liệu báo cáo trong một đối tượng ReportRow, chứa một mảng phương diện và một mảng các đối tượng DateRangeValues, mỗi đối tượng chứa một hoặc hai phạm vi ngày, như biểu đồ sau đây mô tả:

Hàng báo cáo

Hàng

v3

"rows": [
    [
        "google",
        "Philadelphia",
        "60",
        "5"
    ],
    [
        "google",
        "Johnstown",
        "21",
        "1"
    ],
    [
        "google",
        "Progress",
        "7",
        "1"
    ]
],

v4

"rows": [
    {
        "dimensions": [
            "google",
            "Philadelphia"
        ],
        "metrics": [
            {
                "values": [
                    "60",
                    "5"
                ]
            }
        ]
    },
    {
        "dimensions": [
            "google",
            "Johnstown"
        ],
        "metrics": [
            {
                "values": [
                    "21",
                    "1"
                ]
            }
        ]
    },
    {
        "dimensions": [
            "google",
            "Progress"
        ],
        "metrics": [
            {
                "values": [
                    "7",
                    "1"
                ]
            }
        ]
    }
],

Dữ liệu được lấy mẫu

Nếu kết quả được lấy mẫu, API Báo cáo chính v3 sẽ trả về trường boolean containsSampledData được đặt thành true.

API Báo cáo Analytics phiên bản 4 không trả về giá trị boolean nếu dữ liệu được lấy mẫu; thay vào đó, API sẽ trả về các trường samplesReadCountssamplingSpaceSizes. Nếu kết quả không được lấy mẫu thì các trường này sẽ không được xác định. Ví dụ dùng đoạn mã Python sau đây cho thấy cách tính toán xem một báo cáo có chứa dữ liệu được lấy mẫu hay không:

def ContainsSampledData(report):
  """Determines if the report contains sampled data.

   Args:
       report (Report): An Analytics Reporting API v4 response report.

  Returns:
      bool: True if the report contains sampled data.
  """
  report_data = report.get('data', {})
  sample_sizes = report_data.get('samplesReadCounts', [])
  sample_spaces = report_data.get('samplingSpaceSizes', [])
  if sample_sizes and sample_spaces:
    return True
  else:
    return False

Dưới đây là phản hồi mẫu chứa dữ liệu được lấy mẫu của một yêu cầu có 2 phạm vi ngày. Kết quả được tính toán từ gần 500 nghìn mẫu có quy mô không gian lấy mẫu khoảng 15 triệu phiên:

{
  "reports":
  [
    {
      "columnHeader": {
        ...
      },
      "data": {
        ...
        "samplesReadCounts": [ "499630","499630"],
        "samplingSpaceSizes": ["15328013","15328013"],
      }
    }
  ]
}

Phân tích cú pháp phản hồi v4

Mã mẫu sau đây sẽ phân tích cú pháp và in phản hồi của Analytics Reporting API phiên bản 4:

Python

def printResponse(self, response):
  """Parses and prints the Analytics Reporting API v4 response"""

  for report in response.get('reports', []):
    columnHeader = report.get('columnHeader', {})
    dimensionHeaders = columnHeader.get('dimensions', [])
    metricHeaders = columnHeader.get('metricHeader', {}).get('metricHeaderEntries', [])
    rows = report.get('data', {}).get('rows', [])

    for row in rows:
      dimensions = row.get('dimensions', [])
      dateRangeValues = row.get('metrics', [])

      for header, dimension in zip(dimensionHeaders, dimensions):
        print header + ': ' + dimension

      for i, values in enumerate(dateRangeValues):
        print 'Date range (' + str(i) + ')'
        for metricHeader, value in zip(metricHeaders, values.get('values')):
          print metricHeader.get('name') + ': ' + value

Java

public static void printResponse(GetReportsResponse response) {

  for (Report report: response.getReports()) {
    ColumnHeader header = report.getColumnHeader();
    List<String> dimensionHeaders = header.getDimensions();
    List<MetricHeaderEntry> metricHeaders = header.getMetricHeader().getMetricHeaderEntries();
    List<ReportRow> rows = report.getData().getRows();

    for (ReportRow row: rows) {
      List<String> dimensions = row.getDimensions();
      List<DateRangeValues> metrics = row.getMetrics();
      for (int i = 0; i < dimensionHeaders.size() && i < dimensions.size(); i++) {
        System.out.println(dimensionHeaders.get(i) + ": " + dimensions.get(i));
      }

      for (int j = 0; j < metrics.size(); j++) {
        System.out.print("Date Range (" + j + "): ");
        DateRangeValues values = metrics.get(j);
        for (int k = 0; k < values.size() && k < metricHeaders.size(); k++) {
          System.out.println(metricHeaders.get(k).getName() + ": " + values.get(k));
        }
      }
    }
  }
}

Xử lý lỗi

Vì định dạng phản hồi lỗi trong v4 khác với định dạng trong v3, hãy cập nhật mã của bạn để xử lý các phản hồi lỗi v4.

Các ví dụ sau đây so sánh phản hồi lỗi trong v3 và phản hồi lỗi tương đương trong v4:

v3

{
 "error": {
  "errors": [
   {
    "domain": "global",
    "reason": "insufficientPermissions",
    "message": "User does not have sufficient permissions for this profile.",

   }
  ],
  "code": 403,
  "message": "User does not have sufficient permissions for this profile."
 }
}

v4

{
 "error": {
  "code": 403,
  "message": "User does not have sufficient permissions for this profile.",
  "status": "PERMISSION_DENIED",
  "details": [
   {
    "@type": "type.googleapis.com/google.rpc.DebugInfo",
    "detail": "[ORIGINAL ERROR] generic::permission_denied: User does not have sufficient permissions for this profile. [google.rpc.error_details_ext] { message: \"User does not have sufficient permissions for this profile.\" }"
   }
  ]
 }
}