I'm trying out a new default clientID dimension in Google Analytic Reporting API.
I keep getting duplicate clientIDs and total event action count for the same day when the RowCount is > 10000. I can easily get rid of unwatned rows but I wonder why it happens.
I retrieve data for one day and filter on Event Action. I get the sampled data.
What's more the count of total events retrieved by Reporting API is larger than the one retrived by User Activity API for the same clientID. The former is sampled while the latter is not so the count should actually be bigger in the second case.
My queries look like this:
Reporting API
query = {
'reportRequests': [
{
'viewId': '',
'dateRanges': [{'startDate':'2019-08-21', 'endDate': '2019-08-21'}],
'metrics': [
{'expression': 'ga:totalEvents'} ],
'dimensions': [{'name':'ga:clientID'}],
'dimensionFilterClauses': [
{ 'operator': 'OR',
'filters': [
{
'dimensionName': 'ga:eventAction',
'not': False,
'expressions':[
''
],
'caseSensitive': False
},
],
}
],
'segments': [],
'samplingLevel':'LARGE',
'pageSize':'10000',
}
]
}
User API
queryUser = {
"viewId": "",
"user": {
"type": "CLIENT_ID",
"userId": ""
},
"dateRange": {
"startDate": "2019-08-21",
"endDate": "2019-08-21",
}
}
It's still an undocumented feature so maybe that's why I'm getting these errors. Or could there be more fixable reasons?
Related
My goal is to pull in purchase transaction count and transaction revenue from a client, segmented by Google Ads campaign ID. My current query looks like the following:
{
"propertyId": "*********",
"query": {
"dateRanges": [
{
"startDate": "2022-09-30",
"endDate": "2022-10-06"
}
],
"dimensions": [
{
"name": "googleAdsCampaignId"
},
{
"name": "googleAdsCampaignName"
}
],
"metrics": [
{
"name": "advertiserAdClicks"
},
{
"name": "advertiserAdCost"
},
{
"name": "transactions"
},
{
"name": "purchaseRevenue"
}
],
"dimensionFilter": {
"andGroup": {
"expressions": [
{
"filter": {
"fieldName": "googleAdsCustomerId",
"stringFilter": {
"matchType": "EXACT",
"value": "*********",
"caseSesnsitive": false
}
}
}
]
}
}
}
}
What I expect when querying the 'transactions' dimension is, as the API schema describes, "The count of transaction events with purchase revenue. Transaction events are in_app_purchase, ecommerce_purchase, purchase, app_store_subscription_renew, app_store_subscription_convert, and refund."
The response from my query comes back with these numbers, for an example campaign:
{
"dimensionValues": [
{
"value": "***********",
"oneValue": "value"
},
{
"value": "Example Campaign",
"oneValue": "value"
}
],
"metricValues": [
{
"value": "2482480",
"oneValue": "value"
},
{
"value": "6492393600000",
"oneValue": "value"
},
{
"value": "331",
"oneValue": "value"
},
{
"value": "31374.205645000002",
"oneValue": "value"
}
]
}
However, if, in the GA4 dashboard, I attempt to view a report of purchase conversions by campaign over the same date range, this is what is displayed for the 'example campaign':
6 Example Campaign 239.47 31,981.63
Where 239.47 is the number of transactions, and 31,981.63 is the event value (transaction revenue). Notably, the transactions are off by over 25%. The revenue/event value is similar but also off by a slight amount. This is consistent for all campaigns under the client, with the API response being significantly (but by varying percentages) higher. The dashboard value is always lower. These numbers don't change if the report is run on different dates.
Additionally, I suspected that there may be some additional event being tracked under the transactions api field that was not displaying in the dashboard, so I also tried adding this filter to my query:
{
"filter": {
"fieldName": "eventName",
"stringFilter": {
"matchType": "EXACT",
"value": "purchase",
"caseSesnsitive": false
}
}
}
the transactions field still came back as 331.
What I want to figure out is if I'm querying the wrong field, the frontend is under reporting data, or the API is over reporting data. I found that I was not able to post on the official GA4 Issue tracker so I've come here.
Someone better versed in GA4 at my company explained that the issue here had to do with dimension scopes. The transactions field is session scoped, but the dimensions I was pulling in were event scoped. This means that the numbers being output were basically meaningless. As a matter of fact through the dashboard, it won't let you create a free-form explore report using the combination of fields that I did in my query, explaining that the metrics are incompatible. It appears to just be a bug that the API would allow that to happen.
As an alternative, I'm now pulling the conversions field, with a filter on eventName as listed above, including only purchase events.
I'm trying to measure the API calls made via my server and instead of storing the API usage in my server I'm pushing it to GA4 using Measurement Protocol. I've successfully implemented it and am pushing events successfully using this code:
$eventData = [
'appInstanceId' => $appInstanceId,
'userId' => $userId,
'events' => [
'name' => 'api_request',
'params' => []
]
];
$firebaseAppId = Settings::get('firebase_app_id');
$appSecret = Settings::get('firebase_api_secret');
$out = Http::get(sprintf('https://www.google-analytics.com/mp/collect?firebase_app_id=%s&api_secret=%s', $firebaseAppId, $appSecret), function ($http) use ($eventData) {
$http->setOption(CURLOPT_POSTFIELDS, json_encode($eventData));
});
Which is basically a PHP adaptation of this code.
And it successfully pushes the event to firebase and I can even view it on the firebase analytics console. However, when I try to fetch the same using the GA4 data API, it fails. I tried to manually create the metric from the Google Analytics dashboard "Custom Definitions" tab's and it appeared in the meta API and it showed under the metrics array. However, when I fetch the data it fails.
I was experimenting a bit and tried renaming the field to api_request_2 and used the same code. This time when I went to the custom definitions section, it auto-created the field except as a "dimension". I was confused and so I tried doing a fetch of the same using runReport API, except this time using it as a dimension, and the metric as eventCount. That actually worked and returned a result. But this isn't useful for me because I need it as a metric so I can put it on a graph against it's dimension (Date) so I have a count of the APIs requests on a per-day basis. How do I go about making this work?
If you're trying to get a count of "API requests" events on a per-day basis, you don't need to use Custom Definitions. The Measurement Protocol code that you shared will send events with an eventName of api_request. You can create a per-day report through the GA4 Data API through the following request:
POST https://analyticsdata.googleapis.com/v1alpha:runReport
{
"entity": { "propertyId": "YOUR_GA4_PROPERTY_ID" },
"dateRanges": [{ "startDate": "2021-03-01", "endDate": "2021-03-20" }],
"dimensions": [{ "name": "date" }],
"metrics": [{ "name": "eventCount" }],
"dimensionFilter": {
"filter": {
"fieldName": "eventName",
"stringFilter": {
"value": "api_request"
}
}
},
}
There are examples of using dimension filters in the Data API here.
What could you use custom definitions for?
If you want to log additional information about the request, you could add an event parameter, register a custom definition, and use the custom definition in a Data API request. For example, let's say you're making API requests to multiple APIs (the Drive API and the Youtube API for example). You could add a api_method parameter to the event like this:
$eventData = [
'appInstanceId' => $appInstanceId,
'userId' => $userId,
'events' => [
'name' => 'api_request',
'params' => [
'api_method': 'drive-api'
]
]
];
After registering a Custom Definition for the parameter api_method, you can use the parameter in Reports (Guide). This request creates a per-day report through the GA4 Data API that is additionally broken down by api_method:
POST https://analyticsdata.googleapis.com/v1alpha:runReport
{
"entity": { "propertyId": "YOUR_GA4_PROPERTY_ID" },
"dateRanges": [{ "startDate": "2021-03-01", "endDate": "2021-03-20" }],
"dimensions": [{ "name": "date" },{ "name": "customEvent:api_method" }],
"metrics": [{ "name": "eventCount" }],
"dimensionFilter": {
"filter": {
"fieldName": "eventName",
"stringFilter": {
"value": "api_request"
}
}
},
}
An example response row for the Report follows. This row would mean you logged 1337 request to the drive-api on March 10th.
"rows": [
...
{
"dimensionValues": [
{
"value": "20210310"
},
{
"value": "drive-api"
}
],
"metricValues": [
{
"value": "1337"
}
]
},
...
In docs for Google Analytics API Response body contains queryCost and resourceQuotasRemaining. But, when I do
curl -i -H 'Content-Type: application/json' -X POST 'https://analyticsreporting.googleapis.com/v4/reports:batchGet?access_token=mytoken' -d '{"reportRequests":[{"viewId":"ga:myviewId","dateRanges":[{"startDate":"2019-12-04","endDate":"2019-12-04"}],"dimensions":[{"name":"ga:campaign"},{"name":"ga:adContent"},{"name":"ga:keyword"},{"name":"ga:currencyCode"}],"dimensionFilterClauses":[{"filters":[{"dimensionName":"ga:sourceMedium","operator":"EXACT","expressions":["Yandex.Market / cpc"]}]},{"filters":[{"dimensionName":"ga:campaign","operator":"PARTIAL","expressions":["msk"]}]}],"metrics":[{"expression":"ga:goal12Completions"}],"metricFilterClauses":[{"filters":[{"metricName":"ga:goal12Completions","operator":"GREATER_THAN","comparisonValue":"0"}]}],"hideTotals":true,"hideValueRanges":true}]}'
response body do not contain queryCost and resourceQuotasRemaining
{"reports":[{"columnHeader":{"dimensions":[...],"metricHeader":{"metricHeaderEntries":[...]}},"data":{"rows":[{"dimensions":[...],"metrics":[...]}],"rowCount":1,"isDataGolden":true}}]}
If I add to JSON in POST "useResourceQuotas":true, I get error: "The request is not eligible for resource quotas. Check if account is premium and whitelisted." (code 400).
How I can get information about query cost, quotas remaining and other limit stats using API? Or it is possible only for premium accounts?
Pete,
Resource based quota feature is only available to Analytics 360 users.
Thanks,
Ilya
your request doesn't include useResourceQuotas = true. its default false
{
"reportRequests": [
{
"viewId": "ga:xxxx",
"dateRanges": [
{
"startDate": "2019-12-04",
"endDate": "2019-12-04"
}
],
"metrics": [
{
"expression": "ga:users"
}
],
"hideTotals": true,
"hideValueRanges": true
}
],
"useResourceQuotas": true
}
Result
{
"reports": [
{
"columnHeader": {
"metricHeader": {
"metricHeaderEntries": [
{
"name": "ga:users",
"type": "INTEGER"
}
]
}
},
"data": {
"rows": [
{
"metrics": [
{
"values": [
"1298"
]
}
]
}
],
"rowCount": 1,
"isDataGolden": true
}
}
],
"resourceQuotasRemaining": {
"dailyQuotaTokensRemaining": 100000,
"hourlyQuotaTokensRemaining": 25000
}
}
useResourceQuotas
Doesn't work with every request. I would suggest that you go though yours adding different things to see what the exact problem is. Start by removing all those filters. Once you figure out exactly which one is giving you the error with the userREsourceQuotas let me know and i will ping the team about having the documentation updated. It doesnt say currently that there should be an issue with using it with anything. I cant test your request I dont have any accounts with goals setup like that that i could test with.
Can someone give an example of the query to be used?How do we access the acquisitions and then campaign data from that ?
The simplest method would be to make an Analytics Reporting API V4 request with the ga:newusers metric and the ga:source, ga:medium, ga:campaign.
POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
"reportRequests":
[
{
"viewId": "1174",
"dateRanges":
[
{
"startDate": "2014-11-01",
"endDate": "2014-11-30"
}
],
"metrics":
[
{
"expression": "ga:newusers"
}
],
"dimensions":
[
{
"name": "ga:campaign"
},
{
"name": "ga:source"
},
{
"name": "ga:medium"
}
]
}
]
}
And again in the API Explorer.
The API also allows you to construct a cohort request to measure engagement overtime.
If you are new to Google's APIs, they make available many client libraries as well as set of quickstart guides.
I'm trying to make calls the Analytics Reporting API V4 and keep getting back unspecific error messages when trying to use certain dimensions and metrics. For example, I consistently get
{
"error": {
"code": 400,
"message": "Unknown dimension(s): ga:acquisitionTrafficChannel",
"status": "INVALID_ARGUMENT"
}
}
when passing ga:acquisitionTrafficChannel, despite it being documented as a valid dimension. Similarly, I get
{
"error": {
"code": 400,
"message": "Selected dimensions and metrics cannot be queried together.",
"status": "INVALID_ARGUMENT"
}
}
when passing ga:acquisitionSourceMedium (documented here), even when not passing any metrics whatsoever.
Are the docs out of date? Is there some documentation elsewhere about valid combinations of dimensions and metrics?
All the Lifetime Value reports and thus ga:acquisition... dimensions are only valid for App views not web views.
Secondly the cohort/LTV dimensions can only be queried in within a cohort requests for example:
POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
"reportRequests": [
{
"viewId": "XXXX",
"dimensions": [
{
"name": "ga:cohort"
},
{
"name": "ga:acquisitionTrafficChannel"
}
],
"metrics": [
{
"expression": "ga:cohortSessionsPerUser"
}
],
"cohortGroup": {
"cohorts": [
{
"name": "cohort 1",
"type": "FIRST_VISIT_DATE",
"dateRange": {
"startDate": "2015-08-01",
"endDate": "2015-09-01"
}
},
{
"name": "cohort 2",
"type": "FIRST_VISIT_DATE",
"dateRange": {
"startDate": "2015-07-01",
"endDate": "2015-08-01"
}
}
],
"lifetimeValue": true
}
}
]
}
The error messages should probably be a bit clearer.
I ran into this problem as well. When I was in the Google Analytics Dashboard, I clicked on Acquisition->All Traffic->Channels and was fooled into thinking that I needed to combine the ga:acquisitionMedium dimension and ga:newUsers metric together.
When I clicked on ga:acquisitionMedium, it said that combining it with ga:newUsers was valid, despite the error that you mentioned in your question! In reality, I just needed to combine ga:medium and ga:newUsers together.
I know this is not the exact query that you were doing, but here is an example of how I queried New Users count where the dimension channel equaled "organic" (note that I am forming the JSON request with Javascript and then using JSON.stringify(req) to send it):
var req = {
reportRequests: [{
viewId: '<Your Google Analytics view ID>',
dimensions: [{ name: 'ga:medium' }],
dimensionFilterClauses: [{
filters: [{
dimensionName: 'ga:medium',
operator: 'EXACT',
expressions: ['organic']
}]
}],
dateRanges: [{ startDate: '2019-11-01', endDate: '2019-11-30' }],
metrics: [{ expression: "ga:newUsers" }]
}]
};
The above query returns 5,654, which is the same as seen in the "Acquisition" section of Google Analytics.
I definitely think the documentation and error message around this could be improved.