---
name: google-analytics-oauth-app
description: >-
  The Google Analytics (GA4) layer on top of the shared
  `google-cloud-console-oauth` skill — the `analytics.*` scope family and
  which API accepts which member, the Universal Analytics sunset and its
  leftover scopes and endpoints, the Data API / Admin API split, property vs
  measurement vs stream IDs and the call that discovers what a user can see,
  the per-property token quota a multi-tenant reader hits, and the sampling,
  cardinality and thresholding effects that change a report's numbers. Use
  when asked to get Google Analytics OAuth credentials, register or scope a
  GA4 app, decide between `analytics.readonly`, `analytics.edit` and
  `analytics`, explain a GA4 quota or permission failure, or work out why two
  runs of the same report disagree. Read `google-cloud-console-oauth` first
  for the console mechanics; use the relevant product skill for other Google
  products.
---

# Google Analytics (GA4) OAuth2 App Registration

The registration itself is unremarkable: no Analytics scope is restricted, so there is no security assessment and no
permitted-application-type gate. What costs time here is everything *after* the consent screen. Analytics is **two
APIs behind one scope family**, and picking the wrong member of that family gets a token that authorizes half the
product. Its quota is metered **per Analytics property**, so a connector reading a hundred customers hits the ceiling
a hundred separate times and no amount of project-level headroom helps. And the API answers a great many questions
with a `200` that is quietly approximate — sampled, condensed into an `(other)` row, or thresholded away.

This file covers those. Everything about the console is shared.

## Built on: `google-cloud-console-oauth`

**Read `google-cloud-console-oauth` first, then this file.** It owns all the console mechanics, and this file does not
repeat them:

- Choosing/creating the Cloud project and organization, enabling APIs, and who may administer it.
- Configuring the app on the Google Auth Platform (Branding, Audience, Data Access, Clients) and creating a **Web
  application** client — the only type that yields a usable client secret.
- Redirect-URI rules (exact matching, HTTPS-only, propagation delay) and the platform's per-data-center callback list.
- The generic scope model: declaring every scope on Data Access, the non-sensitive / sensitive / restricted tiers, and
  the rule that the app's tier is its most sensitive scope.
- The client secret being shown and downloadable **only once at creation**, add-then-disable rotation, `Testing` vs
  `In production` (including the seven-day refresh-token expiry), the unverified-app screen, the 100-user caps, brand
  and scope verification, and the `access_type=offline` / `prompt=consent` rules for getting a refresh token at all.

If you are reading only this file, you are missing all of the above.

## Inputs to collect before you start

The base skill lists the console inputs. These are the Analytics-specific ones:

| Input | Notes |
| --- | --- |
| **Reporting, configuration, or both?** | Decides which of the two APIs to enable and which scope to request (§1, §3) |
| **Read-only, or does the app change property settings?** | `analytics.readonly` vs `analytics.edit` — not `analytics` for config (§1) |
| **Does the app need to read or change user access?** | A separate scope family member and an alpha-only surface (§1) |
| **How many customer properties, and how often will each be polled?** | Quota is per property; this is the sizing question (§5) |
| **Has anyone specified Universal Analytics endpoints or `UA-` IDs?** | They are gone; the spec needs rewriting before the work starts (§2) |
| **Standard properties or Analytics 360?** | Ten-times quotas and much higher sampling limits (§5, §6) |
| **Will the app join Analytics data to anything else?** | Sampling, `(other)` and thresholding make joins lossy (§6) |

## Quick Start

1. Work the base skill's console steps. **Enable each Analytics API you actually call — they are separate**
   enablements on the same project (§3).
2. Settle the scope down to the exact member of the family, per API and per direction (§1).
3. Check that nothing in the requirements still assumes Universal Analytics endpoints, `UA-` IDs, views, or the legacy
   user-deletion or management APIs (§2).
4. Decide how the app discovers which properties a user can see, and store the right identifier (§4).
5. Size the polling against **per-property** quota before promising a refresh interval (§5).
6. Decide what the app does when a report comes back sampled, condensed or thresholded (§6).
7. Finish the base skill's capture, round-trip and handoff steps, adding the Analytics checks in §8.

