App guides
The Google Analytics 4 app sends your store's purchases, refunds and sign-ups to Google Analytics 4 from the server, with GA4's Measurement Protocol. The events are recorded even when an ad blocker or a closed tab stops browser tracking, and they can be joined to the shopper's browser session.
| When | What the app does |
| An order is paid, or submitted if you choose | Sends a purchase event with the order number, total, tax, shipping, coupon and items, once per order, and records on the order when it was sent. |
| A payment of an order is refunded | Sends a refund event with that refund's amount, once per refund. |
| An order is canceled | With Refund canceled orders on, reports the part of the order total that isn't refunded yet as a refund. |
| A customer account is created | Sends a sign_up event. |
| You run Send to GA4 on orders | Sends the purchases of selected orders from the last 72 hours that weren't sent yet. |
| You run Validate setup | Sends a sample purchase to GA4's validation server and shows its answer. Nothing is recorded in GA4. |
- A GA4 property with a web data stream, and access to its Admin settings to create a Measurement Protocol API secret.
- Optionally, access to your storefront's code, to save the shopper's GA4 client and session IDs on the cart. Without them, server events can't be joined to the shopper's browser session.
Install Google Analytics 4 from the Swell App Store, and set it up in your test environment before the live one.
Get the Measurement ID and an API secret
In GA4, go to Admin > Data streams and open your web stream. Copy the Measurement ID, which looks like G-XXXXXXXXXX. Under Measurement Protocol API secrets, create a secret and copy its value.
Add them to the app
In Swell, go to Apps > Google Analytics 4 > Settings. Enter the Measurement ID and the Measurement Protocol API secret, and click Save settings.
Validate the setup
Choose Actions > Validate setup. The app sends a sample purchase to GA4's validation server, which checks the Measurement ID and the event, and records nothing. The validation server doesn't check the API secret, so the test order in step 6 confirms it.
Choose the events
On the Events tab, choose when purchases are sent and which other events to send. Then turn on Enable Integration and save.
Join the shopper's session
This step is optional. To count server events toward the same visitor, session and traffic source as the shopper's browser events, save the GA4 client and session IDs in the cart metadata from your storefront. Swell copies the cart metadata to the order.
// Storefront: after gtag.js is loaded and the cart exists
const MEASUREMENT_ID = 'G-XXXXXXXXXX';
gtag('get', MEASUREMENT_ID, 'client_id', (clientId) => {
gtag('get', MEASUREMENT_ID, 'session_id', (sessionId) => {
swell.cart.update({ metadata: { ga_client_id: clientId, ga_session_id: sessionId } });
});
});For sign-ups, save the same values in the account metadata with swell.account.update.
Place a test order
On the Advanced tab, turn on Debug mode and save. Place a test order and pay for it. Within a minute, the purchase shows in GA4 under Admin > DebugView, and the order's Google Analytics tab shows when it was sent. Turn off Debug mode when you're done.
Go live
Settings are saved separately for each environment. In the live environment, repeat steps 2 to 4. Use a separate GA4 property or data stream for the test environment, so test orders stay out of your reports.
If your storefront also sends purchase events with gtag.js, turn those off, or GA4 may count purchases twice.
Each order is sent once, as a purchase event, when it's paid, or when it's submitted if Send purchase when is set to Order is submitted. Drafts and canceled orders aren't sent. The event has:
- transaction_id: the order number.
- value, currency, tax and shipping: the order's grand total, currency, tax total and shipping total, rounded to cents.
- coupon: the order's coupon code, if it has one.
- items: up to 200 items, each with the variant SKU, product SKU or product ID as item_id, the product name, the variant name, the unit price after item discounts and the quantity.
When the order is less than 72 hours old, the event is dated with the order's submission time.
With Send refunds on, every successful refund of an order's payment is sent as its own refund event, with that refund's amount and the Swell refund ID as transaction_id. An order refunded several times sends several refund events. Each event also carries the custom parameters order_id and order_number. To use them in GA4 reports, register them as event-scoped custom dimensions under Admin > Custom definitions.
With Refund canceled orders on, canceling an order reports the part of its total that isn't refunded yet, with the order number as transaction_id. Refunds are only sent for orders whose purchase was sent, never add up to more than the order total, and don't list items.
With Send sign-ups on, a sign_up event with method: email is sent when a customer account is created, including accounts created at checkout.
GA4 links events through the client ID. The app uses the client and session IDs your storefront saved in the cart or account metadata. Without them, it uses swell.<customer ID>, or swell.<order ID> for guest orders, and each event starts its own session. Those events still count in reports and show in Realtime and DebugView, but they're attributed to (direct) / (not set) traffic. With Send user ID on, the Swell customer ID is also sent as user_id, so GA4 can join a customer's devices.
To send purchases that were missed, for example orders placed before you set up the app, open an order and choose Actions > Send purchase to GA4, or select up to 25 orders in the order list and choose Send to GA4. GA4 only accepts events up to 72 hours old, so older orders are skipped, along with orders that were already sent or aren't paid. The result lists the skipped orders.
| Where | What it's for |
| Apps > Google Analytics 4 > Settings | The Measurement ID and API secret, the Events and Advanced tabs, and Actions > Validate setup. |
| An order's Google Analytics tab | When the purchase was sent, the GA4 client ID it was sent with, the amount reported as refunded, when the last refund was sent, and the last error. |
| The order list | A GA4 column with the time the purchase was sent, and the Send to GA4 action for selected orders. |
| An order's Actions menu | Send purchase to GA4, until the order's purchase has been sent. |
Settings are in Apps > Google Analytics 4 > Settings and are saved separately for each environment. Events and Advanced settings are on their own tabs.
| Setting | Description | Default |
| Measurement ID | The Measurement ID of your GA4 web stream, like G-XXXXXXXXXX. Required. | None |
| Measurement Protocol API secret | An API secret created for the same web stream. Masked on the settings page. Required. | None |
| Enable Integration | Sends events to GA4 and allows the Send to GA4 actions. | Off |
| Send purchase when | Order is paid, or Order is submitted. | Order is paid |
| Send refunds | Sends a refund event for every refund, full or partial. | On |
| Refund canceled orders | Reports the rest of a canceled order's total as refunded. Needs Send refunds on. | On |
| Send sign-ups | Sends a sign_up event when a customer account is created. | On |
| Collection endpoint | Global (www.google-analytics.com) or EU (region1.google-analytics.com). | Global |
| Send user ID | Sends the Swell customer ID as user_id. | On |
| Debug mode | Shows events in GA4 under Admin > DebugView. Turn it off when you're done testing. | Off |
- GA4 accepts any well-formed event without reporting errors, and drops invalid ones silently. Use Validate setup and DebugView to check events.
- GA4 accepts events up to 72 hours old, so past orders can't be imported. A purchase sent later is recorded at the time it's sent.
- If your storefront also sends purchase events with gtag.js, GA4 may count purchases twice.
- Without the client and session IDs from your storefront, server events start their own sessions and are attributed to (direct) / (not set) traffic.
- The app doesn't send consent signals. If your site uses Consent Mode, check that collecting from the server matches your consent policy before you turn the app on.
- Refunds report an amount, not which items were returned, and GA4 reports them separately from the purchase, because their transaction ID is the Swell refund ID. Totals and net revenue are still correct.
- Refunds of payments that don't belong to an order, such as subscription invoices, aren't sent.
- Events that GA4 refuses with a 4xx error, for example because of a wrong Measurement ID, aren't retried.
- Realtime and DebugView show events within a minute. Standard reports take 24 to 48 hours.
Each order's Google Analytics tab shows the last error the app got for it. The app also logs each event it sends. In the Swell dashboard, the logs are under Developer > Console > Logs.
Validate setup checks the saved settings. Copy the Measurement ID from your GA4 web stream, click Save settings, then run Validate setup again.
Create an API secret for the web stream in GA4, enter it, and save before you validate.
The message lists what GA4's validation server didn't accept. Check that the Measurement ID is the one from your web stream.
The validation server doesn't check the API secret. Check that the secret belongs to the same web stream as the Measurement ID and that Enable Integration is on. Turn on Debug mode and look in Admin > DebugView, since standard reports take 24 to 48 hours.
Purchases are sent when the order is paid, or submitted if you chose that, and only while the integration is on. Drafts and canceled orders aren't sent. If the order is less than 72 hours old, choose Actions > Send purchase to GA4 on the order.
GA4 doesn't accept events older than 72 hours, so these orders can't be sent.
Your storefront probably sends purchase events with gtag.js too. Turn those off.
The storefront doesn't save the shopper's GA4 client and session IDs. Add the snippet from step 5 of Set up.
Check that Send refunds is on and that the order's purchase was sent. Refunds of payments without an order aren't sent. In GA4, refunds have the Swell refund ID as their transaction ID, not the order number.
Uninstalling the app stops sending events to GA4, and removes the Google Analytics tab, the GA4 column and the Send to GA4 actions from your dashboard. Uninstalling applies to the environment you are in, so remove the app from the test and live environments separately.
Events already sent stay in GA4. If you no longer need the Measurement Protocol API secret, delete it in GA4.
| Function | Runs on | What it does |
| order-events | order.submitted, order.paid, order.canceled | Sends the purchase on the event Send purchase when names, and the refund for a canceled order. |
| refund-events | payment.refund.succeeded | Sends one refund for each refund of an order's payment. |
| account-events | account.created | Sends sign_up. |
| send-to-ga4 | Order record and bulk actions | Sends the purchases of up to 25 selected orders from the last 72 hours. |
| validate-event | Settings action | Checks a sample purchase with GA4's validation server. |
Events are posted to https://www.google-analytics.com/mp/collect, or https://region1.google-analytics.com/mp/collect with the EU endpoint.
The app keeps its status on orders under $app.ga4: ga4_purchase_sent_at, ga4_client_id, ga4_refund_value, ga4_refunds (the amounts reported, by Swell refund ID, or canceled), ga4_refund_sent_at and ga4_error. It saves them with $events: false, so they don't trigger order events.
The storefront fields it reads are metadata.ga_client_id and metadata.ga_session_id, on the cart, which Swell copies to the order, or on the account for sign-ups.
Swell builds and maintains the Google Analytics 4 app. For help with the app, email support@swell.is. For questions about your GA4 property, see Google Analytics Help.