استفاده از نگارش سوم Google Analytics API در سرویس‌های ویندوز یا برنامه‌های وب
اندازه‌ی قلم متن
تخمین مدت زمان مطالعه‌ی مطلب: هفت دقیقه

در زمان نگارش این مطلب، آخرین نگارش API مخصوص Google Analytics، نگارش سوم آن است و ... کار کردن با آن دارای مراحل خاصی است که حتما باید رعایت شوند. در غیر اینصورت عملا در یک برنامه‌ی وب یا سرویس ویندوز قابل اجرا نخواهند بود. زیرا در حالت متداول کار با API مخصوص Google Analytics، ابتدا یک صفحه‌ی لاگین به Gmail باز می‌شود که باید به صورت اجباری، مراحل آن را انجام داد تا مشخصات تائید شده‌ی اکانت در حال استفاده‌ی از API، در پوشه‌ی AppData ویندوز برای استفاده‌های بعدی ذخیره شود. این مورد برای یک برنامه‌ی دسکتاپ معمولی مشکل ساز نیست؛ زیرا کاربر برنامه، به سادگی می‌تواند صفحه‌ی مرورگری را که باز شده‌است، دنبال کرده و به اکانت گوگل خود وارد شود. اما این مراحل را نمی‌توان در یک برنامه‌ی وب یا سرویس ویندوز پیگیری کرد، زیرا عموما امکان لاگین از راه دور به سرور و مدیریت صفحه‌ی لاگین به Gmail وجود ندارد یا بهتر است عنوان شود، بی‌معنا است. برای حل این مشکل، گوگل راه حل دیگری را تحت عنوان اکانت‌های سرویس، ارائه داده است که پس از ایجاد آن، یک یک فایل X509 Certificate برای اعتبارسنجی سرویس، در اختیار برنامه نویس قرار می‌گیرد تا بدون نیاز به لاگین دستی به Gmail، بتواند از API گوگل استفاده کند. در ادامه نحوه‌ی فعال سازی این قابلیت و استفاده از آن‌را بررسی خواهیم کرد.


ثبت برنامه‌ی خود در گوگل و انجام تنظیمات آن

اولین کاری که برای استفاده از نگارش سوم Google Analytics API باید صورت گیرد، ثبت برنامه‌ی خود در Google Developer Console است. برای این منظور ابتدا به آدرس ذیل وارد شوید:
سپس بر روی دکمه‌ی Create project کلیک کنید. نام دلخواهی را وارد کرده و در ادامه بر روی دکمه‌ی Create کلیک نمائید تا پروفایل این پروژه ایجاد شود.



تنها نکته‌ی مهم این قسمت، بخاطر سپردن نام پروژه است. زیرا از آن جهت اتصال به API گوگل استفاده خواهد شد.
پس از ایجاد پروژه، به صفحه‌ی آن وارد شوید و از منوی سمت چپ صفحه، گزینه‌ی Credentials را انتخاب کنید. در ادامه در صفحه‌ی باز شده، بر روی دکمه‌ی Create new client id کلیک نمائید.


در صفحه‌ی باز شده، گزینه‌ی Service account را انتخاب کنید. اگر سایر گزینه‌ها را انتخاب نمائید، کاربری که قرار است از API استفاده کند، باید بتواند توسط مرورگر نصب شده‌ی بر روی کامپیوتر اجرا کننده‌ی برنامه، یکبار به گوگل لاگین نماید که این مورد مطلوب برنامه‌های وب و همچنین سرویس‌ها نیست.


در اینجا ابتدا یک فایل مجوز p12 را به صورت خودکار دریافت خواهید کرد و همچنین پس از ایجاد client id، نیاز است، ایمیل آن‌را جایی یادداشت نمائید:


