Η Google παρέχει μια σειρά από εργαλεία – Search Console, PageSpeed Insights (PSI) και το Chrome User Experience Report (CrUX) – που επιτρέπουν στους developers να παρακολουθούν το web performance του site τους σε σχέση με τα Core Web Vitals metrics για τους πραγματικούς χρήστες.
Αυτά τα εργαλεία είναι εξαιρετικά, καθώς παρέχουν μια high-level εικόνα για το πραγματικό site performance όσον αφορά πραγματικούς χρήστες, και δεν απαιτούν απολύτως καμία περίπλοκη ρύθμιση για να ξεκινήσεις να τα χρησιμοποιείς.
Ωστόσο, υπάρχουν μερικοί κρίσιμοι λόγοι για τους οποίους δεν θέλεις να βασίζεσαι μόνο σε αυτά τα εργαλεία για να μετρήσεις το web performance του site σου:
- Τα CrUX-based εργαλεία κάνουν report δεδωμένων είτε ανά μήνα είτε ανά περίοδο με lookback window 28 ημερών. Αυτό σημαίνει ότι θα πρέπει να περιμένεις πολύ καιρό μετα την πραγματοποίηση οποιωνδήποτε αλλαγών πριν δεις τα αποτελέσματα.
- Τα CrUX-based εργαλεία μπορούν να δημιουργήσουν segments μόνο με περιορισμένο αριθμό από dimensions, όπως Country, Connection Type και Device Category (Desktop, Mobile). Δεν μπορείς να διαχωρίσεις τα δεδομένα με dimensions εξατομικευμένα στην επιχείρησή σου (π.χ. engaged users, users που ανήκουν σε ένα συγκεκριμένο experiment group, κ.λπ.).
- Τα CrUX-based εργαλεία μπορούν να σου πουν ποιο είναι το performance σου, αλλά δεν μπορούν να σου πουν το γιατί. Με analytics εργαλεία μπορείς να στείλεις πρόσθετα δεδμένα για να σε βοηθήσει να εντοπίσεις και να διορθώσεις σφάλματα.
Για αυτούς τους λόγους, προτείνουμε σε όλους τους site owners να παρακολουθούν τα Core Web Vitals metrics τους χρησιμοποιώντας το υπάρχον εργαλείο ανάλυσης που χρησιμοποιούν. Αυτό το post εξηγεί πώς μπορείς να χρησιμοποιήσεις τα δωρεάν εργαλεία της Google για να το πετύχεις.
Μόλις έχεις ρυθμίσει τα πάντα, θα μπορείς να δημιουργήσεις dashboards όπως τα παρακάτω:


