Mobil sitede hız nasıl ölçülür?

Google mobil için yeni ranking algoritmasını Temmuz ayında paylaştı. Speed Update adını verdikleri algoritma, mobilde kullanıcıya yavaş deneyim sunan sayfaların rankingini düşürecek. Yani mobilde “iPhone Xs” kelimesinde ön sıralarda çıkmak istiyorsan hızın da artık iyi olmalı.

Sayfa hızı ölçümlemede geleneksel yöntemler

Geleneksel performans metricleri yükleme süresini (load time) baz alır. Örneğin window.onload websitesinin hızını belirlemek için uzun yıllar doğru bir metric olarak görüldü. 10 yıl önceki teknoloji için doğru; fakat yeni teknolojiler JavaScript, CSS, HTML ve Ajax sayfanın render süresini artık geciktirebiliyor. Örneğin Amazon browserda ekranın üst kısmının neredeyse 2.0 saniye içinde yüklüyorken; kalan kısmını scroll edince yüklüyor. Bu da window.onload süresini yükseltiyor.

Bir diğer sorun sitenin yüklenme zamanını kendi internet hızından yola çıkılarak verilmesi “Uygulamayı test ettim ve X.XX saniyede yüklendi” sözünü sıklıkla duyarız. Site yükleme süreleri aygıt özelliklerine ve ağ koşullarına bağlı olarak kullanıcıdan kullanıcıya değişiklik gösterir. Dolayısıyla yükleme sürelerini tek bir sayı baz alınarak göstermek daha uzun sürede sitenizi yükleyen kullanıcılarınızı yok saymanız anlamına gelir. Google Analytics Site Speed metrikleri load time sürelerine göre örnek bir data sunuyor.

Tinder, PWapps sonrası ve öncesinin page load sürelerini Google Analytics- Site Site Speed üzerinden ölçümlüyor.
Hızı ölçmek için görmemiz gereken saniye bazlı yükleme zamanları
Analytics, Site Speed Page Timings-Distribution tab saniye bazlı page load sample

Bahsettiğimiz performans yanlışlarının temel sorunu, kullanıcı deneyimiyle çok az veya hiç ilgisi olmayan konulara odaklanmalarıdır. Bu hataları tekrarlamamak için şu soruları cevaplamalıyız:

  • User’ın algıladığı performansı en doğru şekilde ölçen hangi metriklerdir?
  • Bu metrikleri gerçek kullanıcılarımız üzerinde nasıl ölçebiliriz?
  • Bir uygulamanın “hızlı” olup olmadığını belirlemek için ölçümlerimizi nasıl yorumlayabiliriz?
  • Uygulamamızın gerçek kullanıcı performansını anladıktan sonra, performans gerilemelerini önlemek ve gelecekteki performansı artırmak için ne yapmalıyız?

User-centric performance metrics

Kullanıcı bir web sayfasına gittiğinde her şeyin beklediği gibi çalışacağına dair çeşitli görsel geribildirimler ister. Google mobile ranking algoritması da hızı kullanıcıya göre ölçüm yaparak arama sonuçlarında sizin sıralamanızı değiştiriyor. Bu noktalar:

Is it happening? Navigasyon başarıyla başlatıldı mı? Sunucu yanıt verdi mi?

Is it useful? Ziyaretçilerin kullanabileceği yeterli içerik var mı?

Is it usable? Ziyaretçiler sayfayla etkileşim kurabiliyor mu, yoksa hala sayfa yükleniyor mu?

Is it delightful? Interactionlar pürüzsüz ve doğal olmalı, gecikme ve takılma içermemeli.

First Paint ve First Contentful Paint

Paint Timing API iki metriği tanımlar: birincisi First Paint (FP) ikincisi First Contentful Paint (FCP). First Paint (FP) Browser’ ın pixeli renderlamasını işaretler. Bu işaretleme kullanıcı için ilk geribildirimdir ve önemlidir; çünkü ilk sorumuzun cevabıdır: “Is it happening?”

Bir uygulama açıldığında ilk yüklenen şey First Paint; birden fazla şeyin yüklenmesi ise First Contenful Paint’tir.

First Meaningful Paint ve Hero Element

First Meaningful Paint (FMP) ikinci sorumuzun karşılığıdır: “Is it useful? Anlamlı bir içeriğin yüklenmesi noktasında hangi parçaların user için daha yararlı olduğu sorusunun cevabı önemlidir.

Youtube’ta hero element’i videodur. Twittter’da first tweet ve notification badge.
Bazı parçalar diğerlerinden daha önemlidir ve bu parçalar diğerlerine göre çok daha hızlı yüklenirse kullanıcı sayfanın hızlı yüklendiği fikrine kapılır.

Time To Interactive