از این ایمیل و همچنین فایل p12 ارائه شده، جهت لاگین به سرور استفاده خواهد شد.
همچنین نیاز است تا به برگه‌ی APIs پروژه‌ی ایجاد شده رجوع کرد و گزینه‌ی Analytics API آن‌را فعال نمود:


تا اینجا کار ثبت و فعال سازی برنامه‌ی خود در گوگل به پایان می‌رسد.


دادن دسترسی به Client ID ثبت شده در برنامه‌ی Google Analytics

پس از اینکه Client ID سرویس خود را ثبت کردید، نیاز است به اکانت Google Analytics خود وارد شوید. سپس در منوی آن، گزینه‌ی Admin را پیدا کرده و به آن قسمت، وارد شوید:


در ادامه به گزینه‌ی User management آن وارد شده و به ایمیل Client ID ایجاد شده در قسمت قبل، دسترسی خواندن و آنالیز را اعطاء کنید:


در صورت عدم رعایت این مساله، کلاینت API، قادر به دسترسی به Google Analytics نخواهد بود.


استفاده از نگارش سوم Google Analytics API در دات نت

قسمت مهم کار، تنظیمات فوق است که در صورت عدم رعایت آن‌ها، شاید نصف روزی را مشغول به دیباگ برنامه شوید. در ادامه نیاز است پیشنیازهای دسترسی به نگارش سوم Google Analytics API را نصب کنیم. برای این منظور، سه بسته‌ی نیوگت ذیل را توسط کنسول پاورشل نیوگت، به برنامه اضافه کنید:
 PM> Install-Package Google.Apis
PM> Install-Package Google.Apis.auth
PM> Install-Package Google.Apis.Analytics.v3
پس از نصب، کلاس GoogleAnalyticsApiV3 زیر، جزئیات دسترسی به Google Analytics API را کپسوله می‌کند:
using System;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using Google.Apis.Analytics.v3;
using Google.Apis.Analytics.v3.Data;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Services;

namespace GoogleAnalyticsAPIv3Tests
{
    public class AnalyticsQueryParameters
    {
        public DateTime Start { set; get; }
        public DateTime End { set; get; } 
        public string Dimensions { set; get; } 
        public string Filters { set; get; }
        public string Metrics { set; get; }
    }

    public class AnalyticsAuthentication
    {
        public Uri SiteUrl { set; get; }
        public string ApplicationName { set; get; }
        public string ServiceAccountEmail { set; get; }
        public string KeyFilePath { set; get; }
        public string KeyFilePassword { set; get; }

        public AnalyticsAuthentication()
        {
            KeyFilePassword = "notasecret";
        }
    }

    public class GoogleAnalyticsApiV3
    {
        public AnalyticsAuthentication Authentication { set; get; }
        public AnalyticsQueryParameters QueryParameters { set; get; }

        public GaData GetData()
        {
            var service = createAnalyticsService();
            var profile = getProfile(service);
            var query = service.Data.Ga.Get("ga:" + profile.Id,
                                QueryParameters.Start.ToString("yyyy-MM-dd"),
                                QueryParameters.End.ToString("yyyy-MM-dd"),
                                QueryParameters.Metrics);
            query.Dimensions = QueryParameters.Dimensions;
            query.Filters = QueryParameters.Filters;
            query.SamplingLevel = DataResource.GaResource.GetRequest.SamplingLevelEnum.HIGHERPRECISION;
            return query.Execute();
        }

        private AnalyticsService createAnalyticsService()
        {
            var certificate = new X509Certificate2(Authentication.KeyFilePath, Authentication.KeyFilePassword, X509KeyStorageFlags.Exportable);
            var credential = new ServiceAccountCredential(
                new ServiceAccountCredential.Initializer(Authentication.ServiceAccountEmail)
                {
                    Scopes = new[] { AnalyticsService.Scope.AnalyticsReadonly }
                }.FromCertificate(certificate));

            return new AnalyticsService(new BaseClientService.Initializer
            {
                HttpClientInitializer = credential,
                ApplicationName = Authentication.ApplicationName
            });
        }

