Perché il Real User Monitoring è essenziale per WordPress
Il Real User Monitoring (RUM) misura le performance reali dei siti WordPress dal browser degli utenti, non da test sintetici. Mentre strumenti come Lighthouse o GTmetrix forniscono snapshot controllati, il RUM raccoglie dati da sessioni reali con variabili imprevedibili: connessioni lente, dispositivi obsoleti, estensioni browser invasive.
Per le agenzie che gestiscono decine di siti client, il RUM offre vantaggi concreti:
- Rilevamento proattivo di regressioni di performance prima delle lamentele dei clienti
- Dati segmentati per geografía, dispositivo e tipo di connessione
- Correlazione diretta tra performance e metriche di business (conversioni, bounce rate)
- Validazione degli interventi di ottimizzazione con dati reali
Dal 2021, Google considera i Core Web Vitals fattore di ranking. Monitorarli con RUM è diventato un requisito operativo, non un optional.
Core Web Vitals e Performance API
I tre pilastri dei Core Web Vitals richiedono misurazioni specifiche tramite JavaScript:
Largest Contentful Paint (LCP)
Misura quando l’elemento principale del viewport diventa visibile. L’API Performance Observer lo intercetta così:
const observer = new PerformanceObserver((list) => {
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
console.log('LCP:', lastEntry.renderTime || lastEntry.loadTime);
});
observer.observe({ type: 'largest-contentful-paint', buffered: true });
Target: sotto 2.5 secondi. Sul campo, siti WordPress complessi raggiungono 3-4 secondi senza ottimizzazioni.
First Input Delay (FID) e Interaction to Next Paint (INP)
FID misura la latenza del primo input utente. Dal marzo 2024, Google lo ha sostituito con INP che valuta tutte le interazioni. Implementazione INP:
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
const duration = entry.processingStart - entry.startTime;
console.log('INP candidate:', duration, entry.name);
}
});
observer.observe({ type: 'event', buffered: true, durationThreshold: 16 });
Target INP: sotto 200ms. Plugin JavaScript pesanti (slider, form builder) sono i principali colpevoli di valori alti.
Cumulative Layout Shift (CLS)
Misura gli spostamenti inattesi di layout. Critico per WordPress dove immagini senza dimensioni e banner dinamici causano problemi:
let clsValue = 0;
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
clsValue += entry.value;
}
}
});
observer.observe({ type: 'layout-shift', buffered: true });
Target: sotto 0.1. Temi con lazy loading mal implementato superano facilmente 0.3.
Implementare un sistema RUM completo su WordPress
Un’implementazione production-ready richiede raccolta dati, batching, invio beacon e gestione errori. Ecco uno script completo da inserire nel footer:
<script>
(function() {
const endpoint = '/wp-json/agencypilot/v1/rum';
const metrics = {};
const sessionId = Date.now() + Math.random().toString(36);
function sendMetrics(data) {
const payload = {
url: window.location.href,
sessionId: sessionId,
userAgent: navigator.userAgent,
connection: navigator.connection?.effectiveType,
timestamp: Date.now(),
...data
};
if (navigator.sendBeacon) {
navigator.sendBeacon(endpoint, JSON.stringify(payload));
} else {
fetch(endpoint, {
method: 'POST',
body: JSON.stringify(payload),
keepalive: true
});
}
}
// LCP
new PerformanceObserver((list) => {
const entries = list.getEntries();
const lastEntry = entries[entries.length - 1];
metrics.lcp = lastEntry.renderTime || lastEntry.loadTime;
}).observe({ type: 'largest-contentful-paint', buffered: true });
// FID (legacy)
new PerformanceObserver((list) => {
const entry = list.getEntries()[0];
metrics.fid = entry.processingStart - entry.startTime;
}).observe({ type: 'first-input', buffered: true });
// CLS
let clsValue = 0;
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (!entry.hadRecentInput) {
clsValue += entry.value;
}
}
metrics.cls = clsValue;
}).observe({ type: 'layout-shift', buffered: true });
// Navigation Timing
window.addEventListener('load', () => {
const nav = performance.getEntriesByType('navigation')[0];
metrics.ttfb = nav.responseStart - nav.requestStart;
metrics.domLoad = nav.domContentLoadedEventEnd - nav.fetchStart;
metrics.windowLoad = nav.loadEventEnd - nav.fetchStart;
});
// Invio al page hide
window.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'hidden') {
sendMetrics(metrics);
}
});
// Fallback dopo 10 secondi
setTimeout(() => sendMetrics(metrics), 10000);
})();
</script>
Questo script raccoglie metriche essenziali e le invia tramite sendBeacon (garantito anche se l’utente chiude la tab) o fetch con keepalive.
Backend WordPress: REST API endpoint
Lato server serve un endpoint per ricevere i dati. Esempio minimale in functions.php:
add_action('rest_api_init', function() {
register_rest_route('agencypilot/v1', '/rum', [
'methods' => 'POST',
'callback' => 'handle_rum_data',
'permission_callback' => '__return_true'
]);
});
function handle_rum_data($request) {
$data = json_decode($request->get_body(), true);
// Validazione base
if (empty($data['lcp']) || empty($data['sessionId'])) {
return new WP_Error('invalid_data', 'Missing required fields', ['status' => 400]);
}
// Salvataggio in custom table o invio a servizio esterno
global $wpdb;
$wpdb->insert(
$wpdb->prefix . 'rum_metrics',
[
'session_id' => sanitize_text_field($data['sessionId']),
'url' => esc_url_raw($data['url']),
'lcp' => floatval($data['lcp']),
'fid' => floatval($data['fid'] ?? 0),
'cls' => floatval($data['cls']),
'ttfb' => floatval($data['ttfb']),
'user_agent' => sanitize_text_field($data['userAgent']),
'connection' => sanitize_text_field($data['connection'] ?? 'unknown'),
'created_at' => current_time('mysql')
]
);
return ['success' => true];
}
Per volumi alti (>100k pageview/mese), conviene inviare i dati a servizi esterni come Elasticsearch o ClickHouse invece di salvare in MySQL.
Strumenti e servizi RUM pronti all’uso
Implementare RUM da zero è istruttivo ma time-consuming. Alternative commerciali mature:
Google Analytics 4 + Web Vitals
Dal 2022 GA4 raccoglie automaticamente Core Web Vitals. Integrazione con la libreria ufficiale:
<script type="module">
import {onCLS, onFID, onLCP} from 'https://unpkg.com/web-vitals@3?module';
function sendToGA({name, delta, id}) {
gtag('event', name, {
event_category: 'Web Vitals',
value: Math.round(delta),
event_label: id,
non_interaction: true
});
}
onCLS(sendToGA);
onFID(sendToGA);
onLCP(sendToGA);
</script>
Pro: gratuito fino a 10M eventi/mese, integrato con Analytics. Contro: sampling aggressivo, limitazioni query.
Soluzioni dedicate
- SpeedCurve: il più completo, $20/mese per sito. Heatmap CLS, filmstrip, correlazione con business metrics
- Datadog RUM: enterprise grade, ottimo per agenzie con infrastruttura complessa. Da $1.27 per 10k sessioni
- Sentry Performance: focus su errori JS + performance. $26/mese per 50k transazioni
- Cloudflare Web Analytics: gratuito, privacy-first, limiti nelle funzionalità avanzate
Per agenzie con portfolio 20+ siti, strumenti centralizzati come AgencyPilot che aggregano RUM da tutti i client fanno risparmiare ore di dashboard hopping.
Ottimizzare in base ai dati RUM
Raccogliere dati è inutile senza azione. Pattern comuni rilevati via RUM su WordPress:
LCP alto su mobile
Cause frequenti:
- Hero image non ottimizzata: serve responsive images con
srcsete formati moderni (WebP, AVIF) - Font web bloccanti: usare
font-display: swape preload selettivo - CSS render-blocking: critical CSS inline, defer del resto
CLS da advertising e lazy loading
Soluzioni:
- Riservare spazio con
aspect-ratioCSS per banner dinamici - Specificare
widtheheightsu tutte le immagini - Evitare lazy loading above-the-fold
INP degradato da plugin
Con RUM si identificano eventi specifici lenti. Colpevoli tipici: slider Swiper con troppe slide, form validation sincrona, mega menu con animazioni complesse. Soluzione: code splitting, web workers per operazioni pesanti, debouncing eventi.
Privacy e GDPR compliance
Il RUM raccoglie dati utente. Considerazioni legali:
- IP anonymization: troncare gli ultimi ottetti prima di salvare
- No PII: escludere parametri URL sensibili (email, token)
- Cookie banner: alcuni interpretano RUM come tracking, altri no. Posizione conservativa: richiedere consenso analytics
- Data retention: cancellare metriche dopo 90-180 giorni
Cloudflare Web Analytics e Plausible sono alternative privacy-first che non richiedono consenso in UE.
FAQ
Qual è la differenza tra RUM e Synthetic Monitoring?
Il Synthetic Monitoring (Lighthouse, WebPageTest) esegue test controllati da location e configurazioni predefinite. Il RUM raccoglie dati da utenti reali con infinite variabili: dispositivi, connessioni, estensioni browser. Synthetic è ottimo per baseline e regression testing, RUM per capire l’esperienza reale degli utenti. Servono entrambi.
Quanto impatta il codice RUM sulle performance?
Gli script RUM ben scritti pesano 2-5KB gzipped e usano API native del browser (PerformanceObserver) con overhead minimo. L’impatto misurato è sotto 50ms sul load time totale. Script mal implementati con polling continuo o invii sincroni possono degradare proprio le metriche che cercano di misurare. Usare sempre sendBeacon o fetch con keepalive.
Quanti dati servono per avere statistiche significative?
Dipende dal traffico. Per siti con 1000+ pageview/giorno, una settimana fornisce dati sufficienti per identificare pattern. Sotto 500 pageview/giorno servono 2-4 settimane. Segmentare sempre per device type e connection: mobile 3G ha performance radicalmente diverse da desktop su fibra. Il 75° percentile (P75) è la metrica standard per valutare Core Web Vitals.
Come integrare RUM in workflow CI/CD?
Impostare alert automatici quando le metriche RUM superano soglie per più di X% delle sessioni. Esempio: se P75 LCP supera 3 secondi per 48 ore consecutive, bloccare i deploy e investigare. Strumenti come SpeedCurve offrono API per interrogare metriche RUM da pipeline CI. Alternativa: webhook che notificano Slack quando regressioni sono rilevate.
RUM funziona con cache e CDN?
Sì, anzi è ancora più importante. Con cache aggressive (Cloudflare, Varnish) i test sintetici vedono performance irrealisticamente alte. Il RUM misura l’esperienza reale includendo cold cache, miss CDN, variabilità geografica. Per siti WordPress con cache multi-livello, solo RUM rivela problemi come cache warming lento o edge location sottoperformanti.