Steve Borman
Steve Borman

Reputation: 375

Google Analytics Realtime API .Net Client

Does anyone have any example c# code they can share using the Google.Apis.Analytics.v3 API and server authentication to get the current number of users on my website.

Background: I have an MVC internal website that has a support dashboard. It hooks into may different API's to collate some useful data. I have had a request to add the number of users currently on the our website as seen in the Google Analytics web portal.

I don't want to have users sign in using a google account individually, I was hoping I could use the "ServiceCredentials" method but I've got lost.

Appreciate any help.

Thanks

Upvotes: 1

Views: 1563

Answers (1)

Linda Lawton - DaImTo
Linda Lawton - DaImTo

Reputation: 117281

Make sure you grant your service account access in Google analytics at the account level.

Warning: The quota on the Google Analytics api is 10000 requests per day per view. If you make more then 10000 requests in a day you are going to be locked out. Don't try to refresh the real-time data to often, ideally do it in a background script once a minute or something.

Auth:

    /// <summary>
    /// Authenticating to Google using a Service account
    /// Documentation: https://developers.google.com/accounts/docs/OAuth2#serviceaccount
    /// </summary>
    /// <param name="serviceAccountEmail">From Google Developer console https://console.developers.google.com</param>
    /// <param name="serviceAccountCredentialFilePath">Location of the .p12 or Json Service account key file downloaded from Google Developer console https://console.developers.google.com</param>
    /// <returns>AnalyticsService used to make requests against the Analytics API</returns>
    public static AnalyticsService AuthenticateServiceAccount(string serviceAccountEmail, string serviceAccountCredentialFilePath)
    {
        try
        {
            if (string.IsNullOrEmpty(serviceAccountCredentialFilePath))
                throw new Exception("Path to the service account credentials file is required.");
            if (!File.Exists(serviceAccountCredentialFilePath))
                throw new Exception("The service account credentials file does not exist at: " + serviceAccountCredentialFilePath);
            if (string.IsNullOrEmpty(serviceAccountEmail))
                throw new Exception("ServiceAccountEmail is required.");

            // These are the scopes of permissions you need. It is best to request only what you need and not all of them
            string[] scopes = new string[] { AnalyticsReportingService.Scope.Analytics };             // View your Google Analytics data

            // For Json file
            if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".json")
            {
                GoogleCredential credential;
                using (var stream = new FileStream(serviceAccountCredentialFilePath, FileMode.Open, FileAccess.Read))
                {
                    credential = GoogleCredential.FromStream(stream)
                         .CreateScoped(scopes);
                }

                // Create the  Analytics service.
                return new AnalyticsService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Analytics Service account Authentication Sample",
                });
            }
            else if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".p12")
            {   // If its a P12 file

                var certificate = new X509Certificate2(serviceAccountCredentialFilePath, "notasecret", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable);
                var credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail)
                {
                    Scopes = scopes
                }.FromCertificate(certificate));

                // Create the  Analytics service.
                return new AnalyticsService(new BaseClientService.Initializer()
                {
                    HttpClientInitializer = credential,
                    ApplicationName = "Analytics Authentication Sample",
                });
            }
            else
            {
                throw new Exception("Unsupported Service accounts credentials.");
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine("Create service account AnalyticsService failed" + ex.Message);
            throw new Exception("CreateServiceAccountAnalyticsFailed", ex);
        }
    }
}

Request:

public static class RealtimeSample
{

    public class RealtimeGetOptionalParms
    {
        /// A comma-separated list of real time dimensions. E.g., 'rt:medium,rt:city'.
        public string Dimensions { get; set; }  
        /// A comma-separated list of dimension or metric filters to be applied to real time data.
        public string Filters { get; set; }  
        /// The maximum number of entries to include in this feed.
        public int Max-results { get; set; }  
        /// A comma-separated list of dimensions or metrics that determine the sort order for real time data.
        public string Sort { get; set; }  

    }

    /// <summary>
    /// Returns real time data for a view (profile). 
    /// Documentation https://developers.google.com/analytics/v3/reference/realtime/get
    /// Generation Note: This does not always build corectly.  Google needs to standardise things I need to figuer out which ones are wrong.
    /// </summary>
    /// <param name="service">Authenticated analytics service.</param>  
    /// <param name="ids">Unique table ID for retrieving real time data. Table ID is of the form ga:XXXX, where XXXX is the Analytics view (profile) ID.</param>
    /// <param name="metrics">A comma-separated list of real time metrics. E.g., 'rt:activeUsers'. At least one metric must be specified.</param>
    /// <param name="optional">Optional paramaters.</param>        /// <returns>RealtimeDataResponse</returns>
    public static RealtimeData Get(analyticsService service, string ids, string metrics, RealtimeGetOptionalParms optional = null)
    {
        try
        {
            // Initial validation.
            if (service == null)
                throw new ArgumentNullException("service");
            if (ids == null)
                throw new ArgumentNullException(ids);
            if (metrics == null)
                throw new ArgumentNullException(metrics);

            // Building the initial request.
            var request = service.Realtime.Get(ids, metrics);

            // Applying optional parameters to the request.                
            request = (RealtimeResource.GetRequest)SampleHelpers.ApplyOptionalParms(request, optional);

            // Requesting data.
            return request.Execute();
        }
        catch (Exception ex)
        {
            throw new Exception("Request Realtime.Get failed.", ex);
        }
    }


}
    public static class SampleHelpers
{

    /// <summary>
    /// Using reflection to apply optional parameters to the request.  
    /// 
    /// If the optonal parameters are null then we will just return the request as is.
    /// </summary>
    /// <param name="request">The request. </param>
    /// <param name="optional">The optional parameters. </param>
    /// <returns></returns>
    public static object ApplyOptionalParms(object request, object optional)
    {
        if (optional == null)
            return request;

        System.Reflection.PropertyInfo[] optionalProperties = (optional.GetType()).GetProperties();

        foreach (System.Reflection.PropertyInfo property in optionalProperties)
        {
            // Copy value from optional parms to the request.  They should have the same names and datatypes.
            System.Reflection.PropertyInfo piShared = (request.GetType()).GetProperty(property.Name);
            if (property.GetValue(optional, null) != null) // TODO Test that we do not add values for items that are null
                piShared.SetValue(request, property.GetValue(optional, null), null);
        }

        return request;
    }
}

Code ripped from my sample project for Google Analytics API v3 I also have a tutorial which can be found here Google Analytics Real-Time API with C# – What's happening now!

Upvotes: 1

Related Questions