## Analytics platform state (verified 2026-09-20 — re-verify before trusting)

- **No Analytics scope appears on Google's restricted-scope list.** There is no CASA security assessment and no
  permitted-application-type gate for Analytics, which is the main way this product is cheaper than Drive or Gmail.
  The `analytics.*` scopes are not identity-only either, so expect the **sensitive**-scope path: app verification with
  a justification per scope and a demo video. Read each scope's tier off the console's Data Access picker rather than
  trusting this line, and expect `External` + `Testing` to bite exactly as the base skill describes.
- **Universal Analytics sunset on 1 July 2024** and its API surface went with it. Standard UA properties stopped
  processing data on 1 July 2023; UA 360 properties with a current order got a one-time extension to 1 July 2024.
- **Reporting and configuration are different APIs**: the Data API (`analyticsdata.googleapis.com`) and the Admin API
  (`analyticsadmin.googleapis.com`), enabled separately, with partly different scopes.
- **Data API quota is charged against the Analytics property**, in tokens, with separate per-property and
  per-project-per-property ceilings, plus concurrency and server-error ceilings.
- **The Admin API's stable surface is v1beta**; access bindings (user management) and user-deletion live in
  **v1alpha**, which Google may change without the usual stability promise.

If the docs do not look like this, stop and report what you actually see.

## 1. The `analytics.*` scope family — and which API accepts which

There is one family, but the two APIs accept different members. This is the single most common way to end up with a
token that authorizes half the product.

| Scope | Accepted by | What it does |
| --- | --- | --- |
| `.../auth/analytics.readonly` | **Both** Data API and Admin API | Read reports; read accounts, properties, data streams, custom dimensions and metrics |
| `.../auth/analytics` | **Data API only** | "View and manage" — but the Data API is a reporting API, so in practice this is `analytics.readonly` with a scarier consent string |
| `.../auth/analytics.edit` | **Admin API only** | Create/patch/delete properties, data streams, custom dimensions, custom metrics, key events; provision accounts; submit user deletions |
| `.../auth/analytics.manage.users` | Admin API **v1alpha** only | Create, update and delete access bindings — who can see the property |
| `.../auth/analytics.manage.users.readonly` | Admin API **v1alpha** only | Read access bindings without being able to change them |

Four traps live in that table:

- **`analytics` is not the superset it reads like.** The Admin API's own method reference lists `analytics.readonly`
  and `analytics.edit` as the acceptable scopes; the broad `analytics` scope is *not* among them. An app that requests
  `analytics` expecting "everything" gets a token that reads reports fine and cannot write a single configuration
  object. If you want configuration writes, the string you need is `analytics.edit`.
- **`analytics.edit` is a write scope that also reads.** Every Admin API read method accepts either `analytics.readonly`
  or `analytics.edit`, so a config-writing app does not need both. Requesting both anyway widens the consent screen and
  the verification review for nothing.
- **User management is a third axis.** Neither `analytics.edit` nor `analytics` grants it: changing who can see a
  property needs `analytics.manage.users`, and even reading the access list needs `analytics.manage.users.readonly`.
  Both are **v1alpha**-only surfaces. Requesting them raises obvious questions in a verification review — a connector
  that only reports on analytics data has no business asking for them.
- **The Data API is read-only in practice.** There is no scope that lets an app write *hits* through these APIs. Data
  goes in through the Measurement Protocol with its own per-stream secret, which is not OAuth and not covered here.

## 2. Universal Analytics: what died, what survives, what to do with a UA-shaped request

**Universal Analytics sunset on 1 July 2024** and this is not a deprecation with a grace period — the properties were
queued for deletion and the data is gone. If a ticket, a customer spec or an older runbook tells you to call the
Analytics Reporting API v4, the Analytics Management API v3 or the User Deletion API v3, the work cannot be done as
written and no OAuth scope changes that.

The timeline, because people quote the wrong date:

| Date | What happened |
| --- | --- |
| March 2023 | Google began auto-creating GA4 properties for un-migrated standard UA properties |
| **1 July 2023** | Standard UA properties **stopped processing hits** |
| **1 July 2024** | **Full shutdown.** Interface *and API* access to current and historical UA data ended for most users; properties queued for deletion; BigQuery backfills could only be *requested* up to 30 June 2024 |