Αν θες μια οπτική επισκόπηση όλων των βημάτων που περιγράφονται εδώ, δες το παρακάτω βίντεο από το Google I/IO ’21:
Measurement
Η μέτρηση του performance ήταν πάντα δυνατή μέσω του Google Analytics χρησιμοποιώντας custom metrics, αλλά υπάρχουν μερικές νέες λειτουργίες στο GA4 που θα πρέπει να ενθουσιάσουν, ειδικά τους developers.
- Zero-configuration, custom event parameters.
- Free BigQuery export, ώστε να είναι εφικτή η διαχείριση των data με SQL.
Ενώ το interface του Google Analytics διαθέτει ισχυρά εργαλεία ανάλυσης, είναι δύσκολο να ξεπεραστεί η ισχύς και η ευελιξία του να δουλεύεις με raw event data χρησιμοποιώντας μια “query language” για να βρεις απαντήσεις.
Για να ξεκινήσεις να μετράς τα Core Web Vitals με τα Google Analytics 4 και το BigQuery, πρέπει να κάνεις 3 πράγματα:
- Να δημιουργήσεις ένα GA4 property και ένα BigQuery project.
- Να ενεργοποιήσεις το BigQuery export στο Google Analytics property config, ώστε όλα τα δεοδμένα που λαμβάνεις να συμπληρώνονται αυτόματα στα tables του BigQuery.
- Να προσθέσεις την web-vitals JavaScript library στο site σου, ώστε να μετράς τα Core Web Vitals metrics και να στέλνεις τα δεδομένα στο GA4, συμπεριλαμβανομένων των attribution data.
Analysis
Μόλις ολοκληρώσεις το setup, θα μπορείς να δεις τα event data να συμπληρώνονται στο interface του BigQuery, και θα μπορείς να τρέξεις queries για δεδομένα, όπως παρακάτω:
SELECT * FROM `my_project_id.analytics_XXXXX.events_*`
WHERE event_name IN ('LCP', 'INP', 'CLS')
Εδώ είναι ένα preview από τα αποτελέσματα του παραπάνω query:
Πώς να τρέξεις queries στα Web Vitals data
Πριν ξεκινήσεις να γράφεις queries στα Web Vitals data, είναι σημαντικό να κατανοήσεις πώς συγκεντρώνονται τα δεδομένα.
Το πιο σημαντικό πράγμα που πρέπει να κατανοήσεις είναι ότι, σε ορισμένες περιπτώσεις, ενδέχεται να ληφθούν πολλαπλά events για το ίδιο metric, στην ίδια σελίδα.
Αυτό μπορεί να συμβεί εάν αλλάξει η τιμή της μέτρησης και αναφερθεί μια ενημερωμένη τιμή (ένα συνηθισμένο φαινόμενο με το CLS).
Για τα Web Vitals events, η τελευταία τιμή που στάλθηκε είναι πάντα η πιο ακριβής, επομένως πριν από την εκτέλεση οποιασδήποτε ανάλυσης, είναι σημαντικό να φιλτράρεις μόνο για αυτές τις τιμές.
Το code snippet που παρέχεται από τη βιβλιοθήκη JavaScript web-vitals για την αποστολή δεδομένων στο Google Analytics 4 περιλαμβάνει την αποστολή ενός unique ID ανά metric, επομένως μπορείς να χρησιμοποιήσεις το ακόλουθο queryγια να περιορίσεις τα αποτελέσματά σου μόνο στην τελευταία τιμή που ελήφθη για κάθε metric ID:
# Subquery all Web Vitals events from the last 28 days
WITH web_vitals_events AS (
SELECT event_name as metric_name, * EXCEPT(event_name, is_last_received_value) FROM (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id') ORDER BY (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'metric_start_time') DESC
) = 1 AS is_last_received_value
FROM `bigquery_project_id.analytics_XXXXX.events_*`
WHERE event_name in ('CLS', 'INP', 'LCP') AND
_TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY))
) WHERE is_last_received_value
)
Σημείωση: Όλα τα άλλα ερωτήματα που αναφέρονται σε αυτό το post θα ξεκινούν με αυτό το subquery.
Παραδείγματα
Παρακάτω, παρουσιάζουμε μερικά παραδείγματα συνηθισμένων Web Vitals queries που ίσως θέλεις να εκτελέσεις.
LCP, INP, and CLS at the 75% percentile (p75) for the whole site
# Subquery all Web Vitals events from the last 28 days
WITH web_vitals_events AS (
SELECT event_name as metric_name, * EXCEPT(event_name, is_last_received_value) FROM (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id') ORDER BY (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'metric_start_time') DESC
) = 1 AS is_last_received_value
FROM `bigquery_project_id.analytics_XXXXX.events_*`
WHERE event_name in ('CLS', 'INP', 'LCP') AND
_TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY))
) WHERE is_last_received_value
)
# Main query logic
SELECT
metric_name,
APPROX_QUANTILES(metric_value, 100)[OFFSET(75)] AS p75,
COUNT(1) as count
FROM (
SELECT
metric_name,
ROUND((SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = "metric_value"), 3) AS metric_value,
FROM web_vitals_events
)
GROUP BY 1
All individual LCP values from highest to lowest
# Subquery all Web Vitals events from the last 28 days
WITH web_vitals_events AS (
SELECT event_name as metric_name, * EXCEPT(event_name, is_last_received_value) FROM (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id') ORDER BY (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'metric_start_time') DESC
) = 1 AS is_last_received_value
FROM `bigquery_project_id.analytics_XXXXX.events_*`
WHERE event_name in ('CLS', 'INP', 'LCP') AND
_TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY))
) WHERE is_last_received_value
)
# Main query logic
SELECT
ROUND((SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = "metric_value"), 3) AS metric_value,
FROM web_vitals_events
WHERE metric_name = 'LCP'
ORDER BY metric_value DESC
LCP scores (p75) of the 10 most popular pages
# Subquery all Web Vitals events from the last 28 days
WITH web_vitals_events AS (
SELECT event_name as metric_name, * EXCEPT(event_name, is_last_received_value) FROM (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id') ORDER BY (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'metric_start_time') DESC
) = 1 AS is_last_received_value
FROM `bigquery_project_id.analytics_XXXXX.events_*`
WHERE event_name in ('CLS', 'INP', 'LCP') AND
_TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY))
) WHERE is_last_received_value
)
# Main query logic
SELECT
page_path,
APPROX_QUANTILES(metric_value, 100)[OFFSET(75)] AS LCP,
COUNT(1) as count
FROM (
SELECT
REGEXP_SUBSTR((SELECT value.string_value FROM UNNEST(event_params) WHERE key = "page_location"), r'\.com(\/[^?]*)') AS page_path,
ROUND((SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = "metric_value"), 3) AS metric_value,
FROM web_vitals_events
WHERE metric_name = 'LCP'
)
GROUP BY 1
ORDER BY count DESC
LIMIT 10
Top 10 pages with the worst CLS (p75)
# Subquery all Web Vitals events from the last 28 days
WITH web_vitals_events AS (
SELECT event_name as metric_name, * EXCEPT(event_name, is_last_received_value) FROM (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id') ORDER BY (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'metric_start_time') DESC
) = 1 AS is_last_received_value
FROM `bigquery_project_id.analytics_XXXXX.events_*`
WHERE event_name in ('CLS', 'INP', 'LCP') AND
_TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY))
) WHERE is_last_received_value
)
# Main query logic
SELECT
page_path,
APPROX_QUANTILES(metric_value, 100)[OFFSET(75)] AS CLS,
COUNT(1) as count
FROM (
SELECT
REGEXP_SUBSTR((SELECT value.string_value FROM UNNEST(event_params) WHERE key = "page_location"), r'\.com(\/[^?]*)') AS page_path,
ROUND((SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = "metric_value"), 3) AS metric_value,
FROM web_vitals_events
WHERE metric_name = 'CLS'
)
GROUP BY 1
HAVING count > 50 # Limit to relatively popular pages
ORDER BY CLS DESC
LIMIT 10
Debug
Τα προηγούμενα queries δείχνουν πώς να τρέξεις queries για τα Web Vitals data, κάτι που είναι χρήσιμο για την κατανόηση της τρέχουσας απόδοσης και της τάσης που παρουσιάζει με την πάροδο του χρόνου. Αλλά τι μπορείς να κάνεις εάν η απόδοσή σου είναι χειρότερη από την αναμενόμενη, αλλά δεν είσαι σίγουρος γιατί;
Η γνώση των scores σου δεν είναι χρήσιμη εάν δεν μπορείς να κάνεις ενέργειες και να διορθώσεις τα προβλήματα.
Το performance debugging εξηγεί πώς μπορείς να στείλεις πρόσθετες πληροφορίες για σφάλματα με τα analytics data σου. Εάν ακολουθήσεις τις οδηγίες που περιγράφονται λεπτομερώς παρακάτω, θα δεις ότι οι πληροφορίες εντοπισμού σφαλμάτων εμφανίζονται και στο BigQuery.
Παραδείγματα
Τα ακόλουθα queries δείχνουν πώς να χρησιμοποιήσεις την παράμετρο debug_target για να εντοπίσεις την αιτία των προβλημάτων στο performance.
Top elements contributing to CLS
Το debug_target είναι ένας CSS Selector που αντιστοιχεί στο element μιας σελίδας που είναι πιο σχετικό με την metric value.
Με το CLS, το debug_target αντιπροσωπεύει το element με το μεγαλύτερο layout shift που συνέβαλε στην τιμή CLS. Εάν δεν υπάρξουν στοιχεία με layout shift, τότε η τιμή debug_target θα είναι μηδενική.
Το ακόλουθο query θα παραθέσει σελίδες από τη χειρότερη στην καλύτερη μέτρηση με βάση το CLS τους στο 75ο εκατοστημόριο, ομαδοποιημένες με βάση το debug_target:
# Subquery all Web Vitals events from the last 28 days
WITH web_vitals_events AS (
SELECT event_name as metric_name, * EXCEPT(event_name, is_last_received_value) FROM (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id') ORDER BY (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'metric_start_time') DESC
) = 1 AS is_last_received_value
FROM `bigquery_project_id.analytics_XXXXX.events_*`
WHERE event_name in ('CLS', 'INP', 'LCP') AND
_TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY))
) WHERE is_last_received_value
)
# Main query logic
SELECT
page_path,
debug_target,
APPROX_QUANTILES(metric_value, 100)[OFFSET(75)] AS CLS,
COUNT(1) as count
FROM (
SELECT
REGEXP_SUBSTR((SELECT value.string_value FROM UNNEST(event_params) WHERE key = "page_location"), r'\.com(\/[^?]*)') AS page_path,
(SELECT value.string_value FROM UNNEST(event_params) WHERE key = "debug_target") as debug_target,
ROUND((SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = "metric_value"), 3) AS metric_value,
*
FROM web_vitals_events
WHERE metric_name = 'CLS'
)
GROUP BY 1, 2
HAVING count > 50 # Limit to relatively popular pages
ORDER BY CLS DESC