Üçüncü sorumuzun karşılığıdır: “Is it usable?” Uygulamanızın görsel olarak kullanıcıya kullanıma hazır olduğu bilgisini verir.

Long Task

Son sorumuzun karşılığıdır: Is it delightful?

Bazı Javascriptlerin çalıştırılması uzun sürebilir ve bu geçikme sıradaki diğer tüm görevlerin beklemesine neden olur. Bu bekleme de sitenin yükleme süresini uzatır ve kullanıcı için kötü bir deneyime neden olur. Long Task API 50 milisaniye üzeri taskları potansiyel problemli alan olarak görür.

Neden 50 ms?

Bir inputa bastığımızda arkaplanda sayfada başka işlemler de yapılır. 50 ms içerisinde bir işlem yapılırsa 50ms’ye kadar bir işin sıraya alınabileceği anlamına gelir.

Bir inputa bastığımızda arkaplanda sayfada başka işlemler de yapılır. 50 ms içerisinde bir işlem yapılırsa 50ms’ye kadar bir işin sıraya alınabileceği anlamına gelir.

Performans Gecikmesinde Kullanıcı Algısı

0–16 ms: Kullanıcılar hareketleri izleme konusunda dikkatlidirler. Animasyonlar düzgün olmadığında beğenmezler. Bu yumuşak geçiş için animasyon her saniyede 60 kare göstermeli. Bu da 16 milisaniyeye yakındır.

0–100ms: Kullanıcılar sonucun anında geldiği fikrine kapılırlar.Bu saniyenin üstü gecikme olarak düşünülür.

100- 300 ms: Kullanıcılar az da olsa algılanabilir bir gecikme yaşarlar.

300–1000 ms: İşlemin devam ettiği izlenimi yaratır.

1000 ms ve fazlası: Kullancı odağını kaybetmeye başlıyor.

10000 ms ve fazlası: 10000 milisaniyeden (10 saniye) sonra kullanıcılar hayal kırıklığına uğruyor ve görevlerini bırakıyorlar.

Özet

Ölçümleme

Tracking FP/FCP

Belli bir performans etkinliğine ait verileri aldıktan sonra, metriği yakalamak için kullandığınız herhangi bir analitik hizmetine gönderebilirsiniz. Örneğin, Google Analytics’i kullanarak FP sürelerini aşağıdaki gibi izleyebilirsiniz.

<head>
<!-- Add the async Google Analytics snippet first. -->
<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>

<!-- Register the PerformanceObserver to track paint timing. -->
<script>
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// `name` will be either 'first-paint' or 'first-contentful-paint'.
const metricName = entry.name;
const time = Math.round(entry.startTime + entry.duration);

ga('send', 'event', {
eventCategory: 'Performance Metrics',
eventAction: metricName,
eventValue: time,
nonInteraction: true,
});
}
});
observer.observe({entryTypes: ['paint']});
</script>

<!-- Include any stylesheets after creating the PerformanceObserver. -->
<link rel="stylesheet" href="...">
</head>

Tracking FMP using hero elements

Henüz FMP için standartlaştırılmış bir tanım olmadığından ölçümlemenin de standartı yok.

<img src="hero.jpg" onload="performance.clearMarks('img displayed'); performance.mark('img displayed');">

<script>

performance.clearMarks("img displayed");

performance.mark("img displayed");

</script>

Steve Souders’un bu konudaki tanımlamalarından yararlanabiliriz.

https://speedcurve.com/blog/user-timing-and-custom-metrics/

http://www.stevesouders.com/blog/2015/05/12/hero-image-custom-metrics/

Tracking TTI

getFirstConsistentlyInteractive() yöntemi ile Google Analytics entegrasyonu gerçekleşir.

import ttiPolyfill from './path/to/tti-polyfill.js';

ttiPolyfill.getFirstConsistentlyInteractive().then((tti) => {
ga('send', 'event', {
eventCategory: 'Performance Metrics',
eventAction: 'TTI',
eventValue: tti,
nonInteraction: true,
});
});

Tracking long tasks

Long Task kullanıcı deneyimine zarar vermektedir. Bunun ne sıklıkla yaşandığının farkında olmak ve en aza indirgemek bizim için önemli.

const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
ga('send', 'event', {
eventCategory: 'Performance Metrics',
eventAction: 'longtask',
eventValue: Math.round(entry.startTime + entry.duration),
eventLabel: JSON.stringify(entry.attribution),
});
}
});

observer.observe({entryTypes: ['longtask']});

Tracking Input Latency

Bazı Javascriptlerin çalıştırılması uzun sürerse diğer tüm görevlerin beklemesine neden olarak yüklenme süresini uzatır.

Input Latency, koddaki bu süreleri karşılaştırmanı sağlar. Süre 100 ms’den büyükse raporlamalısınız.