**What survives, and where it hides.** The family did not shrink as cleanly as the product did, which is why this is
worth reading rather than assuming:

- **The scope strings survive, listed under the legacy API.** Google's OAuth scopes page still lists
  `analytics.manage.users`, `analytics.manage.users.readonly`, `analytics.provision` and `analytics.user.deletion`
  under "Google Analytics API, v3" — the dead one. Two of those four were re-homed onto the Admin API's v1alpha access
  bindings (above); the other two were **not**. Account provisioning and user deletion both moved to the Admin API and
  both now take **`analytics.edit`**, so `analytics.provision` and `analytics.user.deletion` are orphans: still
  spelled out on a live Google page, no longer the scope for the job. Requesting one buys a wider consent screen and a
  harder verification conversation in exchange for nothing.
- **The User Deletion API v3 is gone**, replaced by a user-deletion method on the Admin API's v1alpha property
  surface — which is why a privacy/GDPR requirement written before 2024 will name an endpoint that no longer exists.
- **Legacy developer docs answer `200` with a tombstone.** The old UA devguide URLs still resolve, with an HTTP 200
  and a page body that says the documentation is for Universal Analytics and it sunset on 1 July 2024. A link checker
  passes them; a reader following them gets nothing. Do not treat "the docs page loads" as evidence the API exists.
- **Live GA4 docs still point at the dead API.** The Data API's own property-identifier page tells anyone holding a
  `UA-` tracking ID to use the Reporting API v4 instead. That advice has been wrong since July 2024. Google's current
  pages are not uniformly current, and this is the clearest example.

Practically: a `UA-123456-1`-shaped identifier in a requirement is a signal to stop and go back to whoever wrote it.
There is no GA4 property ID derivable from it and no archive to read.

## 3. Two APIs, two enablements

The base skill's rule — enable the APIs the scopes belong to — needs saying concretely here, because "Google
Analytics" is not one API and the scopes do not tell you which one you missed.

| API | Host | What it is for |
| --- | --- | --- |
| **Data API v1** | `analyticsdata.googleapis.com` | Reporting. Standard and pivot reports, batch reports, realtime, funnels, metadata, compatibility checks, audience exports |
| **Admin API v1** | `analyticsadmin.googleapis.com` | Configuration. Accounts, account summaries, properties, data streams, custom dimensions, custom metrics, key events, data-retention settings, access reports, change history |

Enable each one you call, on the same Cloud project, from the console's API library or the Enable button on the
corresponding quickstart page. A correct client with correct scopes against a project where only one is enabled
authorizes cleanly and then fails on the first call to the other — with `accessNotConfigured`, not with anything that
mentions scopes. An app that lists properties *and* reports on them needs both, always.

One client, one consent screen and one declared scope list serve both APIs. The split is about enablement and about
which scope each API accepts (§1), not about registering twice.

## 4. Property IDs, measurement IDs, stream IDs — and discovering what a user can see

Three identifiers, all called "the Analytics ID" by somebody, and only one of them works in an API path.

| Identifier | Looks like | What it is | Use in the APIs |
| --- | --- | --- | --- |
| **Property ID** | `123456789` (numeric) | The GA4 property — the reporting unit | **Yes.** Every Data API call is `properties/<id>:<method>`; every Admin API property call hangs off the same name |
| **Measurement ID** (Google tag ID) | `G-1A2BCD345E` | Identifies a *web data stream* to the tag on the page | **No.** Output-only on the data-stream resource. Not a report target, not convertible to a property ID |
| **Stream ID** | numeric, per data stream | The data stream within a property | Only as a **report dimension** and in data-stream config calls — never as the report target |
| **Firebase app ID** | per app | The linked Firebase app | Only a cross-reference; it can change if the app is deleted and recreated |

A property has many streams, so a measurement ID identifies at most one stream of one property and cannot address the
property at all. Customers hand over `G-…` constantly because it is the one they have seen; treat it as a prompt to go
find the numeric property ID, not as input.

**How a caller discovers which properties a user can see: account summaries.** This is the one call that answers
"what does this token have access to" in a single sweep, and it is the right first call after connecting an account:

