5

I'm fetching Google Analytics data using Core Reporting API v4. I'm able to capture at most 10,000 records for a given combination of Dimensions & Metrics. My question is that if my query can produce more than 10,000 search results then how can I fetch all those records? I have gone through the documentation and found that in a single request we can't access more than 10,000 records by setting the properties of ReportRequest object.

ReportRequest request = new ReportRequest()
    .setDateRanges(Arrays.asList(dateRange)) 
    .setViewId(VIEW_ID)
    .setDimensions(Arrays.asList(dimension))
    .setMetrics(Arrays.asList(metric))
    .setPageSize(10000); 

How can we enable multiple requests in a single run depending upon the number of search-results that can be obtained.

For example : If my query can return 35,000 records then there should be 4 requests (10,000,10,000, 10,000 & 3,500) managed internally.

Please look into this and facilitate me some guidance. Thanks in Advance.

Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
Balajee Venkatesh
  • 1,041
  • 2
  • 18
  • 39

3 Answers3

3

The Analytics Core Reporting API returns a maximum of 10,000 rows per request, no matter how many you ask for.

If the request you are making will generate more then 10000 rows then there will be additional rows you can request. The response returned from the first request will contain a parameter called nextPageToken which you can use to request the next set of data.

You will have to dig around the Java library the only documentation on how to do it I have found is HTTP.

