GA4 and A/B Testing: The Complete Integration Guide
GA4 and A/B testing together: what GA4 measures, what it cannot decide, real property limits, BigQuery export, event structure and significance.

GA4 (Google Analytics 4) does not decide which version won your A/B test. It measures, in detail, the behaviour and revenue of every variant you showed to visitors, but the judgment call of “was that luck or real” requires a statistical calculation GA4 does not perform natively. This guide shows exactly where GA4 delivers real value for teams that test variations (events, funnels, revenue, segmentation), where it stops (significance, visitor assignment, statistical power), and how to close that gap with a correct event structure, BigQuery and an honest significance calculator.
It answers a question that comes up every week in growth and CRO teams: “Google Optimize is gone and GA4 became the centre of everything, so can I run A/B tests with GA4 alone?” The short answer is that you can measure with GA4 alone, but you cannot decide with it alone. The long answer is everything below, with real numbers, a worked example and a source for every technical limit cited.
What GA4 does well in A/B testing, and what it does not
GA4 is probably the most widely used behavioural analytics tool on the market, and that is not an accident: it is free, it integrates with Google Ads, BigQuery and Tag Manager, and its event-based data model fits anything you want to measure, including the variants of an experiment.
What GA4 does well:
- Records behaviour at event granularity. Clicks, page views, scrolls, form submissions, each becomes an event with parameters, and you decide which parameters matter.
- Segments by almost any dimension. Device, acquisition channel, geography, and, if you configure it correctly, the test variant the visitor was shown.
- Connects behaviour to revenue. The
purchaseevent (or the equivalent key event) carries a monetary value, and GA4 cross-references it with any other dimension you have marked, including the test variant. - Serves as a single source of truth for funnels. A funnel exploration shows step by step drop-off, which helps decide where testing is worth the effort before you run any experiment at all.
- Feeds BigQuery with raw data. It is the exit door for any statistical analysis more rigorous than the standard reports allow.
What GA4 does not do, and what teams used to Google Optimize miss:
- It does not randomize visitors between variations. That is the job of an A/B testing tool, or of a feature flag system with bucketing, which decides for each visitor which version to render and keeps that assignment stable.
- It does not compute statistical significance natively. The standard report shows the raw difference between two numbers. It does not tell you whether that difference is statistically trustworthy or just small-sample noise.
- It does not control statistical power or sample size. GA4 will never tell you “you need 4,000 more visitors for this difference to be reliable”. That is on whoever is doing the analysis.
- It does not correct for peeking. If you check the report daily and stop the moment one variant “looks” ahead, GA4 will not warn you that the practice inflates your false positive rate.
The division of labour, summarised:
| Task | GA4 does it natively | Needs another piece |
|---|---|---|
| Count visitors, events and conversions per variant | Yes | |
| Segment revenue by variant | Yes (via custom dimension) | |
| Randomize and keep a visitor in the same variant | Yes, an A/B testing tool | |
| Compute p-value, confidence interval and power | Yes, a statistical calculator | |
| Warn about insufficient sample or peeking | Yes, discipline plus tooling | |
| Export raw, unsampled data | Yes, via BigQuery Export |
Keep that division in mind: it is the thread running through the rest of this guide.
A concrete scenario shows how the confusion starts. A growth team changes the copy of a primary button, looks at GA4 two weeks later and sees the new variant with 8% more conversions. The natural reaction is to celebrate and ship it permanently. The problem is that GA4 never claimed those 8% were statistically reliable, only that it was the difference observed in that slice of time. Without running the same pair of numbers through a significance calculator, the team has no way of knowing whether it is looking at a real gain or at sampling noise that would have vanished on the next batch of traffic.
The gap Google Optimize left behind
Until 30 September 2023, Google Optimize (and its paid tier, Optimize 360) was the free tool many teams used to test page variations wired into the then Universal Analytics. Google announced the sunset on 20 January 2023, giving roughly eight months for migration, as trade publications recorded at the time (Search Engine Roundtable, 2023).
The stated reason for the sunset was that Google wanted to focus engineering effort on third-party integrations with GA4, leaving the “experimentation engine” role to dedicated tools while GA4 becomes the measurement and machine learning layer behind them. In practice that left two choices for anyone who wants to keep testing variations rigorously:
- Use a dedicated A/B testing tool (client-side or server-side) that already randomizes visitors and ideally embeds the statistics, sending the relevant events into GA4 as the measurement and revenue layer.
- Build the split yourself (via feature flag, bucketing cookie or backend logic) and use GA4 purely to collect the numbers, computing significance separately with a calculator such as the significance calculator on this blog.
Both paths run through the same requirement: GA4 has to know, for every visitor and every conversion, which variant was in play. That is what the next section is about.
How to structure custom events to mark experiment and variant
The common practice, and the one recommended by GA4’s own experiment integration documentation for teams running their own framework outside a third-party tool, is to dedicate one event to experiment exposure and carry on it the parameters that identify which test and which variant the visitor saw (Google for Developers, “Create an experiment integration with Google Analytics”). A typical pattern:
- Event name:
view_experiment(orexperiment_impression; the name matters less than the consistency). - Parameter
experiment_id: a stable identifier for the test, for examplecta_button_color_aug26. - Parameter
variant_id: which variant the visitor saw, for examplecontrolorvariant_b.
After firing the event with those parameters, the step teams forget is registering the parameters as custom dimensions in GA4 (Admin, under custom definitions). Without it, the parameter arrives on the raw event but never appears as an available column in reports and explorations.
Two scope decisions matter:
- Event scope: the value applies only to that specific event. It works well for
view_experiment, but if you want to filter thepurchaseevent by variant, the variant parameter has to be present on the purchase event too, or you use the next scope. - User scope: stores the variant as a user property, valid for the whole session (and future sessions, if the same identifier persists). It is the sturdiest way to guarantee that a
purchaseevent happening minutes or days after exposure still carries the information about which variant that visitor saw.
The suggested convention:
| Element | Suggested name | GA4 scope | Where it shows up |
|---|---|---|---|
| Exposure event | view_experiment |
Event | Every time a variant is rendered |
| Test parameter | experiment_id |
Event-scoped custom dimension | Reports and explorations |
| Variant parameter | variant_id |
Event-scoped custom dimension | Reports and explorations |
| Persistent property | experiment_bucket |
User-scoped custom dimension | Any event in the same session or user, purchase included |
One detail that saves rework: agree on the naming convention before the first test goes live, and document it somewhere visible to everyone (marketing, product and whoever touches the tag manager). Teams that let each person pick their own event or parameter name (exp_view in one campaign, experiment_seen in another) end up with duplicated custom dimensions, reports that do not reconcile, and wasted custom dimension quota.
Fire the exposure event on render, not on assignment
A subtle failure mode: firing view_experiment at the moment the visitor is bucketed rather than at the moment the variant is actually painted on screen. If the variation renders below the fold, or on a page that a slice of visitors abandon before it finishes loading, the exposure count includes people who never saw the change. That dilutes the measured effect toward zero and inflates the sample you need, without anything looking broken in the report. Fire the event when the variation is visible, and if the change sits below the fold, consider firing on visibility rather than on load.
The real GA4 limits every experimenter should know
Before designing your event taxonomy, it is worth knowing GA4’s technical ceilings, because they change over time and differ between a standard (free) property and GA4 360 (paid). The numbers below were checked against the official Google Analytics documentation in August 2026; because Google updates them periodically, confirm the current value at the source before planning anything that sits near a limit.
| Resource | Standard property | GA4 360 |
|---|---|---|
| Custom dimensions (event scope) | 50 | 125 |
| Custom dimensions (user scope) | 25 | 100 |
| Custom dimensions (item scope) | 10 | 25 |
| Custom metrics | 50 | 125 |
| User data retention | 2 or 14 months | 2 or 14 months |
| Event data retention | 2 or 14 months | 2, 14, 26, 38 or 50 months |
| Exploration sampling (per query) | from about 10 million events | from about 100 million (up to about 1 billion) |
| Daily BigQuery Export (batch) | 1 million events/day | 20 billion events/day |
According to the official Google Analytics documentation on custom definitions, standard properties get 50 event-scoped custom dimensions, 25 user-scoped and 10 item-scoped, plus 50 custom metrics, with GA4 360 ceilings well above that (Google Analytics Help, “About custom dimensions and metrics”). That is rarely a constraint for an ordinary A/B testing programme, but teams running dozens of simultaneous experiments with many parameters per event can approach the limit, particularly in user scope.
On retention: by default GA4 keeps user and event data for 2 months. On a standard property you can extend that to 14 months in Admin, under data collection and modification. Paid GA4 360 properties have additional options of 26, 38 and 50 months for event data (Google Analytics Help, “Data retention”). This matters especially for long-cycle tests, for example experiments measuring subscription retention over several months: if retention is left at the 2-month default, older exploration data simply disappears before you can analyse it.
On sampling: GA4 exploration reports apply sampling when a query exceeds the property’s event quota, roughly 10 million events per query on standard properties, and a much larger initial quota (up to about 100 million, capped near 1 billion) on GA4 360 (Google Analytics Help, “About data sampling”). A data quality icon warns you when the result on screen is sampled and what share of the data was used. For a high-traffic A/B test that matters: if you read significance straight from a sampled exploration, the p-value you compute on top of already sampled numbers carries an extra error the calculator cannot correct for.
BigQuery export: the route to unsampled analysis
The sturdiest way to escape sampling is to export raw GA4 events to BigQuery and run the statistical calculation yourself on the complete data, bypassing GA4’s reporting layer. Setup is free for standard properties (Admin, under product integrations), with one important caveat: the daily batch export is capped at 1 million events per day, and if the property consistently exceeds that, Google may pause the export (Google Analytics Help, “Set up BigQuery Export”). High-traffic sites that need more usually move to streaming export, which has no such cap, or to a GA4 360 account.
With raw events in BigQuery, the flow for validating an A/B test looks like this:
- Filter
view_experimentevents (or whichever name you chose) by theexperiment_idof the test in question, split byvariant_id. - Count unique visitors per variant (the randomization unit, normally
user_pseudo_id). - Count conversions per variant, joining with the relevant conversion event (
purchase,sign_up, or whichever key event that test was defined on). - Run the same two-proportion calculation a significance calculator uses (the z-score formula for two proportions), either in SQL inside BigQuery or by exporting the four numbers (visitors and conversions on each side) into a calculator such as the one on this blog.
The shape of that query, simplified to the part that matters:
select
variant_id,
count(distinct user_pseudo_id) as visitors,
count(distinct case when converted then user_pseudo_id end) as conversions
from experiment_exposures
where experiment_id = 'cta_button_color_aug26'
group by variant_id
Two implementation notes that decide whether those numbers are trustworthy. First, count distinct users, not events: a visitor who reloads the page three times is one unit of randomization, not three. Second, count conversions only for users who appear in the exposure table, so someone who converted without ever seeing the tested screen never enters either side of the comparison.
It is exactly that last step, the four numbers coming out of BigQuery (or even out of an unsampled standard report, when volume is low) and going into a significance calculator, that the worked example below demonstrates.
Google Tag Manager as the firing layer
In practice most implementations do not write the view_experiment event directly in page code. It is fired by Google Tag Manager (GTM), with a tag configured to read the active variant (normally exposed by the A/B testing tool as a JavaScript variable or a data layer push) and send it as a GA4 event, with experiment_id and variant_id as tag parameters.
That intermediate layer has a practical advantage: if you swap A/B testing tools later, or move the split to your own feature flag system, you only adjust the trigger and the variable inside GTM, without touching the event arriving in GA4 or the custom dimension taxonomy you already configured.
Client-side, server-side, or a server-side tag container
The same view_experiment event can reach GA4 by three different routes, and the choice affects data reliability, not just implementation. Through GTM in the browser (client-side), implementation is fast but exposed to ad blockers and load-order delays. Straight from the backend (server-side), firing is sturdier and immune to browser blocking, the recommended default for product and SaaS experiments. A server-side GTM container sits in between: it centralises firing logic on a server you control, reducing dependence on the visitor’s browser without requiring every event to be hand-written in the application backend. None of the three solves statistical significance, that remains the calculator’s job, but the wrong choice can bias event counts between variants before the calculation even starts. The client-side vs server-side testing guide compares the trade-offs in full.
How to attribute revenue to a test winner in GA4
The question that decides a test is rarely “which variant got more clicks”, it is “which variant produced more revenue, or more of the conversions that pay the bills”. GA4 already knows how to do that arithmetic, as long as the conversion event (purchase, with the value parameter populated, or the equivalent key event for a SaaS product) also carries the variant dimension, either directly or through the experiment_bucket user property described above.
With that segmentation in hand, a funnel exploration (or a free-form table with the variant dimension and the revenue metric) shows side by side how much each variant converted and how much each variant earned. This is precisely where GA4 delivers value no calculator delivers on its own: the cross-section of variant, funnel step and monetary value, with all the extra segmentation (device, channel, new vs returning) the rest of the tool already provides.
What GA4 still does not deliver, even with revenue correctly segmented, is the answer to “is that revenue difference statistically trustworthy, or explainable by sampling luck”. For that, the four funnel numbers (visitors and conversions on each side) feed the significance calculator, exactly as in the example that follows.
A worked example: from GA4 to statistical significance
Imagine you exported from GA4 (a funnel exploration segmented by the variant_id dimension, unsampled because the volume sits below the 10 million events per query ceiling) the following numbers from a checkout A/B test:
- Control (A): 12,000 visitors who saw
view_experiment, 480 purchases. - Variant (B): 12,000 visitors, 540 purchases.
The standard GA4 report shows the raw difference: A converts at 480 ÷ 12,000 = 4.00%, B at 540 ÷ 12,000 = 4.50%, a relative improvement of +12.5%. So far it is pure arithmetic, exactly what GA4 delivers on its own, with an encouraging green cell on variant B. It is also exactly where a lot of teams celebrate too early.
Running the same four numbers (visitors and conversions on each side) through this blog’s significance calculator, which uses the same two-proportion test described in the statistical significance guide:
Two-sided two-proportion z-test. "Not significant" almost always means not enough sample, not that the versions are equal.
The result, computed from those numbers: the z-score lands at approximately 1.92, giving a two-sided p-value of approximately 0.055 (5.5%). At the conventional 5% threshold, this test is not statistically significant, even though variant B is nominally ahead. The 95% confidence interval on the difference runs from approximately −0.01 percentage points to +1.01 percentage points, meaning it practically touches zero.
How much sample would that test have needed
The same math answers the follow-up question. To detect a 12.5% relative improvement over a 4.0% baseline, at 95% confidence and 80% power, you need 25,551 visitors per variation. The test above ran with 12,000, less than half of that, which means its statistical power was about 48%: a coin flip on whether a real effect of that size would show up at all. At 20,000 weekly visitors split between the two variants, reaching 25,551 per variation takes about 18 days.
That reframes the result. The test was not inconclusive because the change failed; it was inconclusive because it was stopped at roughly half the sample the effect required. Underpowered tests are the most common way a good idea gets filed as “did not work”.
The honest options with a result like this are the ones any inconclusive test offers: keep it running until it reaches the sample the calculator recommends for that effect, accept that the real gain may be smaller than the observed 12.5%, or treat the result as learning (the change is probably not harmful, but it is not proven either) and move to the next hypothesis in the backlog. What is not honest is publishing “we increased conversion by 12.5%” based only on the number the standard GA4 report displayed.
Privacy and consent: Consent Mode and data protection law
Every number coming out of GA4 depends on what the visitor consented to share. Google Consent Mode is the layer that communicates to Google tags (GA4 included) what each visitor authorised in terms of storage and data use; when consent is denied, GA4 reduces collection and uses statistical and behavioural modelling to fill part of the gap rather than simply recording nothing (Google for Developers, “Consent mode overview”).
That has two direct implications for anyone reading an A/B test result in GA4:
- Raw event counts per variant can drift from real behaviour, especially in markets or segments with high cookie refusal rates, because part of what you see has been modelled rather than directly observed.
- The Consent Mode implementation has to be consistent across variants. If variant B changes the position of the consent banner (common in layout tests), it can shift the cookie acceptance rate between A and B, contaminating the comparison with a variable that has nothing to do with the original hypothesis.
Treat the consent implementation as part of the experiment design, not as a separate compliance detail: a test run on an inconsistent consent base carries a bias no significance calculator can remove afterwards.
One cheap check removes most of the risk: before looking at the test result itself, compare the consent acceptance rate between the group that saw A and the group that saw B. If the two rates are similar, consent is not a relevant confounder for that test. If they diverge noticeably, investigate whether something in the variation (banner position, script load order, even the colour of the accept button) changed consent behaviour before trusting any conversion difference between the two sides.
The most common mistakes when using GA4 to decide a test
None of the mistakes below is exotic, which is exactly why they are so frequent: each one looks like a reasonable time saving, right up to the moment the wrong decision gets expensive (a change reverted months later, or worse, a bad change that stayed live because “GA4 showed it went up”).
| Mistake | Why it is a problem | Fix |
|---|---|---|
| Trusting the raw percentage difference in the standard report | GA4 shows the observed difference, not whether it is statistically trustworthy | Run the numbers through a significance calculator before declaring a winner |
| Not filtering internal and bot traffic | Team visits and automated traffic distort each variant’s conversion rate, usually unevenly | Configure internal traffic filters in GA4 and exclude known bot traffic |
| Watching the wrong metric (engagement instead of business) | Engaged sessions and average engagement time are useful, but rarely the metric that pays the bills | Define the primary metric (purchase, sign-up, trial) before running, and do not switch mid-test |
| Reading sampled reports as if they were exact | Above the per-query event ceiling GA4 samples the exploration and the quality icon warns you, but it is easy to ignore | Check the sampling icon, or export to BigQuery when volume demands full precision |
| Forgetting Consent Mode as a confounder | A difference in cookie acceptance between variants contaminates the comparison | Keep the consent implementation identical across control and variation |
| Analysing without setting the variant as a user-scoped dimension | The purchase event, which happens after exposure, does not carry the variant if it was only marked at event scope | Use a user property (experiment_bucket) to persist the variant across the session |
| Using GA4 audiences as the experiment split | Audiences are evaluated after the fact and cannot guarantee a stable, balanced assignment | Randomize in the testing tool or feature flag layer, and use audiences only for analysis |
GA4 alone vs GA4 with a calculator: what each one solves
| What you need to know | GA4 alone | GA4 plus a calculator or statistical engine |
|---|---|---|
| How many visitors saw each variant | Yes | Yes (same source) |
| How many conversions and how much revenue per variant | Yes | Yes (same source) |
| Whether the difference is statistically significant | No | Yes |
| Confidence interval of the difference | No | Yes |
| Sample size required for the effect you want to detect | No | Yes |
| A warning about insufficient sample or peeking | No | Depends on the analyst’s discipline, but the calculator makes the number visible |
| Cross-segmentation (device, channel, new vs returning) | Yes | Yes (same source) |
The direct reading of that table is the thesis of this entire guide: GA4 is irreplaceable as a data source, and a statistical calculator (or a testing tool that embeds one) is irreplaceable as the decision layer. Using only one of the two leaves half the job undone.
Make this automatic with Donnu
You have just seen the manual work that joins GA4 and statistics: structuring the right event, registering the custom dimensions, exporting to BigQuery when volume demands it, and only then running the numbers through a calculator to learn whether the difference is real. Donnu A/B closes that loop automatically: the snippet assigns and keeps each visitor’s variant, the platform computes significance (with honest Bayesian statistics) without you assembling the calculation separately, and the relevant events stay available for you to cross-reference with GA4 and BigQuery whenever you want the full revenue picture.
Start a 14-day free trial and stop deciding A/B tests by the green cell in a GA4 report. If you want to go deeper first, read what an A/B test is from scratch, how statistical significance works behind the calculator, or the common mistakes that invalidate an A/B test, including the ones this guide covered in GA4-specific detail.
Read also: How to Run an A/B Test · Client-Side vs Server-Side A/B Testing · Leia em português
References
- Google Analytics Help. About custom dimensions and metrics. support.google.com/analytics/answer/14240153.
- Google Analytics Help. Data retention. support.google.com/analytics/answer/7667196.
- Google Analytics Help. About data sampling. support.google.com/analytics/answer/13331292.
- Google Analytics Help. Set up BigQuery Export. support.google.com/analytics/answer/9358801.
- Google for Developers. Consent mode overview. developers.google.com/tag-platform/security/concepts/consent-mode.
- Google for Developers. Create an experiment integration with Google Analytics. developers.google.com/analytics/devguides/collection/ga4/integration.
- Search Engine Roundtable. Google Optimize To Sunset September 30, 2023. seroundtable.com.
Frequently asked questions
- Does GA4 replace an A/B testing tool?
- No. GA4 records events, sessions and conversions, so it is the source of truth for behaviour and revenue, but it does not randomize visitors between variations and it does not compute statistical significance natively. To declare a winner with rigor you still need an A/B testing tool, or a statistical calculator run on top of the numbers GA4 recorded.
- Does Google Optimize still exist?
- No. Google Optimize and Optimize 360 were sunset on 30 September 2023, more than six years after Google made them free to everyone in March 2017 as the A/B testing layer attached to Analytics. Since then GA4 has remained the measurement core for teams that test variations, but without the significance engine Optimize had built in.
- How many custom dimensions does GA4 allow per property?
- On a standard property the ceiling is 50 event-scoped custom dimensions, 25 user-scoped and 10 item-scoped, plus 50 custom metrics. Paid GA4 360 properties have higher ceilings. Because Google updates these numbers periodically, always confirm the current value in the official documentation before designing an event taxonomy that sits close to the limit.
- How long does GA4 keep event data?
- Two months by default. On a standard property you can extend that to 14 months; on a paid GA4 360 property, up to 26, 38 or 50 months depending on the plan. The setting lives in Admin, under data collection and modification, and it affects exploration and funnel reports rather than the standard reports.
- Do I need BigQuery to analyse an A/B test with GA4 data?
- It is not mandatory, but it is the recommended path when you want real statistical significance without the sampling that exploration reports apply above a certain volume. The free daily export for standard properties is capped at 1 million events per day; from the raw exported data you can run the same two-proportion test a significance calculator uses.
- Does Google Consent Mode affect the event counts in my A/B test?
- Yes. When a visitor denies consent, GA4 does not record the event in full and uses statistical modelling to fill part of the gap. That means raw conversion counts per variant can drift slightly from real behaviour, especially in regions with high cookie refusal rates, which is one more reason never to decide a test on the raw report number alone.
- Can I use GA4 audiences as A/B test variants?
- You can build an audience per variant for reporting and remarketing, but an audience is not a randomization mechanism. Audience membership is evaluated after the fact from events GA4 already collected, so it cannot decide which version a visitor sees, and it cannot guarantee a stable, balanced split. Use audiences to analyse a test, never to run one.