        private Profile getProfile(AnalyticsService service)
        {
            var accountListRequest = service.Management.Accounts.List();
            var accountList = accountListRequest.Execute();
            var site = Authentication.SiteUrl.Host.ToLowerInvariant();
            var account = accountList.Items.FirstOrDefault(x => x.Name.ToLowerInvariant().Contains(site));
            var webPropertyListRequest = service.Management.Webproperties.List(account.Id);
            var webPropertyList = webPropertyListRequest.Execute();
            var sitePropertyList = webPropertyList.Items.FirstOrDefault(a => a.Name.ToLowerInvariant().Contains(site));
            var profileListRequest = service.Management.Profiles.List(account.Id, sitePropertyList.Id);
            var profileList = profileListRequest.Execute();
            return profileList.Items.FirstOrDefault(a => a.Name.ToLowerInvariant().Contains(site));
        }
    }
}
در اینجا در ابتدا بر اساس فایل p12 ایی که از گوگل دریافت شد، یک X509Certificate2 ایجاد می‌شود. پسورد این فایل مساوی است با ثابت notasecret که در همان زمان تولید اکانت سرویس در گوگل، لحظه‌ای در صفحه نمایش داده خواهد شد. به کمک آن و همچنین ServiceAccountEmail ایمیلی که پیشتر به آن اشاره شد، می‌توان به AnalyticsService لاگین کرد. به این ترتیب به صورت خودکار می‌توان شماره پروفایل اکانت سایت خود را یافت و از آن در حین فراخوانی service.Data.Ga.Get استفاده کرد.


مثالی از نحوه استفاده از کلاس GoogleAnalyticsApiV3

در ادامه یک برنامه‌ی کنسول را ملاحظه می‌کنید که از کلاس GoogleAnalyticsApiV3 استفاده می‌کند:
using System;
using System.Collections.Generic;
using System.Linq;

namespace GoogleAnalyticsAPIv3Tests
{
    class Program
    {

        static void Main(string[] args)
        {
            var statistics = new GoogleAnalyticsApiV3
            {
                Authentication = new AnalyticsAuthentication
                {
                    ApplicationName = "My Project",
                    KeyFilePath = "811e1d9976cd516b55-privatekey.p12",
                    ServiceAccountEmail = "10152bng4j3mq@developer.gserviceaccount.com",
                    SiteUrl = new Uri("https://www.dntips.ir/")
                },
                QueryParameters = new AnalyticsQueryParameters
                {
                    Start = DateTime.Now.AddDays(-7),
                    End = DateTime.Now,
                    Dimensions = "ga:date",
                    Filters = null,
                    Metrics = "ga:users,ga:sessions,ga:pageviews"
                }
            }.GetData();


            foreach (var result in statistics.TotalsForAllResults)
            {
                Console.WriteLine(result.Key + " -> total:" + result.Value);
            }
            Console.WriteLine();

            foreach (var row in statistics.ColumnHeaders)
            {
                Console.Write(row.Name + "\t");
            }
            Console.WriteLine();

            foreach (var row in statistics.Rows)
            {
                var rowItems = (List<string>)row;
                Console.WriteLine(rowItems.Aggregate((s1, s2) => s1 + "\t" + s2));
            }

            Console.ReadLine();
        }
    }
}

چند نکته
ApplicationName همان نام پروژه‌ای است که ابتدای کار، در گوگل ایجاد کردیم.
KeyFilePath مسیر فایل مجوز p12 ایی است که گوگل در حین ایجاد اکانت سرویس، در اختیار ما قرار می‌دهد.
ServiceAccountEmail آدرس ایمیل اکانت سرویس است که در قسمت ادمین Google Analytics به آن دسترسی دادیم.
SiteUrl آدرس سایت شما است که هم اکنون در Google Analytics دارای یک اکانت و پروفایل ثبت شده‌است.
توسط AnalyticsQueryParameters می‌توان نحوه‌ی کوئری گرفتن از Google Analytics را مشخص کرد. تاریخ شروع و پایان گزارش گیری در آن مشخص هستند. در مورد پارامترهایی مانند Dimensions و Metrics بهتر است به مرجع کامل آن در گوگل مراجعه نمائید:
Dimensions & Metrics Reference