POST https://analyticsreporting.googleapis.com/v4/reports:batchGet
{
  "reportRequests":[
  {
    ...
    # Taken from `nextPageToken` of a previous response.
    "pageToken": "XDkjaf98234xklj234",
    "pageSize": "10000",
  }]
}
Linda Lawton - DaImTo
  • 106,405
  • 32
  • 180
  • 449
  • Is there a way to know the number of actual records my request is supposed to return in Java ? – Balajee Venkatesh Jun 27 '16 at 12:08
  • the result set return should have something like total rows. Note I contacted someone to see if I can find you some sample code for Java. Have to wait to see if they reply to this or not. – Linda Lawton - DaImTo Jun 27 '16 at 14:03
  • 1
    You should look at the [ReportData rowCount](https://developers.google.com/analytics/devguides/reporting/core/v4/rest/v4/reports/batchGet#ReportData.FIELDS.row_count). `response.getReports()[0].getData().getRowCount()`. The [reference docs](https://developers.google.com/analytics/devguides/reporting/core/v4/rest/v4/reports/batchGet) should really help you out. Each object there becomes a class in the Java client libraries, each field becomes a property you can access with `getProperty()`. – Matt Jun 27 '16 at 14:49
  • I'm able to find the total number of records my request is supposed to return using 'response.getReports().get(0).getData().getRowCount()' . Now, I literally need sone help in implementing the iteration of 'nextPageToken' in Java. I have added the 'setPageToken(null)' property into the request but how can I enable iterating through the nextPage and display all the records? – Balajee Venkatesh Jun 28 '16 at 07:55
3

Here's a stable and extensively tested solution in Java. It is a recursive solution that stores every 10000 results batch (if any) and recalls itself until finds a null nextToken. In this specific solution every 10000 results batch is saved into a csv and then a recursive call is performed! Note that the first time this function called from somewhere outside, the nextPageToken is also null!! Focus on the recursive rationale and the null value check!

private static int getComplexReport(AnalyticsReporting service,int 
reportIndex,java.lang.String startDate,String endDate,ArrayList<String>
metricNames,ArrayList<String> dimensionNames,String pageToken)    
throws IOException

ReportRequest req = createComplexRequest(startDate,endDate,metricNames,dimensionNames,pageToken);

ArrayList<ReportRequest> requests = new ArrayList<>();
requests.add(req);

// Create the GetReportsRequest object.
GetReportsRequest getReport = new GetReportsRequest()
    .setReportRequests(requests);

// Call the batchGet method.
GetReportsResponse response = service.reports().batchGet(getReport).execute();
      //printResponse(response);


saveBatchToCsvFile("dummy_"+startDate+"_"+endDate+"_"+Integer.toString(reportIndex)+".csv",startDate+"_"+endDate,response,metricNames,dimensionNames);
String nextToken = response.getReports().get(0).getNextPageToken();
//System.out.println(nextToken);
if(nextToken!=null)
    return getComplexReport(service,reportIndex+1,"2016-06-21","2016-06-21",metricNames,dimensionNames,nextToken);

return reportIndex; 
} 
P. Str
  • 580
  • 1
  • 5
  • 18
  • If you need to change extractionDate you should put some "logic" inside the above code and play with the handy Date java libraries during every recursion. – P. Str Jun 28 '16 at 14:00
  • The code really helped me a lot. Now, the only thing I'm stuck is the 'startDate' for the next iteration. I'm working on this to resolve. If you have any suggestion to make, Please let me know how to change the 'startDate' for each iteration. – Balajee Venkatesh Jun 29 '16 at 09:15
  • Hi again! I'm glad that I helped you but since it helped you a lot please upVote my answer...just to be fair. What exactly do you mean by startDate problem? Do you want to perform multiple runs for multiple dateRanges? – P. Str Jun 29 '16 at 09:34
  • 'startDate' problem means suppose there are 15000 records for date 01-01-2015 to 01-08-2015. For the first iteration 10000 results are returned for date-range 01-01-2015 to 25-07-2015. Now for the next iteration the remaining records starting from 25-07-2015 to 01-08-2015 how will the getComplexMethod() get the corresponding 'startDate' and 'endDate' parameter? There is no need to change the 'endDate' but how will the 'startDate' be updated automatically for next iteration. – Balajee Venkatesh Jun 29 '16 at 09:47
  • The above code performs as many iterations as needed for a specific DateRange. In the specific code there are the hardcoded values "2016-06-21","2016-06-21" which means that all results will be fetched for one day time range(2016-06-21). If you want to get all the results for a different date range you should trigger a different call of getComplexReport from an external function with a different dateRange. If you want to programmaticaly change your date range see this: http://stackoverflow.com/questions/428918/how-can-i-increment-a-date-by-one-day-in-java – P. Str Jun 29 '16 at 09:55
  • Forgot to mention that in the code above, the number of batch per query is the reportIndex variable. You can see that each recursion call uses "reportIndex+1" value. The last recursion returns the number of batches fetched for this query. – P. Str Jun 29 '16 at 15:44
  • Thanks a lot. I have resolved 'startDate' problem now.My logic brings the 'date' whenever the 10,000th record is fetched and next recursion is triggered. I pass this 'date' as a 'startDate' for the next recursion and this process continues till the last record. Just a little java logic and it worked perfectly. – Balajee Venkatesh Jun 30 '16 at 03:27
  • Hi. Glad I helped you, but you downVoted my answer. Don't you think that this is the best answer to your problem since it helped you do want you wanted to? – P. Str Jun 30 '16 at 08:18
  • Hey !!! Trust me I have no idea of this. I can't see my votes because I'm newbie here. Hope you can see my up-vote now. – Balajee Venkatesh Jun 30 '16 at 13:20
  • Yes my friend! Thanks! – P. Str Jun 30 '16 at 13:21
0
var reportRequest = new ReportRequest
{
    DateRanges = new List<DateRange> { dateRange },
    Dimensions = new List<Dimension> { date, UserId, DeviceCategory},
    Metrics = new List<Metric> { sessions },
    ViewId = view,
    PageSize = 400000
};
Robert
  • 7,394
  • 40
  • 45
  • 64
siva
  • 9
  • 1
  • 3
    While this code may answer the question, providing additional context regarding *how* and *why* it solves the problem would improve the answer's long-term value. – Alexander Aug 22 '18 at 16:34
  • This is a comment on a rather old post, but I couldn't find any examples of working with pageTokens using C#. I got an application which imports data from Google Analytics into a table in SQL server. I deleted all existing data in the existing SQL table and set a high number on PageSize. It actually works, and I got approx. 20,000 records imported, even though the documentation states that pageSize can only hold a value of maximum 10,000. Perhaps the library does the pagination using pageToken itself or perhaps the pageSize limitation is increased. – Cenderze Dec 06 '18 at 15:45