@@ -44,6 +44,7 @@ export enum EventCategory {
44
44
EXPOSURE_NOTIFICATIONS = 'exposure notifications' ,
45
45
SEARCH = 'search' ,
46
46
VACCINATION = 'vaccination' ,
47
+ WEB_VITALS = 'web vitals' ,
47
48
NONE = 'none' , // use NONE for development
48
49
}
49
50
@@ -65,6 +66,11 @@ export enum EventAction {
65
66
REDIRECT = 'redirect' ,
66
67
FOCUS = 'focus' ,
67
68
NAVIGATE = 'navigate' ,
69
+ CLS = 'Cumulative Layout Shift (*1000)' ,
70
+ FCP = 'First Contentful Paint (ms)' ,
71
+ FID = 'First Input Delay (ms)' ,
72
+ LCP = 'Largest Contentful Paint (ms)' ,
73
+ TTFB = 'Time to First Byte' ,
68
74
}
69
75
70
76
/**
@@ -77,9 +83,17 @@ export function trackEvent(
77
83
label ?: string ,
78
84
value ?: number ,
79
85
nonInteraction ?: boolean ,
86
+ transport : 'beacon' | 'xhr' | 'image' = 'beacon' ,
80
87
) {
81
88
if ( category !== EventCategory . NONE ) {
82
- ReactGA . event ( { category, action, label, value, nonInteraction } ) ;
89
+ ReactGA . event ( {
90
+ category,
91
+ action,
92
+ label,
93
+ value,
94
+ nonInteraction,
95
+ transport,
96
+ } ) ;
83
97
}
84
98
}
85
99
@@ -106,3 +120,34 @@ export function trackShare(label: string) {
106
120
export function trackVoteClick ( label : string ) {
107
121
trackEvent ( EventCategory . VOTE_2020 , EventAction . CLICK_LINK , label ) ;
108
122
}
123
+
124
+ /**
125
+ * Callback passed to web-vitals to report important performance events
126
+ */
127
+ export function trackWebVitals ( {
128
+ name,
129
+ delta,
130
+ id,
131
+ } : {
132
+ name : 'CLS' | 'FID' | 'LCP' | 'FCP' | 'TTFB' ;
133
+ delta : number ;
134
+ id : string ;
135
+ } ) {
136
+ trackEvent (
137
+ EventCategory . WEB_VITALS ,
138
+ EventAction [ name ] ,
139
+ // The `id` value will be unique to the current page load. When sending
140
+ // multiple values from the same page (e.g. for CLS), Google Analytics can
141
+ // compute a total by grouping on this ID (note: requires `eventLabel` to
142
+ // be a dimension in your report).
143
+ id ,
144
+ // Google Analytics metrics must be integers, so the value is rounded.
145
+ // For CLS the value is first multiplied by 1000 for greater precision
146
+ // (note: increase the multiplier for greater precision if needed).
147
+ Math . round ( name === 'CLS' ? delta * 1000 : delta ) ,
148
+ // Use a non-interaction event to avoid affecting bounce rate.
149
+ true ,
150
+ // Use `sendBeacon()` if the browser supports it.
151
+ 'beacon' ,
152
+ ) ;
153
+ }
0 commit comments