Migrate from Google Analytics to PostHog

A practical plan for moving GA4 measurement to self-hosted PostHog: what moves cleanly, what needs rework, the export route, cutover sequence and the cost drivers that decide effort.

On this page

How do you migrate from Google Analytics to PostHog without losing the history that matters?

Moving from GA4 to PostHog is a re-instrumentation exercise plus a data-carrying exercise. Your new events have to be sent from your own code, while historical GA data can be brought across mainly through the GA4 BigQuery export and PostHog's documented scripted path for Google Analytics. How much work this takes depends on two things you decide early: how cleanly you map GA event names such as page_view to PostHog events, and whether you run PostHog on your own servers or on PostHog Cloud. Product analytics engineers usually own the event design, data and platform engineers own the export and the pipeline, and the marketing team should own the goal and conversion definitions, since those are the numbers they will check first after cutover.

Plan the operating side before the data move. PostHog states that self-hosted deployments are officially unsupported and that it does not offer customer support for product, infrastructure or other questions on self-hosted instances, so upgrades, backups, capacity and incident response sit with your team or with an implementation partner you contract. Confirm the current self-host requirements in PostHog's documentation before you size a server, and ask whether your expected event volume fits the self-hosted hobby deployment or needs PostHog Cloud. Also check which features you need from the ee directory, because those require a PostHog license on a self-hosted instance.

Set expectations for old history now. Google stopped processing standard Universal Analytics data on July 1, 2023, and access to Universal Analytics data, the interface and the API ended the week of July 1, 2024, after which unexported data was permanently deleted. Any Universal Analytics history that matters to your team therefore survives only if it was exported at the time. For GA4, export to BigQuery now, decide which historical window you need in PostHog, and keep a record of what each import covers, because PostHog's direct import jobs are limited to one year of data each and events are not deduplicated.

What maps cleanly from GA4 to PostHog, and what needs rework or has no equivalent

This table compares common GA4 capabilities with their closest PostHog counterparts and marks each row as clean, needs rework or gap. Read it as a planning checklist: confirm every PostHog feature against the current PostHog documentation before you commit, since parity claims change between releases.

GA4 capabilityPostHog equivalentMigration notes
Page views and custom eventsAutocaptured pageview events and custom events in PostHog's web and product analyticsClean for the event model, but map each GA event name such as page_view to a PostHog event name and property set. Confirm the autocapture settings in the current docs.
User identity and user propertiesPerson identification and person propertiesNeeds rework. GA user IDs and user-scoped dimensions must be sent as distinct IDs and person properties, and anonymous-to-identified merging needs testing.
SessionsSession concept in web analytics and session replayNeeds rework. Session boundaries and timeouts can differ from GA4, so reconcile session counts for a parallel period before cutover.
Traffic sources and UTMsUTM properties captured on pageview eventsNeeds rework. Confirm which UTM and referrer fields PostHog stores by default and how channel grouping is rebuilt, because GA4 default channel groups do not carry over automatically.
Conversions and funnelsFunnels and conversion events in product analyticsNeeds rework. Conversions must be re-declared as PostHog events, and funnels rebuilt from those events. Historical conversion counts from GA4 are not recreated.
AudiencesCohorts and person-based filtersNeeds rework. GA audiences used for Google Ads must be rebuilt as PostHog cohorts, and any export to ad platforms needs its own integration.
Exploration reportsInsights and dashboards in PostHog product analyticsNeeds rework. Explorations are rebuilt as PostHog insights. Expect differences in attribution models and default aggregation.
BigQuery exportsNo direct equivalent. Use PostHog data pipelines or scripted imports, and archive GA4 BigQuery tables separatelyGap for ongoing reporting. Export GA4 history to your own storage before the GA4 export stops feeding your reports. PostHog's documented route for GA history uses the BigQuery export as its source, so confirm the current steps.
Google Ads linkageNo equivalent in PostHogGap. Google Ads conversion import and audience sharing depend on Google's own integration and stay with GA4 or a Google Ads tag.
Consent mode and session replayPostHog session replay with its own consent handling; consent mode is a Google featureNeeds rework for consent mode, which is Google-specific. Session replay is in the same product family, but confirm masking and consent configuration for your jurisdictions.

How do GA event names such as page_view become PostHog events?

Decide the mapping before any historical data moves. The BigQuery export keeps Google's event schema: each row carries an event_name, an event_params array and user_properties, so GA names and parameters arrive exactly as Google recorded them. PostHog stores events under its own names and properties, and the two tools do not share a vocabulary. Start with an inventory. Query a sample of the export, list every distinct event_name and every parameter key, and mark which ones your reports and experiments still use. Give each row a named owner, such as the product manager for sign_up or the finance lead for purchase. For each GA event, record the target PostHog event name, the properties to carry over, and whether PostHog captures it automatically or your code sends it.

Confirm the auto-captured pageview behavior in the PostHog docs before you write custom capture for page views. If the SDK already records pageviews, a hand-written page_view call doubles every page count from the first day, and the migrated GA history will not match live data. Decide which layer owns each event: the PostHog SDK, your tag manager or your backend. Recommended GA4 events such as purchase carry value, currency and item parameters, so decide whether they become PostHog events with those properties or feed a separate revenue pipeline. Keep the finished map in a version-controlled file so each change is reviewed and dated.

The mapping must be settled before the historical import because it cannot be undone selectively. PostHog's managed migrations do not deduplicate events, and PostHog documents no way to delete imported event data selectively. A parameter stored under the wrong key, or a sign_up renamed to the wrong event, becomes permanent history that every dashboard reads. Run the map on a test project first. Compare one day of GA counts with the matching PostHog counts for each event, and only then run the full import. Follow the steps in PostHog's Google Analytics migration guide, and get written sign-off from the analytics owner and the engineers who maintain the tracking code.

Which exports, identities and integrations carry over, and which must be rebuilt

GA4 history, event identities and downstream reports do not move on their own, and each one takes a different route into PostHog. The cards below separate the data paths that exist from the parts your team must rebuild by hand, so you can scope the work before choosing a method.

GA4 BigQuery export as the historical route

The BigQuery export is the documented way to get raw GA4 events out of Google and into a system you control. Standard properties operate under a daily export cap, so a large property may need several days of exports to be complete. Confirm that cap, and whether your property is standard or 360, in Google's current documentation before you plan the backfill window. Check that the export was enabled before the history you need was recorded, because data collected earlier is not recoverable from it.

Scripted migration through the export

PostHog documents a scripted migration from Google Analytics that reads the BigQuery export and sends events into PostHog. This is a script you run and monitor, not a managed import job. Ask the PostHog team or read the migration documentation for throughput, row limits and retry behavior, because the facts available to this page do not give those figures. Plan for a test import into a separate project to confirm event names, timestamps and user identifiers before the full run.

Managed imports exclude GA

PostHog's managed migrations import historical events directly from Mixpanel or Amplitude, or from JSONL files in an S3 bucket. Google Analytics is not on that list, so teams coming from GA4 cannot use the managed path for their history. Each direct import job covers at most one year of data, and events are not deduplicated, so a GA export that overlaps with live tracking can double count. Decide the cutover date so that the history and the live stream meet without overlap.

Replacing the gtag snippet

Live tracking changes from the gtag snippet to the PostHog JavaScript snippet, and the event calls in page code must be rewritten rather than copied. GA4 page_view and custom events need a named PostHog equivalent, and identify calls must be added where you want to tie visitors to accounts. Consent handling changes too: decide whether PostHog loads before or after consent, and whether you use a cookieless mode, before the tag goes live in the EU. Test both consent states in a staging environment.

Google Tag Manager tags and dataLayer

If GA4 tags are deployed through Google Tag Manager, the PostHog snippet and its custom events must be added as new tags, and triggers must be rebuilt around the same dataLayer pushes. Many dataLayer variables were written for GA4 parameter names, so map each one to a PostHog property before deleting old tags. Keep the GA4 container running in parallel until event counts match in both systems. Check whether any consent mode settings in the container control the new tag.

Dashboards, Looker Studio and Google Ads audiences

Looker Studio reports, saved GA4 explorations and Google Ads audiences depend on GA4 data and identifiers, and none of them move into PostHog. Dashboards and insights must be recreated as PostHog insights, and each KPI should be checked against the GA4 figure over the same date range. Google Ads audiences built from GA4 signals need a different source, such as server-side conversion uploads, and that work must be scoped separately. Name an owner for each downstream report before cutover.