Γνωρίζοντας ποια elements στη σελίδα μεταβάλλονται, θα πρέπει να είναι πολύ πιο εύκολο να εντοπίσεις και να διορθώσεις τη βασική αιτία του προβλήματος.
Λάβε υπόψη ότι τα elements που αναφέρονται εδώ ενδέχεται να μην είναι τα ίδια elements που βλέπεις να μεταβάλλονται όταν κάνεις debugging στις σελίδες σου τοπικά, γι’ αυτό είναι τόσο σημαντικό να αναλύσεις αυτά τα δεδομένα εξαρχής. Είναι πολύ δύσκολο να διορθώσεις πράγματα που δεν συνειδητοποιείς ότι αποτελούν προβλήματα!
Visualizations
Μπορεί να είναι δύσκολο να βγάλεις insights μόνο και μόνο κοιτάζοντας τα αποτελέσματα των queries. Για παράδειγμα, το ακόλουθο query παραθέτει ημερήσιες τιμές 75ου percentile για το LCP στο σύνολο δεδομένων.
# Subquery all Web Vitals events from the last 28 days
WITH web_vitals_events AS (
SELECT event_name as metric_name, * EXCEPT(event_name, is_last_received_value) FROM (
SELECT *, ROW_NUMBER() OVER (
PARTITION BY (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id') ORDER BY (SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'metric_start_time') DESC
) = 1 AS is_last_received_value
FROM `bigquery_project_id.analytics_XXXXX.events_*`
WHERE event_name in ('CLS', 'INP', 'LCP') AND
_TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 28 DAY)) AND FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE, INTERVAL 1 DAY))
) WHERE is_last_received_value
)
# Main query logic
SELECT
event_date,
metric_name,
APPROX_QUANTILES(ROUND(metric_value, 2), 100)[OFFSET(75)] AS p75
FROM
(
SELECT
event_date,
metric_name,
ROUND((SELECT COALESCE(value.double_value, value.int_value) FROM UNNEST(event_params) WHERE key = 'metric_value'), 3) AS metric_value
FROM web_vitals_events
WHERE
metric_name = 'LCP'
)
GROUP BY
1, 2
ORDER BY event_date
Από αυτά τα queries , είναι δύσκολο να εντοπιστούν τάσεις ή outliers απλώς εξετάζοντας τα δεδομένα.

