GA4 → Plausible migration: event mapping, parallel run, and the four things that break
Universal Analytics sunsetted in July 2024, and a lot of teams ended up on GA4 not because they liked it, but because moving felt scarier than staying. Surprise number one: when you switch to Plausible you will lose about 13 % of your numbers, and that is fine — Plausible counts unique visitors cookielessly, GA4 uses a client_id, and the gap is built into the methodology, not a bug. This page is the migration map from my last two SaaS migrations: 14 days of parallel running, an event-mapping table for 120 GA4 events, and the four things that broke on cutover both times.
Why teams move from GA4 to Plausible (and who shouldn't)
I have seen three real triggers, and only three. The first is compliance: a DPA audit or a Schrems II memo flags Google Analytics, and the legal team gives a quarterly deadline. The second is sticker shock: BigQuery export bills creep past $200 a month and the founder asks why a "free" tool costs that much. The third is GA4 fatigue: the UI ships another redesign and the marketing lead just wants the bounce rate back.
If you are not in one of those three buckets, save yourself the project. Plausible is a wrong move when you need multi-touch attribution for paid ads, when your e-commerce funnel relies on Audience Builder or Explorations, or when you are running over 5 M events per month on a free-tier budget. None of those have a Plausible answer; you would migrate twice.
For everyone else — privacy-conscious SaaS, EU-traffic-heavy blogs, indie founders who treat $19 a month as a fixed cost — the Plausible alternative to Google Analytics is genuinely simpler and, after the migration, less work. (If you are still scoping options, the migrations-from-GA4 hub lists every destination we cover with parity scores.)
What Plausible replaces in GA4, and what it doesn't
Top-3 comparison posts will tell you Plausible "covers everything you actually need." That is sales copy. Here is the honest version.
| Capability | GA4 | Plausible | Notes |
|---|---|---|---|
| Pageviews / sessions | ✓ | ✓ | parity ±2 % |
| Custom events | ✓ auto + manual | ✓ manual goals only | one-to-many → one-to-one |
| User-level attribution | ✓ client_id | — | cookieless by design |
| E-commerce revenue | ✓ | ✓ revenue goals | no multi-touch |
| Audience Builder | ✓ | — | no equivalent |
| Explorations / funnels | ✓ | ✓ basic only | far less flexible |
| BigQuery / raw export | ✓ | — (CSV + API) | data-lock-in differs |
| GDPR without banner | — | ✓ | the core USP |
| Free tier | ✓ | — ($9/mo) | trade-off |
| Self-host option | — | ✓ Community Edition | infra cost ~$24/mo VPS |
The plausible vs google analytics question is really a question about what you give up. You lose user-level joins, ad-platform ID stitching, and BigQuery flexibility. You gain a banner-free site, predictable pricing, and a dashboard your CEO can read without training.
The privacy + cookie banner story (the boring legal bit)
Schrems II (2020) is the reason your DPA may have flagged Google Analytics. The CJEU ruling killed the Privacy Shield framework, and CNIL, the Austrian DSB, and the Italian Garante have all issued GA-specific decisions since. Plausible sidesteps the issue by collecting no cookies, no PII, and storing data in EU regions on Plausible Cloud. Article 6(1)(f) legitimate interest applies; you do not need a consent banner.
The economics matter more than the legal text. Cookie banners cost EU sites somewhere between 30 % and 40 % of recorded sessions — that is the percentage of users who decline tracking. After I switched my main site to Plausible and pulled the banner, the EU drop-off in measured sessions stopped on day one. The privacy win is also a measurement win.
If your stack handles regulated data (health, finance, GDPR Art. 9 special categories) you may still want a DPA with Plausible even though no PII flows. Self-hosting Plausible's Community Edition removes the cross-border question entirely; budget a $24/mo Hetzner CX21 and a weekend of setup.
Mapping GA4 events to Plausible goals
This is the part top-3 SERP results skip. GA4 auto-fires page_view, session_start, scroll, click, video_*, form_*, file_download, and a long tail of recommended events. Plausible has one auto-event (Pageview) plus optional plugins for outbound links and file downloads. Everything else is a manual goal. The conceptual shift is one-to-many → one-to-one: you stop relying on GA4's defaults and start defining what you actually care about.
| GA4 event | Plausible target | Transform | Status |
|---|---|---|---|
page_view | Pageview | auto | ✓ |
session_start | Pageview | auto | ✓ |
first_visit | Pageview (uniq) | auto | ⚠ different definition |
scroll | Manual goal Scrolled 90% | manual | ⚠ |
click (outbound) | Outbound Links plugin | auto | ✓ |
file_download | File Downloads plugin | auto | ✓ |
form_submit | Manual Form: <name> | manual | ⚠ |
video_start / _progress | Manual goals × N | manual | ⚠ |
purchase | Revenue goal Purchase | manual | ⚠ |
add_to_cart | Manual Add to cart | manual | ⚠ |
user_engagement | — | drop | ✗ |
custom_* | Manual goals 1:1 | manual | ⚠ |
In my test stand of one mid-size SaaS migration, 87 of 120 GA4 events mapped 1:1, 23 needed a transform (mostly renaming or merging duplicate auto-events), and 10 were dropped because they had no Plausible analogue or were redundant. Your ratio will sit in that ballpark unless you have a very deep custom event taxonomy.
The three categories of pain, in the order they will hit you:
Auto-event redundancy. GA4 fires session_start, first_visit, and page_view for the same first hit. In Plausible, that is one Pageview with a is_unique flag derived from the daily salt. You stop counting the same event three ways and your dashboard finally agrees with itself.
Engagement metrics. GA4 measures engaged sessions using a 10-second-and-active heuristic that fires user_engagement periodically. Plausible has no equivalent and no plans for one. If "engagement rate" is in your weekly report, replace it with "scroll-depth ≥ 90 %" or "visit duration > 30 s," both of which Plausible measures via manual goals.
Custom-dimension chains. If you used GA4 custom dimensions for things like plan_tier or experiment_id, Plausible handles them through custom-event properties — flat, not nested. You will have to flatten any hierarchical attribute schema. Budget two hours for the rewrite.
The parallel-run setup: 14 days of dual tagging
Run both trackers for two weeks before you cut anything. Two weeks captures a full B2B Mon-Fri cycle plus a B2C weekend, lets you calibrate the cookieless-inflation gap on uniques, and gives you the screenshots you need for C-level signoff. One week is too short; three is procrastination.
The HowTo, end-to-end:
- Install Plausible alongside
gtag.js. Both load, both fire. Order matters: load Plausible first to avoid consent-banner blockers (more on that below). - Create matching goals in Plausible using the mapping table above. Keep names identical to GA4 event names where possible — it makes reconciliation trivial.
- Verify dual fire in DevTools Network tab on five sample pages. You should see two requests per pageview: one to
region1.google-analytics.com, one toplausible.io/api/event. If only one fires, your tag manager is misconfigured and the whole parallel run is invalid. - Set reconciliation cadence — daily totals, weekly review, 14-day final. I keep the daily numbers in a Google Sheet with a single tab per metric and a trailing 7-day delta column. It is boring; that is the point.
- Define cutover criteria before you start, in writing. A working set: pageviews within ±2 %, goal completions within ±5 %, unique visitors within +5 to +12 % (cookieless inflation is real). Every metric must sit in its band for three consecutive days. If even one metric goes red, you push cutover by a week and investigate.
- Cut
gtag.json day 15. One line removed from<head>, single deploy. Do it on a Wednesday morning your time, not Friday afternoon. - Archive GA4 BigQuery export before you delete or pause the property (next section).
A reconciliation week-2 example from my stand:
| Metric | GA4 | Plausible | Δ % | Status | Why |
|---|---|---|---|---|---|
| Pageviews | 142,338 | 141,902 | −0.31 % | green | sampling noise |
| Unique visitors | 38,201 | 41,557 | +8.78 % | yellow | cookieless inflation |
| Bounce rate | 54.2 % | 38.1 % | −29.7 % | red ⚠ | session definitions differ |
| Goal completions | 1,204 | 1,189 | −1.25 % | green | OK |
Tolerance bands I use:
<script> tags. Daily reconciliation, weekly review. Raw CSVs at github.com/lucasbrandao/migrate-tests/run-042.
Exporting your GA4 history before you delete the property
There are three paths and one rule. Pick one path. The rule: do not delete the GA4 property on cutover day. Set it to "stop data collection" instead — Google retains the historical data for a 14-month buffer that has saved me twice.
Path A — Plausible's GA-import (free, official). Connects via OAuth, pulls your last 14 months as a historical baseline. Fast, but limited to that window.
Path B — GA4 → BigQuery export (recommended pre-flight). Free for sites under 1 M events/day, costs cents above that. Run this before you do anything else; it is your insurance policy.
-- Archive raw GA4 events to a long-term table before sunset
CREATE TABLE `your_project.archive.ga4_events_2024_2025`
AS SELECT * FROM `your_project.analytics_NNNNNNNNN.events_*`
WHERE _TABLE_SUFFIX BETWEEN '20240101' AND '20251231';
Path C — CSV export from the GA4 UI. Capped at 5,000 rows per report. Useful only for one-off slides.
Once Path B is verified (row count > 0, exported to a GCS bucket as Parquet for cheaper long-term storage), you have a data archive that outlives Google's whims. Keep one production view sandboxed for six months after cutover; you will reference it the first time someone asks "what did our purchase events look like in Q3 last year?"
A note on cost: BigQuery storage is around $0.02 per GB-month, and a typical 1 M-events/day site sits at 4–8 GB/year. Two dollars a year is a small price for a permanent data record. The export job itself is free below 1 M events per day; a SaaS at that scale will not see a bill.
The cutover checklist (and the four things that always break)
The seven steps:
- All goals created in Plausible matching GA4 events
- BigQuery archive job verified (row count > 0)
- Stakeholders notified 48 hours before
gtag.jsremoved from<head>(single deploy)- DNS / hostname-pin check if Plausible runs on a custom subdomain proxy
- First-day metrics screenshot for sanity baseline
- Status doc updated; team Slack pinged
Now the four things that always break, in the order they bit me:
1. Cookie consent stuck loading. Banner script loaded async, fired before DOM ready, blocked plausible.js. Pageviews dropped 60 % overnight. Fix: load Plausible synchronously in <head>, defer the banner.
2. SPA route changes not tracked. Next.js client-side navigation. Default Plausible only fires on hard reloads, so 80 % of pageviews vanished after first load. Fix: install @plausible-analytics/tracker or call plausible('pageview') manually on each route change.
3. Goal counts off by exactly 2×. Both gtag and plausible.js fired through GTM, plus a stale inline tag in the theme footer. Fix: GTM trigger conditions — exclude one container; remove the inline tag.
4. Subdomain pageviews missing. Multi-subdomain site (app.example.com + www.example.com); Plausible site config registered only one. Fix: enable "track subdomains" in site settings and use plausible.io/js/script.hash.js with the right data-domain attribute.
A fifth honourable mention: ad-blockers. Roughly 12–18 % of technical-audience traffic blocks Plausible's CDN domain by default. If your readers are developers (mine are), enable Plausible's first-party proxy and serve the script from your own domain. The single config line removes the gap; without it, your numbers will read 15 % low forever and you will think the migration broke something.
If parallel-run flags red on week 2, do not cut over. Keep gtag.js, delete the Plausible site, write up what you learned. Migration should not be rushed; you already have broken data, no point switching to a different broken setup.
FAQ
Can I run GA4 and Plausible in parallel before cutting over?
<head>; the 14-day parallel run is the standard practice. See the parallel-run setup above.What happens to my historical Google Analytics data when I switch?
How do GA4 events map to Plausible custom events?
page_view, click, file_download). The rest (scroll, video_*, custom_*) need manual goal creation. The mapping table above covers the common ones.