Google Analytics ile Kritik Performans Metriklerini Ölçme

Bu codelab'de, web sitenizin veya uygulamanızın gerçek dünya performansını ölçmek ve kullanıcılarınızın deneyimini iyileştirmek için optimize etmek üzere Google Analytics ve User Timings API'yi nasıl kullanacağınızı öğreneceksiniz.

WebPagetest.org gibi araçlar, performans optimizasyonları için harika bir başlangıç noktasıdır ancak site performansının gerçek testi her zaman gerçek kullanıcılardan elde edilen veriler olacaktır.

Web siteniz varsa trafiği ve cihaz ile tarayıcı kullanımı gibi metrikleri ölçmek için Google Analytics'i kullanıyor olabilirsiniz. Yalnızca biraz daha kod ekleyerek performans metriklerini de dahil edebilirsiniz.

Neler öğreneceksiniz?

  • User Timings API'yi kullanarak performans metriklerini doğru ve etkili bir şekilde ölçme
  • Bu verileri raporlarınıza dahil edilebilmesi için Google Analytics'e gönderme

İhtiyacınız olanlar

  • Geliştirici konsolu olan bir tarayıcı
  • Web Server for Chrome veya kendi web sunucunuzu kullanın.
  • Örnek kod
  • Metin düzenleyici
  • (İsteğe bağlı) Google Analytics hesabı

Bu eğitimi nasıl kullanacaksınız?

Yalnızca okuyun Okuyun ve alıştırmaları tamamlayın

Web sitesi veya uygulama oluşturma deneyiminizi nasıl değerlendirirsiniz?

Başlangıç Orta İleri

Örnek kodun tamamını bilgisayarınıza indirebilirsiniz.

Zip dosyasını indir

...veya GitHub deposunu komut satırından kopyalayın.

git clone https://github.com/googlecodelabs/performance-analytics.git

Örnek kod, bu kod laboratuvarındaki numaralandırılmış adımların her birine karşılık gelen alt dizinlere ayrılmıştır. Bu özelliği, kod laboratuvarında kolayca ilerlemek veya uygulamanızın doğru olduğunu doğrulamak için kullanabilirsiniz.

Fark karşılaştırma programına erişiminiz varsa bu programı kullanarak adım adım nelerin değiştiğini görebilirsiniz.

Bu kod laboratuvarında, aşağıdaki öğeleri yükleyen tek bir HTML dosyası kullanacaksınız:

  • Web yazı tipleri
  • Stil sayfaları
  • Resimler
  • JavaScript

Ayrıca, bu öğe türlerinin her biri için temel performans metriklerini ölçen yeni bir kod yazacaksınız.

Öğe performansıyla ilgili dikkat edilmesi gereken noktalar

Performans optimizasyonu hakkında herhangi bir şey okuduysanız bu öğe türlerinin her birinin kendine özgü özellikleri olduğunu ve genel algılanan performansı çeşitli şekillerde etkileyebileceğini biliyorsunuzdur.

CSS

Örneğin, stil sayfaları DOM'da kendilerinden sonra gelen tüm öğelerin oluşturulmasını engeller. Bu nedenle, tarayıcının stil sayfası için istekte bulunması, stil sayfasını indirmesi ve ayrıştırması gerekir. Ancak bu işlemlerden sonra DOM'da stil sayfasından sonra gelen içeriklerin herhangi birini oluşturabilir. Bu nedenle, stil sayfalarını genellikle belgenin <head> bölümüne yerleştirmek en iyisidir. CSS'nin engelleme özelliği nedeniyle, kritik CSS'nizi yalnızca <head> bölümüne yerleştirmeniz ve kritik olmayan CSS'yi daha sonra eşzamansız olarak yüklemeniz de genellikle önerilir.

JavaScript

JavaScript ise oluşturmayı engellemez ancak DOM'un ayrıştırılmasını ve oluşturulmasını engeller. JavaScript, DOM'u değiştirebildiği için bu gereklidir. Bu nedenle, tarayıcı bir <script> etiketi gördüğünde (eşzamansız komut dosyaları hariç) bir sonraki etikete geçmeden önce kodu yürütmesi gerekir. <script> etiketi harici bir JavaScript dosyasına referans veriyorsa devam etmeden önce kodu indirip yürütmesi gerekir.

Bu nedenle, DOM'un büyük bir bölümünün mümkün olduğunca hızlı bir şekilde kullanılabilir olması için JavaScript'inizin kapanış </body> etiketinden hemen önce yüklenmesi genellikle önerilir.

Web yazı tipleri

Web yazı tiplerini yüklerseniz yazı tipi kullanılabilir hale gelene kadar dokümanın oluşturulmasını engellemeyi de seçebilirsiniz. Bu durumda, kullanıcılarınızın bu işlemi ne kadar sürede tamamladığını anlamanız çok önemlidir. Bir web yazı tipi sizin için hızlı yüklenebilir ancak sitenizi ziyaret eden çoğu kullanıcı için çok yavaş yüklenebilir. Bu nedenle ölçüm yapmak ve gerçek verilere dayalı kararlar almak çok önemlidir.

Resimler

Son olarak, resimler bir siteye hayat verebilir ancak genellikle yüklenmeleri en uzun süren öğelerdir. Bunun gerçekte ne anlama geldiğini anlamak ve kullanım kalıpları ile sayfa yükleme süreleri arasındaki korelasyonları tespit edebilmek, optimizasyonun nasıl yapılacağını anlamak için çok önemlidir.

