Ensure every customer action is captured accurately by building a custom tracking plan or auditing your existing setup for errors. You will gain confidence in your numbers with properly configured conversion tracking and a clear view of how users move through your site. Reach for this when launching a new project, verifying campaign performance, or troubleshooting missing data in your reports.
name: “analytics-tracking”
description: “Set up, audit, and debug analytics tracking implementation — GA4, Google Tag Manager, event taxonomy, conversion tracking, and data quality. Use when building a tracking plan from scratch, auditing existing analytics for gaps or errors, debugging missing events, or setting up GTM. Trigger keywords: GA4 setup, Google Tag Manager, GTM, event tracking, analytics implementation, conversion tracking, tracking plan, event taxonomy, custom dimensions, UTM tracking, analytics audit, missing events, tracking broken. NOT for analyzing marketing campaign data — use campaign-analytics for that. NOT for BI dashboards — use product-analytics for in-product event analysis.”
license: MIT
metadata:
version: 1.0.0
author: Alireza Rezvani
category: marketing
updated: 2026-03-06
Analytics Tracking
You are an expert in analytics implementation. Your goal is to make sure every meaningful action in the customer journey is captured accurately, consistently, and in a way that can actually be used for decisions — not just for the sake of having data.
Bad tracking is worse than no tracking. Duplicate events, missing parameters, unconsented data, and broken conversions lead to decisions made on bad data. This skill is about building it right the first time, or finding what’s broken and fixing it.
Before Starting
Check for context first:
If marketing-context.md exists, read it before asking questions. Use that context and only ask for what’s missing.
Gather this context:
1. Current State
Do you have GA4 and/or GTM already set up? If so, what’s broken or missing?
What’s your tech stack? (React SPA, Next.js, WordPress, custom, etc.)
Do you have a consent management platform (CMP)? Which one?
What events are you currently tracking (if any)?
2. Business Context
What are your primary conversion actions? (signup, purchase, lead form, free trial start)
What are your key micro-conversions? (pricing page view, feature discovery, demo request)
Do you run paid campaigns? (Google Ads, Meta, LinkedIn — affects conversion tracking needs)
3. Goals
Building from scratch, auditing existing, or debugging a specific issue?
Do you need cross-domain tracking? Multiple properties or subdomains?
Mark these events as conversions in GA4 → Admin → Conversions:
signup_completed
checkout_completed
demo_requested
trial_started (if separate from signup)
Rules:
Max 30 conversion events per property — curate, don’t mark everything
Conversions are retroactive in GA4 — turning one on applies to 6 months of history
Don’t mark micro-conversions as conversions unless you’re optimizing ad campaigns for them
Google Tag Manager Setup
Container Structure
GTM Container├── Tags│ ├── GA4 Configuration (fires on all pages)│ ├── GA4 Event — [event_name] (one tag per event)│ ├── Google Ads Conversion (per conversion action)│ └── Meta Pixel (if running Meta ads)├── Triggers│ ├── All Pages│ ├── DOM Ready│ ├── Data Layer Event — [event_name]│ └── Custom Element Click — [selector]└── Variables ├── Data Layer Variables (dlv — for each dL key) ├── Constant — GA4 Measurement ID └── JavaScript Variables (computed values)
Tag Patterns for SaaS
Pattern 1: Data Layer Push (most reliable)
Your app pushes to dataLayer → GTM picks it up → sends to GA4.
// In your app code (on event):window.dataLayer = window.dataLayer || [];window.dataLayer.push({ event: 'signup_completed', signup_method: 'email', user_id: userId, plan_name: "trial"});
campaign-analytics: Use for analyzing marketing performance and channel ROI. NOT for implementation — use this skill for tracking setup.
ab-test-setup: Use when designing experiments. NOT for event tracking setup (though this skill’s events feed A/B tests).
analytics-tracking (this skill): covers setup only. For dashboards and reporting, use campaign-analytics.
seo-audit: Use for technical SEO. NOT for analytics tracking (though both use GA4 data).
gdpr-dsgvo-expert: Use for GDPR compliance posture. This skill covers consent mode implementation; that skill covers the full compliance framework.
Tracking Debug Playbook
Step-by-step methodology for diagnosing and fixing analytics tracking issues.
The Debug Mindset
Analytics bugs are harder than code bugs because:
They fail silently — no error thrown, just missing data
They often only appear in production
They can be caused by timing, consent, ad blockers, or just configuration
Work systematically. Don't guess. Verify at each layer before moving to the next.
The Debug Stack (Bottom-Up)
Layer 5: GA4 Reports / DebugView ← what you seeLayer 4: GA4 Data Processing ← where it landsLayer 3: Network Request ← what was sentLayer 2: GTM / Tag firing ← what GTM didLayer 1: dataLayer / App code ← what your app pushed
When something's missing at Layer 5, start at Layer 1 and verify each layer before going up.
Tool Setup
GTM Preview Mode
GTM → Preview (top right)
Enter your site URL → Connect
A blue bar appears at the bottom of your site: "Google Tag Manager"
GTM Preview panel opens in a separate tab
Perform the action you're debugging
Check: did the expected tag fire?
Reading GTM Preview:
Left panel: events as they occur (Page View, Click, Custom Event, etc.)
Middle panel: Tags fired / Tags NOT fired for selected event
Right panel: Variables values at the time of the event
GA4 DebugView
GA4 → Admin → DebugView
Enable debug mode via:
GTM: add debug_mode: true to your GA4 Event tag parameters
Extension: install "GA Debugger" Chrome extension
URL parameter: add ?_gl= or use GA4 debug parameter
Perform actions on your site
Watch events appear in real-time (10-15 second delay)
Chrome DevTools — Network Tab
Open DevTools → Network
Filter by: collect or google-analytics or analytics
Perform the action
Look for requests to https://www.google-analytics.com/g/collect
Click the request → Payload tab → view parameters
Common Issues and Fixes
Issue: Event fires in GTM Preview but not in GA4
Possible causes:
Consent mode blocking — user is in denied state
Check: In GTM Preview, look at Variables → Analytics Storage — is it denied?
Fix: Test with consent granted, or implement Advanced Consent Mode
Filters blocking data — internal traffic filter is active
Check: GA4 → Admin → Data Filters — is "Internal Traffic" filter active?
Fix: Disable filter temporarily, test, then re-enable and exclude your IP correctly
Debug mode not enabled — DebugView only shows debug-mode traffic
Check: Is debug_mode: true parameter on the GA4 Event tag?
Fix: Add it, or use the GA4 Debugger Chrome extension
Wrong property — you're looking at a different GA4 property
Check: Confirm Measurement ID in GTM matches the GA4 property you're viewing
Fix: Compare G-XXXXXXXXXX in GTM vs. GA4 Data Stream settings
Duplicate GA4 configuration tags — two config tags = double sessions + weird data
Check: GTM → Tags → filter by "GA4 Configuration" — more than one?
Fix: Delete duplicates, keep one with All Pages trigger
Issue: Event not firing in GTM Preview at all
Diagnosis path:
Step 1: Check the trigger
Is the trigger for this tag listed under the action in GTM Preview?
If not: the trigger didn't fire
Step 2: Check trigger conditions
Open the trigger in GTM
Reproduce the exact scenario step by step
In GTM Preview, check Variables at the moment the action happened
Do the variable values match your trigger conditions?
If parameter isn't registered here: it'll exist in raw data but won't show in Explore reports
Issue: Duplicate events (event fires 2x per action)
Find the duplicates:
GTM Preview → find the action → how many tags with the same name fired?
DevTools → Network → filter by collect → count hits for the action
Common causes:
Enhanced Measurement + manual GTM tag
e.g., Enhanced Measurement tracks outbound clicks, GTM also has an outbound click tag
Fix: disable the Enhanced Measurement setting OR remove the GTM tag
Two GTM Configuration tags
Each sends its own hits
Fix: delete one, keep one
SPA router fires pageview + History Change trigger also fires
Fix: disable Enhanced Measurement pageview, use only History Change tag
Event fires on multiple triggers that both match
Fix: make triggers more specific — add exclusion conditions
Issue: Sessions/users look wrong (too high or too low)
Too many sessions:
Multiple GA4 Configuration tags
History Change trigger firing + Enhanced Measurement pageview on SPA
Client ID not persisting (cookie being blocked or cleared)
Too few sessions / users:
Consent blocking analytics for non-consenting users (expected under strict consent mode)
Bot filtering too aggressive
GA4 tags firing on wrong pages only
Sessions reset unexpectedly (user shows as new on every page):
Cross-domain tracking not configured
Cookie domain mismatch
GTM cookie settings incorrect
Issue: Conversions not matching between GA4 and Google Ads
Check 1: Attribution window mismatch
GA4 default: 30-day last click
Google Ads: check conversion action settings for window
These legitimately produce different numbers
Check 2: Conversion event names
In Google Ads → Tools → Conversions → imported from GA4
Does the linked event name exactly match the GA4 event?
Check 3: Import is linked
Google Ads → Tools → Linked Accounts → Google Analytics 4
Is the correct GA4 property linked and synced?
Sync can take 24-48 hours after changes
Check 4: Enhanced Conversions
If GA4 uses a user_id or email parameter, Enhanced Conversions can improve matching
Google Ads → Conversions → Enhanced Conversions for Web → Enable
Debug Checklist Template
Use this for any new tracking issue:
[ ] Confirmed exact event name and parameters expected[ ] Verified app code is pushing to dataLayer (console: dataLayer)[ ] GTM Preview: trigger fires at correct moment[ ] GTM Preview: parameters resolve to correct values (not undefined)[ ] Network: GA4 collect request appears with correct payload[ ] GA4 DebugView: event appears within 30 seconds[ ] GA4 DebugView: parameters present and correct[ ] GA4 Reports: event appears (24-48h delay for standard reports)[ ] Consent check: tested with analytics consent granted[ ] Filter check: internal traffic filter not blocking test traffic
Event Taxonomy Guide
Complete reference for naming conventions, event structure, and parameter standards.
Why Taxonomy Matters
Analytics data is only as good as its naming consistency. A tracking system with FormSubmit, form_submit, form-submitted, and formSubmitted as four separate "events" is useless for aggregation. One naming standard, enforced from day one, avoids months of cleanup later.
This guide is the reference for that standard.
Naming Convention: Full Specification
Format
[object]_[action]
Object = the thing being acted upon (noun)
Action = what happened (verb, past tense or gerund)
Casing & Characters
Rule
✅ Correct
❌ Wrong
Lowercase only
video_started
Video_Started, VIDEO_STARTED
Underscores only
form_submit
form-submit, formSubmit
Noun before verb
plan_selected
selected_plan
Past tense or clear state
checkout_completed
checkout_complete, checkoutDone
Specific > generic
trial_started
event_triggered
Max 4 words
onboarding_step_completed
user_completed_an_onboarding_step_in_the_flow
Action Vocabulary (Standard Verbs)
Use these verbs consistently — don't invent synonyms:
Verb
Use for
_started
Beginning of a multi-step process
_completed
Successful completion of a process
_failed
An attempt that errored out
_submitted
Form or data submission
_viewed
Passive view of a page, modal, or content
_clicked
Direct click on a specific element
_selected
Choosing from options (plan, variant, filter)
_opened
Modal, drawer, chat window opened
_closed
Modal, drawer, chat window closed
_downloaded
File download
_activated
Feature turned on for first time
_upgraded
Plan or feature upgrade
_cancelled
Intentional termination
_dismissed
User explicitly closed/ignored a prompt
_searched
Search query submitted
Complete SaaS Event Catalog
Acquisition Events
Event
Required Parameters
Optional Parameters
ad_clicked
utm_source, utm_campaign
utm_content, utm_term
landing_page_viewed
page_location, utm_source
variant (A/B)
pricing_viewed
page_location
referrer_page
demo_requested
source (page slug or section)
plan_interest
content_downloaded
content_name, content_type
gated (boolean)
Acquisition → Registration
Event
Required Parameters
Optional Parameters
signup_started
—
plan_name, method
signup_completed
method
user_id, plan_name
email_verified
—
method
trial_started
plan_name
trial_length_days
invitation_accepted
inviter_user_id
plan_name
Onboarding Events
Event
Required Parameters
Optional Parameters
onboarding_started
—
onboarding_variant
onboarding_step_completed
step_name, step_number
time_spent_seconds
onboarding_completed
steps_total
time_to_complete_seconds
onboarding_skipped
step_name
step_number
feature_activated
feature_name
activation_method
integration_connected
integration_name
integration_type
team_member_invited
—
invite_method
Conversion Events
Event
Required Parameters
Optional Parameters
plan_selected
plan_name, billing_period
previous_plan
checkout_started
plan_name, value, currency
billing_period
checkout_completed
plan_name, value, currency, transaction_id
billing_period, coupon_code
checkout_failed
plan_name, error_reason
value, currency
upgrade_completed
from_plan, to_plan, value, currency
trigger
coupon_applied
coupon_code, discount_value
plan_name
Engagement Events
Event
Required Parameters
Optional Parameters
feature_used
feature_name
feature_area, usage_count
search_performed
search_term
results_count, search_area
filter_applied
filter_name, filter_value
result_count
export_completed
export_type, export_format
record_count
report_generated
report_name
date_range
notification_clicked
notification_type
notification_id
Retention Events
Event
Required Parameters
Optional Parameters
subscription_cancelled
cancel_reason
plan_name, save_offer_shown, save_offer_accepted
save_offer_accepted
offer_type
plan_name, discount_pct
subscription_paused
pause_duration_days
pause_reason
subscription_reactivated
—
plan_name, days_since_cancel
churn_risk_detected
—
risk_score, risk_signals
Support / Help Events
Event
Required Parameters
Optional Parameters
help_article_viewed
article_name
article_id, source
chat_opened
—
page_location, trigger
support_ticket_submitted
ticket_category
severity
error_encountered
error_type, error_message
page_location, feature_name
Custom Dimensions & Metrics
GA4 limits: 50 custom dimensions (event-scoped), 25 user-scoped, 50 item-scoped.
Prioritize the ones that matter for segmentation.
Recommended User-Scoped Dimensions
Dimension Name
Parameter
Example Values
User ID
user_id
usr_abc123
Plan Name
plan_name
starter, professional, enterprise
Billing Period
billing_period
monthly, annual
Account Created Date
account_created_date
2024-03-15
Onboarding Completed
onboarding_completed
true, false
Company Size
company_size
1-10, 11-50, 51-200
Recommended Event-Scoped Dimensions
Dimension Name
Parameter
Used In
Cancel Reason
cancel_reason
subscription_cancelled
Feature Name
feature_name
feature_used, feature_activated
Content Name
content_name
content_downloaded
Signup Method
method
signup_completed
Error Type
error_type
error_encountered
Taxonomy Governance
The Tracking Plan Document
Maintain a single tracking plan document (Google Sheet or Notion table) with:
Column
Values
Event Name
e.g., checkout_completed
Trigger
"User completes Stripe checkout"
Parameters
{value, currency, plan_name, transaction_id}
Implemented In
GTM / App code / server
Status
Draft / Implemented / Verified
Owner
Engineering / Marketing / Product
Change Protocol
New events → add to tracking plan first, get sign-off before implementing
Rename events → use a deprecation period (keep old + add new for 30 days, then remove old)
Remove events → archive in tracking plan, don't delete — historical data reference
Add parameters → non-breaking, implement immediately and update tracking plan
Remove parameters → treat as rename (deprecation period)
Versioning
Include schema_version as a parameter on critical events if your taxonomy evolves rapidly:
Click Element matches CSS selector: [data-track="demo-cta"]
OR
Click Text equals "Request a Demo"
Name: Click - Demo CTA
Create Tag:
Type: GA4 Event
Event Name: demo_requested
Event Parameters:
page_location: {{Page URL}}
click_text: {{Click Text}}
Trigger: Click - Demo CTA
Best practice: Add data-track attributes to important elements in your HTML rather than relying on brittle CSS selectors or text matching.
<button data-track="demo-cta" data-track-source="pricing-hero"> Request a Demo</button>
Pattern 3: Form Submission Tracking
Two approaches depending on whether the form submits via JavaScript or full page reload.
For JavaScript-handled forms (AJAX/fetch):
Use Pattern 1 (dataLayer push) after successful form submission callback
For traditional form submit:
Create Trigger:
Type: Form Submission
Check Validation: ✅ (only fires if form passes HTML5 validation)
Enable History Change: ✅ (for SPAs)
Fire On: Some Forms
Conditions: Form ID equals contact-form OR Form Classes contains js-track-form
Name: Form Submit - Contact
Create Tag:
Type: GA4 Event
Event Name: form_submitted
Parameters:
form_name: contact
page_location: {{Page URL}}
Trigger: Form Submit - Contact
Pattern 4: SPA Page View Tracking
Single-page apps often don't trigger standard page view events on route changes.
Approach A: History Change trigger (simplest)
Create Trigger:
Type: History Change
Name: History Change - Route
Create Tag:
Type: GA4 Event
Event Name: page_view
Parameters:
page_location: {{Page URL}}
page_title: {{Page Title}}
Trigger: History Change - Route
Important: Disable the default pageview in your GA4 Configuration tag if using this, or you'll get duplicates on initial load.
Approach B: dataLayer push from router (more reliable)
// In your router's navigation handler:router.afterEach((to, from) => { window.dataLayer.push({ event: 'page_view', page_path: to.path, page_title: document.title });});
Pattern 5: Scroll Depth Tracking
For content engagement measurement:
Option A: Use GA4 Enhanced Measurement (90% depth only)
Enable in GA4 → Data Streams → Enhanced Measurement → Scrolls
Fires when user scrolls 90% down the page
No GTM configuration needed
Option B: Custom milestones via GTM
Create Trigger for each depth:
Type: Scroll Depth
Vertical Scroll Depths: 25, 50, 75, 100 (percent)
Enable for: Some Pages → Page Path contains /blog/
Name: Scroll Depth - Blog
Create Tag:
Type: GA4 Event
Event Name: content_scrolled
Parameters:
scroll_depth_pct: {{Scroll Depth Threshold}}
page_location: {{Page URL}}
Trigger: Scroll Depth - Blog
Pattern 6: Consent Mode Integration
For GDPR compliance — connect your CMP to GTM.
Basic Consent Mode (blocks all when declined):
// In your CMP callback:window.dataLayer.push({ event: 'cookie_consent_update', ad_storage: 'denied', // or 'granted' analytics_storage: 'denied', // or 'granted' functionality_storage: 'denied', personalization_storage: 'denied', security_storage: 'granted' // always granted});
Advanced Consent Mode (modeled data for declined users):
Add to <head> BEFORE GTM loads:
window.dataLayer = window.dataLayer || [];function gtag(){dataLayer.push(arguments);}// Default all to deniedgtag('consent', 'default', { ad_storage: 'denied', analytics_storage: 'denied', wait_for_update: 500 // ms to wait for CMP to initialize});