---
title: Google Analytics 4 and GTM
slug: google-analytics-4-and-gtm
description: How Personizely sends A/B test and widget events to GA4 and Google Tag Manager: event names, parameters, GA4 reports, GTM triggers, consent, ecommerce.
image: https://archbee-image-uploads.s3.amazonaws.com/1y1Fr-DMGy_apx7FwibyA/ORDTWfNKMXiY3ZRv0QSgP_personizely-docs-og.png
docTags: 
createdAt: 2026-10-17T09:57:43.251Z
---

The Google Analytics integration sends an event to Google Analytics 4 every time a visitor sees a Personizely campaign or interacts with a widget, with the campaign, variation and widget as parameters. You can then compare A/B test variations in GA4, build audiences from them or trigger other tags in Google Tag Manager. On sites that aren't on Shopify or Wix, it also works the other way: Personizely records the GA4 ecommerce events your site already sends (purchase, begin checkout, add to cart) as Personizely conversions.

**Available on:** all platforms. Needs GA4 (gtag.js) or Google Tag Manager on your site.

## Set up

1. Make sure GA4 or GTM is installed on your site, in the page itself (not only in a sandboxed pixel, see [Gotchas](docId\:NwHWpmwoIntBLz7-PTe3q)).
2. In Personizely, go to **Settings → Integrations**, find **Google Analytics** and click **Enable**. There's nothing else to configure.
3. Events start on the next page view. Check them in GA4's **Admin → DebugView** or GTM's **Preview** mode.

## How events are sent

When an event happens, Personizely records it, then hands it to Google on the page:

- **If the Google tag (gtag.js) is on the page**, Personizely calls `gtag('event', …)`. The event goes to the GA4 properties your Google tag is configured for.
- **Otherwise**, Personizely pushes the event to the data layer for Google Tag Manager: `dataLayer.push({ event: 'campaign_view', … })`. GTM only forwards it to GA4 if you set up a tag for it (see [Google Tag Manager](docId\:NwHWpmwoIntBLz7-PTe3q)).

Sites that install GA4 through GTM (with a Google tag inside the container) use the data-layer path.

## Events

| Event                 | Sent when                                                                                                         |
| --------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `campaign_view`       | A visitor sees a campaign variation or the control, on each page view where the campaign runs for them            |
| `widget_view`         | A widget is displayed, or would have been for a visitor in a widget A/B test's control group                      |
| `widget_click`        | A button, image or product button is clicked and does something (opens a URL, goes to a step, or has automations) |
| `widget_submit`       | A form or survey is submitted                                                                                     |
| `widget_spin`         | A wheel of fortune is spun                                                                                        |
| `widget_succeed`      | A countdown timer reaches zero, or a cart progress bar reaches its goal, while the widget is displayed            |
| `widget_coupon_copy`  | A visitor copies a code from a Coupon element                                                                     |
| `widget_coupon_apply` | A Coupon element applies its code to the cart (Shopify)                                                           |

Events aren't sent in [preview](https://docs.personizely.net/preview-qa), for visitors excluded by [traffic filtering](https://docs.personizely.net/traffic-filtering), or for deployed winners (a [deployed variation](https://docs.personizely.net/deploy-winners) is no longer a test).

## Parameters

### Campaign events

| Parameter        | Value                                                                                                                                                   |
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `event_source`   | `Personizely`                                                                                                                                           |
| `campaign_id`    | The campaign's ID                                                                                                                                       |
| `campaign_name`  | The campaign's name                                                                                                                                     |
| `variation_id`   | The variation's ID. Empty for the control of an A/B test                                                                                                |
| `variation_name` | A/B tests: the variation's name, or `Original` for the control. Personalizations: the target's name, or `<target name> - Control` for its control group |
| `control`        | `true` for control visitors, `false` otherwise                                                                                                          |

### Widget events

| Parameter        | Value                                                                                                                               |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `event_source`   | `Personizely`                                                                                                                       |
| `widget_id`      | The widget's ID                                                                                                                     |
| `widget_name`    | The widget's name                                                                                                                   |
| `experiment_id`  | The widget A/B test's ID, when the widget is in a [widget A/B test](https://docs.personizely.net/widget-experiments-and-ab-testing) |
| `variation_id`   | The variation's ID. Empty for the control group                                                                                     |
| `variation_name` | The variation's name. Empty for the control group                                                                                   |
| `control`        | `true` for the control group, `false` otherwise                                                                                     |

Agencies using white label see their brand name in `event_source`.

## Build GA4 reports

### 1. Register the parameters

GA4 only shows event parameters in reports once they're registered. In GA4, go to **Admin → Custom definitions → Create custom dimension**, scope **Event**, and add at least `campaign_name`, `variation_name` and `widget_name`. Add `control`, `campaign_id`, `widget_id` and `experiment_id` if you need them. Data appears from the moment you register; earlier events aren't backfilled.

### 2. Compare variations of an A/B test

1. Go to **Explore → Free form**.
2. Create a **user segment** per variation: "Event `campaign_view` where `campaign_name` = *Hero test* and `variation_name` = *Original*", and the same for each variation.
3. Add the segments to the exploration, with metrics such as **Total users**, **Purchasers**, **Purchase revenue** and **Ecommerce purchases**.

Because `campaign_view` repeats on every page view in the campaign, count **users**, not events.

