Skip to content

GA4. Refund events. Report net revenue after returns.

What this means for your store

Gross purchase revenue lies when returns run 15–30%. The refund event reverses all or part of a prior purchase. GA4 matches on transaction_id and subtracts value from ecommerce revenue. Skip refunds and ROAS, margin, and merchandising decisions all look better than they are.

Scenario on a real storefront

TrailPeak, a DTC boot brand, approves a partial return on order #US-884210. The OMS job sends the refund through Measurement Protocol - never from the shopper's browser:

// Partial refund - one line item returned
gtag('event', 'refund', {
  transaction_id: 'US-884210',
  value: 89.00,
  currency: 'USD',
  items: [
    {
      item_id: 'SKU-BOOT-09-W',
      item_name: 'Trail Boot - Walnut / 9',
      quantity: 1,
    },
  ],
});

// Full refund - transaction_id + total value only
gtag('event', 'refund', {
  transaction_id: 'US-881902',
  value: 214.50,
  currency: 'GBP',
});

// BigQuery net revenue (simplified)
// SUM(purchase.value) - SUM(refund.value) GROUP BY item_id

Shopify's native GA4 connector may send refunds automatically. Reconcile against your OMS before adding a duplicate server-side refund.

What to do next

  • Build a weekly net revenue chart in Looker Studio: purchases minus refunds by category.
  • Flag SKUs where refund rate beats the category average - sizing charts, defects, or misleading PDP copy.
  • Audit transaction_id pairs between purchase and refund; GA4 ignores mismatched IDs.

Bottom line

Refunds belong on the server, tied to the original transaction_id. Finance cares about net revenue. Gross purchase value alone will mislead paid media and merchandising.