---
title: "Google Analytics"
description: "Use Google Analytics for MainSDK product analytics - GA4 property, measurement ID, main.yaml, consent before sending, local testing and swapping."
section: "integrations"
canonical: "https://mainsdk.dev/docs/integrations/google-analytics"
updated: "2026-10-28"
---

# Google Analytics

> Use Google Analytics for MainSDK product analytics - GA4 property, measurement ID, main.yaml, consent before sending, local testing and swapping.

Canonical: https://mainsdk.dev/docs/integrations/google-analytics · Updated: 2026-10-28

> **Note:** Not planned. ADR-0031 removed Google Analytics from `analytics`, because it links people across sites. Use the built-in store, PostHog or OpenTelemetry instead, see [analytics](https://mainsdk.dev/docs/interfaces/analytics).


Google Analytics (GA4) is Google's web and app analytics service. Behind [`analytics`](https://mainsdk.dev/docs/interfaces/analytics), it receives your app's page views and events, with MainSDK holding them back until consent is given where consent is required. Pick it when your marketing team already reports in Google Analytics or needs it alongside Google's advertising tools.

> **Note:** `analytics` has no spec yet. The options on this page are provisional, taken from the catalog and the product requirements, and may change when the spec lands.

## Interfaces it serves

## Before you start

1. **Create a GA4 property** in your Google Analytics account.
2. **Add a data stream** for your web app (and one per mobile app if you have them). Each web stream has a measurement ID.
3. **For server-side events,** create a Measurement Protocol API secret on the data stream. Events sent from your server or jobs use it.
4. **Store the API secret** in your secrets manager, never in code or a committed env file.

## Configure

```yaml title="main.yaml"
analytics:
  driver: google-analytics
  # [TBD] measurement ID, and the Measurement Protocol secret as secret:GA_API_SECRET
```

Consent comes from [`privacy`](https://mainsdk.dev/docs/interfaces/privacy). If you already run a consent platform, MainSDK reads its IAB TCF or GPP signal, so there is no second banner.

## Use it

```ts title="app/checkout/actions.ts"
"use server";
import { analytics, auth } from "mainsdk";

export async function startCheckout(req: Request, plan: string) {
  const session = await auth.require(req);
  analytics.track("checkout.started", { plan }, { for: session.user });
}
```

`analytics.page()` records page views in the browser, and `analytics.identify(user)` links events to a pseudonymised ID, never an email or name.

## Local development and testing

- **A test property:** send development and stage to a separate GA4 property so test traffic stays out of your reports.
- **Tests:** `createTestApp()` from `@mainsdk/testing` runs `analytics` on an in-memory fake, so tests send nothing to Google. `chaos.on("analytics", { outage: true })` simulates Google Analytics being unreachable.

## What MainSDK adds on top

- Nothing is sent without consent where it is required. A TCF string that denies the analytics purpose means nothing is sent.
- Only pseudonymised user IDs leave your app, so erasing a user is a mapping delete.
- The same calls work if you later move to another analytics tool.

See [Product analytics](https://mainsdk.dev/docs/interfaces/analytics) for the full contract.

## Limits and notes

- Planned driver from the product requirements; `analytics` has no spec yet. Per-market consent rules are not decided yet [TBD].
- Consent matters most with this driver. In the EU and other markets with consent rules, Google Analytics generally needs consent before it runs; `privacy` decides, and MainSDK sends nothing until it allows.
- Google's terms do not allow sending personally identifiable information to Google Analytics. Keep it out of event properties.
- MainSDK regions are US, EU and India. Google Analytics processes data on Google's infrastructure; check that this meets your data residency rules.
- On mobile, consent is decided on the device from phase 3.

## Swap to or from it

```yaml title="main.yaml"
analytics:
  driver: posthog   # was google-analytics
```

Your calls stay the same. Past reports stay in Google Analytics.

## FAQ

**Do I still add Google's tag to my pages?** No. A separate tag sends data outside MainSDK's consent check. Track through `analytics`.

**Does MainSDK support Google's consent mode?** Not defined yet [TBD]. Consent is decided by `privacy` before anything is sent.

## Next

- [Product analytics](https://mainsdk.dev/docs/interfaces/analytics) and [Privacy and data rights](https://mainsdk.dev/docs/interfaces/privacy)
- [Plausible](https://mainsdk.dev/docs/integrations/plausible) and [PostHog](https://mainsdk.dev/docs/integrations/posthog)
- [Swap a driver](https://mainsdk.dev/docs/guides/swap-a-driver)
