Google Site Kit quietly shipped something that changes the GA4 setup game for WordPress sites: automatic event tracking for checkouts and form submissions across eight popular plugins. No GTM, no dataLayer.push, no gtag snippets. Install Site Kit, connect GA4, and purchase and generate_lead events start flowing.
Sounds great. In practice, I’ve audited a dozen WooCommerce stores running this feature and found the same three problems every time: duplicate purchase events inflating revenue by 40-100%, generate_lead events missing from AJAX form submissions, and transaction IDs that don’t match the WooCommerce order table. If you’re running Site Kit alongside any existing GTM container (and most serious sites are), you have a measurement problem whether you know it or not.
Here’s how to audit what Site Kit is actually sending, where it collides with your existing tracking, and how to decide which system wins.
What Site Kit Auto-Tracks (and the Exact Event Names)
Site Kit’s enhanced measurement for WordPress plugins is driven by the Google Tag for WordPress integration. When enabled, it detects supported plugins on the page and injects event listeners that fire GA4 events on form submission or checkout completion.
Here’s the plugin coverage and the events each one fires:
| Plugin | Trigger | GA4 Event Name | Parameters Sent |
|---|---|---|---|
| WooCommerce | Order received page | purchase | transaction_id, value, currency, tax, shipping, items[] |
| WooCommerce | Add to cart (any product) | add_to_cart | currency, value, items[] |
| WooCommerce | Checkout page view | begin_checkout | currency, value, items[] |
| Contact Form 7 | wpcf7mailsent event | generate_lead | form_id, form_name |
| WPForms | Successful submission | generate_lead | form_id, form_name |
| Formidable Forms | frmFormComplete | generate_lead | form_id, form_name |
| Ninja Forms | nfFormSubmitResponse | generate_lead | form_id, form_name |
| Easy Digital Downloads | Purchase confirmation | purchase | transaction_id, value, currency, items[] |
| MemberPress | Signup completion | sign_up / purchase | depends on offer type |
| Gravity Forms | gform_confirmation_loaded | generate_lead | form_id, form_name |
A few things worth flagging immediately:
- The
generate_leadevent has no monetary value by default. If your lead tracking in GA4 depends onvalueandcurrencyfor conversion value reporting, you’ll see zeros across the board. purchaseevents from WooCommerce pull from the thank-you page order object, which means refunded or cancelled orders still fire if the customer reloads that page.form_idis sent as a number, not a string. If you’ve built audiences in GA4 usingform_id = "47"(string match), they won’t trigger. Use number comparison.
Auditing Site Kit Events in GA4 DebugView
Before you touch anything, verify what’s actually firing. Install the GA4 Debugger Chrome extension or append ?_dbg=1 to your URL after enabling debug mode via GTM.
Run through these flows on your site:
- Add a product to cart → check for
add_to_cart - Hit the checkout page → check for
begin_checkout - Place a test order → check for
purchase - Submit a contact form → check for
generate_lead
In DebugView, you’re looking for two things: whether the event fires at all, and whether it fires twice. If you see two purchase events with the same transaction_id landing within a few seconds of each other, Site Kit and your existing GTM ecommerce tag are both firing. This is the single most common issue I see.
Here’s what a healthy single-fire looks like in DebugView:
19:42:11 page_view /checkout/order-received/12847/
19:42:12 purchase transaction_id: 12847
value: 189.50
currency: GBP
items: [3]
And here’s the duplicate pattern:
19:42:11 page_view /checkout/order-received/12847/
19:42:12 purchase transaction_id: 12847 (Site Kit)
value: 189.50
19:42:13 purchase transaction_id: 12847 (GTM tag)
value: 189.50
Two events, same ID, same value. GA4 does deduplicate purchase events by transaction_id within a short window, but this behaviour is inconsistent across reports — the Realtime report shows duplicates, the Monetization report sometimes dedupes, and BigQuery exports keep both rows. You cannot rely on GA4 to clean this up for you.
The Deduplication Decision: Site Kit vs GTM
Once you’ve confirmed duplicates, you have to pick one system. Here’s the decision framework I use with clients:
Disable Site Kit auto-events when:
- You have an existing GTM ecommerce setup that includes custom dimensions (customer type, product category hierarchy, coupon details, etc.)
- You run server-side GTM and want all events to route through your sGTM container
- You use Consent Mode v2 with granular consent signals that your GTM tags respect
- You need to send purchase data to multiple destinations (GA4, Meta CAPI, Google Ads, TikTok)
Disable your GTM ecommerce tags and keep Site Kit when:
- Your GTM setup is basic (just a GA4 purchase tag with no enrichment)
- You’re a small WooCommerce store without developer resources
- Your
dataLayerimplementation is unreliable or incomplete - You only need GA4 as a destination
To disable Site Kit’s auto-events selectively, go to Site Kit → Settings → Analytics → Advanced and toggle off “Enhanced measurement for supported plugins.” Unfortunately, Site Kit treats this as all-or-nothing per plugin category. You cannot keep add_to_cart auto-tracking while disabling purchase. If you need that granularity, you have to disable the whole feature and rebuild in GTM.
For most clients I work with on GA4 setup projects, the answer is to keep GTM as the source of truth and disable Site Kit’s duplicative events. GTM gives you control over timing, enrichment, and routing that Site Kit’s black box doesn’t.
Plugin-Specific Gotchas I’ve Hit in Production
WooCommerce Block Checkout vs Shortcode Checkout
WooCommerce ships two checkout experiences: the classic shortcode checkout ([woocommerce_checkout]) and the newer block-based checkout. Site Kit handles both, but the begin_checkout event timing differs:
- Shortcode checkout: fires on page load
- Block checkout: fires after the React component mounts, which can be 200-800ms later
This matters if you’re building audiences based on begin_checkout and users bounce quickly. On block checkouts, you’ll undercount by 5-15% because fast-bouncers leave before the event fires.
Worse, the block checkout emits a wc-blocks_checkout_render_checkout_form event that Site Kit sometimes misses on cached pages. If you use a page cache plugin like WP Rocket or LiteSpeed Cache with aggressive JS deferral, test the checkout page in incognito and verify begin_checkout fires every time.
Multi-Step Forms
WPForms, Formidable, and Gravity Forms all support multi-step forms. Site Kit fires generate_lead only on final submission, which is correct behaviour. But if you want funnel analysis across steps, you need to add that yourself via GTM listeners on the step-change events each plugin exposes:
- WPForms:
wpformsPageChange - Gravity Forms:
gform_page_loaded - Formidable:
frmPageTurn
Site Kit does nothing for these. If multi-step funnel analysis matters to you, keep GTM in play.
AJAX Form Submissions That Silently Fail
This is the one that burns people. Contact Form 7 and Ninja Forms both support AJAX submission. Site Kit listens for the plugin’s success event (wpcf7mailsent for CF7). But if a form uses a redirect-on-success configuration, the event listener may unbind before the redirect fires on slow connections.
I’ve seen generate_lead events miss 10-20% of actual form submissions on CF7 forms with redirects. The fix is to delay the redirect by 300ms using the on_sent_ok hook (deprecated but still works) or by binding a custom listener:
document.addEventListener('wpcf7mailsent', function(event) {
// Fire your own event immediately
if (window.gtag) {
gtag('event', 'generate_lead', {
form_id: event.detail.contactFormId,
form_name: event.detail.contactFormId,
send_to: 'G-XXXXXXXXXX'
});
}
// Delay any redirect
setTimeout(function() {
if (event.detail.apiResponse.into) {
window.location.href = event.detail.apiResponse.into;
}
}, 500);
}, false);
If you’re going to override Site Kit’s listener, disable the Site Kit auto-track for CF7 first or you’ll double-count.
WooCommerce Subscriptions and Renewal Orders
Site Kit fires purchase on the order-received page for renewal orders too, if the customer views the renewal confirmation. For subscription businesses this inflates purchase counts because the initial sign-up and every renewal view can trigger events. If you run subscriptions, verify in BigQuery how many of your purchase events have transaction_ids matching renewal orders in wp_wc_orders.
Cross-Checking Site Kit Purchases Against WooCommerce Orders
The only way to prove whether Site Kit is capturing every order (and not inventing extras) is to join GA4 BigQuery export data against your WooCommerce order table.
Export your WooCommerce orders to a BigQuery table (I use a scheduled script that pulls from the REST API nightly). Then run this query to find mismatches:
WITH ga4_purchases AS (
SELECT
event_date,
(SELECT value.string_value FROM UNNEST(event_params)
WHERE key = 'transaction_id') AS transaction_id,
(SELECT value.double_value FROM UNNEST(event_params)
WHERE key = 'value') AS ga4_value,
COUNT(*) AS event_count
FROM `your-project.analytics_XXXXXX.events_*`
WHERE event_name = 'purchase'
AND _TABLE_SUFFIX BETWEEN
FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY))
AND FORMAT_DATE('%Y%m%d', CURRENT_DATE())
GROUP BY 1, 2, 3
),
woo_orders AS (
SELECT
CAST(order_id AS STRING) AS transaction_id,
DATE(date_created) AS order_date,
total AS woo_value,
status
FROM `your-project.woocommerce.orders`
WHERE date_created >= DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
AND status IN ('completed', 'processing')
)
SELECT
COALESCE(g.transaction_id, w.transaction_id) AS transaction_id,
w.order_date,
g.event_count,
g.ga4_value,
w.woo_value,
w.status,
CASE
WHEN g.transaction_id IS NULL THEN 'MISSING_IN_GA4'
WHEN w.transaction_id IS NULL THEN 'GHOST_IN_GA4'
WHEN g.event_count > 1 THEN 'DUPLICATED'
WHEN ABS(g.ga4_value - w.woo_value) > 0.01 THEN 'VALUE_MISMATCH'
ELSE 'OK'
END AS audit_status
FROM ga4_purchases g
FULL OUTER JOIN woo_orders w USING (transaction_id)
WHERE
g.transaction_id IS NULL
OR w.transaction_id IS NULL
OR g.event_count > 1
OR ABS(COALESCE(g.ga4_value, 0) - COALESCE(w.woo_value, 0)) > 0.01
ORDER BY w.order_date DESC;
Four audit statuses to watch:
- MISSING_IN_GA4: Order exists in WooCommerce, no purchase event in GA4. Usually caused by consent-mode denial, ad blockers, or users closing the thank-you page before JS loads.
- GHOST_IN_GA4: Purchase event fired but no matching order. Often a reloaded thank-you page from an old transaction, or a test order you never completed.
- DUPLICATED: Multiple purchase events for the same order. This is your Site Kit + GTM collision.
- VALUE_MISMATCH: Revenue reported to GA4 differs from WooCommerce total. Usually tax/shipping configuration mismatch.
Run this weekly for a month and you’ll have a defensible number for your purchase event accuracy. In my experience, a well-tuned setup lands at 93-97% match rate. Anything below 85% means something’s broken.
For teams running server-side GTM, you can extend this to compare client-side (Site Kit) events against server-side events and quantify what Consent Mode and ad blockers are costing you.
Common Mistakes and Troubleshooting
Problem: Revenue in GA4 is roughly 2x WooCommerce reports.
Cause: Site Kit auto-events plus GTM purchase tag both firing. Fix: disable one. The quickest check is to look at event_count by transaction_id in BigQuery for the last 7 days.
Problem: generate_lead events show in Realtime but don’t appear in standard reports.
Cause: You haven’t marked generate_lead as a key event (formerly conversion) in GA4 Admin. Enhanced measurement doesn’t do this for you. Go to Admin → Events → toggle “Mark as key event.”
Problem: Site Kit shows events firing in DebugView but your Looker Studio dashboards show nothing.
Cause: Your reports are filtered to a specific session_source or session_medium that excludes direct traffic. Site Kit events inherit whatever session attribution exists at firing time, which for thank-you pages is often direct (after payment gateway redirect strips referrer).
Problem: items array in purchase events is empty.
Cause: WooCommerce order object isn’t being read correctly, usually because a custom theme has overridden the thank-you page template and removed the order object from scope. Check wp-content/themes/your-theme/woocommerce/checkout/thankyou.php for modifications.
Problem: Forms submit but no generate_lead event fires.
Causes to check in order: (1) Site Kit’s “Enhanced measurement for supported plugins” is off, (2) the form plugin version is older than Site Kit supports, (3) a page cache is serving stale JS, (4) a JS error earlier on the page is halting execution, (5) the form uses a custom redirect that fires before the event listener.
Problem: Transaction IDs in GA4 don’t match WooCommerce order numbers. Cause: You’re using a sequential order numbers plugin (like WooCommerce Sequential Order Numbers Pro) that creates a separate order_number distinct from post_id. Site Kit uses the raw post_id. Fix: either align your BigQuery join on post_id, or write a custom tag that reads the sequential order number.
Key Takeaways
- Site Kit’s auto-tracking covers eight major WordPress plugins and emits standard GA4 ecommerce and lead events, but it operates as a black box with no granular on/off switches per event type.
- Duplicate purchase events are the default outcome when Site Kit is enabled on a site with existing GTM ecommerce tags. Audit DebugView and BigQuery before trusting your revenue numbers.
- Pick one system as the source of truth: keep GTM when you need enrichment, consent handling, or multi-destination routing; keep Site Kit when your setup is basic and you have no developer resources.
- Block-based WooCommerce checkouts, AJAX forms with redirects, and multi-step forms all have known failure modes that cost you 5-20% of event volume. Test every flow in incognito, not just the ones you expect to work.
- The only reliable accuracy check is a BigQuery join between GA4 purchase events and your WooCommerce order table. Run it weekly, flag anything under 90% match rate, and investigate the top three audit statuses.
generate_leadevents need to be manually marked as key events in GA4 Admin before they appear in standard reporting. Site Kit does not do this for you.
Share this article