Visualization των queries στο Looker Studio
Το BigQuery παρέχει έναν γρήγορο τρόπο για visualizations οποιωνδήποτε αποτελεσμάτων μέσω του Data Studio. Το Looker Studio είναι ένα data visualization εργαλείο που είναι δωρεάν στη χρήση.
Για να οπτικοποιήσετε τα αποτελέσματα των queries, αφού εκτελέσετεις το query σου στο user interface του BigQuery, κάνε κλικ στο κουμπί Explore Data και επίλεξε Explore με το Looker Studio.

Αυτό θα δημιουργήσει ένα direct link από το BigQuery στο Looker Studio στο Explore View. Σε αυτήν την προβολή, μπορείς να επιλέξεις τα πεδία που θέλετε να οπτικοποιήσεις, να επιλέξετε τύπους γραφημάτων, να ρυθμίσεις φίλτρα και να δημιουργήσεις ad hoc γραφήματα για γρήγορη οπτική ανάλυση. Από τα προηγούμενα αποτελέσματα δεδομένων, μπορείς να δημιουργήσεις αυτό το line chart για να δείς την τάση των τιμών LCP με την πάροδο του χρόνου:

Με αυτό το direct link μεταξύ των BigQuery και Looker Studio, μπορείς να δημιουργήσεις γραφήματα από οποιοδήποτε από τα queries σου και να δημιουργήσεις visualizations.
Ωστόσο, εάν θέλεις να κάνεις επιπλέον ανάλυση, ίσως θελήσεις να δημιουργήσεις ένα interactive dashboard για να μπορέσεις να εμβαθύνεις στα δεδομένα σου. Έχοντας ένα εύχρηστο dashboard, δεν χρειάζεται να δημιουργείς queries και γραφήματα χειροκίνητα, κάθε φορά που θες να αναλύσεις τα metrics σου.
Μπορείς να δημιουργήσεις ένα dashboard στο Looker Studio χρησιμοποιώντας τον native BigQuery connector. Για να το κάνεις αυτό, μπορείς να μεταβείς στο datastudio.google.com, να δημιουργήσεις ένα νέο data source, να επιλέξεις τον BigQuery connector και να επιλέξεις το dataset με το οποίο θέλεις να εργαστείς.