Bu kod laboratuvarındaki ilk adım, herhangi bir performans ölçümü kodu eklemeden önce demo sayfasının nasıl göründüğünü görmektir.

Demoyu görüntülemek için yeni bir klasör oluşturun ve içine index.html adlı bir dosya ekleyin. Ardından, aşağıdaki kodu kopyalayıp index.html dosyasına yapıştırın.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Performance Analytics Demo</title>

  <!-- Start fonts -->
  <link href="https://fonts.googleapis.com/css?family=Roboto:400,700,400italic" rel="stylesheet">
  <!-- End fonts -->

  <!-- Start CSS -->
  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
  <style>
    body { font-family: Roboto, sans-serif; margin: 1em; }
    img { float: left; height: auto; width: 33.33%; }
    .gallery { overflow: hidden; }
  </style>
  <!-- End CSS -->

</head>
<body>

  <div class="container">

    <!-- Start images -->
    <div class="gallery">
      <img src="http://lorempixel.com/380/200/animals/1/">
      <img src="http://lorempixel.com/380/200/animals/2/">
      <img src="http://lorempixel.com/380/200/animals/3/">
    </div>
    <!-- End images -->

    <h1>Performance Analytics Demo</h1>
    <p>Real performance data from real users.</p>

  </div>

  <!-- Start JavaScript -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
  <!-- End JavaScript -->

</body>
</html>

Ardından, Chrome için Web Sunucusu'nu açın ve az önce oluşturduğunuz dizinde yerel bir sunucu başlatın. "index.html dosyasını otomatik olarak göster" seçeneğinin işaretli olduğundan emin olun.

Screen Shot 2016-05-11 at 1.03.43 PM.png

Artık tarayıcınızda http://127.0.0.1:8887/ adresine giderek demo dosyasını görebilirsiniz. Şuna benzer bir görünümde olacaktır:

Screen Shot 2016-05-11 at 10.59.03 AM.png

Demo sayfası çalıştıktan sonra kodu inceleyip yüklenen çeşitli öğe türlerini görün. Sonraki birkaç adımda, bu öğelerin ne zaman yüklendiğini ve kullanıcı tarafından ne zaman kullanılabileceğini ölçmek için kod ekleyeceksiniz.

Önceki öğe performansı ile ilgili dikkat edilmesi gereken noktalar bölümünde belirtildiği gibi, CSS, DOM öğelerinin oluşturulmasını ve DOM'da kendisinden sonra gelen komut dosyalarının yürütülmesini engeller.

Yeni oluşturduğunuz demo dosyası, Bootstrap'e ve birkaç satır içi stile referans veren aşağıdaki CSS'yi içerir.

<!-- Start CSS -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
<style>
  body { font-family: Roboto, sans-serif; margin: 1em; }
  img { float: left; height: auto; width: 33.33%; }
  .gallery { overflow: hidden; }
</style>
<!-- End CSS -->

CSS hem DOM öğelerinin oluşturulmasını hem de komut dosyalarının yürütülmesini engellediğinden, geçerli saati depolayan CSS'nin hemen ardından bir <script> etiketi ekleyerek CSS'nin engellemeyi ne zaman bitirdiğini belirlemek mümkündür.

Bunu bir değişken oluşturup new Date() değerini atayarak yapabilirsiniz ancak User Timings API sayesinde çok daha kolay bir yol vardır: performance.mark yöntemi.

CSS'nin hem oluşturmayı hem de komut dosyası yürütmeyi engellediği zamanı işaretlemek için aşağıdaki kod satırını kapanış <!-- End CSS --> yorumundan hemen önce ekleyin.

<script>performance.mark('css:unblock');</script>

performance.mark yöntemi, tam olarak bu anda yüksek çözünürlüklü bir zaman damgası oluşturur ve bunu yönteme iletilen adla ilişkilendirir. Bu durumda, işaretin adını "css:unblock" olarak belirlediniz.

