What counts as a lead
Two GA4 events are flagged as conversions on property 358764239:
generate_lead — hero form + contact form submissionphone_call_click — click on any tel: link (renamed by GTM from dataLayer click_phone_number)
The "Total Leads" KPI counts both. "Form Submits" and "Phone Clicks" KPIs split them.
W/W · M/M · Y/Y
W/W shifts back by the current range length (immediately prior period of same length). M/M shifts back 28 days (4 weeks, day-of-week aligned). Y/Y shifts back 364 days (52 weeks).
Y/Y may show "—" for periods before Frontline's GA4 property history began (mid-2024). Y/Y becomes reliable once a full year of data has accumulated.
Form funnel
Sessions → form_start → generate_lead.
- form_start fires on first focus into any
<form id="..."> field - form_abandon fires on
visibilitychange if form_start fired but no submit - Form abandon rate = form_abandon ÷ form_start
GTM container v13 (published 2026-05-28) added these triggers + tags. Field data backfills ~24hr after.
Content group · funnel stage
Pages bucket into 8 content groups, each pinned to a funnel stage:
| Path | Group | Stage |
|---|
/ | homepage | conversion |
/services/* | service | consideration |
/locations/* | location | consideration |
/blog/* | blog | awareness |
/contact | contact | conversion |
/faq | faq | consideration |
/about | about | awareness |
/careers, /job/* | careers | other |
Today the panel infers content group from page path. Once page_context events backfill (registered as GA4 custom dimension 2026-05-28), the panel switches to a true dimension query.
Core Web Vitals
Field measurement of 5 metrics via the web-vitals library. Each ships a good / needs-improvement / poor rating tied to Google's CWV thresholds:
| Metric | Good | Poor |
|---|
| LCP (Largest Contentful Paint) | < 2.5s | > 4s |
| INP (Interaction to Next Paint) | < 200ms | > 500ms |
| CLS (Cumulative Layout Shift) | < 0.1 | > 0.25 |
| FCP (First Contentful Paint) | < 1.8s | > 3s |
| TTFB (Time to First Byte) | < 800ms | > 1.8s |
LCP, INP, CLS are the three "Core" vitals — they affect Google search ranking. FCP + TTFB are diagnostic.
Event health
8 dataLayer events instrumented in BaseLayout.astro: generate_lead, click_phone_number (→ phone_call_click), click_outbound_link, scroll_depth, page_context, form_start, form_abandon, web_vitals.
The Event Health panel counts how many actually reach GA4 in the selected range. "Arriving" means we saw at least one in the window. "Missing" means the dataLayer push is happening but GA4 doesn't see it (typically a GTM trigger/tag gap).
Geo split — 7 markets
Frontline's service area cities are pinned with a "Market" chip:
Woodridge IL, Lombard IL, Indianapolis IN, Richmond IN, Davenport IA, Hermitage TN, Pendleton IN.
Other cities appear ranked by sessions but are not the targeted market — useful for spotting unexpected traffic patterns or remote-employee referrals.
Caveats
Singapore bot traffic. ~50% of recent sessions come from Singapore IPs with 0% engagement — almost certainly bots. Pending Cloudflare WAF block. Until then, conv-rate denominators are inflated; filter Singapore out of any client-facing number.
Conversion value. generate_lead currently carries no value parameter, so GA4 monetization reports and Google Ads value-bidding are unavailable. Deferred until storm-season Ads activate.
CRM hand-off. Dashboard counts form submissions, not qualified leads. CRM webhook → Measurement Protocol bridge is future work.
Data plumbing
GA4 Property 358764239 · Stream 4744883144 · Measurement G-8PWJ4XM2DL.
GTM container GTM-PQVHF2T — latest published version 13.
Service account pai-analytics-reader@paidoc-485820 reads via GA4 Data API. Cloudflare KV caches per-dataset responses at 10-min TTL.