- `GET https://analyticsadmin.googleapis.com/v1beta/accountSummaries` returns every account the caller can reach, each
  with summaries of its child properties — property resource name, display name and parent.
- It takes `pageSize` (default 50, **maximum 200**, higher values are silently coerced down) and `pageToken`. Paginate;
  do not assume one page.
- It accepts `analytics.readonly` or `analytics.edit`, so read-only connectors can call it.

**The obvious alternative does not work.** The Admin API's property-listing method takes a **required** filter naming a
parent account, ancestor account or linked Firebase project. There is no "list every property I can see" form of it.
Without an account list first, there is nothing to filter by — which is precisely why account summaries exists and why
a connector that skips it ends up asking customers to type property IDs by hand.

Store the **numeric property ID** as the connection's key, alongside the account it belongs to. Display names change,
measurement IDs belong to streams, and a property can be moved between accounts.

## 5. Quota is per property — so a multi-tenant reader pays per customer

This is the Analytics constraint most likely to break a connector in production, and it is invisible in a single-tenant
test.

**Data API quota is charged in *tokens* against the Analytics property**, not against the Cloud project. Requests fall
into categories — Core (standard, pivot, batch, access reports, metadata, compatibility, audience exports), Realtime,
Funnel and Chat — each with its own bucket. Per-property Core limits, verified 2026-09-20:

| Quota | Standard property | Analytics 360 property |
| --- | --- | --- |
| Core tokens per property per **day** | 200,000 | 2,000,000 |
| Core tokens per property per **hour** | 40,000 | 400,000 |
| Core tokens **per project** per property per hour | 14,000 | 140,000 |
| Core **concurrent requests** per property | 10 | 50 |
| Core **server errors** per project per property per hour | 10 | 50 |

Realtime and Funnel carry the same numbers in their own buckets. Daily quotas reset at midnight Pacific; hourly ones
refresh within the hour but not on the hour boundary.

What follows from "per property", and what people get wrong:

- **Headroom does not pool across customers.** A hundred connected properties do not share one allowance; each one has
  its own, and each one can be exhausted on its own. Conversely, one customer running a heavy backfill cannot starve
  another — the isolation cuts both ways.
- **The per-project-per-property ceiling is the one that binds you.** At 14,000 of the property's 40,000 hourly tokens,
  a single calling project can only ever use about **35%** of a standard property's hourly allowance. Google states the
  arithmetic plainly: a property must be read by **more than three projects** before the property-wide hourly quota can
  be exhausted before the per-project one. For a connector, the practical hourly budget per customer is 14,000 tokens,
  not 40,000 — size the polling interval against that number.
- **Ten concurrent requests per property.** Fanning out a customer's report set in parallel is the easiest way to trip
  this, and it is per property, so per-customer concurrency control is what is needed, not a global worker pool.
- **Server errors have their own quota, and exhausting it blocks you.** Ten 500/503 responses per project per property
  per hour and *all* requests from that project to that property are refused. A tight retry loop against a flapping
  property converts a transient fault into an hour-long outage of your own making. Exponential backoff is not optional.
- **Token cost is not knowable in advance.** It rises with rows requested, number of dimensions and metrics, filter
  complexity, date-range length, dimension cardinality and the property's event volume — so the same query costs more
  against a big customer. The only honest way to know is to send `"returnPropertyQuota": true` and read the quota
  object off the response. Do that from the first day and log it per property; it is the difference between diagnosing
  a quota problem and guessing at one.
- **The non-Data APIs are metered differently.** The Admin API allows 1,200 requests per minute (600 per user) and 600
  writes per minute (180 per user), plus a shared Analytics-wide ceiling of 50,000 requests per project per day and 10
  QPS per IP for everything except the Data API. Property discovery and reporting therefore exhaust on completely
  different axes.
- Exhaustion surfaces as **`429 RESOURCE_EXHAUSTED`** (sometimes `403`), which is not an authorization problem. Do not
  respond to it by re-authorizing the customer.
- Separately, a property allows **120 potentially-thresholded requests per hour** — see §6.