performance.mark yöntemi, iki işaret arasındaki zaman farkını hesaplamak için kullanılan performance.measure yöntemiyle birlikte kullanılır (işaretlediğiniz yerlerin yanı sıra, tarayıcının Navigation Timing API'deki çeşitli noktalar için otomatik olarak işaretlediği yerleri de kullanabilirsiniz).

Aşağıdaki yardımcı işlev, eklediğiniz bir işaret ile Navigation Timing API tarafından oluşturulan responseEnd işareti arasındaki süreyi ölçer ve döndürür.

function measureDuration(mark, opt_reference) {
  var reference = opt_reference || 'responseEnd';
  var name = reference + ':' + mark;

  // Clears any existing measurements with the same name.
  performance.clearMeasures(name);

  // Creates a new measurement from the reference point to the specified mark.
  // If more than one mark with this name exists, the most recent one is used.
  performance.measure(name, reference, mark);

  // Gets the value of the measurement just created.
  var measure = performance.getEntriesByName(name)[0];

  // Returns the measure duration.
  return measure.duration;
}

Bu yardımcı işlevi kullanmaya başlamak için perf-analytics.js adlı yeni bir dosya oluşturun (index.html dosyasıyla aynı dizinde) ve yukarıdaki kodu kopyalayıp bu dosyaya yapıştırın.

Bu işlev tanımlandığına göre, onu çağırabilir ve "css:unblock" işaret adını iletebilirsiniz. Başka kaynak yüklemelerine müdahale etmemek için bu ölçümleri pencerenin yükleme etkinliği tetiklendikten sonra çalıştırmayı ertelemelisiniz.

Bu kodu çağırmak için bir işlev yazdıktan sonra perf-analytics.js dosyanız şu şekilde görünmelidir:

window.onload = function() {
  measureCssUnblockTime();
};


/**
 * Calculates the time duration between the responseEnd timing event and when
 * the CSS stops blocking rendering, then logs that value to the console.
 */
function measureCssUnblockTime() {
  console.log('CSS', 'unblock', measureDuration('css:unblock'));
}


/**
 * Accepts a mark name and an optional reference point in the navigation timing
 * API and returns the time duration between the reference point and the last
 * mark (chronologically).
 * @param {string} mark The mark name.
 * @param {string=} opt_reference An optional reference point from the
 *     navigation timing API. Defaults to 'responseEnd'.
 * @return {number} The time duration
 */
function measureDuration(mark, opt_reference) {
  var reference = opt_reference || 'responseEnd';
  var name = reference + ':' + mark;

  // Clears any existing measurements with the same name.
  performance.clearMeasures(name);

  // Creates a new measurement from the reference point to the specified mark.
  // If more than one mark with this name exists, the most recent one is used.
  performance.measure(name, reference, mark);

  // Gets the value of the measurement just created.
  var measure = performance.getEntriesByName(name)[0];

  // Returns the measure duration.
  return measure.duration;
}

Son olarak, index.html'dan perf-analytics.js komut dosyasını yüklemeniz gerekir. Bunu yapmak için ana dokümanınıza aşağıdaki komut dosyası etiketini ekleyin. Diğer kaynakların yüklenmesini engellememesi için bu kodu en son eklediğinizden emin olun.

<!-- Start performance analytics -->
<script async src="perf-analytics.js"></script>
<!-- End performance analytics -->

Bu adımı tamamladığınızda kodunuz, kod laboratuvarı deposunun 01-css dizinindeki kodla eşleşmelidir.

Sayfayı bir tarayıcıda yükleyip geliştirici konsolunu açarsanız aşağıdaki gibi bir çıkış görürsünüz:

Screen Shot 2016-05-17 at 11.13.02 AM.png

Web yazı tipleri genellikle ilk demo dosyasında görüldüğü gibi harici bir stil sayfası aracılığıyla yüklenir:

<!-- Start fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto:400,700,400italic" rel="stylesheet">
<!-- End fonts -->

Bu, bir CSS dosyasına yönelik bir <link> etiketi olduğundan, yazı tiplerinin ne zaman yüklendiğini ve kullanıma hazır olduğunu belirlemek, 1. adımda olduğu gibi <link> etiketinden hemen sonra <script> etiketinin içine bir işaret eklemek kadar basit görünebilir.

Maalesef bu kadar basit değil.

Stil sayfalarının içerikleri CSSOM'u oluşturmak için kullanıldığından stil sayfaları JavaScript'in yürütülmesini engeller. Yüklenen JavaScript'in CSSOM'a erişmesi mümkün olduğundan yürütme, CSSOM tamamen oluşturulana kadar ertelenmelidir.

Ancak tarayıcı, CSSOM'yi yazı tipini gerçekten indirmeden oluşturabilir. Bu da yazı tipinin stil sayfası <link> etiketinden hemen sonra DOM'a satır içi komut dosyası etiketi aracılığıyla bir işaret eklerseniz işaretin yazı tipi tamamen yüklenmeden önce gerçekleşeceği anlamına gelir.

Tarayıcılarda yazı tipi yükleme etkinlikleri kullanıma sunulana kadar, bir yazı tipinin gerçekten etkin olup olmadığını ve sayfada kullanıma hazır olup olmadığını belirlemek için JavaScript gerekir. Neyse ki JavaScript üzerinden yazı tipi yüklemek, CSS dosyasına ek bir engelleme isteği gerektirmediğinden performans açısından da avantajlıdır.

Google ve Typekit tarafından ortaklaşa geliştirilen webfont.js komut dosyası aracılığıyla Google Fonts, Typekit ve font.com yazı tipleri de dahil olmak üzere çoğu web yazı tipi yüklenebilir.

Ana dokümanı, yazı tiplerini yüklemek için <link> etiketi yerine webfont.js kullanacak şekilde güncellemek istiyorsanız kodun yazı tipleri bölümünü aşağıdakilerle değiştirin:

<!-- Start fonts -->
<script>
window.WebFontConfig = {
  google: {families: ['Roboto:400,700,400italic']},
  timeout: 10000,
  active: function() {
    performance.mark('fonts:active');
  }
};
</script>
<script async src="https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"></script>
<!-- End fonts -->

Yukarıdaki kodla ilgili dikkat edilmesi gereken iki önemli nokta vardır:

  • Etkin geri çağırmada "fonts:active" işaretini oluşturur. Böylece, yazı tiplerinin yüklenmesinin ne kadar sürdüğünü daha sonra ölçebilirsiniz.
  • webfonts.js dosyasını yükleyen <script> etiketi async özelliğini içerdiğinden belgenin geri kalanının ayrıştırılmasını veya oluşturulmasını engellemez (bu durum <link> etiketleri için geçerli değildir).

Yukarıdaki kodlar "fonts:active" işaretini oluşturur ancak bu işareti ölçmek ve konsola kaydetmek, "css:unblock" işaretinde olduğu kadar basit değildir. Bunun nedeni, yazı tipi yüklemenin artık eşzamansız olarak gerçekleşmesidir. Bu nedenle, window.onload işleyicisinde "fonts:active" işaretini ölçmeye çalışırsanız (ör. "css:unblock" ile yaptığınız gibi) yazı tipi henüz yüklenmemiş olabilir.

Bu sorunu çözmek için yazı tipi yüklendikten sonra çözülen bir söz oluşturabilirsiniz. Aşağıdaki işlev bunu sizin yerinize yapar. Kodu kopyalayıp perf-analytics.js dosyasına yapıştırın:

/**
 * Creates a promise that is resolved once the web fonts are fully load or
 * is reject if the fonts fail to load. The resolved callback calculates the
 * time duration between the responseEnd timing event and when the web fonts
 * are downloaded and active. If an error occurs loading the font, this fact
 * is logged to the console.
 */
function measureWebfontPerfAndFailures() {
  new Promise(function(resolve, reject) {
    // The classes `wf-active` or `wf-inactive` are added to the <html>
    // element once the fonts are loaded (or error).
    var loaded = /wf-(in)?active/.exec(document.documentElement.className);
    var success = loaded && !loaded[1]; // No "in" in the capture group.
    // If the fonts are already done loading, resolve immediately.
    // Otherwise resolve/reject in the active/inactive callbacks, respectively.
    if (loaded) {
      success ? resolve() : reject();
    }
    else {
      var originalAciveCallback = WebFontConfig.active;
      WebFontConfig.inactive = reject;
      WebFontConfig.active = function() {
        originalAciveCallback();
        resolve();
      };
      // In case the webfont.js script fails to load, always reject the
      // promise after the timeout amount.
      setTimeout(reject, WebFontConfig.timeout);
    }
  })
  .then(function() {
    console.log('Fonts', 'active', measureDuration('fonts:active'));
  })
  .catch(function() {
    console.error('Error loading web fonts')
  });
}

Ayrıca, bu yeni işlevi çağırmak için window.onload işleyicisini de güncelleyin.

window.onload = function() {
  measureCssUnblockTime();
  measureWebfontPerfAndFailures();
};

Bu adımı tamamladığınızda kodunuz, kod laboratuvarı deposunun 02-fonts dizinindeki kodla eşleşmelidir.

Sayfayı bir tarayıcıda yükleyip geliştirici konsolunu açarsanız aşağıdaki gibi bir çıkış görürsünüz:

Screen Shot 2016-05-17 at 11.13.22 AM.png

Bir resmin ne zaman görünür olduğunu bilmek göründüğü kadar basit değildir. Önceki adımlardan, stil sayfalarının ve senkron <script> etiketlerinin oluşturmayı, ayrıştırmayı ve komut dosyası yürütmeyi engelleyebileceğini biliyorsunuz. Ancak bu iki uzantının da tarayıcının önceden yükleme tarayıcısını engellemediğini bilmiyor olabilirsiniz.

Ön yükleme tarayıcısı, çok sayıda engelleme öğesi içeren ve performans odaklı olmayan sitelerde bile performansı artırmaya yönelik birçok girişimden biri olarak tüm modern tarayıcılar tarafından uygulanan bir özelliktir. Buradaki fikir, bazı öğeler ayrıştırmayı, oluşturmayı veya komut dosyası yürütmeyi engelleyebilse de indirmeyi engellemek zorunda olmamasıdır. Bu nedenle tarayıcı, DOM'u oluşturmaya başlamadan önce HTML dosyasını tarar ve hemen indirmeye başlayabileceği öğeleri arar.

Resimler söz konusu olduğunda, bu durum resimleriniz DOM'a eklendiğinde zaten indirilmiş olabileceği anlamına gelir. Bu aynı zamanda bir resmin indirildiği noktanın mutlaka iyi bir performans metriği olmadığı anlamına da gelir. Önemsemeniz gereken performans metriği, bir resmin kullanıcıya görünür olduğu noktadır.

DOM'a eklenmeden önce indirilen bir resim, DOM'da görünür hale geldiği noktada görünür olur. Öte yandan, bir resim DOM'a eklenmeden önce indirilmezse görünür hale geldiği nokta, onload işleyicisinin tetiklendiği zamandır.

Bu nedenle, bir resmin ne zaman görünür olduğunu bilmek için her iki durumu da ele almanız gerekir.

Bunu, her resmin onload işleyicisine ve DOM'daki son resmin hemen sonrasına satır içi bir <script> etiketi ekleyerek yapabilirsiniz. Buradaki fikir, en son oluşan işaretin tüm resimlerin görünür olduğu zamanı temsil eden işaret olacağıdır.

Resimlerin yüklendiği ve oluşturulduğu zamanlar için işaret eklemek üzere index.html içindeki resim kodunu aşağıdaki şekilde güncelleyin:

<!-- Start images -->
<div class="gallery">
  <img onload="performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/1/">
  <img onload="performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/2/">
  <img onload="performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/3/">
</div>
<script>performance.mark('img:visible')</script>
<!-- End images -->

Belirli bir işaret adı için performance.measure yöntemi her zaman son işareti kullanacağından (aynı ada sahip birden fazla işaret bulursa) perf-analytics.js dosyasındaki measureDuration yardımcı işlevi, ek değişiklik yapmadan bu amaçla kullanılabilir:

/**
 * Calculates the time duration between the responseEnd timing event and when
 * all images are loaded and visible on the page, then logs that value to the
 * console.
 */
function measureImagesVisibleTime() {
  console.log('Images', 'visible', measureDuration('img:visible'));
}

Yukarıdaki işlevi perf-analytics.js dosyasına ekleyin ve ardından window.onload işleyicisini bu işlevi çağıracak şekilde güncelleyin:

window.onload = function() {
  measureCssBlockTime();
  measureWebfontPerfAndFailures();
  measureImagesVisibleTime();
};

Bu adımı tamamladığınızda kodunuz, kod laboratuvarı deposunun 03-images dizinindeki kodla eşleşmelidir.

Sayfayı bir tarayıcıda yükleyip geliştirici konsolunu açarsanız aşağıdaki gibi bir çıkış görürsünüz:

Screen Shot 2016-05-17 at 11.13.39 AM.png

<script> özelliği olmayan <script> etiketleri hem indirilip hem de yürütülene kadar DOM ayrıştırmasını engellediğinden, DOM'daki son senkron <script> etiketinden hemen sonra satır içi bir komut dosyası etiketine işaret ekleyerek tüm komut dosyalarının yürütülmesinin tamamlandığı noktayı belirleyebilirsiniz.async

Tarayıcının komut dosyasını yükledikten sonra yürütmesi gerektiği ve bu işlemin zaman aldığı için bu durumda onload işleyicilerinin kullanılamayacağını unutmayın. Yüklenmesi hızlı ancak yürütülmesi yavaş olan bir komut dosyası, yüklenmesi yavaş olan bir komut dosyası kadar kötü olabilir.

Ana belgede tüm JavaScript'in ne zaman yüklendiğini ve yürütüldüğünü izlemek için index.html bölümündeki JavaScript kodunu aşağıdaki kodla güncelleyin:

<!-- Start JavaScript -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script>performance.mark('js:execute');</script>
<!-- End JavaScript -->

Bu işlem, jQuery ve Bootstrap'in eklentilerine ait komut dosyaları indirilip yürütme işlemi tamamlandıktan hemen sonra"js:execute" adlı bir işaret ekler.

Bu işlemin ne kadar sürdüğünü ölçmek için perf-analytics.js'ya aşağıdaki işlevi ekleyin:

/**
 * Calculates the time duration between the responseEnd timing event and when
 * all synchronous JavaScript files have been downloaded and executed, then
 * logs that value to the console.
 */
function measureJavaSciptExecutionTime() {
  console.log('JavaScript', 'execute', measureDuration('js:execute'));
}

Ardından, window.onload işleyiciden çağırın:

window.onload = function() {
  measureCssBlockTime();
  measureWebfontPerfAndFailures();
  measureImagesVisibleTime();
  measureJavaSciptExecutionTime();
};

Bu adımı tamamladığınızda kodunuz, kod laboratuvarı deposunun 04-javascript dizinindeki kodla eşleşmelidir.

Sayfayı bir tarayıcıda yükleyip geliştirici konsolunu açarsanız aşağıdaki gibi bir çıkış görürsünüz:

Screen Shot 2016-05-17 at 11.14.03 AM.png

Tüm tarayıcılar JavaScript sözlerini veya Kullanıcı Zamanlaması API'lerini desteklemez. Şimdiye kadar yazdığınız kodu bu özelliklerden birini desteklemeyen bir tarayıcıda çalıştırırsanız hatalarla karşılaşırsınız.

Bu sorunu çözmek için özellik algılamayı kullanabilirsiniz. Aşağıdaki kodu yazı tipleri bölümünün hemen öncesine ekleyin. Bu JavaScript satırı, performance.mark yönteminin desteklenip desteklenmediğini algılar. Bu nedenle, bu yöntem kullanılmadan önce sayfaya eklenmelidir:

<!-- Start feature detects -->
<script>window.__perf = window.performance && performance.mark;</script>
<!-- End feature detects -->

Ardından, index.html içinde performance.mark numarasına yaptığınız tüm aramalarda, numarayı özellik algılama ile başlayacak şekilde girin. Aşağıda, resim bloğundaki kodu güncelleyen bir örnek verilmiştir. Ancak diğer bölümleri de güncellediğinizden emin olmanız gerekir.

<!-- Start images -->
<div class="gallery">
  <img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/1/">
  <img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/2/">
  <img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/3/">
</div>
<script>__perf && performance.mark('img:visible')</script>
<!-- End images -->

__perf değişkeni window üzerinde ayarlandığına göre, geçerli tarayıcıda desteklenmeyen bir yöntemi çağırmadığınızdan emin olmak için perf-analytics.js içinde de kullanabilirsiniz.

Aşağıdaki koşulu eklemek için measureDuration işlevinin güncellenmesi gerekir:

function measureDuration(mark, opt_reference) {
  if (window.__perf) {
    // ...
  }
}

Son olarak, tüm tarayıcılar JavaScript sözlerini desteklemediğinden measureWebfontPerfAndFailures işlevi de koşullu bir ifadeyle sarmalanmalıdır:

function measureWebfontPerfAndFailures() {
  if (window.Promise) {
    // ...
  }
}

Artık kodunuzu herhangi bir tarayıcıda sorunsuz bir şekilde çalıştırabilirsiniz.

Bu adımı tamamladığınızda kodunuz, kod laboratuvarı deposunun 05-feature-detects dizinindeki kodla eşleşmelidir.

Bu codelab'deki son adım, konsola kaydedilen verileri Google Analytics'e göndermektir. Ayrıca, Google Analytics'e veri gönderebilmek için sayfanıza analytics.js kitaplığını ve varsayılan izleme snippet'ini eklemeniz gerekir.

Aşağıdaki kodu, ana JavaScript bloğundan sonra ancak perf-analytics.js komut dosyası yüklenmeden önce index.html öğesine ekleyin:

<!-- Start analytics tracking snippet -->
<script>
window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
ga('create', 'UA-XXXXX-Y', 'auto');
ga('send', 'pageview');
</script>
<script async src="https://www.google-analytics.com/analytics_debug.js"></script>
<!-- End analytics tracking snippet -->

Daha önce bir web sitesine Google Analytics eklediyseniz "UA-XXXXX-Y" yer tutucusunu, Google Analytics'te yeni bir mülk oluştururken aldığınız izleme kimliğiyle değiştirmeniz gerektiğini bilirsiniz.

analytics.js izleme snippet'i dört ana işlevi yerine getirir:

  • analytics.js JavaScript kitaplığını indiren asenkron bir <script> öğesi oluşturur.
  • analytics.js kitaplığı yüklendikten ve kullanıma hazır hale geldikten sonra komutların çalıştırılmasını planlamanıza olanak tanıyan global bir ga() işlevi (ga() komut sırası olarak adlandırılır) başlatır.
  • "UA-XXXXX-Y" parametresiyle belirtilen mülk için yeni bir izleyici nesnesi oluşturmak üzere ga() komut kuyruğuna bir komut ekler.
  • Geçerli sayfa için Google Analytics'e sayfa görüntüleme göndermek üzere ga() komut sırasına başka bir komut ekler.

Yalnızca sayfa görüntülemelerinden toplanan veriler faydalı olsa da konuya dair eksiksiz bir bakış sunmaz. Kullanıcıların siteniz veya uygulamanızla ilgili deneyimlerini daha iyi anlamak için Google Analytics'e ek etkileşim verileri göndermeniz gerekir.

Google Analytics, çeşitli etkileşim verisi türlerini destekler: sayfa görüntülemeler, etkinlikler, sosyal etkileşimler, istisnalar ve (son olarak) kullanıcı zamanlamaları. Kullanıcı zamanlaması verilerini Google Analytics'e göndermek için aşağıdaki komut imzasını kullanabilirsiniz:

ga('send', 'timing', timingCategory, timingVar, timingValue);

Burada timingCategory, zamanlama isabetlerini mantıksal gruplar halinde düzenlemenize olanak tanıyan bir dizedir, timingVar ölçtüğünüz değişkendir ve timingValue milisaniye cinsinden gerçek süre uzunluğudur.

Bunun pratikte nasıl çalıştığını görmek için measureCssUnblockTime işlevindeki console.log ifadesi aşağıdaki gibi güncellenebilir:

ga('send', 'timing', 'CSS', 'unblock', measureDuration('css:unblock'));

Yukarıdaki kod bazı durumlarda çalışsa da dikkat etmeniz gereken iki önemli nokta vardır:

  • Önceki adımda, measureDuration işlevi yalnızca tarayıcı, User Timings API'sini destekliyorsa çalışacak şekilde güncellendi. Bu nedenle, bazen undefined değerini döndürecektir. Tanımlanmamış verileri Google Analytics'e göndermek için bir neden olmadığından (bazı durumlarda raporlarınızı bile bozabilir) bu zamanlama isabetini yalnızca measureDuration bir değer döndürürse göndermelisiniz.
  • measureDuration bir değer döndürdüğünde bu değer, milisaniyeden daha yüksek hassasiyete sahip bir DOMHighResTimeStamp olur. Google Analytics'teki timingValue değeri tam sayı olmalıdır. Bu nedenle, measureDuration tarafından döndürülen değeri yuvarlamanız gerekir.

Bu tuzakları hesaba katmak için measureDuration işlevindeki return ifadesini, dönüş değerini yuvarlayacak şekilde güncelleyin:

function measureDuration(mark, opt_reference) {
  if (window.__perf) {
    // ...
    return Math.round(measure.duration);
  }
}

Ayrıca, zamanlama komutlarını yalnızca söz konusu metrik için bir değer varsa çalışacak şekilde güncelleyin. Örneğin, measureCssUnblockTime işlevi aşağıdaki gibi bir ifadeyle güncellenmelidir:

function measureCssUnblockTime() {
  var cssUnblockTime = measureDuration('css:unblock');
  if (cssUnblockTime) {
    ga('send', 'timing', 'CSS', 'unblock', cssUnblockTime);
  }
}

Diğer tüm ölçüm işlevlerinde de benzer güncellemeler yapmanız gerekir. İşlem tamamlandığında nihai perf-analytics.js dosyası şu şekilde görünmelidir:

window.onload = function() {
  measureCssUnblockTime();
  measureWebfontPerfAndFailures();
  measureImagesVisibleTime();
  measureJavaSciptExecutionTime();
};


/**
 * Calculates the time duration between the responseEnd timing event and when
 * the CSS stops blocking rendering, then sends this measurement to Google
 * Analytics via a timing hit.
 */
function measureCssUnblockTime() {
  var cssUnblockTime = measureDuration('css:unblock');
  if (cssUnblockTime) {
    ga('send', 'timing', 'CSS', 'unblock', cssUnblockTime);
  }
}


/**
 * Calculates the time duration between the responseEnd timing event and when
 * the web fonts are downloaded and active, then sends this measurement to
 * Google Analytics via a timing hit. If an error occurs loading the font, an
 * error event is sent to Google Analytics.
 */
function measureWebfontPerfAndFailures() {
  if (window.Promise) {
    new Promise(function(resolve, reject) {
      var loaded = /wf-(in)?active/.exec(document.documentElement.className);
      var success = loaded && !loaded[1]; // No "in" in the capture group.
      if (loaded) {
        success ? resolve() : reject();
      }
      else {
        var originalAciveCallback = WebFontConfig.active;
        WebFontConfig.inactive = reject;
        WebFontConfig.active = function() {
          originalAciveCallback();
          resolve();
        };
        // In case the webfont.js script failed to load.
        setTimeout(reject, WebFontConfig.timeout);
      }
    })
    .then(function() {
      var fontsActiveTime = measureDuration('fonts:active');
      if (fontsActiveTime) {
        ga('send', 'timing', 'Fonts', 'active', fontsActiveTime);
      }
    })
    .catch(function() {
      ga('send', 'event', 'Fonts', 'error');
    });
  }
}


/**
 * Calculates the time duration between the responseEnd timing event and when
 * all images are loaded and visible on the page, then sends this measurement
 * to Google Analytics via a timing hit.
 */
function measureImagesVisibleTime() {
  var imgVisibleTime = measureDuration('img:visible');
  if (imgVisibleTime) {
    ga('send', 'timing', 'Images', 'visible', imgVisibleTime);
  }
}


/**
 * Calculates the time duration between the responseEnd timing event and when
 * all synchronous JavaScript files are downloaded and executed, then sends
 * this measurement to Google Analytics via a timing hit.
 */
function measureJavaSciptExecutionTime() {
  var jsExecuteTime = measureDuration('js:execute');
  if (jsExecuteTime) {
    ga('send', 'timing', 'JavaScript', 'execute', jsExecuteTime);
  }
}


/**
 * Accepts a mark name and an optional reference point in the navigation timing
 * API and returns the time duration between the reference point and the last
 * mark (chronologically). The return value is rounded to the nearest whole
 * number to be compatible with Google Analytics.
 * @param {string} mark The mark name.
 * @param {string=} opt_reference An optional reference point from the
 *     navigation timing API. Defaults to 'responseEnd'.
 * @return {?number} The time duration as an integer or undefined if no
 *     matching marks can be found.
 */
function measureDuration(mark, opt_reference) {
  if (window.__perf) {
    var reference = opt_reference || 'responseEnd';
    var name = reference + ':' + mark;

    // Clears any existing measurements with the same name.
    performance.clearMeasures(name);

    // Creates a new measurement from the reference point to the specified mark.
    // If more than one mark with this name exists, the most recent one is used.
    performance.measure(name, reference, mark);

    // Gets the value of the measurement just created.
    var measure = performance.getEntriesByName(name)[0];

    // Returns the measure duration.
    return Math.round(measure.duration);
  }
}

Son index.html dosyası şu şekilde görünmelidir:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Performance Analytics Demo</title>

  <!-- Start navigation timing feature detect -->
  <script>window.__perf = window.performance && performance.mark;</script>
  <!-- End navigation timing feature detect -->

  <!-- Start fonts -->
  <script>
  window.WebFontConfig = {
    google: {families: ['Roboto:400,700,400italic']},
    timeout: 10000,
    active: function() {
      __perf && performance.mark('fonts:active');
    }
  };
  </script>
  <script async src="https://ajax.googleapis.com/ajax/libs/webfont/1/webfont.js"></script>
  <!-- End fonts -->

  <!-- Start CSS -->
  <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
  <style>
    body { font-family: Roboto, sans-serif; margin: 1em; }
    img { float: left; height: auto; width: 33.33%; }
    .gallery { overflow: hidden; }
  </style>
  <script>__perf && performance.mark('css:unblock');</script>
  <!-- End CSS -->

</head>
<body>

  <div class="container">

    <!-- Start images -->
    <div class="gallery">
      <img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/1/">
      <img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/2/">
      <img onload="__perf && performance.mark('img:visible')" src="http://lorempixel.com/380/200/animals/3/">
    </div>
    <script>__perf && performance.mark('img:visible')</script>
    <!-- End images -->

    <h1>Performance Analytics Demo</h1>
    <p>Real performance data from real users.</p>

  </div>

  <!-- Start JavaScript -->
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
  <script>__perf && performance.mark('js:execute');</script>
  <!-- End JavaScript -->

  <!-- Start analytics tracking snippet -->
  <script>
  window.ga=window.ga||function(){(ga.q=ga.q||[]).push(arguments)};ga.l=+new Date;
  ga('create', 'UA-XXXXX-Y', 'auto');
  ga('send', 'pageview');
  </script>
  <script async src="https://www.google-analytics.com/analytics.js"></script>
  <!-- End analytics tracking snippet -->

  <!-- Start performance analytics -->
  <script async src="perf-analytics.js"></script>
  <!-- End performance analytics -->

</body>
</html>

Bu sayfayı yükleyip ağ panelindeki isteklere göz atarsanız aşağıdakine benzer bir sonuç görürsünüz:

Screen Shot 2016-05-10 at 6.57.23 PM.png

Bu yararlı olsa da bu verilere URL kodlu bir istek olarak bakmak zahmetli olabilir. Bu istekleri herhangi bir nedenle görmüyorsanız hatanın nerede oluştuğunu tespit etmek çok zordur.

Yerel olarak geliştirme yaparken daha iyi bir yaklaşım, her analytics.js komutu çalıştırıldığında konsola yararlı hata ayıklama bilgilerini kaydeden analytics.js'nin hata ayıklama sürümünü kullanmaktır. Şu durumda:

index.html içindeki analytics.js URL'sini analytics_debug.js olarak güncelleyip tarayıcı konsolunuzu açtığınızda, aşağıdakine benzer ifadelerin yazdırıldığını görürsünüz:

Screen Shot 2016-05-10 at 6.54.13 PM.png

Bu demo sayfası için performans ölçümünün nasıl uygulanacağını öğrendiğinize göre, kendi sitenize eklemeyi deneyebilir ve gerçek kullanıcı verilerini Google Analytics'e gönderebilirsiniz.

Topladığınız verilerle ilgili rapor oluşturma

Birkaç gün boyunca performans verileri topladıktan sonra, sitenizin ve kaynaklarının gerçek kullanıcılar için ne kadar hızlı yüklendiği hakkında uygulanabilir analizler elde etmek üzere bu verilerle ilgili rapor oluşturabilirsiniz.

Google Analytics'teki Kullanıcı Zamanlaması raporlarına gitmek için üst kısımdaki Raporlama sekmesini tıklayın ve kenar çubuğu gezinmesinden "Davranış > Site Hızı > Kullanıcı Zamanlamaları"nı seçin (veya Yardım Merkezi'ndeki Kullanıcı Zamanlamaları raporunu görüntüleme talimatlarını uygulayın).

