Blog

Track refunds and partial refunds with GA4 server-side

Refunds need negative values, refund event names, and the original transaction_id. Most teams send the wrong combination.

Refund tracking in GA4 is structurally simple but frequently misconfigured. The event name is refund, the value is positive (representing the refund amount), and the transaction_id must match the original purchase. Missing any of these makes the refund invisible to GA4's revenue calculations.

Full refunds

gtag('event', 'refund', {
  transaction_id: 'T-12345',
  value: 99.00,
  currency: 'EUR'
});

GA4 subtracts the value from your purchase revenue automatically. Reports show net revenue (gross minus refunds) when the refund event arrives within the same processing period.

Partial refunds

For refunds of specific items rather than the whole order, include an items array:

gtag('event', 'refund', {
  transaction_id: 'T-12345',
  value: 29.00,
  currency: 'EUR',
  items: [
    { item_id: 'SKU-A', quantity: 1, price: 29.00 }
  ]
});

GA4 attributes the refund to the specific items and recalculates per-item revenue. Without the items array, GA4 records the refund value but cannot tie it back to specific products.

From a webhook

Most refunds happen in your billing system, not on your website. Wire your billing webhook to your sGTM container and forward refund events from there. The webhook payload from Stripe, Chargebee, etc. has the transaction ID and the refunded amount; map them to the GA4 refund event.

The 90-day window

GA4 only attributes refunds to the original purchase if the refund arrives within 90 days. After that, the refund is recorded as a standalone event with no revenue impact. For subscription businesses with chargebacks coming in months later, this can suppress refund tracking quietly.

If your refunds frequently land outside 90 days, send them as a custom event (late_refund) so they at least show up in Explore reports, even if they do not net against revenue automatically.

Verify in GA4

In GA4 reports > Monetisation > Ecommerce purchases, the columns include "Item refund amount" and "Item refunded quantity." Both should show data within 24 hours of firing your first refund event. If they show zero after a week, your refund event is reaching GA4 but missing the items array, or the transaction_id does not match a known purchase.

For the broader ecommerce migration, refunds are usually the last event type added; do not skip them.