## 6. Sampling, cardinality and thresholding — a `200` that is not the whole answer

Three independent mechanisms make a GA4 report approximate or incomplete, none of which changes the status code. A
connector that ignores all three will produce numbers that do not reconcile with the customer's own UI, and that is
what the support ticket will say.

**Sampling.** When a query needs more events than the property's limit, Analytics reads a subset and scales up.
The event-level query limit is **10 million events for standard properties** and up to **1 billion for Analytics 360**
(360 defaults to 100 million per query for speed, with the higher limit available on request). The response's metadata
carries sampling information **per date range** when — and only when — the result was sampled; the field is absent
otherwise. So the presence of that block is the signal, and the same query can be sampled for one customer and exact
for another purely because of traffic volume.

**Cardinality and the `(other)` row.** When a table needs more rows than its limit, Analytics keeps the most common
dimension values and rolls the rest into a single `(other)` row. Google's guidance: treat **any dimension with more
than 500 distinct values as high-cardinality** — page path and most custom dimensions qualify immediately. Adding
secondary dimensions, filters or comparisons multiplies the row count and makes it far likelier. The response metadata
carries a data-loss flag, and it is populated from the underlying aggregate table **regardless of the filters and
limits in your request** — so it can be true even when no `(other)` row appears in the rows you got back. Treat the
flag, not the visible rows, as the truth.

**Thresholding.** Reports touching demographics, interests, audience membership or search queries withhold rows below a
minimum aggregation threshold, to stop anyone inferring an individual. It is system-defined and cannot be turned off.
The response metadata flags that a report was *subject* to thresholding — which is not the same as data having been
withheld, since everything may have been above the threshold. Widening the date range is the usual mitigation. And
recall the per-property cap of **120 potentially-thresholded requests per hour**, charged on the dimensions that
trigger it.

**A fourth, non-statistical one: data restrictions.** Analytics roles carry optional *No Cost Metrics* and *No Revenue
Metrics* restrictions. A user with them authenticates perfectly, reads the report, and gets it back with those metrics
stripped and a schema-restriction block in the metadata explaining why. It looks exactly like a scope problem and is
not one — it is that user's role.

The design consequence: **read the response metadata on every report and carry it forward**. If the app caches,
aggregates, or presents these numbers as authoritative, sampling and `(other)` must be surfaced to whoever reads them,
because two runs of the same query can legitimately disagree.

## 7. Organization, account and Workspace-level restrictions

The base skill covers the Workspace admin's OAuth API controls. Analytics adds three more places a connection can be
blocked or narrowed, none of which is fixed by re-registering the client:

- **Analytics is an *additional* Google service, not a core Workspace one.** A Workspace administrator can turn it off
  for an organizational unit, and a user in that OU then cannot use Analytics at all — the consent flow is not where
  this surfaces helpfully. When one company's users can connect and another's cannot, ask their admin about additional
  services before touching anything on your side.
- **Analytics has its own permission hierarchy, independent of the Google account.** Roles (Administrator, Editor,
  Analyst, Viewer and a no-access state) are assigned at organization, account and property level, directly or through
  Google Groups, and the *effective* permission is the inherited set plus the direct one. OAuth grants your app the
  user's access — never more. An `analytics.edit` token held by a user who is only an Analyst on a property still
  cannot write to it, and the failure is `403 PERMISSION_DENIED` at call time, not at consent.
- **Data restrictions are assigned alongside roles** (§6) and silently narrow what a perfectly scoped token returns.

None of this is visible from the token, so a connector should verify the account's actual reach with an account-summary
call (§4) immediately after connecting, rather than discovering it on the first report.

## Product fact — what the Analytics connectors ask for