Google Analytics'te Kullanıcı Zamanlamaları raporunu yüklediğinizde, gönderdiğiniz verilerle eşleşen zamanlama kategorilerini görebilirsiniz. Zamanlama verilerinizin ayrıntılı görselleştirmelerini görmek için bunlardan herhangi birini tıklayın. Aşağıdaki resimde, son 24 saat içinde Google Fonts'u kullanan gerçek bir web sitesindeki yazı tipi yükleme sürelerine dair bir örnek verilmiştir.

Screen Shot 2016-05-10 at 7.16.07 PM.png

Tebrikler! Bu kod laboratuvarını başarıyla tamamladınız. Daha ayrıntılı bilgi edinmek isterseniz sonraki bölümde, daha fazla analiz elde etmek için bu kodun üzerine nasıl inşa edeceğinizle ilgili birkaç öneri sunulacaktır.

Bu kod laboratuvarında ele alınan performans metrikleri, sitenizin gerçek kullanıcılar için nasıl yüklendiğini ölçmek açısından kritik öneme sahiptir ancak bu metrikler yalnızca başlangıçtır. Performans analizleri hakkında daha fazla bilgi edinmek isterseniz bir sonraki adım olarak daha fazla metrik izleyebilirsiniz.

Bu kod laboratuvarında, kaynakların kullanıcıya ne zaman sunulduğuyla ilgili metrikleri izlediniz. İsterseniz bunların çoğunu daha da ayrıntılı bir şekilde inceleyebilirsiniz. Örneğin, JavaScript'in yürütülmesinin ne zaman tamamlandığını ölçmek yerine yüklenmeye ne zaman başladığını, yüklenmesinin ne zaman tamamlandığını, yürütülmeye ne zaman başladığını ve yürütülmesinin ne zaman tamamlandığını ölçebilirsiniz. Bu metriklerin her biri, tek başına ele alındığında fark edilmeyecek bir sorunu ortaya çıkarabilir.

