RUM (Real User Monitoring), sitenize gelen gerçek kullanıcıların tarayıcısından Core Web Vitals ve diğer performans metriklerini toplar. web-vitals.js, GA4 custom event, Netlify Edge Function ve Vercel Speed Insights ile ücretsiz ya da düşük maliyetli RUM kurulumunu adım adım açıklayan pratik rehber.
Gerçek Kullanıcı Verisi Toplamak İçin RUM Nasıl Kurulur: Ücretsiz Yöntemler
RUM (Real User Monitoring - Gerçek Kullanıcı İzleme), sitenizi ziyaret eden kişilerin kendi tarayıcısından performans ölçümleri toplar. Lighthouse veya benzeri araçların ürettiği lab verisi, sabit bir bağlantı hızı ve sabit bir donanım simülasyonuyla çalışır; ziyaretçileriniz ise farklı ağlar, farklı cihazlar ve farklı coğrafi konumlardan gelir. Bu iki veri kaynağı arasındaki fark bazen şaşırtıcı boyutlara ulaşır. Düşük uçlu bir akıllı telefonda 4G bağlantısıyla yaşanan LCP değeri, geniş bantlı masaüstü kullanıcısının değerinin iki katı olabilir ve lab testiniz bunu hiç göstermez.
Kurumsal RUM çözümlerinin büyük çoğunluğu aylık yüzlerce dolar maliyete ulaşır; bu rakam küçük ekipler ve bireysel geliştiriciler için caydırıcıdır. Ancak ücretsiz ya da çok düşük maliyetli birkaç yöntem, belirli bir trafik hacmine kadar makul doğrulukta gerçek kullanıcı verisi toplamanıza izin verir: web-vitals.js kütüphanesi, GA4 custom event entegrasyonu, Netlify Edge Function ve Vercel Speed Insights bunların başında gelir. Her birinin kurulum yükü, veri güvenilirliği ve ölçeklenme sınırları birbirinden ayrışır.
Dört yaklaşım pratikte farklı eşiğe oturur: hangisi hangi projede anlamlı veri üretir, hangisi çaba-getiri dengesinde zayıf kalır, hangisi düşük trafikte beklentinin altında kalır. Kurulumdan önce bu ayrımı netleştirmek, yanlış aracı seçmemek için yeterlidir.
Lab verisi ile alan verisi arasındaki gerçek fark
Lab verisi deterministiktir: aynı araç, aynı URL için her seferinde benzer koşullar altında çalışır. Bu tekrarlanabilirlik, bir kod değişikliğinin etkisini izole etmek açısından değerlidir. Ancak deterministik olmak, temsili olmak anlamına gelmez. Sitenizin gerçek ziyaretçileri arasında eski Android cihazlar, güçsüz işlemciler, aralıklı 3G bağlantılar ve arka planda çalışan onlarca sekme bulunanlar olabilir.
Alan verisi bu karmaşıklığı yansıtır. Chrome Kullanıcı Deneyimi Raporu (CrUX), Search Console'daki Core Web Vitals raporu ve kendi topladığınız RUM verisi hepsi kullanıcıların gerçekte ne yaşadığını gösterir. Lighthouse puanı yüksek olduğu halde kullanıcıların yavaş hissetmesi tam da bu boşluktan kaynaklanır; RUM kurmadan önce bu soruyu sormaya değer: Lighthouse skorum gerçek ziyaretçi deneyimimi yansıtıyor mu?
RUM'un olmadığı durumda CrUX verisi bir alternatif olarak devreye girer, ancak CrUX yalnızca belirli bir trafik eşiğini aşmış sayfalar için veri üretir ve geriye dönük olarak 28 günlük bir pencere sunar. Kendi RUM altyapınız kuruluysa daha ayrıntılı veriye, daha hızlı güncellemeye ve özel segmentlere ulaşırsınız. Yeni bir özellik deploy ettikten sonra LCP değerinin değişip değişmediğini görmek istiyorsanız, CrUX bu hızı veremez.
web-vitals.js ile ölçüm koleksiyonu kurmak
Google'ın yayımladığı web-vitals kütüphanesi, LCP, INP, CLS, FCP ve TTFB metriklerini tarayıcıdan toplar ve bir callback fonksiyonu aracılığıyla istediğiniz herhangi bir endpoint'e gönderebilmenizi sağlar. Kütüphane açık kaynaklıdır, yaklaşık 2 KB boyutundadır (gzip sonrası) ve düzenli olarak güncellenmektedir. Temel kurulum şöyle görünür:
import { onLCP, onINP, onCLS, onFCP, onTTFB } from 'web-vitals';
function sendToAnalytics(metric) {
const body = JSON.stringify({
name: metric.name,
value: metric.value,
rating: metric.rating,
id: metric.id,
navigationType: metric.navigationType
});
navigator.sendBeacon('/api/vitals', body);
}
onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);
onFCP(sendToAnalytics);
onTTFB(sendToAnalytics);
navigator.sendBeacon tercih edilmesinin nedeni, sayfa kapanırken bile güvenilir biçimde veri göndermesidir. Standart fetch çağrısı sayfa boşaltılırken iptal edilebilir; beacon bu riski ortadan kaldırır. Endpoint olarak bir Netlify Edge Function, Cloudflare Worker veya kendi sunucunuzdaki basit bir API rotası kullanılabilir.
Ne zaman işe yarar? Siteye doğrudan JavaScript ekleyebildiğiniz her durumda. Tag manager üzerinden de yüklenebilir, ancak bu durumda kütüphanenin yüklenme zamanlaması biraz kayar ve bazı erken sayfaların metriklerini kaçırabilirsiniz. Ne zaman ters etki yaratır? Tek başına toplama kodu yeterli değildir. Verileri bir yerde depolamanız ve sorgu atabilmeniz gerekir; depolama tarafını çözmeden sadece beacon göndermek, geriye bakış imkanı olmayan anlık yanıp sönen bir sinyal gibidir.
GA4 custom event ile RUM verisi biriktirmek
GA4 zaten çoğu sitede yüklüdür ve custom event desteği sunar. web-vitals.js'ten gelen callback'i GA4'e yönlendirmek, ayrı bir backend kurma yükünü ortadan kaldırır. Veri GA4'ün kendi altyapısına yazılır; sorgulama için BigQuery bağlantısı ya da GA4 arayüzü kullanılabilir.
import { onLCP, onINP, onCLS } from 'web-vitals';
function sendToGA4(metric) {
gtag('event', metric.name, {
value: Math.round(metric.name === 'CLS' ? metric.value * 1000 : metric.value),
metric_id: metric.id,
metric_value: metric.value,
metric_rating: metric.rating
});
}
onLCP(sendToGA4);
onINP(sendToGA4);
onCLS(sendToGA4);
CLS değerini 1000 ile çarpmanın nedeni, GA4'ün olay değerlerini tam sayı olarak kaydetmesidir; 0.12 gibi bir değer 0'a yuvarlanırdı. Sonradan veriyi yorumlarken bu dönüşümün akılda tutulması gerekir.
GA4 yolunun güçlü bir tarafı vardır: mevcut segment altyapısı cihaz türü, ülke, tarayıcı ve sayfa bazlı kırılımlara olanak tanır. Aylık site hızı takibini yalnızca CrUX verisine değil kendi topladığınız RUM verilerine dayandırmak isterseniz GA4 bu açıdan elverişli bir zemin sağlar; bir önceki ayın LCP değerini bu ayla karşılaştırmak da mümkündür.
Sınırlar da bellidir. GA4 veri örnekleme uygulayabilir; yüksek trafikli sayfalarda bu örnekleme bazı uç değerleri gizler. GA4 verisi gerçek zamanlı değildir, işleme süresi birkaç saate ulaşabilir. Reklam engelleyiciler GA4 beacon'larını bloke edebilir, dolayısıyla özellikle teknik kitleye sahip sitelerde veri eksiklikleri yaşanabilir. Bu eksikliklerin trafik segmentinizde ne kadar büyük olduğunu önceden bilmeden GA4 yolunu tek kaynak olarak kullanmak riskli olabilir.
Netlify Edge Function: veri toplama ve kalıcı depolama
Netlify Edge Functions, CDN katmanında çalışan küçük sunucu tarafı kodlardır ve ücretsiz planda belirli bir çağrı limitiyle gelir. web-vitals.js'in beacon gönderdiği endpoint olarak bir Edge Function kullanmak, ek bir backend sunucusu kurmadan veri toplamayı mümkün kılar. Basit bir örnek:
// netlify/edge-functions/vitals.ts
import type { Context } from "netlify:edge";
export default async (request: Request, context: Context) => {
if (request.method !== "POST") {
return new Response("Method Not Allowed", { status: 405 });
}
const data = await request.json();
console.log(JSON.stringify({
...data,
timestamp: new Date().toISOString(),
userAgent: request.headers.get("user-agent"),
country: context.geo?.country?.code
}));
return new Response("OK", { status: 200 });
};
Ne zaman anlamlıdır? Netlify'de barındırılan projeler için ek altyapı kurmadan veri akışı başlatmak için idealdir. Coğrafi konum bilgisi (context.geo) ücretsiz olarak gelir; hangi ülkeden gelen kullanıcıların kötü LCP yaşadığını anlamak için bu değerli bir girdidir. Ancak tek başına loglama yeterli değildir. Verileri kalıcı bir depoya yazmak gerekir: Supabase'in ücretsiz katmanı, SQLite tabanlı edge veritabanları veya Netlify Blobs bu iş için kullanılabilir.
Ne zaman ters etki yaratır? Ücretsiz plandaki çağrı limitleri yüksek trafikli sitelerde erken tükenir. Her sayfa görüntülemesinde beş ayrı metrik için beacon gönderildiğini düşünürsek, aylık 100.000 sayfa görüntülemesi yaklaşık 500.000 Edge Function çağrısına dönüşebilir. Bu sayı ücretsiz planın sınırını aşar ve ölçüm durur; limit hesabını önceden yapmak zorunludur.
Vercel Speed Insights: kolay kurulum, kapalı kutu
Vercel Speed Insights, Vercel üzerinde barındırılan projeler için sıfır konfigürasyonla çalışan bir RUM çözümüdür. Next.js projelerine entegrasyon tek bir paket kurulumu ve tek satır kod gerektirir:
import { SpeedInsights } from "@vercel/speed-insights/next";
export default function RootLayout({ children }) {
return (
<html>
<body>
{children}
<SpeedInsights />
</body>
</html>
);
}
Ücretsiz planda aylık belirli bir sayfa görüntüleme limiti vardır; limit aşıldığında ölçüm o ay için durur ve sessizce veri kaybı yaşanır. Toplanan metrikler Vercel'in kendi kontrol panelinde sayfa bazlı kırılımlarla gösterilir. Next.js projelerinde performans darboğazlarını bulmak için başlangıç noktası olarak kullanışlıdır; ham veriye erişim ve dışa aktarma yalnızca ücretli planlarda mevcuttur.
Vercel Speed Insights'ı diğer yöntemlerden ayıran şey, kurulum kolaylığının veri üzerindeki kontrolün azlığıyla birlikte gelmesidir. Veriyi kendiniz depolayamadığınız, özel segmentler ya da özel özellikler ekleyemediğiniz ve limitin ne zaman dolduğunu takip etmediğiniz durumlarda bu önemli bir kısıtlama olur. Proje büyüyüp trafik arttıkça bu kısıtlama giderek daha belirgin hale gelir.
Toplanan veriyi nasıl okumalısınız?
Ham RUM verisi kendi başına yanıltıcı olabilir. Ortanca (p50) değer iyi görünse de kullanıcıların yaklaşık yüzde yirmibeşini oluşturan yavaş segmentin deneyimi çok farklı bir tablo çizebilir. Bu nedenle RUM verisi yorumlanırken p75 ve p95 yüzdeliklerine bakmak standart bir pratiktir; Core Web Vitals değerlendirmesi de p75 üzerinden yapılır.
Şu sorular veriyi anlamlı kılar: Hangi sayfalar en kötü LCP değerine sahip? Mobil ve masaüstü arasında fark ne kadar büyük? Belirli bir ülke veya tarayıcı sürümü belirgin biçimde ayrışıyor mu? Performans sorununu düzeltirken önce neye bakılacağına karar vermek için bu segmentasyon kritiktir. Tüm kullanıcılar için genel ortancayı iyileştirmek yerine en kötü segmenti hedeflemek, çoğu durumda daha az çabayla daha büyük etki yaratır.
Bir deploy sonrası değişimi izlemek için RUM verisi idealdir, ancak sabır gerektirir. Trafik yeterince yoğun değilse yüzdelik değerler günden güne büyük dalgalanmalar gösterir; düşük trafikli sitelerde RUM verisi tek başına karar vermek için yeterli olmayabilir. LCP öğesini tespit etmek için lab araçları, bu öğenin gerçek kullanıcılarda ne kadar geç yüklendiğini anlamak için ise RUM verisi gerekir; ikisi birbirini tamamlar, biri diğerinin yerine geçmez.
CLS gibi bir metrik, lab ortamında çoğunlukla 0 çıkar çünkü dinamik içerik yüklenmesi gerçek kullanıcıda olduğu gibi gerçekleşmez. RUM bu metriği çok daha doğru ölçer. TTFB düşük ama FCP yüksek olan durumlarda da RUM'dan gelen FCP dağılımı, sorunun belirli bir kullanıcı segmentinde mi yoksa genel ziyaretçi tabanında mı yaşandığını netleştirir.
Hangi yöntemi seçeceğinize karar verirken birkaç soru yol gösterir: Siteniz nerede barındırılıyor, aylık trafik hacmi ne kadar ve bu veriye ne ölçüde kontrollü erişmek istiyorsunuz? Vercel'de barındırılmış bir Next.js projesi için Speed Insights hızlı bir başlangıç sağlar. Netlify kullanan bir proje için Edge Function yolu esneklik ve coğrafi veri getirir. GA4 zaten kuruluysa custom event entegrasyonu ek altyapı gerektirmez ve çoğu küçük ile orta ölçekli site için yeterlidir.
Herhangi bir yöntemin ücretsiz olması, sınırsız olduğu anlamına gelmez. Ücretsiz katman limitlerini hesaplamak, aylık trafik tahmininizi ve her ziyaretçinin kaç metrik tetiklediğini göz önüne alarak önceden yapılmalıdır. Sınırı aşan durumda ya ücretli katmana geçmek ya da kendi altyapınızı işletmek gerekir; ikincisi operasyonel yük getirir ama veri üzerinde tam kontrol sağlar.
RUM kurulumu tek seferlik bir iş değildir. Toplanan veri düzenli olarak okunmadığında, segmentlere ayrılmadığında ve optimizasyon kararlarına dönüştürülmediğinde toplama altyapısının değeri sıfıra yaklaşır. Ölçümün amacı veriyi depolamak değil, doğru yerde doğru müdahaleye rehberlik etmektir.