يقدّم هذا الدليل إرشادات لنقل بيانات الإصدار الثالث من واجهة برمجة التطبيقات الأساسية لإعداد التقارير إلى الإصدار الرابع من واجهة برمجة التطبيقات لإعداد التقارير في "إحصاءات Google".
مقدمة
للاستفادة من الميزات الجديدة التي تم تقديمها في الإصدار 4 من Analytics Reporting API، انقل الرمز لاستخدام واجهة برمجة التطبيقات. يعرض هذا الدليل الطلبات في الإصدار الثالث من واجهة برمجة التطبيقات الأساسية لإعداد التقارير والطلبات المشابهة في الإصدار الرابع من واجهة برمجة التطبيقات لإعداد التقارير في "إحصاءات Google" لتسهيل نقل البيانات.
نقل بيانات بايثون
إذا كنت من مطوّري لغة Python، استخدِم مكتبة المساعدة GAV4 على GitHub لتحويل طلبات الإصدار 3 من Google Analytics Core Reporting API إلى طلبات الإصدار 4 من Analytics Reporting API.
نقاط النهاية
يحتوي الإصدار الثالث من Core Reporting API عن الإصدار 4 من Analytics Reporting API على نقاط نهاية مختلفة وطرق HTTP مختلفة:
الإصدار 3: نقطة النهاية
GET https://www.googleapis.com/analytics/v3/data/ga
الإصدار 4: نقطة النهاية
POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
تقارن الأمثلة التالية بين طلب في الإصدار 3 وطلب مكافئ في الإصدار 4:
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&dimensions=ga:pagePath
v4
الإصدار 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"
}]
}]
}
خدمة مكتبات العملاء واستكشافها
إذا كنت تستخدم لغة Python أو JavaScript أو أيّ مكتبة برامج أخرى تعتمد على خدمة Google Discovery، عليك تحديد موقع مستند الاكتشاف الخاص بالإصدار 4 من Reporting API.
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(...)
وقد تم إنشاء مكتبات عملاء Java وPHP مسبقًا، ولكن يمكنك استخدام خدمة الاكتشاف ومنشئ Google APIs لإنشائها.
طلبات
يصف مرجع الإصدار 4 من واجهة برمجة التطبيقات بنية نص الطلب بالتفصيل. تصف الأقسام التالية نقل معلَمات طلب الإصدار 3 إلى معلَمات طلب الإصدار 4.
عرض أرقام التعريف
في الإصدار 3، تكون المَعلمة ids
التي تقبل "معرّف الجدول" بتنسيق ga:XXXX
،
حيث يكون XXXX
هو معرّف الملف الشخصي. في الإصدار 4، يتم تحديد رقم تعريف الملف الشخصي
في الحقل viewId
في نص الطلب.
تقارن الأمثلة التالية المعلَمة ids
في طلب الإصدار 3 والحقل viewId
في طلب الإصدار 4:
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",
...
}]
}
النطاقات الزمنية
يتيح لك الإصدار 4 من Analytics Reporting API تحديد نطاقات زمنية متعددة في طلب واحد. يأخذ الحقل dateRanges
قائمة بكائنات DateRange.
في الإصدار 3، يمكنك استخدام المعلمتين start-date
وend-date
لتحديد نطاق زمني
في الطلب.
تقارن الأمثلة التالية بين المعلمتَين start-date
وend-date
في طلب الإصدار 3 والحقل dateRanges
في طلب الإصدار 4:
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"
}],
....
}]
}
المقاييس
تتوافق المَعلمة v3 metrics
مع الحقل metrics
في الإصدار 4 الذي يتضمّن قائمة بكائنات
المقاييس.
تقارن الأمثلة التالية بين معلَمات metrics
في طلب الإصدار 3
والحقل metrics
في طلب الإصدار 4:
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"
}],
...
}]
}
الأبعاد
تتوافق المعلَمة v3 dimensions
مع الحقل dimensions
v4 الذي يتضمّن قائمة بكائنات السمة.
تقارن الأمثلة التالية بين معلَمات dimensions
في طلب الإصدار 3
والحقل dimensions
في طلب الإصدار 4:
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"
}],
...
}]
}
ترتيب
تُعادل المَعلمة v3 sort
الحقل v4
orderBys
الذي يأخذ قائمة بكائنات OrderBy.
في الإصدار 4، لترتيب النتائج حسب قيمة سمة أو مقياس:
- أدخِل اسمه أو اسمه المستعار من خلال
الحقل
fieldName
. - حدِّد نظام الفرز (
ASCENDING
أوDESCENDING
) من خلال الحقلsortOrder
.
تقارن الأمثلة التالية المعلَمة sort
في طلب الإصدار 3 والحقل orderBy
في طلب الإصدار 4. كلتاهما ترتّب المستخدمين بترتيب تنازلي والمصادر أبجديًا:
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"
}],
}]
}
مستوى أخذ العينات
تتوافق المعلَمة v3 samplingLevel
مع الحقل v4
samplingLevel
. في الإصدار 3، تكون قيم samplingLevel
المقبولة هي FASTER
وHIGHER_PRECISION
وDEFAULT
، وفي الإصدار 4، تكون قيم samplingLevel
المقبولة هي SMALL
وLARGE
وDEFAULT
.
يُرجى العِلم أنّه تم تغيير FASTER
في الإصدار 3 إلى SMALL
في الإصدار 4 وHIGHER_PRECISION
إلى LARGE
.
تقارن الأمثلة التالية المعلَمة samplingLevel
في طلب الإصدار 3
والحقل samplingLevel
في طلب الإصدار 4:
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"
}]
}
الشرائح
تتوافق المعلَمة v3 segment
مع الحقل v4
segments
الذي يضم قائمة بكائنات الشريحة.
أرقام تعريف الشرائح
في الإصدار 4، لطلب شريحة حسب رقم تعريف الشريحة، يمكنك إنشاء عنصر شريحة وإدخال رقم تعريفه من خلال الحقل segmentId.
تقارن الأمثلة التالية المعلَمة segment
في طلب الإصدار 3
والحقل segments
في طلب الإصدار 4:
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"
}]
}]
}
الشرائح الديناميكية
في الإصدار 4، للتعبير عن تعريفات الشرائح الأكثر تعقيدًا، استخدِم الحقل segments
الذي يتضمّن كائن DynamicSegment.
تقارن الأمثلة التالية المعلَمة segment
في طلب الإصدار 3 والحقل segments
الذي يحتوي على عنصر DynamicSegment
في طلب الإصدار 4:
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" ]
}
}]
}]
}
}]
}
}
}]
}]
}
يمكنك الجمع بين الشروط والتسلسلات في شريحة:
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"]
}
}]
}]
}]
}
}]
}
}
}]
}]
v3 بنية الشرائح في v4
يتيح الحقل segmentId في v4 API بنية الشريحة في واجهة برمجة التطبيقات v3.
توضّح الأمثلة التالية كيفية توافق الحقل segmentId
في الطلب المكافئ في الإصدار 4 مع المعلَمة segment
في الطلب ذي الإصدار 3:
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"
}]
}]
}
فلاتر
يستخدم الإصدار 4 dimensionFilterClauses
لفلترة السمات،
وmetricFilterClauses
لفلترة المقاييس. تحتوي السمة dimensionFilterClauses
على قائمة بكائنات
DimensionFilter،
وتحتوي metricFilterClauses
على قائمة بكائنات MetricFilter.
تقارن الأمثلة التالية المعلَمة filters
في طلب الإصدار 3
والحقل dimensionFilterClauses
في طلب الإصدار 4:
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"]
}]
}]
}]
بنية فلاتر الإصدار 3 في الإصدار 4
على الرغم من أنّ الحقل filtersExpression
في الإصدار 4 يتوافق مع بنية filters
في الإصدار 3، يمكنك استخدام
dimensionFilterClauses
وmetricFilterClauses
لفلترة السمات والمقاييس.
توضّح الأمثلة التالية كيفية توافق الحقل filtersExpression
في الطلب المكافئ في الإصدار 4 مع المعلَمة filters
في الطلب ذي الإصدار 3:
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"
}]
}
صفوف فارغة
تتجاوب معلمة v3 include-empty-rows
مع الحقل
includeEmptyRows
في الإصدار 4. يتم ضبط المَعلمة v3 تلقائيًا على true، بينما يتم ضبط قيمة الحقل
التلقائي في الإصدار 4 على false. إذا لم يتم ضبط القيمة في الإصدار 3، ستحتاج إلى ضبط القيمة على true في الإصدار 4.
تقارن الأمثلة التالية المَعلمة include-empty-rows
في طلب الإصدار 3 بالحقل includeEmptyRows
في طلب الإصدار 4:
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",
}]
}
تقسيم النتائج على عدّة صفحات
يستخدم الإصدار 4 الحقلين pageToken
وpageSize
للتقسيم على صفحات عدد كبير من النتائج. يتم الحصول على pageToken
من السمة
nextPageToken
لكائن الاستجابة.
تقارن الأمثلة التالية بين المعلمتَين start-index
وmax-results
في طلب الإصدار 3
مع الحقلين pageToken
وpageSize
في طلب الإصدار 4:
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",
}]
}
المَعلمات القياسية
يتوافق الإصدار 4 من Analytics Reporting API مع معظم
مَعلمات طلب البحث العادية
في الإصدار 3 من واجهة برمجة التطبيقات، باستثناء المَعلمتَين userIp
وcallback
.
تقارن الأمثلة التالية المعلَمة quotaUser
في طلب الإصدار 3 بتلك المعلَمة في طلب الإصدار 4:
الإصدار 3: نقطة النهاية
GET https://www.googleapis.com/analytics/v3/data/ga?quotaUser=1X3F2F2
الإصدار 4: نقطة النهاية
POST https://analyticsreporting.googleapis.com/v4/reports:batchGet?quotaUser=1X3F2F2
الردود
بما أنّ الإصدار 4 يسمح لك بإرسال كائنات ReportRequest متعددة في طلب HTTP واحد، ستحصل على مصفوفة من كائنات التقرير في الاستجابة. مقابل كل ReportRequest يتم إرساله، يمكنك الحصول على تقرير مقابل في الرد.
التقارير
يتضمّن تقرير الإصدار 4
ثلاثة حقول من المستوى الأعلى: columnHeader
وdata
وnextPageToken
.
بما أنّ نص الاستجابة v4 لا يتضمّن ردودًا على جميع مَعلمات طلب البحث كما هو الحال في الاستجابة v3، يجب أن يضيف تطبيق العميل هذه المَعلمة إلى ReportRequest للحصول على استجابة لمَعلمة طلب بحث محدَّدة.
لقد عالجنا nextPageToken
في قسم تقسيم النتائج على عدّة صفحات، لذا لنلقِ نظرة أولاً على كائن columnHeader.
عنوان العمود
يحتوي عنوان العمود على قائمة السمات المُسمّاة والكائن MetricHeader الذي يحتوي على قائمة بكائنات MetricHeaderEntry. يحدِّد كل عنصر MetricHeaderEntry
المقياس name
وtype
الخاص به (العملة والنسبة المئوية وما إلى ذلك).
، مما يساعدك على تنسيق المخرجات.
تقارن الأمثلة التالية الحقل columnHeaders
في استجابة الإصدار 3
والحقل columnHeader
في استجابة الإصدار 4:
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"
}
]
}
},
صفوف التقرير
يعرض الإصدار الثالث من "واجهة برمجة التطبيقات الأساسية لإعداد التقارير" بيانات التقارير في مصفوفة الصفوف التي تحتوي على السمات والمقاييس المطلوبة.
يعرض الإصدار 4 من "واجهة برمجة التطبيقات لإعداد التقارير في Analytics" بيانات التقرير في عنصر ReportRow، الذي يحتوي على مصفوفة من السمات ومصفوفة من عناصر DateRangeValues، يحتوي كل منها على نطاق زمني واحد أو نطاقين، كما يوضِّح الرسم البياني التالي:
الصفوف
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"
]
}
]
}
],
عينات البيانات
إذا كانت النتائج مستنِدة إلى عيّنات، يعرض الإصدار الثالث من واجهة برمجة التطبيقات الأساسية لإعداد التقارير الحقل المنطقي
containsSampledData
،
المعيّن على true
.
لا يعرض الإصدار 4 من "إحصاءات Google Reporting API" قيمة منطقية إذا كانت البيانات مستندة إلى عيّنات، بل تعرض واجهة برمجة التطبيقات الحقلَين samplesReadCounts
وsamplingSpaceSizes
.
وإذا لم تكن النتائج مستندة إلى عيّنات، لن يتم تحديد هذه الحقول.
يوضّح مثال بايثون التالي كيفية احتساب ما إذا كان التقرير يحتوي على عيّنات بيانات:
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
يوجد أدناه مثال للرد الذي يحتوي على عينة بيانات من طلب بنطاقين زمنيين. تم احتساب النتائج من حوالي 500 ألف عينة لمساحة أخذ العينات حوالي 15 مليون جلسة:
{
"reports":
[
{
"columnHeader": {
...
},
"data": {
...
"samplesReadCounts": [ "499630","499630"],
"samplingSpaceSizes": ["15328013","15328013"],
}
}
]
}
تحليل الاستجابة الإصدار 4
يُحلل نموذج الرمز التالي الاستجابة للإصدار 4 من Analytics Reporting API يطبعها:
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));
}
}
}
}
}
خطأ أثناء المعالجة
نظرًا لاختلاف تنسيق استجابة الخطأ في الإصدار 4 عن تنسيقه في الإصدار 3، عدِّل الرمز للتعامل مع استجابات الخطأ في الإصدار 4.
تقارن الأمثلة التالية بين استجابة الخطأ في الإصدار 3 واستجابة الخطأ المكافئة في الإصدار 4:
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.\" }"
}
]
}
}