What happens in each step of the GA4 to PostHog cutover

The sequence moves measurement from gtag to PostHog in controlled stages, so every event, report and alert has a named owner and a recorded sign-off before Google Analytics is switched off. Each step closes with a document that shows the work is finished.

  1. Inventory GA4 events, properties and reports

    Export the list of GA4 events, custom dimensions, conversions, audiences, reports and alerts from the property, and check the GA4 event names your site or app actually sends, such as page_view, scroll and purchase. Assign each item an owner from marketing, product, or engineering, and record which dashboards and business decisions depend on it. The output is an inventory with an owner against every row. Done means each owner has confirmed their rows are complete, including anything sent from server-side tagging or the BigQuery export.

  2. Draft the signed event map

    Map each GA4 event and parameter to a PostHog event and property name, and decide where PostHog's autocapture or web analytics will replace a GA4 event and where a custom capture call is needed. Note which user identifiers you will send and how they are stored, since that drives the consent and data residency review. The output is a signed event map. The product owner and the analytics owner sign it, and privacy or legal reviews any personal data fields before the pilot starts.

  3. Pilot on one site or property

    Install PostHog on a single site or app, using PostHog Cloud EU or a self-hosted hobby instance from the self-host documentation, and send the mapped events alongside the existing gtag tag. Compare counts for the same period, page by page, and document each gap with its cause, such as bot filtering, a missing parameter or duplicate firing. The output is a pilot comparison report. The analytics owner signs it off only when the differences are explained and accepted in writing. Note that self-hosted instances are unsupported by PostHog, so the operator must own that risk.

  4. Run a parallel period with both tools collecting

    Keep gtag and PostHog collecting on the agreed properties for a period the stakeholders set in advance, and build the replacement dashboards in PostHog while GA4 remains the reference. Check each key metric weekly against the mapped definitions, and log every discrepancy in a shared register. The output is a parallel run log and a dashboard sign-off for each report on the inventory. Business owners sign off on each dashboard, and the parallel period ends only when every critical metric has an accepted definition.

  5. Cut over dashboards, alerts and tags

    Remove the gtag snippet and any Google Tag Manager tags that load GA4 from production templates, deploy the PostHog snippet or SDK, and point dashboards, alerts and scheduled reports at PostHog. Confirm in a staging copy and in production that no GA4 hits are still sent. The output is a cutover checklist with timestamps, the release reference and the list of repointed alerts. The engineering lead and the analytics owner sign the checklist, and each business owner confirms their reports load from PostHog.

  6. Decommission GA4 flows, exports and access

    Disable any BigQuery export jobs that are no longer needed, revoke GA4 user access and API credentials, and remove the GA property from consent management and privacy notices where it is no longer used. Keep a record of what was exported before shutdown and where it is stored, under your retention policy. The output is a decommission record listing each flow, access grant and retention decision. The privacy owner and the IT lead sign it, and the record is kept with the migration file for later audit requests.

How the PostHog hosting choice changes the migration for different teams

A small product team that wants to keep data on its own server can start with the free Docker Compose deployment. PostHog publishes it under the MIT license and installs it with a deploy-hobby script. The migration sequence starts with provisioning a host, then running the script, then pointing the tracker at the new instance. Because the deployment is not officially supported, the team owns upgrades, backups and incident response.

  • Server sizing: PostHog recommends a server equivalent to 4 vCPU, 16 GB of RAM and more than 30 GB of storage. Confirm storage growth against your own event volume.
  • Volume ceiling: The README says open-source deployments should scale to approximately 100k events per month. Measure your current GA4 hit volume before committing.
  • Support model: PostHog does not provide customer support for self-hosted instances, so vendor help is not part of this path.
  • Parallel running: Keep GA4 active during validation so you can compare funnels and pageview counts before cutover.
  • Upgrade plan: Assign an owner for version upgrades and backup testing from day one.

Before you start, confirm that your monthly event volume sits comfortably below the ceiling and that someone on the team can operate the host.

What drives the cost and duration of moving off GA4

This table lists the factors that change the cost and effort of moving from GA4 to PostHog, and how to keep each one manageable. Read it as a checklist for scoping: each driver shows why it matters and where it usually adds work. Cost components are paid to whoever runs the server, to your team's time, and to any implementation partner, so ask for a quote that itemizes them from a written scope.

DriverWhy it mattersHow to keep it down
Event volume and the 100k ceilingPostHog's README says open-source deployments should scale to about 100k events per month and recommends PostHog Cloud above that, so volume decides the hosting model before anything else.Measure monthly GA4 event counts from your reports or BigQuery export, then trim low-value custom events before mapping them.
Number of properties, streams and custom eventsEach GA4 event name and parameter must be mapped to a PostHog event or property, and every unmapped name becomes cleanup work later.Inventory events in a spreadsheet, merge duplicates such as page_view variants, and map only events used in dashboards or decisions.
BigQuery export setupThe documented route runs through the GA4 BigQuery export, which needs a Google Cloud project, datasets, permissions and scripts to load history into PostHog. Standard properties face a daily export cap, so large histories take longer.Confirm the export is enabled and check the daily cap for your property before scheduling. Ask the vendor or partner which history window the scripts will load.
Self-hosting versus PostHog CloudSelf-hosting adds server, storage, backup and upgrade costs. PostHog Cloud charges by usage, and its pricing page lists a free first 1 million analytics events per month, with regional hosting in US (Virginia) and EU (Frankfurt).Compare projected monthly events against the 1 million free tier and the open-source ceiling, then decide hosting before building scripts.
Paid plan for migration importsPostHog's migration documentation says a paid product analytics plan is required to unlock import features, and imported events cannot be selectively deleted. Historical imports are free of ingestion fees only when sent with the historical_migration flag.Confirm the plan tier and the historical_migration flag with PostHog before testing. Import a small test window first, since removal is not selective.
Consent and cookie configuration in the EUConsent banners, tag changes, and the rules for analytics trackers affect how the new tracking code is deployed and tested across EU sites. CNIL states that most large audience measurement offerings fall outside the consent exemption regardless of configuration.Agree the consent design with legal counsel before rewriting the tag. Confirm which regions and data residency choice apply to your traffic.
EE license featuresPostHog's ee directory needs a PostHog license for premium features on self-hosted instances, while posthog-foss is free of proprietary code. Features you need can change the license cost and the design.List the premium features you need, such as SSO or audit logs, and confirm license terms in writing. Decide early whether posthog-foss is sufficient.
Server operations, backups and upgradesPostHog states that self-hosted deployments are officially unsupported and that it offers no customer support for product, infrastructure or other questions on self-hosted instances. Your team or partner carries sizing, backups, upgrades and incident response. PostHog recommends a server equivalent to 4 vCPU, 16 GB RAM and more than 30 GB storage for the hobby deployment, and new Kubernetes deployments of its paid self-hosted product are no longer supported.Ask for a written runbook covering backup, restore testing, upgrade cadence and monitoring. Confirm who owns each item and the recurring effort.
Dashboards, reports and funnels to rebuildEvery GA4 exploration, report and conversion goal has to be recreated in PostHog, and history imported from BigQuery may not match GA4 reporting definitions one for one.Rank reports by who uses them, rebuild the top set first, and retire unused reports instead of copying them.

What usually goes wrong when teams move from GA4 to PostHog

Most failed GA4 to PostHog moves are not technical failures in the tool itself. They come from unclear decisions about history, event naming, scope, operations, hosting limits and licensing, made before anyone writes the first capture call. Each card below names one such risk, the step that prevents it, and the role that should own that step.

Assuming Universal Analytics history is recoverable

Universal Analytics data stopped processing on July 1, 2023, and access to its data, interface and API ended the week of July 1, 2024. Unexported data was permanently deleted, so no PostHog import can bring back those hits. Prevention: confirm with the analytics lead which UA history was exported in earlier years and treat anything else as lost. Owner: analytics lead, with legal confirming what records must be kept.

Mapping GA events without a naming standard

GA4 events such as page_view, scroll and purchase arrive with their own parameters, and a direct rename to PostHog events often produces two versions of the same action. Comparisons then break across dashboards and funnels. Prevention: publish one event dictionary that maps each GA event and parameter to a PostHog event name and property before instrumentation, and review it against a sample of live events. Owner: product analytics lead, with engineering signing off.

Importing history without an agreed scope

PostHog's managed imports from Mixpanel and Amplitude cover at most one year per job, events are not deduplicated, and once imported, event data cannot be selectively deleted. Re-running a job or loading an overlapping date range can double counts that are hard to undo. Prevention: write down the date range, source and event list for each import, run it once against a staging project, and check counts before loading production. Owner: data engineer, approved by the analytics lead.

Running self-hosted PostHog without an operator

PostHog's self-host documentation states that self-hosted deployments are officially unsupported and that PostHog does not provide customer support for product or infrastructure questions on self-hosted instances. Upgrades, backups, storage growth and incident response therefore fall to your team or to a service provider. Prevention: name an on-call operator, document the upgrade and backup routine, and confirm in writing who fixes a failed upgrade. Owner: platform engineering lead, with a named DeployOpen or internal operator if used.

Exceeding the hobby deployment ceiling

The free Docker Compose hobby deployment is installed with a deploy-hobby script and sized for a server equivalent to 4 vCPU, 16 GB of RAM and more than 30 GB of storage. PostHog's README says open-source deployments should scale to approximately 100k events per month and recommends PostHog Cloud above that. Traffic from a campaign or a new SDK can pass that level quickly. Prevention: estimate monthly events from GA4 reports before choosing hosting, set an alert on ingestion volume, and agree a decision point for moving to Cloud or a larger architecture. Owner: product analytics lead, with the platform team for capacity.

Missing EU consent changes or ee license terms

PostHog's repository is MIT licensed except the ee directory, which needs a PostHog license for premium features on self-hosted instances. Moving from GA4 also changes what consent banner and cookie settings are needed in the EU, and CNIL says most large analytics offerings do not qualify for the consent exemption. Prevention: have legal confirm the lawful basis and banner wording for the new setup, and list which features in use sit in the ee directory or require a license. Owner: privacy officer for consent, with the engineering lead for license review.

What do teams ask before they move from Google Analytics to PostHog?

How much does a migration from Google Analytics to self-hosted PostHog cost?

The cost depends on the components you run, not on a single license fee. The PostHog software is MIT licensed for the core repository, so the software itself has no license cost, but a self-hosted deployment still pays for a server, storage, backups, monitoring, the engineering time to instrument the site and app, and the time to rebuild dashboards and funnels. Recurring costs are hosting, storage that grows with event volume, and upgrades. One-time costs are the tracking rebuild, the historical data work and cutover testing. Premium features from the ee directory need a PostHog license, so ask for that item explicitly. For a quote, request a written scope covering tracking coverage, data export scripts, hosting assumptions, backup and upgrade work, and what is excluded. DeployOpen does not publish prices. Compare that quote against PostHog Cloud pricing on the PostHog pricing page, which lists the free event allowance and plan limits.

How long does a move from GA4 to PostHog take?

No fixed duration can be stated from the researched facts, so treat any timeline as something to agree in writing. The main factors are the number of properties and sites, how many GA4 events and conversions need a PostHog equivalent, whether the team runs the tracker through a tag manager, how much of the history must be imported, and how long both tools run in parallel before cutover. Teams with a clear event inventory and a single site usually move faster than teams with many apps and custom reports. Ask for a fixed-scope plan with milestones for instrumentation, data export, validation and cutover, and confirm which of these your own environment and approvals will delay.

Can our team migrate to PostHog in-house, and what skills does it need?

Yes, a capable team can do it in-house, but it needs more than marketing knowledge. Plan for engineers who can deploy and operate Docker Compose or Kubernetes workloads, manage PostgreSQL, ClickHouse and related storage, set up backups and TLS, and handle upgrades. On the product side, someone must map each GA event name, such as page_view, to a PostHog event with the right properties and consent handling. Analysts need to rebuild funnels and reports. Because PostHog states that self-hosted deployments are officially unsupported, your team carries the operational responsibility. Confirm internally whether you have that operations capacity, or scope an outside implementation partner for the parts you cannot staff.

Does PostHog import Google Analytics history, and what does the scripted route need?

PostHog's managed migrations import historical events directly from Mixpanel or Amplitude, and from JSONL files in an S3 bucket, not directly from GA4. For Google Analytics, PostHog documents a scripted migration that starts from the GA4 BigQuery export. That route needs an active BigQuery export from the GA4 property, a Google Cloud project with access to the dataset, a mapping of GA4 event names and parameters to PostHog events and properties, and a script that writes the events to PostHog. Note that the BigQuery export only holds data from the day the export was enabled, so confirm what history exists. Historical imports sent with the historical_migration flag avoid ingestion fees, but a paid product analytics plan is required to unlock the import features, and imported events cannot be selectively deleted. Check the PostHog Google Analytics migration guide before you commit.

Is self-hosted PostHog supported, and what help can we get?

PostHog's self-host documentation states that self-hosted deployments are officially unsupported and that PostHog does not offer customer support for product, infrastructure or other questions on self-hosted instances. That means the support you rely on has to come from your own team, the public documentation and community resources, or a third party you contract. DeployOpen plans, implements, hardens, backs up, upgrades and documents self-hosted open-source platforms in your own infrastructure, and offers ongoing support and upgrades as retainers. Ask any provider to state in writing which upgrade, incident and on-call tasks are covered, and which remain with your team.

Is the free hobby deployment enough, and when should we move to PostHog Cloud?

The hobby deployment is enough for small, low-volume projects, and PostHog offers it as a free Docker Compose deployment under the MIT license, installed with a deploy-hobby script. PostHog recommends a server equivalent to 4 vCPU, 16 GB of RAM and more than 30 GB of storage, and its README says open-source deployments should scale to approximately 100k events per month and recommends PostHog Cloud above that. Check your monthly event volume against that figure before choosing. Also note that new Kubernetes deployments of the paid self-hosted product are no longer supported. If your volume is above the ceiling, or you need the ee features, compare the cost of the paid self-hosted license with PostHog Cloud, which offers a free event allowance on the PostHog pricing page.

Does self-hosting PostHog meet EU data residency, or should we use the EU Cloud region?

Self-hosting keeps the data in the infrastructure you choose, so residency depends on where you deploy the servers and how you back up, monitor and access them. Hosting in an EU data center or your own EU cloud account keeps the event store in the EU, but you must still verify that logs, backups, support tooling and any third-party services stay within the same boundary. PostHog Cloud offers an EU region in Frankfurt alongside a US region in Virginia, which is a managed alternative if you prefer not to run the stack. Confirm with your legal or privacy team which option satisfies your transfer and consent obligations. The European Commission's EU-US data transfers page explains the Data Privacy Framework, which matters only if data reaches US companies or systems.

How DeployOpen scopes, runs and supports a GA4 to PostHog migration

DeployOpen plans, implements, customizes, integrates, hardens, backs up, documents and supports self-hosted open-source platforms inside your own cloud accounts, data centers or air-gapped networks. For a move from Google Analytics 4 to PostHog, that means agreeing the scope in writing first, then building and handing over a PostHog deployment and tracking changes that your team can run.

How we scope

  • Inventory the GA4 properties, events, conversions and BigQuery export datasets that the migration must account for.
  • Decide with you whether PostHog runs as the free self-hosted hobby deployment or whether PostHog Cloud EU is the better fit.
  • Record in the written scope which GA event names map to PostHog events and which reports are out of scope.

How we build

  • Deploy PostHog in your infrastructure, with sizing checked against your expected event volume and the stated limits for self-hosted use.
  • Replace the gtag snippet with PostHog tracking and test each mapped event on staging before cutover.
  • Test the historical data path, including any BigQuery-based import, and confirm the result against a sample of GA4 reports.

How we hand over

  • Document the deployment, configuration keys, event mapping table and the consent and retention settings you chose.
  • Deliver runbooks for backups, upgrades and the rollback path if tracking needs to return to GA4 during parallel running.
  • Walk your product and data teams through the dashboards and event definitions they will use after cutover.

How we support

  • Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.
  • Ongoing support, upgrades and continuous testing are available as a retainer after handover.
  • Because PostHog states that self-hosted deployments get no vendor customer support, confirm early which upgrade and fix work you want covered by a retainer.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.