Google Analytics 4 → PostHog
Move GA4 events, identities, properties, conversions, consent, collection, and historical evidence into PostHog with a BigQuery export, a schema map, and a labeled historical import.
Should you make this move?
Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.
Google Analytics 4
- Event-based measurement connects web, app, audiences, and Google advertising
- Established reporting patterns make recurring measurement easier
- Its data model and reporting interface are difficult for many teams to govern
- Tracking quality still depends on disciplined implementation and governance
PostHog
- Open product analytics, session replay, feature flags, and experiments consolidate product tooling
- Product-focused reporting helps teams understand behavior beyond page views
- Event volume, deployment choice, and broad feature scope add operational complexity
- Event schemas and historical cohorts are expensive to redesign or move
PostHog: Open product analytics, session replay, feature flags, and experiments consolidate product tooling. This removes a major source-side concern: Its data model and reporting interface are difficult for many teams to govern.
What you lose: Event-based measurement connects web, app, audiences, and Google advertising. What you inherit: Event volume, deployment choice, and broad feature scope add operational complexity.
Jump to a section
Know the shape of the move.
This timeline assumes
- Up to 50 properties, 500 events, and five years of retained reports
- A signed measurement plan defines the metrics and conversions that must remain comparable.
- Both collectors can run in parallel for at least one representative business cycle.
- Imported history is labeled separately from destination-native collection.
- The migration team records evidence for every blocking verification check.
What survives the move.
“Partial” and “manual” are not footnotes. They are work that must be scheduled and verified.
| Item | Outcome | Impact | What happens | Mitigation |
|---|---|---|---|---|
| Raw events and GA4 history | partial | critical | PostHog states that Google Analytics historical exports are limited. The documented path is a BigQuery daily or streaming export, then a conversion script. Events only appear in BigQuery after the link is live, often more than 24 hours later. | Link BigQuery first, wait for dated event tables, and pilot one day before a full import. |
| Daily BigQuery export volume | partial | critical | Standard GA4 properties have a 1 million event daily export limit. Google pauses daily export when a property stays over that limit and does not reprocess previous days. Streaming export has no event-count limit. | Exclude noisy streams or events, or enable streaming, before you treat a missing day as a PostHog import bug. |
| Event names, timestamps, and nested payloads | partial | critical | PostHog remaps page_view to $pageview and user_engagement to $autocapture, converts event_timestamp from microseconds to ISO 8601, and flattens event_params, items, device, and geo. There is no way to selectively delete imported events. | Test the converter on a test project, keep a dictionary, and reject unmapped critical events. |
| Anonymous and identified users | partial | critical | The PostHog sample uses user_id, then user_pseudo_id, as distinct_id. Every imported event needs a distinct_id. Identity stitching in GA4 reports will not match PostHog persons without an explicit map. | Approve the identity rule and replay anonymous-then-identified journeys after import. |
| Import timing and paid-plan unlock | partial | high | PostHog requires a paid product analytics plan to unlock historic import features, even though historic imports are free. Timestamps must be ISO 8601 and at least 48 hours before the import time. Capture must set historical_migration to true. | Create the US or EU project, unlock the plan, and import only events older than 48 hours. |
| Managed Amplitude-style import jobs | lost | high | PostHog managed migrations cover Mixpanel, Amplitude, and S3. Google Analytics is a manual BigQuery conversion, not a managed source. | Budget engineering time for the converter and a resumable export-to-object-store step. |
| Historical reports and aggregate metrics | partial | critical | Imported events can support new queries. GA4 chart totals can still differ because of timezone, identity, consent, and bot filtering. | Record source baselines and annotate imported versus native periods. |
| Dashboards, explorations, and saved reports | lost | high | GA4 explorations and collections do not become PostHog insights. | Rebuild only the signed reporting set against destination events. |
| Audiences, cohorts, and segments | manual | high | Dynamic membership rules must be re-expressed against destination data. | Test known members and exclusions for each active audience. |
| Tracking code and data collection | manual | critical | gtag, GTM, Measurement Protocol, consent, domains, and filters need a new PostHog implementation. | Run both collectors in parallel and verify live payloads. |
| Conversions, attribution, and revenue | manual | critical | Names may import while triggers, attribution windows, and ecommerce fields need destination setup. PostHog’s sample also drops values such as (not set). | Create an event dictionary and test every business conversion end to end. |
| Consent, retention, and deletion | manual | critical | Privacy configuration does not transfer with the BigQuery tables. | Rebuild opt-out, deletion, and retention and test them before source collection stops. |
Where each thing goes.
| Source | Destination | Method | Notes |
|---|---|---|---|
| GA4 property or data stream | PostHog project and cloud region | manual | Record timezone, currency, domain, and US or EU host. |
| page_view | $pageview | transform | Map page_location to $current_url and page_referrer to $referrer. |
| user_engagement | $autocapture | transform | Confirm you want engagement events before importing them. |
| Custom event and event_params | PostHog event and properties | transform | Flatten records and reject unmapped critical keys. |
| user_id or user_pseudo_id | distinct_id | transform | Prefer the identified user_id when both exist. |
| event_timestamp | ISO 8601 timestamp | transform | Divide microseconds by 1,000,000 and keep events 48 hours old. |
| user_properties | $set person properties | transform | Do not drop first-touch or LTV fields you still need. |
| Goal, conversion, or purchase event | Destination conversion or revenue event | manual | Recreate the trigger and test it live. |
| Saved exploration or audience | PostHog insight or cohort | unsupported | Rebuild from signed questions, not exported pixels. |
Make the move recoverable.
Create the source-of-truth backup
Preserve GA4 data, configuration, and operating evidence before any destination write.
- Export GA4 property, stream, event, conversion, audience, report, tag, integration, and privacy configuration.
- Save dated metric, conversion, attribution, and traffic baselines from GA4 reports.
- Link BigQuery, wait for a dated events table, and hash a rehearsal export.
- Record timezone, retention, filters, consent, and data-deletion settings.
Proof to capture: A signed manifest reconciles every scoped record class, export file, count, and hash.
GA4-to-PostHog schema map
Define event names, flattened properties, identity rules, and expected metric breaks.
- Inventory source events, parameters, and identity fields.
- Map page_view, user_engagement, and custom keys to PostHog names.
- Reject unmapped critical records.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
Parallel collection and historical import
Build trustworthy live data while loading supported history.
- Run a test day in a test project first.
- Store the BigQuery extract, then import with historical_migration.
- Reconcile accepted, rejected, and transformed events.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
The things most likely to hurt.
These are operating limits. Treat every “Stop if” condition as a blocked migration, not a suggestion.
Metric differences are mistaken for data loss
Timezone, identity, consent, bot filtering, and dropped (not set) values produce different totals.
- Consequence
- Teams reject valid data or make bad decisions.
- Mitigation
- Approve definitions and expected variance before cutover.
Stop if: A critical metric lacks an owner-approved interpretation.
A bad import cannot be deleted by event
PostHog has no selective delete for ingested events, so a wrong name or timestamp stays.
- Consequence
- The production project is polluted and later reports stay wrong.
- Mitigation
- Pilot on a test project and keep a resumable converter with a cursor.
Stop if: The test import shows unmapped critical events or shifted times.
Collection continues in both tools unintentionally
Old tags remain active beyond the comparison window.
- Consequence
- Privacy scope and operating cost exceed approval.
- Mitigation
- Keep a dated parallel-run plan and remove old collectors only after sign-off.
Stop if: An unowned source collector remains active.
Do the work in this order.
- Days 1–3 · inventory
Inventory and decisions
6–12 hours active2–3 days elapsedOwner review waiting- Inventory GA4 events, parameters, identities, audiences, and integrations.
- Approve scope, owners, mappings, and exclusions.
Depends on: Google Analytics 4 and PostHog administrator access
Stop / go checkpointExport?
Go when: Every critical item has an owner and disposition.
Stop when: Consent, billing, access, or system ownership is unclear.
- Days 3–6 · backup
Backup and reconcile
5–12 hours active2–4 days elapsedBigQuery link and first daily table waiting- Link BigQuery, wait for events tables, and hash a rehearsal extract.
- Reconcile counts, totals, and hashes against GA4 baselines.
Depends on: Approved inventory
Stop / go checkpointTransform?
Go when: Source totals and export manifests agree.
Stop when: Any critical dataset or configuration is absent.
- Days 6–14 · pilot
Map and pilot
12–35 hours active4–8 days elapsedDestination processing and review waiting- Convert a representative day in a test PostHog project.
- Run live collection in parallel and compare identity, events, and conversions.
Depends on: Verified backup
Stop / go checkpointScale?
Go when: Pilot mappings, behavior, access, and evidence pass.
Stop when: Any critical check fails or produces unexplained variance.
- Days 12–22 · cutover
Final delta and switch
5–25 hours active1–5 days elapsedImport or sync propagation waiting- Finish historical jobs and freeze new GA4 instrumentation changes.
- Make PostHog the production collector and run blocking checks.
Depends on: Passed pilot and approved rollback
Stop / go checkpointOpen production?
Go when: Counts reconcile and one destination system owns production measurement.
Stop when: A source collector remains the only production source or a blocking check fails.
- Days 14–40 · observe
Observe and close
3–18 hours active3–10 days elapsedOperating-cycle evidence waiting- Monitor one complete operating cycle.
- Sign the verification report and close rollback only after stability.
Depends on: Verified cutover
Stop / go checkpointClose rollback?
Go when: No trigger occurs during the agreed observation period.
Stop when: Data, access, delivery, routing, or business results regress.
Cut over with a way back.
Cutover
Make PostHog the only production measurement system without losing the final GA4 delta.
- Finish approved historical imports and freeze GA4 instrumentation changes.
- Confirm live PostHog collection for every critical client and server event.
- Switch reporting, audiences, and downstream integrations to PostHog.
- Keep GA4 collection only for the signed comparison window.
- Run every blocking verification check and keep the source intact.
Proof to capture: PostHog owns production measurement, totals reconcile, and every blocking check has durable evidence.
Rollback
Return production measurement to Google Analytics 4 without losing destination-era changes.
- Stop treating PostHog as the production collector.
- Restore GA4 tags, SDKs, and downstream integrations.
- Export PostHog events captured after cutover if they must be preserved.
- Review and apply safe destination-era instrumentation changes to GA4.
- Run the same blocking checks against the restored source.
Proof to capture: Google Analytics 4 again owns production measurement with current collection and no duplicate destination action.
- Unexplained critical count or value variance
- Missing or exposed critical data
- Duplicate production action
- Failed access, routing, delivery, or integration check
- A critical feature has no safe destination replacement
Prove the migration worked.
Every blocking check must pass. Capture the evidence before cleanup begins.
| Pass | ID | Check | Method | Expected result | Evidence |
|---|---|---|---|---|---|
V-01Blocking | Live event receipt | Trigger every critical client and server event. | One valid destination event with approved properties. | Event log. | |
V-02Blocking | Business outcome tracking | Complete every approved conversion path. | Conversion and revenue values reconcile. | Conversion report. | |
V-03Blocking | Event and property mapping | Compare the signed schema with live and imported payloads. | No critical event or property is unmapped. | Schema diff. | |
V-04Blocking | Parallel-run interpretation | Compare daily metrics for the approved overlap window. | Variance is explained and owner-approved. | Metric comparison. | |
V-05 | Imported-event coverage | Compare available dates, event counts, and identity values. | Every supported period is imported or explicitly archived. | History ledger. | |
V-06Blocking | user_id and user_pseudo_id mapping | Replay anonymous-then-identified journeys. | Pre-login events attach to the identified person. | Identity report. | |
V-07Blocking | Consent, retention, and deletion | Test opt-out, deletion, access, and retention configuration. | Collection and lifecycle match policy. | Privacy evidence. | |
V-08Blocking | Reporting ownership | Inspect tags, SDKs, APIs, exports, and dashboards. | PostHog owns approved production measurement. | Ownership checklist. |
Remove the scaffolding safely.
Safe after: One complete operating cycle, at least seven stable days, and owner sign-off on every blocking check.
- Create final GA4 and BigQuery exports and archive verification evidence.
- Revoke temporary credentials, API keys, webhooks, and elevated roles.
- Remove obsolete tags, SDKs, jobs, integrations, and unused collectors.
- Keep the source intact through the approved retention window.
- Cancel paid plans only after billing, legal, and recovery review.
- Schedule the next PostHog backup, access, and migration-playbook review.
When the plan met reality.
First-hand accounts are preferred. Vendor case studies are labeled, and every note below is an editorial paraphrase—follow the link for the full context.
Brian Morrison II replaced a broken Google Analytics install on GuardianForge with PostHog after asking in the Learn Build Teach Discord. He installed posthog-js, disabled automatic pageviews for the React SPA, and turned off autocapture because click and keystroke noise was more than he needed. He then identified Destiny membership IDs so he could watch how known players used the app. The post covers live collection and dashboards, not a historical GA export.
- On a single-page app, capture $pageview from the router yourself instead of trusting automatic page detection.
- Turn autocapture off in a rehearsal project if you only need a few product events, then add identify once login exists.
- The move started because GA stopped working, not because a BigQuery history job was ready.
- PostHog’s default dashboard was usable without learning GA terminology first.
Roboto Studio wrote that they never understood their Google Analytics dashboards and that wiring custom events into GA panels was slow. They ran the PostHog wizard on a Next.js site, accepted the two events it guessed, and were monitoring those events in less than an hour. They advise starting with one or two money events, used $rageclick plus session replay to find UI bugs, and identify form submitters by email. This is a collector switch, not a documented historical import.
- Start with one or two events that produce revenue, then add more only after those paths are trusted.
- Treat a wizard-based live setup as the first milestone, and still run a signed measurement plan if you later import GA4 history.
- Setup time mattered more to this team than matching old GA4 charts.
- Rage clicks and session recordings became part of the reason they stayed on PostHog.
Verify against the primary material.
Platform behavior changes. Check these sources and the review dates above before executing a production migration.
- PostHog: migrate from Google AnalyticsAccessed 2026-10-24
- Google Analytics: set up BigQuery ExportAccessed 2026-10-24
- PostHog: historical migrations overviewAccessed 2026-10-24