Event tracking captures specific user interactions — clicks, form submissions, video plays, scrolls, downloads — beyond the automatic pageview. Every analytics platform has its own event model, but the core concept is the same: detect an action, attach metadata, and send it to your collection endpoint.
GA4 Event Model
GA4 uses a flat event model. Every hit is an "event" — including pageviews. Events have a name and up to 25 custom parameters.
Automatic Events (No Setup Required)
GA4 tracks these without any code:
| Event | Trigger |
|---|---|
page_view |
Every page load |
session_start |
New session begins |
first_visit |
First-time visitor |
user_engagement |
10+ seconds of active engagement |
Enhanced Measurement Events
Enable these in GA4 Admin → Data Streams → Enhanced Measurement:
| Event | Trigger | What It Captures |
|---|---|---|
scroll |
90% vertical scroll depth | Page was read (roughly) |
click (outbound) |
Click to external domain | Outbound link URL |
file_download |
Click on .pdf, .docx, .zip, etc. |
File name and extension |
video_start / video_progress / video_complete |
YouTube embed interaction | Video title, % watched |
view_search_results |
URL contains search parameter | Search term |
form_start / form_submit |
Form interaction | Form ID or name |
Custom Events
For anything Enhanced Measurement doesn't cover, fire custom events:
// Track a CTA button click
document.querySelector('.cta-primary').addEventListener('click', function() {
gtag('event', 'cta_click', {
button_text: this.textContent.trim(),
button_location: 'hero_section',
page_path: window.location.pathname
});
});
// Track a pricing toggle
document.querySelector('.pricing-toggle').addEventListener('change', function() {
gtag('event', 'pricing_toggle', {
billing_period: this.checked ? 'annual' : 'monthly'
});
});
Recommended Events
GA4 has a predefined list of event names for ecommerce, lead gen, and content. Using these names unlocks built-in reports:
// Lead generation
gtag('event', 'generate_lead', {
currency: 'USD',
value: 50.00
});
// Sign up
gtag('event', 'sign_up', {
method: 'Google' // or 'email', 'GitHub', etc.
});
// Search
gtag('event', 'search', {
search_term: document.querySelector('#search-input').value
});
For the full ecommerce event list (view_item, add_to_cart, begin_checkout, purchase), see GA4 Ecommerce Tracking.
Event Tracking via GTM
Google Tag Manager decouples event logic from your codebase. Instead of hardcoding gtag() calls, you push to the data layer and let GTM handle tag firing.
Step 1: Push Events to the Data Layer
// In your website code
document.querySelector('#newsletter-form').addEventListener('submit', function(e) {
window.dataLayer = window.dataLayer || [];
dataLayer.push({
event: 'newsletter_signup',
form_location: 'footer',
email_domain: document.querySelector('#email').value.split('@')[1]
});
});
Step 2: Create a GTM Trigger
In GTM:
- Go to Triggers → New
- Trigger type: Custom Event
- Event name:
newsletter_signup - Save
Step 3: Create a GA4 Event Tag
- Go to Tags → New
- Tag type: Google Analytics: GA4 Event
- Measurement ID:
G-XXXXXXXX - Event name:
newsletter_signup - Event parameters: Add
form_location→{{dlv - form_location}} - Trigger: Select the trigger from Step 2
- Save and publish
Built-In GTM Triggers (No Data Layer Needed)
GTM can detect common interactions automatically:
| Trigger Type | What It Detects | Use For |
|---|---|---|
| Click - All Elements | Any click on the page | Button clicks, link clicks |
| Click - Just Links | <a> tag clicks only |
Outbound links, download links |
| Form Submission | HTML form submit event | Contact forms, search forms |
| Scroll Depth | Vertical scroll % thresholds | Content engagement |
| YouTube Video | Play, pause, progress, complete | Embedded video engagement |
| Element Visibility | Element enters viewport | Lazy-loaded sections, CTAs |
| Timer | Time elapsed on page | Time-based triggers |
Meta Pixel Events
Meta Pixel uses a different event model with fbq():
// Standard events (predefined by Meta)
fbq('track', 'Lead', { content_name: 'Contact Form', content_category: 'inquiry' });
fbq('track', 'Purchase', { value: 59.99, currency: 'USD' });
fbq('track', 'AddToCart', { content_ids: ['SKU-001'], content_type: 'product', value: 29.99, currency: 'USD' });
// Custom events (your own names)
fbq('trackCustom', 'PricingPageView', { plan_viewed: 'pro' });
For the full list of Meta standard events and parameters, see Meta Pixel Event Tracking.
Mixpanel, Amplitude, and Other Platforms
Each platform has its own API, but the pattern is identical:
// Mixpanel
mixpanel.track('Button Clicked', { button_name: 'Sign Up', page: '/pricing' });
// Amplitude
amplitude.track('Button Clicked', { button_name: 'Sign Up', page: '/pricing' });
// Segment (forwards to all connected destinations)
analytics.track('Button Clicked', { button_name: 'Sign Up', page: '/pricing' });
Debugging Event Tracking
Browser DevTools
// Check if events are in the data layer
console.table(window.dataLayer.filter(e => e.event && e.event !== 'gtm.js'));
// Check if GA4 is receiving events
// Network tab → filter for "collect" → inspect the payload
// Look for 'en=' parameter (event name) and 'ep.' parameters (event params)
GA4 DebugView
- Install GA4 Debugger Chrome extension
- Enable it, then visit your site
- In GA4 → Admin → DebugView, watch events arrive in real time
- Click any event to inspect its parameters
GTM Preview Mode
- In GTM, click Preview
- Enter your site URL
- Navigate and interact with your site
- The Tag Assistant panel shows which tags fired, which didn't, and why
Common Failures
| Problem | Cause | Fix |
|---|---|---|
| Event doesn't appear in GA4 | Wrong Measurement ID, consent not granted | Check tid parameter in Network tab; check consent state |
| Event fires but parameters are empty | Data layer variable not set before tag fires | Use GTM's tag sequencing or trigger ordering |
| Duplicate events | Tag fires on both GTM and hardcoded gtag() |
Remove one implementation; use GTM exclusively |
Event name shows as (not set) |
Missing event key in dataLayer.push() |
Ensure every push includes event: 'event_name' |
| Conversion not counting | Event not marked as conversion in GA4 | GA4 → Admin → Events → toggle "Mark as conversion" |
Event Naming Conventions
Use consistent naming across your site:
✅ Good: snake_case, descriptive, consistent
cta_click, form_submit, video_play, pricing_toggle
❌ Bad: inconsistent casing, vague names, spaces
CTAClick, click, Button Click, event1
GA4 event names are case-sensitive. CTA_Click and cta_click are different events. Pick a convention and enforce it.
Next Steps
- Data Layers — structure data for multiple tags and platforms
- How Tracking Works — the HTTP request lifecycle behind every event
- Debugging GA4 — systematic GA4 troubleshooting
- Debugging GTM — tag firing, trigger, and variable debugging