Daha ayrıntılı analizler yapmanın yanı sıra genel performans analizi stratejinizi daha bütünsel bir şekilde düşünmeniz de gerekir. Hedefler nelerdir? Başarı nedir?

Herhangi bir analiz söz konusu olduğunda genellikle bir soruyla başlamak ve ardından bu soruyu yanıtlamak için verileri nasıl kullanacağınızı bulmak istersiniz.

Örneğin, aşağıdaki soru listesini ve bu soruları yanıtlamak için analizleri kullanmak üzere bu kod laboratuvarında edindiğiniz bilgileri nasıl kullanacağınızı düşünün:

  • İzlediğiniz metriklerin değerleri zaman içinde azalıyor mu yoksa artıyor mu?
  • Service worker veya yerel depolama alanı aracılığıyla çevrimdışı önbelleğe alma özelliğinin kullanılması, sitenizin genel performansını nasıl etkiler?
  • Kaynaklarınız optimum şekilde yükleniyor mu? Örneğin, kaynağın indirilmesiyle kullanıma hazır olması arasında büyük bir fark var mı?
  • Performans ile izlediğiniz diğer metrikler (ör.kayıt oranı, sitede geçirilen süre, satın alma işlemleri vb.) arasında herhangi bir korelasyon var mı?

Son olarak, web performansı veya Google Analytics hakkında daha fazla bilgi edinmek istiyorsanız başlamanıza yardımcı olacak bazı harika kaynakları aşağıda bulabilirsiniz: