Claude-code-marketing-skills ga4-events

GA4 Event Implementation Reference — complete event taxonomy, parameter lists, implementation patterns (gtag.js, GTM, Measurement Protocol), and validation techniques

install
source · Clone the upstream repo
git clone https://github.com/cognyai/claude-code-marketing-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/cognyai/claude-code-marketing-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/ga4-events" ~/.claude/skills/cognyai-claude-code-marketing-skills-ga4-events && rm -rf "$T"
manifest: skills/ga4-events/SKILL.md
source content

GA4 Event Implementation Reference

Complete reference for implementing Google Analytics 4 events: automatically collected, enhanced measurement, recommended, and custom events with exact parameter lists, code examples, and validation techniques.

Full docs: https://cogny.com/docs/ga4-event-implementation

Usage

/ga4-events                          # Show event model overview
/ga4-events purchase                 # Show purchase event parameters and code
/ga4-events ecommerce                # Full e-commerce event funnel reference
/ga4-events enhanced measurement     # Enhanced measurement events list
/ga4-events custom events            # Custom event naming rules and limits
/ga4-events validation               # DebugView, Realtime, and BigQuery checks
/ga4-events gtm                      # GTM dataLayer implementation patterns
/ga4-events measurement protocol     # Server-side Measurement Protocol examples

Instructions

You are a GA4 event implementation expert. Use this reference to help users implement, audit, and validate GA4 events correctly. Provide precise, copy-paste-ready code examples.

When the user asks a question, find the relevant section below and provide actionable answers with ready-to-use code. If GA4 MCP tools are available, use them to inspect the user's actual property configuration (custom dimensions, data streams, conversion events) for context-aware advice.

If the user provides a specific event name or topic as an argument, focus on that area. Otherwise, provide an overview of the event model.


Event Model Overview

GA4 uses an event-based data model where everything is an event. Unlike Universal Analytics hit types (pageview, event, transaction), GA4 has a single concept: events with parameters.

ConceptUniversal AnalyticsGA4
Data modelHit-based (pageview, event, transaction)Event-based (everything is an event)
Event structureCategory / Action / Label / ValueEvent name + parameters (key-value pairs)
SessionsServer-defined, 30-min timeoutDerived from
session_start
event
PageviewsDedicated hit type
page_view
event with
page_location
parameter
E-commerceEnhanced Ecommerce pluginBuilt-in recommended events with items array
Custom dataCustom dimensions/metrics (index-based)Event parameters + custom dimensions/metrics (name-based)

Every GA4 event has:

  • Event name: String identifier (e.g.,
    page_view
    ,
    purchase
    )
  • Event parameters: Key-value pairs (e.g.,
    page_location
    ,
    transaction_id
    )
  • User properties: Persistent user attributes (e.g.,
    membership_tier
    )

Automatically Collected Events

Collected automatically with no configuration. Cannot be disabled.

Web

EventTriggerKey Parameters
first_visit
First time user visits (new cookie)None
session_start
New session begins (30-min timeout)
ga_session_id
,
ga_session_number
page_view
Every page load (or
history.pushState
in SPAs)
page_location
,
page_title
,
page_referrer
user_engagement
Page in focus for 1+ second with interaction
engagement_time_msec

Mobile (Firebase SDK)

EventTriggerKey Parameters
first_open
First app open after install
previous_gmp_app_id
,
updated_with_analytics
session_start
New session begins
ga_session_id
,
ga_session_number
screen_view
Screen transition
firebase_screen
,
firebase_screen_class
,
firebase_screen_id
user_engagement
App in foreground 1+ second
engagement_time_msec
app_update
App updated and launched
previous_app_version
app_remove
App removed (Android only)None
os_update
OS updated
previous_os_version

Auto-attached Parameters (every event)

language
,
page_location
,
page_referrer
,
page_title
,
screen_resolution
,
ga_session_id
,
ga_session_number
,
engagement_time_msec

Enhanced Measurement Events

Collected automatically when enabled in Admin > Data Streams > Enhanced Measurement. Each can be toggled individually.

EventTriggerKey Parameters
scroll
User scrolls past 90% of page
percent_scrolled
(always 90)
click
Outbound link click
link_url
,
link_domain
,
link_classes
,
link_id
,
outbound
view_search_results
URL contains search query parameter
search_term
video_start
YouTube embed starts playing
video_url
,
video_title
,
video_provider
,
video_current_time
,
visible
video_progress
YouTube video reaches 10/25/50/75%Same as
video_start
plus
video_percent
video_complete
YouTube video reaches endSame as
video_start
file_download
Click on file link (pdf, xls, doc, zip, etc.)
file_name
,
file_extension
,
link_url
,
link_text
,
link_domain
form_start
First interaction with a form
form_id
,
form_name
,
form_destination
form_submit
Form submitted
form_id
,
form_name
,
form_destination
,
form_submit_text

Note: Video tracking only works with YouTube embeds using

enablejsapi=1
.

Recommended Events — All Properties

EventParameters
login
method
(STRING)
sign_up
method
(STRING)
share
method
(STRING),
content_type
(STRING),
item_id
(STRING)
search
search_term
(STRING)
select_content
content_type
(STRING),
content_id
(STRING)
gtag('event', 'login', { method: 'Google' });
gtag('event', 'sign_up', { method: 'Email' });
gtag('event', 'search', { search_term: 'running shoes' });

Recommended Events — E-commerce

Implement in order for full funnel reporting.

view_item_list

gtag('event', 'view_item_list', {
  item_list_id: 'category_123',
  item_list_name: 'Running Shoes',
  items: [{
    item_id: 'SKU_123', item_name: 'Trail Runner Pro', item_brand: 'RunCo',
    item_category: 'Shoes', item_category2: 'Running', item_variant: 'Blue',
    price: 129.99, currency: 'USD', index: 0,
    item_list_id: 'category_123', item_list_name: 'Running Shoes'
  }]
});

select_item

gtag('event', 'select_item', {
  item_list_id: 'category_123', item_list_name: 'Running Shoes',
  items: [{ item_id: 'SKU_123', item_name: 'Trail Runner Pro', price: 129.99, currency: 'USD', index: 0 }]
});

view_item

gtag('event', 'view_item', {
  currency: 'USD', value: 129.99,
  items: [{ item_id: 'SKU_123', item_name: 'Trail Runner Pro', item_brand: 'RunCo',
    item_category: 'Shoes', item_variant: 'Blue', price: 129.99, currency: 'USD', quantity: 1 }]
});

add_to_cart

gtag('event', 'add_to_cart', {
  currency: 'USD', value: 129.99,
  items: [{ item_id: 'SKU_123', item_name: 'Trail Runner Pro', price: 129.99, currency: 'USD', quantity: 1 }]
});

remove_from_cart

gtag('event', 'remove_from_cart', {
  currency: 'USD', value: 129.99,
  items: [{ item_id: 'SKU_123', item_name: 'Trail Runner Pro', price: 129.99, currency: 'USD', quantity: 1 }]
});

view_cart

gtag('event', 'view_cart', {
  currency: 'USD', value: 259.98,
  items: [
    { item_id: 'SKU_123', item_name: 'Trail Runner Pro', price: 129.99, currency: 'USD', quantity: 1 },
    { item_id: 'SKU_456', item_name: 'Road Runner Elite', price: 149.99, currency: 'USD', quantity: 1 }
  ]
});

begin_checkout

gtag('event', 'begin_checkout', {
  currency: 'USD', value: 259.98, coupon: 'SUMMER20',
  items: [
    { item_id: 'SKU_123', item_name: 'Trail Runner Pro', price: 129.99, currency: 'USD', quantity: 1 },
    { item_id: 'SKU_456', item_name: 'Road Runner Elite', price: 149.99, currency: 'USD', quantity: 1 }
  ]
});

add_shipping_info

gtag('event', 'add_shipping_info', {
  currency: 'USD', value: 259.98, coupon: 'SUMMER20', shipping_tier: 'Express',
  items: [{ item_id: 'SKU_123', item_name: 'Trail Runner Pro', price: 129.99, currency: 'USD', quantity: 1 }]
});

add_payment_info

gtag('event', 'add_payment_info', {
  currency: 'USD', value: 259.98, coupon: 'SUMMER20', payment_type: 'Credit Card',
  items: [{ item_id: 'SKU_123', item_name: 'Trail Runner Pro', price: 129.99, currency: 'USD', quantity: 1 }]
});

purchase

gtag('event', 'purchase', {
  transaction_id: 'T12345',  // REQUIRED — unique transaction ID
  value: 259.98,             // REQUIRED — total value
  currency: 'USD',           // REQUIRED — ISO 4217
  tax: 20.80,
  shipping: 9.99,
  coupon: 'SUMMER20',
  items: [
    { item_id: 'SKU_123', item_name: 'Trail Runner Pro', affiliation: 'Online Store',
      coupon: 'ITEM10OFF', discount: 13.00, item_brand: 'RunCo', item_category: 'Shoes',
      item_category2: 'Running', item_variant: 'Blue', price: 129.99, currency: 'USD', quantity: 1 },
    { item_id: 'SKU_456', item_name: 'Road Runner Elite', affiliation: 'Online Store',
      item_brand: 'RunCo', item_category: 'Shoes', price: 149.99, currency: 'USD', quantity: 1 }
  ]
});

Critical:

purchase
requires
transaction_id
,
value
, and
currency
. GA4 deduplicates by
transaction_id
within 72 hours.

refund

// Full refund
gtag('event', 'refund', { transaction_id: 'T12345', value: 259.98, currency: 'USD' });

// Partial refund
gtag('event', 'refund', {
  transaction_id: 'T12345', value: 129.99, currency: 'USD',
  items: [{ item_id: 'SKU_123', price: 129.99, currency: 'USD', quantity: 1 }]
});

Recommended Events — Lead Generation

generate_lead

gtag('event', 'generate_lead', { currency: 'USD', value: 50.00 });

Recommended Events — Gaming

EventParameters
earn_virtual_currency
virtual_currency_name
(STRING),
value
(NUMBER)
spend_virtual_currency
virtual_currency_name
(STRING),
value
(NUMBER),
item_name
(STRING)
level_up
level
(NUMBER),
character
(STRING)
post_score
score
(NUMBER, required),
level
(NUMBER),
character
(STRING)
tutorial_begin
None
tutorial_complete
None
unlock_achievement
achievement_id
(STRING, required)
gtag('event', 'earn_virtual_currency', { virtual_currency_name: 'Coins', value: 100 });
gtag('event', 'spend_virtual_currency', { virtual_currency_name: 'Coins', value: 50, item_name: 'Power Boost' });
gtag('event', 'level_up', { level: 5, character: 'Warrior' });
gtag('event', 'post_score', { score: 15000, level: 5, character: 'Warrior' });
gtag('event', 'tutorial_begin');
gtag('event', 'tutorial_complete');
gtag('event', 'unlock_achievement', { achievement_id: 'first_blood' });

Item Parameter Reference

The

items
array supports these parameters per item:

ParameterTypeDescription
item_id
STRINGSKU/ID (recommended)
item_name
STRINGDisplay name (recommended)
affiliation
STRINGStore or affiliation
coupon
STRINGItem-level coupon
discount
NUMBERDiscount amount
index
NUMBERPosition in list
item_brand
STRINGBrand name
item_category
STRINGPrimary category
item_category2
-
5
STRINGCategory levels 2-5
item_list_id
STRINGList ID
item_list_name
STRINGList name
item_variant
STRINGVariant (color, size)
location_id
STRINGPhysical location
price
NUMBERItem price
currency
STRINGISO 4217 code
quantity
NUMBERQuantity
promotion_id
STRINGPromotion ID
promotion_name
STRINGPromotion name
creative_name
STRINGPromotion creative
creative_slot
STRINGCreative slot

At least one of

item_id
or
item_name
is required. Max 200 items per event.

Custom Events

Use when no automatically collected, enhanced measurement, or recommended event fits.

Naming Rules

  • Max 40 characters
  • Must start with alphabetic character
  • Only
    [a-zA-Z][a-zA-Z0-9_]*
  • Case sensitive
    Add_To_Cart
    and
    add_to_cart
    are different events
  • Cannot use reserved prefixes:
    firebase_
    ,
    google_
    ,
    ga_
  • Cannot use reserved event names (e.g.,
    first_visit
    ,
    session_start
    ,
    app_install
    ,
    in_app_purchase
    , etc.)

Limits

LimitValue
Unique event names per property500
Parameters per event25
Parameter name length40 characters
Parameter value (string)100 characters
User property name length24 characters
User property value (string)36 characters
User properties per project25

Examples

gtag('event', 'newsletter_signup', {
  newsletter_type: 'weekly_digest', signup_location: 'footer'
});

gtag('event', 'feature_used', {
  feature_name: 'export_csv', feature_category: 'data_tools', plan_tier: 'pro'
});

gtag('event', 'article_read', {
  article_id: 'post_12345', article_category: 'technology', read_time_seconds: 245
});

Custom Dimensions and Metrics

Register event parameters or user properties for reporting in Admin > Custom definitions.

Scoping

ScopeSourceUse Case
Event-scoped dimensionEvent parameterPage/action attributes
User-scoped dimensionUser propertyPersistent user attributes
Custom metricEvent parameter (numeric)Numeric aggregation

Quotas

ResourceStandardAnalytics 360
Event-scoped custom dimensions50125
User-scoped custom dimensions25100
Custom metrics50125

Processing time: 24-48 hours for standard reports (immediate in Realtime/DebugView).

// Set user properties
gtag('set', 'user_properties', {
  membership_tier: 'gold', signup_date: '2025-01-15'
});

GTM dataLayer Implementation

// Custom event
window.dataLayer = window.dataLayer || [];
window.dataLayer.push({
  event: 'newsletter_signup',
  newsletter_type: 'weekly_digest',
  signup_location: 'footer'
});

// E-commerce — ALWAYS clear ecommerce first
window.dataLayer.push({ ecommerce: null });
window.dataLayer.push({
  event: 'purchase',
  ecommerce: {
    transaction_id: 'T12345', value: 259.98, currency: 'USD',
    tax: 20.80, shipping: 9.99, coupon: 'SUMMER20',
    items: [{ item_id: 'SKU_123', item_name: 'Trail Runner Pro',
      item_brand: 'RunCo', item_category: 'Shoes', price: 129.99, quantity: 1 }]
  }
});

Measurement Protocol (Server-Side)

POST https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXXXXX&api_secret=YOUR_API_SECRET

{
  "client_id": "abc123.def456",
  "events": [{
    "name": "offline_purchase",
    "params": {
      "transaction_id": "OFFLINE_T789",
      "value": 250.00,
      "currency": "USD"
    }
  }]
}
import requests, json

url = 'https://www.google-analytics.com/mp/collect?measurement_id=G-XXXXXXXXXX&api_secret=YOUR_API_SECRET'
payload = {
    'client_id': 'abc123.def456',
    'events': [{'name': 'offline_purchase', 'params': {
        'transaction_id': 'OFFLINE_T789', 'value': 250.00, 'currency': 'USD'
    }}]
}
response = requests.post(url, data=json.dumps(payload))

Limitations: No response validation (use debug endpoint),

client_id
must match existing GA4 cookie, events not in Realtime (30-min delay), cannot trigger
first_visit
/
session_start
.

Validation Server

POST https://www.google-analytics.com/debug/mp/collect?measurement_id=G-XXXXXXXXXX&api_secret=YOUR_API_SECRET
# Returns validation errors instead of silently accepting

Validation and Debugging

DebugView

Enable debug mode to see events in near real-time in Admin > DebugView:

gtag('config', 'G-XXXXXXXXXX', { debug_mode: true });
// Or per-event:
gtag('event', 'purchase', { debug_mode: true, transaction_id: 'T12345', value: 99.99, currency: 'USD' });

BigQuery Validation Queries

Event volume audit:

SELECT event_name, COUNT(*) as event_count, COUNT(DISTINCT user_pseudo_id) as unique_users
FROM `project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX = FORMAT_DATE('%Y%m%d', CURRENT_DATE() - 1)
GROUP BY event_name ORDER BY event_count DESC

Missing purchase parameters:

SELECT 'missing_transaction_id' as issue, COUNT(*) as count
FROM `project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX = FORMAT_DATE('%Y%m%d', CURRENT_DATE() - 1)
  AND event_name = 'purchase'
  AND (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'transaction_id') IS NULL
UNION ALL
SELECT 'missing_currency', COUNT(*)
FROM `project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX = FORMAT_DATE('%Y%m%d', CURRENT_DATE() - 1)
  AND event_name = 'purchase'
  AND (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'currency') IS NULL

Duplicate transactions:

SELECT transaction_id, COUNT(*) as dupes
FROM (
  SELECT (SELECT value.string_value FROM UNNEST(event_params) WHERE key = 'transaction_id') as transaction_id
  FROM `project.analytics_123456789.events_*`
  WHERE _TABLE_SUFFIX BETWEEN FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY))
                          AND FORMAT_DATE('%Y%m%d', CURRENT_DATE() - 1)
    AND event_name = 'purchase'
)
WHERE transaction_id IS NOT NULL
GROUP BY transaction_id HAVING COUNT(*) > 1
ORDER BY dupes DESC

Naming convention audit:

SELECT event_name, COUNT(*) as event_count,
  CASE
    WHEN LENGTH(event_name) > 40 THEN 'exceeds_40_chars'
    WHEN REGEXP_CONTAINS(event_name, r'^(firebase_|google_|ga_)') THEN 'reserved_prefix'
    WHEN NOT REGEXP_CONTAINS(event_name, r'^[a-zA-Z][a-zA-Z0-9_]*$') THEN 'invalid_characters'
    WHEN event_name != LOWER(event_name) THEN 'mixed_case_warning'
    ELSE 'valid'
  END as naming_issue
FROM `project.analytics_123456789.events_*`
WHERE _TABLE_SUFFIX = FORMAT_DATE('%Y%m%d', CURRENT_DATE() - 1)
GROUP BY event_name HAVING naming_issue != 'valid'

Parameter truncation check:

SELECT event_name, ep.key, MAX(LENGTH(ep.value.string_value)) as max_len,
  COUNTIF(LENGTH(ep.value.string_value) >= 100) as at_limit
FROM `project.analytics_123456789.events_*`, UNNEST(event_params) as ep
WHERE _TABLE_SUFFIX = FORMAT_DATE('%Y%m%d', CURRENT_DATE() - 1)
  AND ep.value.string_value IS NOT NULL
GROUP BY 1, 2 HAVING max_len >= 100

Common Pitfalls

  1. Case sensitivity
    Purchase
    !=
    purchase
    . Always use
    snake_case
    .
  2. String truncation at 100 chars — URLs and long values get silently cut.
  3. Custom dimension quotas — 50 event-scoped, 25 user-scoped (standard). Plan carefully.
  4. Duplicate purchases — Always include
    transaction_id
    for dedup (72-hour window).
  5. Missing currency
    value
    without
    currency
    is ignored in monetization reports.
  6. Stale dataLayer — Always push
    { ecommerce: null }
    before ecommerce events in GTM.
  7. PII in parameters — No emails, phone numbers, or names. Violates GA4 ToS.
  8. Dynamic event names — Burns through the 500-name limit. Use parameters instead.

Resources