> **As of 2026-09-20, Unified.to ships *two* separate Google Analytics connectors**, against the two APIs in §3:
>
> **The reporting connector** (Google Analytics, added mid-2026) targets the **Data API** host and covers property
> information, events and reports. It requests:
>
> - **Login/identity only:** `openid`, `profile`, `email`
> - **Read:** `https://www.googleapis.com/auth/analytics.readonly`
> - **Write:** `https://www.googleapis.com/auth/analytics.edit`
>
> **The admin connector** (Google Analytics (Admin), added mid-2025) targets the **Admin API** host. It requests:
>
> - **Login/identity only:** `openid`, `profile`, `email`
> - **Read:** `https://www.googleapis.com/auth/analytics.readonly`
> - **Write:** `https://www.googleapis.com/auth/analytics`
>
> Four things to take from that, all dated rather than live:
>
> 1. **Both connectors point at the same Google OAuth endpoints and the same registration guidance**, so a single Cloud
>    project and a single Web application client can serve both. **Both Analytics APIs must be enabled on it** (§3).
> 2. **The admin connector's write scope looks wrong against Google's current reference.** Admin API write methods
>    document `analytics.edit` as the required scope, and `analytics` is not listed as acceptable for Admin API
>    methods at all. If configuration writes through that connector fail with a permission error on a token that
>    consented cleanly, this is the first thing to check — and it is a connector-side question, not something a
>    different client registration fixes.
> 3. **Neither connector requests `analytics.manage.users*`**, so user-access management is out of scope for both as
>    shipped — which is the right default, and one less thing to justify in a verification review.
> 4. Both are configured to send `access_type` and `prompt` on the authorize request, which is what makes the base
>    skill's offline/refresh-token rules work; confirm the deployed values rather than assuming.
>
> Scope sets change. This note is dated, not live; **confirm with the connector's owner before submitting anything**,
> and in particular confirm which of the two connectors a given customer is being onboarded to.

## 8. Analytics-specific end-to-end checks

On top of the base skill's authorize → refresh round trip:

1. Call **account summaries** first and confirm it returns at least one account with at least one property. An empty
   list is a real and common outcome: the Google account authenticated fine and simply has no Analytics access.
2. Run one real report against a numeric property ID from that list, with **`"returnPropertyQuota": true`**, and log
   the token cost. Do this against the biggest property you can reach, not a test property with no traffic.
3. Inspect the response **metadata** on that report for sampling, the data-loss/`(other)` flag, thresholding and any
   schema restriction — before concluding the numbers are right (§6).
4. If the app writes configuration, make one real Admin API write. This is the check that catches an `analytics` scope
   where `analytics.edit` was needed (§1), and it fails at call time, never at consent.
5. Test with a **non-administrator** Analytics user — an Analyst, ideally one carrying a data restriction. Testing only
   as the account owner proves nothing about what customers will see.
6. Confirm both APIs are enabled by calling **both** in the same run.
7. Confirm the granted `scope` in the token response matches what was requested; granular consent lets a user drop one.

| Symptom | Cause |
| --- | --- |
| Reports work, configuration writes get `403` | `analytics` requested where the Admin API wants `analytics.edit` (§1) |
| `403 accessNotConfigured` on one API only | That API not enabled on the project — they are separate enablements (§3) |
| `403 PERMISSION_DENIED` on a property, token looks perfect | The Analytics user's own role does not reach that property (§7) |
| Cost or revenue metrics missing, everything else fine | A data restriction on that user's role, not a scope problem (§6) |
| One customer's whole org cannot connect | Analytics turned off for their OU as an additional Google service (§7) |
| `429 RESOURCE_EXHAUSTED` on a busy customer while others are fine | Per-property token quota, likely the per-project-per-property hourly ceiling (§5) |
| Every request to one property refused for an hour | Server-error quota exhausted by retrying into a failing property (§5) |
| Numbers disagree with the customer's Analytics UI | Sampling, `(other)` condensation, or thresholding — check response metadata (§6) |
| The same query is exact for one customer and sampled for another | Event volume against the per-query sampling limit (§6) |
| A caller supplies `G-…` and nothing accepts it | Measurement ID identifies a stream, not a property (§4) |
| A requirement names Reporting API v4 or Management API v3 | Universal Analytics; sunset 1 July 2024 (§2) |
| A legacy docs URL loads fine but the API 404s | UA devguide tombstone pages return HTTP 200 (§2) |

## Stop and ask

Beyond the base skill's list, hand back to a human when:

- A requirement depends on **Universal Analytics data or endpoints** (§2). That is a scope change for the project, not
  a console setting, and the historical data no longer exists.