برای نمونه در مثال فوق، تعداد کاربران، سشن‌های آن و همچنین تعداد بار مشاهده‌ی صفحات، گزارشگیری می‌شود.


برای مطالعه بیشتر
Using Google APIs in Windows Store Apps
How To Use Google Analytics From C# With OAuth
Google Analytic’s API v3 with C#
.NET Library for Accessing and Querying Google Analytics V3 via Service Account
Google OAuth2 C#
  • #
    ‫۱۰ سال و ۵ ماه قبل، چهارشنبه ۲۴ اردیبهشت ۱۳۹۳، ساعت ۱۴:۵۸
    سلام و تشکر از مقاله خوبتان.
    به نظر شما بهتر است که یک اکانت در آنالیتیکس تعریف کنیم و تمام وبسایت‌های خودمان را به این اکانت اضافه کنیم  یا اینکه برای هر وبسایت یک اکانت مجزا بسازیم؟
    • #
      ‫۱۰ سال و ۵ ماه قبل، چهارشنبه ۲۴ اردیبهشت ۱۳۹۳، ساعت ۱۵:۰۶
      - برای متد getProfile نوشته شده تفاوتی نمی‌کند. چون تمام اکانت‌های موجود را جهت یافتن آدرس سایت مدنظر جستجو می‌کند تا شماره پروفایل آن‌را برای کوئری گرفتن استخراج کند.
      + اکانت Client ID ساخته شده، برای تمام سرویس‌های متفاوت گوگل کاربرد دارد؛ و منحصر به Google Analytics نیست. فقط باید در قسمت APIs آن پروژه، سرویس موردنظر را فعال کرد.
      - همچنین مزیت این روش نسبت به پروتکل‌های قدیمی گوگل که از نام کاربری و کلمه‌ی عبور Gmail استفاده می‌کردند، عدم نیاز به ذخیره سازی اطلاعات حساس اکانت گوگل خود در فایل کانفیگ برنامه است. بنابراین نیازی نیست تا اکانت‌های متفاوت گوگلی را برای این‌کار خاص ایجاد کنید.
  • #
    ‫۱۰ سال و ۵ ماه قبل، چهارشنبه ۲۴ اردیبهشت ۱۳۹۳، ساعت ۱۷:۰۱
    با سلام.
    همه چیز بر روی کلاینت درست کار میکند ولی وقتی سایت را بر روی سرور آپلود میکنم خطای زیر روی می‌دهد:
    System.Security.Cryptography.CryptographicException: An internal error occurred

    • #
      ‫۱۰ سال و ۵ ماه قبل، چهارشنبه ۲۴ اردیبهشت ۱۳۹۳، ساعت ۱۷:۵۷
      این سه مورد را بررسی کنید:
      - آیا مسیر فایل p12 را درست تنظیم کرده‌اید؟ در یک برنامه‌ی وب باید به این نحو باشد:
      Server.MapPath("~/folder/" + filename)
      - آیا در application pool برنامه‌ی شما load user profile فعال است؟ اگر خیر، crypto susbsystem کار نخواهد کرد:

      - تنظیم زیر را هم امتحان کنید:
      بجای
      var certificate = new X509Certificate2(Authentication.KeyFilePath, Authentication.KeyFilePassword,
       X509KeyStorageFlags.Exportable);
      بنویسید:
      var certificate = new X509Certificate2(Authentication.KeyFilePath, Authentication.KeyFilePassword,
         X509KeyStorageFlags.MachineKeySet |
         X509KeyStorageFlags.PersistKeySet | 
         X509KeyStorageFlags.Exportable);
      • #
        ‫۱۰ سال و ۵ ماه قبل، چهارشنبه ۲۴ اردیبهشت ۱۳۹۳، ساعت ۱۸:۳۲
        حالت سوم پاسخ شما برای مورد من درست کار کرد. تشکر فراوان.
  • #
    ‫۱۰ سال و ۴ ماه قبل، دوشنبه ۲۹ اردیبهشت ۱۳۹۳، ساعت ۱۹:۵۸
    یک نکته‌ی تکمیلی
    اگر کتابخانه‌ی Google.Apis.Analytics.v3 را بر روی یک سیستم دات نت 4 اجرا کنید، احتمالا خطای ذیل را دریافت خواهید کرد:
    Could not load type 'System.Net.HttpStatusCode' from assembly System.Net
    علت اینجا است که دات نت 4 نیاز به وصله‌ی KB2468871 دارد تا بتواند portable libraries را بارگذاری کند.
  • #
    ‫۱۰ سال و ۲ ماه قبل، سه‌شنبه ۲۱ مرداد ۱۳۹۳، ساعت ۰۷:۲۲
    از این ایراد میگیره میگه null هست، من اکانت ساختم پراپرتی هم درست کردم
    Line 77: var webPropertyListRequest = service.Management.Webproperties.List(account.Id);
    
    Object reference not set to an instance of an object.
     
    • #
      ‫۱۰ سال و ۲ ماه قبل، سه‌شنبه ۲۱ مرداد ۱۳۹۳، ساعت ۱۴:۴۱
      «من اکانت ساختم پراپرتی هم درست کردم»
      کافی نیست. تمام مراحل باید انجام شوند.
      این خطاها صرفا به معنای غیرمعتبر بودن یکی از مراحل است که سبب شده‌اند اطلاعات آن مرحله خاص قابل دریافت نباشد.
      • #
        ‫۱۰ سال و ۲ ماه قبل، سه‌شنبه ۲۱ مرداد ۱۳۹۳، ساعت ۱۵:۲۳
        نه اینکه فقط اکانت و پراپرتی درست کرده باشم، همه مراحل رو انجام دادم اما از خطی که خطا میده متوجه شدم که پرپرتی‌های من رو پیدا نمیکنه یعنی خالی برمیگردونه، قبلا هم کار کرده بودم همین مشکل پیش میومد.
        • #
          ‫۱۰ سال و ۲ ماه قبل، سه‌شنبه ۲۱ مرداد ۱۳۹۳، ساعت ۱۵:۳۹
          در متد getProfile :
          - اگر account نال هست یعنی SiteUrl مشخص شده در ابتدای برنامه، در اکانت آنالیتیکس شما موجود نیست. روی سطر accountList.Items یک break-point قرار دهید تا لیست واقعی اکانت‌های ثبت شده را مشاهده کنید.
          - اگر به مرحله‌ی اجرای accountList نمی‌رسید، یعنی ServiceAccountEmail معتبری وارد نشده‌است.
          • #
            ‫۱۰ سال و ۲ ماه قبل، سه‌شنبه ۲۱ مرداد ۱۳۹۳، ساعت ۱۷:۰۲
            متوجه اشکال شدم.
            من کدهای شما رو کپی کردم و نخوندم چه کردید، کدها رو که بررسی کردم متوجه شدم شما توی لیست اکانتها که واکشی میکنید اکانتی که میخوایم باید همنام یا شبیه آدرس سایت(SiteUrl) باشه و طبیعتا من وقتی توی گوگل آنالیز اکانت و پروفایلهام رو میسازم نام دلخواه میدم، شما بجای استفاده از آی دی از اسم استفاده کردید که از روی اسم آی دی رو در بیارید برای همین چون اسم اکانت با آدرس سایتم یکی نبود چیزی پیدا نمیکرد :
            var account = accountList.Items.FirstOrDefault(x => x.Name.ToLowerInvariant().Contains(site));
            برای پراپرتی هم به همین صورت.
  • #
    ‫۹ سال و ۷ ماه قبل، شنبه ۲۵ بهمن ۱۳۹۳، ساعت ۲۲:۵۰
    با توجه به تحریم بودن این سرویس در ایران شما چه سرویس جایگزینی را پیشنهاد می‌کنید؟
    • #
      ‫۹ سال و ۳ ماه قبل، جمعه ۵ تیر ۱۳۹۴، ساعت ۰۲:۵۷
      از اونجا که بیشتر سایت‌ها روی سرورهای غیر ایرانی هاست میشن مشکل خاصی نیست ولی برای اطلاعات بیشتر آشنایی با سرویس‌های مشابه به اینجا رجوع کنید.
      همچنین خود بینگ هم api هایی رو در این زمینه داره که میتونید مستنداتش رو مطالعه کنید.
  • #
    ‫۸ سال و ۷ ماه قبل، شنبه ۱ اسفند ۱۳۹۴، ساعت ۱۳:۵۱
    "در ادامه به گزینه‌ی User management آن وارد شده و به ایمیل Client ID ایجاد شده در قسمت قبل، دسترسی خواندن و آنالیز را اعطاء کنید"
     ایمیل رو دستی توی این قسمت وارد میکنید یا وقتی وارد این قسمت میشیم ایمیل باید وجود داشته باشه؟
    • #
      ‫۸ سال و ۷ ماه قبل، شنبه ۱ اسفند ۱۳۹۴، ساعت ۱۴:۳۰
      این ایمیل حاصل عملیات «Create new client id» است که در ابتدای مطلب توضیح داده شد (و این «ایمیل Client ID ایجاد شده در قسمت قبل» در همان تصویری که «دکمه‌ی Add» آن با یک دایره‌ی قرمز مشخص شده، باید وارد و Add شود. حاصل این Add کردن در لیست User management نمایش داده می‌شود).
  • #
    ‫۸ سال و ۲ ماه قبل، شنبه ۹ مرداد ۱۳۹۵، ساعت ۱۸:۳۹
    با سلام .
    هنگام اجرا با خطای زیر مواجه میشم.

    • #
      ‫۸ سال و ۲ ماه قبل، شنبه ۹ مرداد ۱۳۹۵، ساعت ۱۹:۲۰
      - به نظر تاریخ شمسی را به آن ارسال کرده‌اید؛ بجای تاریخ میلادی. عنوان می‌کند که 1395 شمسی کمتر است از تاریخ شروع به کار این سرویس در سال 2005.
      - اگر از ویندوز 10 استفاده می‌کنید که در آن تاریخ شمسی فعال شده‌است، قسمت‌های ToString مربوط به تاریخ را به این صورت اصلاح کنید تا تاریخ شمسی را برنگرداند:
      ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)
      اطلاعات بیشتر
      • #
        ‫۸ سال و ۲ ماه قبل، یکشنبه ۱۰ مرداد ۱۳۹۵، ساعت ۱۹:۱۸
        بله مشکل از همین بود.ولی ظاهرا اجازه استفاده به سرورهای ایرانی داده نمیشه

        • #
          ‫۸ سال و ۱ ماه قبل، دوشنبه ۸ شهریور ۱۳۹۵، ساعت ۱۳:۵۶
          بنده هم به همین ارور و عدم دسترسی این api  در ایران برخوردم..ایا راه حلی برای این موضوع هست ؟
          • #
            ‫۸ سال و ۱ ماه قبل، دوشنبه ۸ شهریور ۱۳۹۵، ساعت ۱۴:۲۷
            اگر هاست شما دارای IP غیر ایرانی است، بدون مشکل می‌توانید از این سرویس استفاده کنید.