I'm trying to follow the documentation for analytics reporting, but I'm getting pretty confused between the documentation for Oauth2 (which is in C# but I can't get to work), and the documentation for the analytics reporting API is very sparse (it has examples in Java and Python, but not C#). I've been reading over the following documentation:
https://developers.google.com/analytics/devguides/reporting/core/v4/
https://developers.google.com/analytics/devguides/reporting/core/v4/
https://developers.google.com/api-client-library/dotnet/guide/aaa_oauth
Analytics Reporting API V4 Client Library for .NET
I've put together some code based on the Stack Overflow answer and the Google Developers documentation on Oauth2 for Asp.NET MVC. here is my code:
class GoogleAnalyticsUtil
{
public List<AnalyticsPage> GetReport(DateTime startDate)
{
List<AnalyticsPage> report = new List<AnalyticsPage>();
try
{
var credentialTask = GetCredential();
credentialTask.Wait();
var credential = credentialTask.Result;
using (var svc = new AnalyticsReportingService(
new BaseClientService.Initializer
{
HttpClientInitializer = credential,
ApplicationName = "Google Analytics API Console"
}))
{
var dateRange = new DateRange
{
StartDate = startDate.ToString("yyyy-MM-dd"),
EndDate = DateTime.Now.ToString("yyyy-MM-dd")
};
var sessions = new Metric
{
Expression = "ga:sessions",
Alias = "Sessions"
};
var date = new Dimension { Name = "ga:date" };
var reportRequest = new ReportRequest
{
DateRanges = new List<DateRange> { dateRange },
Dimensions = new List<Dimension> { date },
Metrics = new List<Metric> { sessions },
ViewId = "<<view id>>"
};
var getReportsRequest = new GetReportsRequest
{
ReportRequests = new List<ReportRequest> { reportRequest }
};
var batchRequest = svc.Reports.BatchGet(getReportsRequest);
var response = batchRequest.Execute();
foreach (var x in response.Reports.First().Data.Rows)
{
report.Add(new AnalyticsPage()
{
Path = x.Dimensions.First(),
Views = x.Metrics.First().Values
});
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
return report;
}
static async Task<UserCredential> GetCredential()
{
var clientSecretPath = HttpRuntime.AppDomainAppPath + "client_secret.json";
var credPath = HttpRuntime.AppDomainAppPath + "credentials/GoogleAnalyticsApiConsole/";
UserCredential credential;
using (var stream = new FileStream(clientSecretPath,
FileMode.Open, FileAccess.Read))
{
var secrets = GoogleClientSecrets.Load(stream).Secrets;
credential = await dsAuthorizationBroker.AuthorizeAsync(
secrets,
new[] {AnalyticsReportingService.Scope.Analytics},
"<<username>>",
CancellationToken.None,
new FileDataStore(credPath, true));
return credential;
}
}
}
class AnalyticsPage
{
public string Path { get; set; }
public IList<string> Views { get; set; }
public string ViewString { get; set; }
}
public class dsAuthorizationBroker : GoogleWebAuthorizationBroker
{
public static string RedirectUri = "https://<<my website>>/AuthCallback/IndexAsync";
public new static async Task<UserCredential> AuthorizeAsync(
ClientSecrets clientSecrets,
IEnumerable<string> scopes,
string user,
CancellationToken taskCancellationToken,
IDataStore dataStore = null)
{
var initializer = new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = clientSecrets,
};
return await AuthorizeAsyncCore(initializer, scopes, user,
taskCancellationToken, dataStore).ConfigureAwait(false);
}
private static async Task<UserCredential> AuthorizeAsyncCore(
GoogleAuthorizationCodeFlow.Initializer initializer,
IEnumerable<string> scopes,
string user,
CancellationToken taskCancellationToken,
IDataStore dataStore)
{
initializer.Scopes = scopes;
initializer.DataStore = dataStore ?? new FileDataStore(Folder);
var flow = new dsAuthorizationCodeFlow(initializer);
return await new AuthorizationCodeInstalledApp(flow,
new LocalServerCodeReceiver())
.AuthorizeAsync(user, taskCancellationToken).ConfigureAwait(false);
}
}
public class dsAuthorizationCodeFlow : GoogleAuthorizationCodeFlow
{
public dsAuthorizationCodeFlow(Initializer initializer)
: base(initializer) { }
public override AuthorizationCodeRequestUrl
CreateAuthorizationCodeRequest(string redirectUri)
{
return base.CreateAuthorizationCodeRequest(dsAuthorizationBroker.RedirectUri);
}
}
namespace MySite.Web.Controllers.WebAPI
{
public class AuthCallbackController : Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController
{
protected override Google.Apis.Auth.OAuth2.Mvc.FlowMetadata FlowData
{
get { return new AppFlowMetadata(); }
}
[System.Web.Mvc.HttpGet]
public async Task IndexAsync(CancellationToken cancellationToken)
{
var result = await new AuthorizationCodeMvcApp(this, new AppFlowMetadata()).
AuthorizeAsync(cancellationToken);
if (result.Credential != null)
{
var service = new DriveService(new BaseClientService.Initializer
{
HttpClientInitializer = result.Credential,
ApplicationName = "PMA"
});
// YOUR CODE SHOULD BE HERE..
// SAMPLE CODE:
//var list = await service.Files.List().ExecuteAsync();
}
Response.Redirect(result.RedirectUri);
}
}
}
The authorization in GetCredential()
is failing, with the error
`Failed to launch browser with "https://accounts.google.com/o/oauth2/v2/auth?access_type=offline&response_type=code&client_id=224691372209-3ljoils93ufa13mgk2ahilvniqa30f2p.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fmysite.com%2FAuthCallback%2FIndexAsync&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fanalytics" for authorization. See inner exception for details.
When I try to go directly to mysite.com/AuthCallback/IndexAsync, I get a 404, so maybe that's the problem? But I'm not sure what's wrong with the controller, or why that's causing the authorization to fail. I'm using a Web Application Auth2.0 client ID, but I also tried using type 'Other' which doesn't take RedirectUrls in the parameters, but that didn't work either. Can I get it to authorize without redirecting anywhere? I need credential.result
from the authorization to continue with the rest of my code, or is there another way in C# that I should be getting data from the Google Analytics Reporting API?