Reputation: 16089
I am trying to connect to the Google Analytics API from a .NET application. Here is the code I've come up with:
Public Function GetData() As String
Dim client As AssertionFlowClient = New AssertionFlowClient(GoogleAuthenticationServer.Description,
New X509Certificate2("C:\Users\xxxxx\privatekey.p12", "notasecret",
X509KeyStorageFlags.Exportable Or X509KeyStorageFlags.MachineKeySet)) With {
.Scope = "analytics.readonly",
.ServiceAccountId = "[email protected]"}
Dim authenticator As OAuth2Authenticator(Of AssertionFlowClient) = New OAuth2Authenticator(Of AssertionFlowClient)(client, AddressOf AssertionFlowClient.GetState)
Dim service As AnalyticsService = New AnalyticsService(authenticator)
Dim profileId As String = "ga:xxxxx"
Dim startDate As String = "2013-02-15"
Dim endDate As String = "2013-02-20"
Dim metrics As String = "ga:visitors"
Dim request As DataResource.GaResource.GetRequest = service.Data.Ga.Get(profileId, startDate, endDate, metrics)
Dim data As GaData = request.Fetch()
Return data.ToString()
End Function
My problem is that when I hit this method, I get an exception on the request.Fetch()
line that says "Error occurred while sending a direct message or getting the response." The inner exception says, "The remote server returned an error: (400) Bad Request."
This error is obviously pretty vague. According to Google's documentation of the error codes, 400 Bad Request indicates that the input parameters don't make sense somehow. Can anyone diagnose the problem by looking at the parameters in my code? Otherwise, how would I even begin to track down what I'm doing wrong? There's virtually no information presented in the error.
(At least I've gotten past the authentication stage... I think.)
Upvotes: 0
Views: 4188
Reputation: 16089
Borrowing extensively from this answer, the solution I came up with is this:
Imports System.Security.Cryptography.X509Certificates
Imports Google.Apis.Analytics.v3
Imports Google.Apis.Analytics.v3.Data
Imports Google.Apis.Authentication.OAuth2
Imports Google.Apis.Authentication.OAuth2.DotNetOpenAuth
Imports System.Security.Cryptography
Public Class GoogleAnalytics
Private _profileId As String
Private _service As AnalyticsService
''' <summary>
''' Creates an instance of the Google Analytics interface
''' </summary>
''' <param name="profileId">The Google Analytics profile ID, in the form "ga:123456789". This is *not* the same as the ID number used in the GA JavaScript to initialize the tracking! The number you want is in Google Analytics > Admin > (your profile) > Profile Settings.</param>
''' <param name="serviceAccountId">The e-mail address of the Service Account that will access the API. These accounts can be generated from the Google API Console and then authorized by adding the e-mail address to the list of authorized users in Google Analytics.</param>
''' <param name="privateKeyPath">The path to the private-key (.p12) file from Google.</param>
''' <param name="certificatePassword">The password for the private key. Probably "notasecret".</param>
''' <remarks>Once created, this GoogleAnalytics object can be used to make an arbitrary number of requests.</remarks>
Public Sub New(profileId As String, serviceAccountId As String, privateKeyPath As String, certificatePassword As String)
Dim cert As X509Certificate2 = New X509Certificate2(privateKeyPath, certificatePassword, X509KeyStorageFlags.Exportable Or X509KeyStorageFlags.MachineKeySet)
Dim client As AssertionFlowClient = New AssertionFlowClient(GoogleAuthenticationServer.Description, cert) With {.Scope = "https://www.googleapis.com/auth/analytics.readonly",
.ServiceAccountId = serviceAccountId}
Dim authenticator As OAuth2Authenticator(Of AssertionFlowClient) = New OAuth2Authenticator(Of AssertionFlowClient)(client, AddressOf AssertionFlowClient.GetState)
_service = New AnalyticsService(authenticator)
_profileId = profileId
End Sub
Public Function GetData(startDate As String, endDate As String, metrics As String, dimensions As String, Optional filters As String = Nothing) As GaData
Dim request As DataResource.GaResource.GetRequest = _service.Data.Ga.Get(_profileId, startDate, endDate, metrics)
request.Dimensions = dimensions
If filters IsNot Nothing Then
request.Filters = filters
End If
Return request.Fetch()
End Function
End Class
This is a standalone class that can be used as follows:
Dim analytics As New GoogleAnalytics("ga:12345678", "[email protected]", "C:\privatekey.p12", "notasecret")
Dim data as GaData = analytics.GetData(DateTime.Now.AddDays(-30).ToString("yyyy-MM-dd"),
DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd"),
"ga:totalEvents",
"ga:eventCategory,ga:eventAction")
The biggest gotcha I found with this was the Profile ID. This is not the ID number that you pass to Google's Javascript tracking code; instead, it's a number that you find in Google Analytics > Admin > (your profile) > Profile Settings. Hope this helps someone else!
Upvotes: 1