const subscribeBtn = document.querySelector('#subscribe');

subscribeBtn.addEventListener('click', (event) => {
// Event listener logic goes here...

const lag = performance.now() - event.timeStamp;
if (lag > 100) {
ga('send', 'event', {
eventCategory: 'Performance Metric'
eventAction: 'input-latency',
eventLabel: '#subscribe:click',
eventValue: Math.round(lag),
nonInteraction: true,
});
}
});
Yukarıdaki grafik, TTI’nın masaüstü (mavi) ve mobil (turuncu) arasında dağılımını göstermektedir. Bu örnekten de görebileceğiniz gibi, mobil cihazlardaki TTI değeri masaüstünden biraz daha uzun.

Performans‘ın satın almaya etkisi

Analytics’teki Goal Complation (hedef tamamlamalarını) veya E-commerce (e-ticaret) dönüşümlerini izliyorsanız, bu metrikler ile uygulamanın performans metrikleri arasındaki ilişkiyi araştıran raporlar oluşturabilirsiniz.

Örneğin:

  • Kötü performansın satın almaları olumsuz yönde etkilediği yerleri belirleyin.
  • Daha hızlı performans sergileyen yerlerde kullanıcılar daha fazla şey satın alıyor mu?
  • Daha uzun sürede yüklenen yerlerde kullanıcılar daha yüksek oranlarda mı düşüyor?
  • Uygulamanızın mobil cihazlarda ve masaüstünde nasıl performans gösterdiğini inceleyin.

Bu raporlar arasında bir korelasyon bulunursa, performansın önemli olduğu ve önceliklendirilmesi gereken bir iş olduğu daha kolay kabul ettirilecektir.

Load Abondment

Bir kullanıcının siteyi yüklemesi uzun sürerse sayfadan ayrıldığını biliyoruz. Ve bu tüm performans metriklerimizin Survivorship Bias* sorununu yaşadığını gösteriyor. Sayfanın yüklenmesini beklemeyip çıkanların yükleme sürelerini nasıl ölçebiliriz?

Analytics asenkron yüklenir kullanıcı ayrılmaya karar verdiğinde analytics.js yüklenmemiş olabilir. Bu durumda “Measurement Protocol” ile gönderebiliriz. Bu kod, “visibilitychange”e bir dinleyici ekler (sayfa yüklenirse ya da yüklenmezse) ve bu noktada “performance.now ()” değerini gönderir.

Measurement Protocol:

  • Sayfa hakkındaki bilgileri doğrudan Google Analytics sunucularına gönderir.
  • Geliştiricilerin kullanıcıların siteyle nasıl etkileşime girdiklerini her ortamdan ölçmelerini sağlar.
  • Hem client’tan hem de serverden veri gönderir.
<script>
window.__trackAbandons = () => {
// Remove the listener so it only runs once.
document.removeEventListener('visibilitychange', window.__trackAbandons);
const ANALYTICS_URL = 'https://www.google-analytics.com/collect';
const GA_COOKIE = document.cookie.replace(
/(?:(?:^|.*;)\s*_ga\s*\=\s*(?:\w+\.\d\.)([^;]*).*$)|^.*$/, '$1');
const TRACKING_ID = 'UA-XXXXX-Y';
const CLIENT_ID = GA_COOKIE || (Math.random() * Math.pow(2, 52));

// Send the data to Google Analytics via the Measurement Protocol.
navigator.sendBeacon && navigator.sendBeacon(ANALYTICS_URL, [
'v=1', 't=event', 'ec=Load', 'ea=abandon', 'ni=1',
'dl=' + encodeURIComponent(location.href),
'dt=' + encodeURIComponent(document.title),
'tid=' + TRACKING_ID,
'cid=' + CLIENT_ID,
'ev=' + Math.round(performance.now()),
].join('&'));
};
document.addEventListener('visibilitychange', window.__trackAbandons);
</script>

Survivorship bias hayatta kalanlara odaklanıp, başarısız olanların nedenlerini gözardı etmektir.

Örnek olarak İkinci dünya savaşı sırasında Amerika Hava Kuvvetleri uçaklarının düşmesini engellemek için üsse dönen uçakların mermi deliklerini analiz ediyorlar.Bu çıkarttıkları sonuçlara göre uçaklarını zırh ile kaplayacaklardı. Ancak İstatikçi Abraham Wald duruma müdahale ediyor ve analizlerinin sadece geri dönen uçakları kapsadığını asıl önemin geri dönemeyen uçakların niçin düştüğünü analiz etmektir olduğunu söylüyor.

Araştırmalar sonucunda uçağın gövdesinin, kuyruğunun ve kanatlarının aksine, motorunun çok hassas olduğu, oraya isabet eden kurşunların uçağın düşmesine neden olduğu ortaya çıktı.