Web Vitals Materialization
Όταν δημιουργείτε dashboards με τα δεδομένα συμβάντων (event data) των Web Vitals, όπως περιγράφηκε προηγουμένως, δεν είναι αποδοτικό να χρησιμοποιείτε απευθείας το export dataset του Google Analytics 4.
Λόγω της δομής των δεδομένων του GA4 και της προεπεξεργασίας (preprocessing) που απαιτείται για τα metrics των Web Vitals, τμήματα του query σας θα καταλήξουν να εκτελούνται πολλαπλές φορές.
Αυτό δημιουργεί δύο προβλήματα: την απόδοση (performance) του dashboard και το κόστος του BigQuery.
Μπορείς να χρησιμοποιήσεις το BigQuery sandbox mode χωρίς καμία χρέωση. Με το δωρεάν πακέτο χρήσης (free usage tier) του BigQuery, το πρώτο 1 TB δεδομένων query που επεξεργάζεσαι κάθε μήνα είναι δωρεάν.
Για τις μεθόδους ανάλυσης που αναλύονται σε αυτό το post, θα πρέπει να μπορείτε να παραμένεις εντός αυτού του δωρεάν ορίου κάθε μήνα, εκτός κι αν χρησιμοποιείς ένα εξαιρετικά μεγάλο dataset ή εκτελείς τακτικά “βαριά” queries σε αυτό.
Αν όμως έχεις ένα website με υψηλή επισκεψιμότητα και θέλεiw να παρακολουθείw τακτικά διάφορα metrics μέσω ενός γρήγορου και διαδραστικού (interactive) dashboard, προτείνουμε να κάνεiw preprocess και materialize τα web vitals δεδομένα σoy, αξιοποιώντας παράλληλα efficiency features του BigQuery όπως partitioning, clustering, και caching.
Το παρακάτω script θα κάνει preprocess τα δεδομένα σoy στο BigQuery (source table) και θα δημιουργήσει ένα materialized table (target table). Όταν χρησιμοποιείw αυτό το query για το δικό σου dataset, καλό θα ήταν να ορίσεις ένα date range για τον source table, ώστε να μειώσεις τον όγκο των δεδομένων προς επεξεργασία.
# Materialize Web Vitals metrics from GA4 event export data
# Replace target table name
CREATE OR REPLACE TABLE bigquery_project_id.ga4_demo_dev.web_vitals_summary
PARTITION BY DATE(event_timestamp)
CLUSTER BY metric_name
AS
SELECT
ga_session_id,
IF(
EXISTS(SELECT 1 FROM UNNEST(events) AS e WHERE e.event_name = 'first_visit'),
'New user',
'Returning user') AS user_type,
IF(
(SELECT MAX(session_engaged) FROM UNNEST(events)) > 0, 'Engaged', 'Not engaged')
AS session_engagement,
evt.* EXCEPT (session_engaged, event_name),
event_name AS metric_name,
FORMAT_TIMESTAMP('%Y%m%d', event_timestamp) AS event_date
FROM
(
SELECT
ga_session_id,
ARRAY_AGG(custom_event) AS events
FROM
(
SELECT
ga_session_id,
STRUCT(
country,
device_category,
device_os,
traffic_medium,
traffic_name,
traffic_source,
page_path,
debug_target,
event_timestamp,
event_name,
metric_id,
IF(event_name = 'LCP', metric_value / 1000, metric_value) AS metric_value,
user_pseudo_id,
session_engaged,
session_revenue) AS custom_event
FROM
(
SELECT
(SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id')
AS ga_session_id,
(SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'metric_id')
AS metric_id,
ANY_VALUE(device.category) AS device_category,
ANY_VALUE(device.operating_system) AS device_os,
ANY_VALUE(traffic_source.medium) AS traffic_medium,
ANY_VALUE(traffic_source.name) AS traffic_name,
ANY_VALUE(traffic_source.source) AS traffic_source,
ANY_VALUE(
REGEXP_SUBSTR(
(SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'page_location'),
r'^[^?]+')) AS page_path,
ANY_VALUE(
(SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'debug_target'))
AS debug_target,
ANY_VALUE(user_pseudo_id) AS user_pseudo_id,
ANY_VALUE(geo.country) AS country,
ANY_VALUE(event_name) AS event_name,
SUM(ecommerce.purchase_revenue) AS session_revenue,
MAX(
(
SELECT
COALESCE(
value.double_value, value.int_value, CAST(value.string_value AS NUMERIC))
FROM UNNEST(event_params)
WHERE key = 'session_engaged'
)) AS session_engaged,
TIMESTAMP_MICROS(MAX(event_timestamp)) AS event_timestamp,
MAX(
(
SELECT COALESCE(value.double_value, value.int_value)
FROM UNNEST(event_params)
WHERE key = 'metric_value'
)) AS metric_value,
FROM
# Replace source table name
`bigquery_project_id.analytics_XXXXX.events_*`
WHERE
event_name IN ('LCP', 'INP', 'CLS', 'first_visit', 'purchase')
GROUP BY
1, 2
)
)
WHERE
ga_session_id IS NOT NULL
GROUP BY ga_session_id
)
CROSS JOIN UNNEST(events) AS evt
WHERE evt.event_name NOT IN ('first_visit', 'purchase');
Αυτό το materialized dataset έχει πολλά πλεονεκτήματα:
- Η δομή των δεδομένων είναι flattened και πιο εύκολη για queries.
- Διατηρεί μόνο τα Web Vitals events από το αρχικό GA4 dataset.
- Το Session ID, ο τύπος του χρήστη (νέος έναντι επισκέπτη – new versus returning), και οι πληροφορίες session engagement είναι άμεσα διαθέσιμες σε στήλες (columns).
- Ο πίνακας είναι partitioned ανά ημερομηνία και clustered ανά όνομα του metric. Αυτό συνήθως μειώνει τον όγκο των δεδομένων που επεξεργάζονται σε κάθε query.
- Επειδή δεν χρειάζεται να χρησιμοποιείς wildcards για να κάνεις query σε αυτόν τον πίνακα, τα αποτελέσματα των queries μπορούν να αποθηκευτούν σε cache (cached) για έως και 24 ώρες. Αυτό μειώνει το κόστος από την επανάληψη του ίδιου query.
- Αν χρησιμοποιείς το BigQuery BI engine, μπορείς να εκτελέσεις βελτιστοποιημένα SQL functions και operators σε αυτόν τον πίνακα.
- Μπορείς να κάνεις query απευθείας σε αυτό το materialized table μέσα από το BigQuery UI ή να τον χρησιμοποιήσεις στο Looker Studio μέσω του BigQuery connector.
Χρησιμοποιώντας τον Web Vitals Connector
Δεδομένου ότι η δημιουργία ενός πίνακα ελέγχου από την αρχή είναι χρονοβόρα, έχει αναπτυχεί μια ολοκληρωμένη λύση που θα δημιουργήσει ένα template dashboard για εσένα.
Αρχικά, βεβαιώσου ότι έχετε υλοποιήσει τον πίνακα Web Vitals χρησιμοποιώντας το προηγούμενο query.
Στη συνέχεια, απόκτησε πρόσβαση στον Web Vitals Connector για το Looker Studio χρησιμοποιώντας αυτόν τον σύνδεσμο: goo.gle/web-vitals-connector.
Αφού ολοκληρώσεις το One Time Authentication, θα πρέπει να δεις το ακόλουθο configuration screen:

Στη συνέχεια, όρισε το materialized BigQuery table και το BigQuery billing project ID.
Αφού κάνεις κλικ στην επιλογή Connect, το Looker Studio θα δημιουργήσει ένα νέο templated dashboard και θα συσχετίσει τα δεδομένα σου με αυτόν.
Μπορείς να κάνεις edit, modify και share το dashboard όπως προτιμάς. Αν δημιουργήσεις ένα dashboard για πρώτη φορά, δεν θα χρειασεί να επισκεφθείς ξανά το connector link, εκτός εάν θέλεις να δημιουργήσεις πολλαπλά dashboards από διαφορετικά datasets.
Πλοήγηση στο dashboard
Καθώς πλοηγείσαι στο dashboard, μπορείς να δεις τα daily trends των Web Vitals metrics και ορισμένα usage information για το website σου όπως users και sessions, στο Summary tab.
Στο User Analysis tab, μπορείς να επιλέξεις ένα metric και στη συνέχεια να λάβεις ένα breakdown των metrics, καθώς και του αριθμού των users ανά διαφορετικά usage και business metrics.
Το Page Path Analysis tab θα σε βοηθήσει να εντοπίσεις προβληματικές περιοχές στο website σου. Εδώ, μπορείς να επιλέξεις ένα metric για να δεις το overview.
Μπορείς επίσης να δεις ένα scatter-map όλων των page paths. Το scatter-map μπορεί να βοηθήσει στον εντοπισμό σελίδων που έχουν χαμηλότερες από τις αναμενόμενες τιμές μετρήσεων.
Μόλις επιλέξεις τις σελίδες χρησιμοποιώντας το scatter chart στο Page Path table, μπορείς να κάνεις drill down στην προβληματική περιοχή προβάλλοντας τον Debug Target table.
Το Revenue Analysis tab είναι ένα παράδειγμα του πώς μπορείς να παρακολουθείς τα business και performance metrics στο ίδιο σημείο.
Αυτή η ενότητα απεικονίζει όλα τα sessions όπου ο χρήστης πραγματοποίησε μια αγορά. Μπορείς να συγκρίνεις τα έσοδα που κέρδισες σε σχέση με το user experience κατά τη διάρκεια ενός συγκεκριμένου session.
Advanced use cases
Καθώς εξοικιώνεσαι περισσότερο με το dataset, μπορείς να επεξεργαστείς το dashboard και να προσθέσεις τα δικά σου γραφήματα για πιο εμπλουτισμένη και στοχευμένη ανάλυση. Για να κάνεις το dashboard πιο χρήσιμο, μπορείς να ακολουθήσεις τα επόμενα βήματα:
- Κάνε setup ένα scheduled query στο BigQuery για να λαμβάνεις updated δεδομένα. Το materialization query που εκτελέσαμε προηγουμένως λαμβάνει μόνο ένα snapshot των δεδομένων εκείνη τη στιγμή. Εάν θέλεις να διατηρήσεις το dashboard σου updated με φρέσκα δεδομένα, μπορείς να εκτελείς ένα scheduled query που θα εκτελείται κάθε μέρα και θα ανανεώνει το materialized table με νέα δεδομένα.
- Μπορείς να συνδέσεις τα first party data σου (π.χ. CRM) για business insights. Στον materialized πίνακα, μπορείς να προσθέσεις το user_id ως ξεχωριστή στήλη. Αυτό θα σου επιτρέψει να συνδυάσεις τα first party data σου. Αν τα first party data σου δεν βρίσκονται ήδη στο BigQuery, μπορείς είτε να φορτώσεις τα δεδομένα σου είτε να χρησιμοποιήσεις ένα integrated data source.
- Αν πρόκειται να κάνεις βαριά χρήση του dataset μέσω direct query ή του dashboard, μπορείς να δοκιμάσεις να χρησιμοποιήσεις την paid έκδοση του BigQuery BI Engine.
Συνοψίζοντας
Στο post αυτό καλύψαμε τα βασικά βήματα για τον τρόπο χρήσης του Google Analytics 4 και του BigQuery για τη μέτρηση και τον εντοπισμό σφαλμάτων με δεδομένα πραγματικών χρηστών που συλλέγονται επιτόπου (field data).
Είδαμε επίσης πώς να δημιουργήσεις αυτοματοποιημένα reports και dashboards χρησιμοποιώντας το Looker Studio και το Web Vitals Connector για να κάνεις το visualization των δεδομένων όσο το δυνατόν πιο εύκολo.
Μερικά βασικά συμπεράσματα από τις παραπάνω πληροφορίες:
- Η μέτρηση του performance με πραγματικά δεδομένα χρηστών είναι κρίσιμη για να κατανοήσεις, να εντοπίσεις σφάλματα και να βελτιστοποιήσεις το web performance.
- Μπορείς να λάβεις σημαντικά insights όταν τα performance metrics και τα business metrics βρίσκονται στο ίδιο σύστημα. Το Google Analytics και το BigQuery το καθιστούν δυνατό.
- Η εξαγωγή των raw data του Google Analytics από το BigQuery σου δίνει απεριόριστες δυνατότητες για εις βάθος, custom αναλύσεις χρησιμοποιώντας μια query language που πιθανότατα ήδη γνωρίζεις.
- Η Google διαθέτει μια σειρά από API και visualization tools όπως το Looker Studio που σου δίνουν την ελευθερία να δημιουργείς τα reports σου ακριβώς όπως θέλεις εσύ να δημιουργηθούν.