### 3. Build audiences

Under **Admin → Audiences**, create an audience of users with `campaign_view` where `variation_name` = *Free shipping*. Use it for remarketing or to follow the group in other reports.

### Widget performance

A free-form exploration with **Event name** and `widget_name` as rows and **Event count** and **Total users** as values shows views, clicks and submits per widget. Filter by `experiment_id` to look at one widget A/B test.

:::hint{type="info"}
GA4 and Personizely will report different numbers. GA4 attributes purchases its own way and may drop visitors who declined consent or block analytics. Use Personizely's [campaign reports](https://docs.personizely.net/how-to-read-and-use-the-reports) for test decisions and GA4 for deeper journeys.
:::

## Google Tag Manager

If your site uses GTM without gtag.js on the page, forward the events to GA4 with one tag:

1. **Variables:** create **Data Layer Variables** for `campaign_name`, `variation_name`, `campaign_id`, `variation_id`, `control`, `widget_name`, `widget_id`, `experiment_id` and `event_source`.
2. **Trigger:** create a **Custom Event** trigger with event name `^(campaign|widget)_` and **Use regex matching** on. To forward only test exposures, use `campaign_view` instead.
3. **Tag:** create a **Google Analytics: GA4 Event** tag. Set **Event Name** to `{{Event}}`, add the parameters with the variables from step 1, and attach the trigger.
4. Test in **Preview**, then publish.

You can also use the same triggers for other tools, for example firing a Meta pixel custom event on `widget_submit`, or tagging Hotjar sessions on `campaign_view`.

## Consent

- **Google's consent settings decide what GA4 keeps.** Personizely hands every event to your Google tag or data layer. With Consent Mode, GA4 stores or models the event according to the visitor's `analytics_storage` choice, exactly as it does for your other events.
- **In GTM, your tag's consent rules apply.** If your GA4 tags require consent, or are blocked by a consent trigger, the Personizely event tag should use the same settings.
- **Personizely's own tracking is separate.** On Shopify, Personizely follows the visitor's choice in Shopify's customer privacy settings for its own tracking, recording events from visitors who declined without their IP address. Widgets and campaigns still run for those visitors, so their events are still handed to Google, which applies its consent state. On other platforms, if you load the Personizely snippet only after consent, events reach GA4 only after consent too. See [Cookies and consent](https://docs.personizely.net/cookies-and-consent).

## Ecommerce events into Personizely

On sites that aren't on Shopify or Wix, enabling Google Analytics also lets Personizely use the GA4 ecommerce events your site sends as conversions:

| Your site sends  | Recorded in Personizely as              |
| ---------------- | --------------------------------------- |
| `purchase`       | Purchase, with value and transaction ID |
| `begin_checkout` | Checkout start                          |
| `add_to_cart`    | Add to cart                             |

- Both forms count: `gtag('event', 'purchase', { transaction_id, value, … })` and `dataLayer.push({ event: 'purchase', ecommerce: { transaction_id, value, … } })`, including events pushed before Personizely loaded on that page.
- The value is read from `value` and treated as your website's currency (**Settings → Website → Currency**). The event's `currency` isn't converted.
- They reach the system Purchase goal and your [Event goals](https://docs.personizely.net/goals) for Add to cart and Checkout start, and are [attributed](https://docs.personizely.net/attribution) to campaigns and widgets like any conversion.
- The page that sends them must load the Personizely snippet. A checkout hosted on another domain without the snippet isn't tracked.
- Shopify and Wix stores don't use this: their orders come from the platform directly. See [Shopify order tracking](https://docs.personizely.net/shopify-order-tracking).

## Behavior details and limitations

- **Events follow Personizely's record.** An event is sent to Google after Personizely has recorded it, a moment after it happens. Visitors who leave immediately may not send it.
- **Load the Google tag first.** Put the Google tag snippet above the Personizely snippet in `<head>`. If gtag.js isn't defined yet when the first event fires, that event goes to the data layer instead.
- **Duplicate purchases.** Personizely ignores a repeated `purchase` with the same transaction ID within one page view. If your confirmation page sends the purchase again when reloaded, it's recorded again. Make sure it's sent once per order.
- **Single-page apps.** On themes that change pages without a reload, `campaign_view` is sent again for each detected page where the campaign runs.

## Gotchas

- **Shopify's Google & YouTube app.** If GA4 is installed only through Shopify's Google & YouTube app or a custom pixel, it runs in Shopify's sandbox and doesn't receive events from the page. Add GTM or the Google tag to your theme for Personizely events.
- **Nothing in reports, but events in DebugView** → the parameters aren't registered as custom dimensions, or the data hasn't been processed yet (GA4 standard reports can take up to 48 hours).
- **Events in GTM Preview, but not in GA4** → no GA4 Event tag is forwarding them.
- **`variation_name` empty for widgets** → the visitor is in the widget A/B test's control group, which sees nothing.

## Related

- [Analytics integrations](https://docs.personizely.net/analytics-integrations)
- [Integrations](https://docs.personizely.net/integrations)
- [Reading campaign reports](https://docs.personizely.net/how-to-read-and-use-the-reports)
- [Goals](https://docs.personizely.net/goals)
- [Revenue attribution](https://docs.personizely.net/attribution)
- [Cookies and consent](https://docs.personizely.net/cookies-and-consent)