- Someone wants **`analytics.manage.users`** or its read-only twin. Changing who can see a customer's Analytics
  property is a product decision with an obvious verification conversation attached, and it is an **alpha** surface.
- A polling interval or customer count has been promised without anyone checking it against **per-property** quota
  (§5) — the number that binds is the per-project-per-property hourly one, and it is about a third of the headline.
- The app will present GA4 numbers as authoritative (billing, SLAs, reconciliation) without handling **sampling,
  `(other)` and thresholding** (§6).
- The deployed connector's scope set does not match the **Product fact** section — confirm with its owner rather than
  registering around it.
- The scope-to-API mapping in §1 does not match Google's current method reference.

## References

Analytics-specific only; the base skill carries the generic Google OAuth references. Every URL verified to return 200
on 2026-09-20. Legacy Universal Analytics devguide URLs are deliberately **not** listed: they return 200 with a
sunset notice rather than documentation (§2).

- Data API v1 overview — https://developers.google.com/analytics/devguides/reporting/data/v1
- Data API limits and quotas (token model, per-property ceilings, `returnPropertyQuota`) — https://developers.google.com/analytics/devguides/reporting/data/v1/quotas
- Data API property ID (and its stale UA advice) — https://developers.google.com/analytics/devguides/reporting/data/v1/property-id
- Data API response metadata (sampling, `(other)`, thresholding, schema restrictions) — https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/ResponseMetaData
- Data API `runReport` (authorization scopes) — https://developers.google.com/analytics/devguides/reporting/data/v1/rest/v1beta/properties/runReport
- Data API error responses — https://developers.google.com/analytics/devguides/reporting/data/v1/errors
- Data API quickstart / enable the Data API — https://developers.google.com/analytics/devguides/reporting/data/v1/quickstart-client-libraries
- Admin API REST reference — https://developers.google.com/analytics/devguides/config/admin/v1/rest
- Admin API `accountSummaries.list` (property discovery, page size 200) — https://developers.google.com/analytics/devguides/config/admin/v1/rest/v1beta/accountSummaries/list
- Admin API `properties.list` (the required filter) — https://developers.google.com/analytics/devguides/config/admin/v1/rest/v1beta/properties/list
- Admin API data streams (measurement ID is output-only) — https://developers.google.com/analytics/devguides/config/admin/v1/rest/v1beta/properties.dataStreams
- Admin API `properties.create` (`analytics.edit` required) — https://developers.google.com/analytics/devguides/config/admin/v1/rest/v1beta/properties/create
- Admin API access bindings, v1alpha (`analytics.manage.users`) — https://developers.google.com/analytics/devguides/config/admin/v1/rest/v1alpha/accounts.accessBindings/list
- Admin API user deletion, v1alpha (replaces the sunset User Deletion API) — https://developers.google.com/analytics/devguides/config/admin/v1/rest/v1alpha/properties/submitUserDeletion
- Admin API limits and quotas — https://developers.google.com/analytics/devguides/config/admin/v1/quotas
- Admin API quickstart / enable the Admin API — https://developers.google.com/analytics/devguides/config/admin/v1/quickstart-client-libraries
- Shared Google Analytics API limits and quotas — https://developers.google.com/analytics/devguides/limits-and-quotas
- User Deletion API v3 migration notice — https://developers.google.com/analytics/devguides/config/userdeletion/v3
- GA4 has replaced Universal Analytics (sunset timeline) — https://support.google.com/analytics/answer/11583528
- About data sampling (10M / 1B event limits) — https://support.google.com/analytics/answer/13331292
- About the `(other)` row (cardinality guidance) — https://support.google.com/analytics/answer/13208658
- About data thresholds — https://support.google.com/analytics/answer/9383630
- Access and data-restriction management (roles, No Cost / No Revenue Metrics) — https://support.google.com/analytics/answer/10851388
- Add, edit and delete Analytics users and user groups — https://support.google.com/analytics/answer/9305788
- Stream ID — https://support.google.com/analytics/answer/12332343
- Find your Google tag ID (the `G-` measurement ID) — https://support.google.com/analytics/answer/9539598
- Turn additional Google services on or off (Analytics is one) — https://support.google.com/a/answer/181865
