Learn · Setup guides

Connect Google Analytics GA4 to Outloop

Last updated:

In short

Google Analytics GA4 uses OAuth, not an API key.

You enable the GA4 Admin and Data APIs, create one Google Cloud OAuth client, and exchange it for a refresh token. Outloop stores the OAuth credential locally in macOS Keychain, pins it to the numeric GA4 Property ID, and lets agents use it only through the API Bridge — minting short-lived access tokens host-side, so the agent never sees the Google token.

Summarize this setup guide with AI ChatGPTClaudePerplexity

What this setup gives you

You will enable the GA4 APIs in Google Cloud, create a Google OAuth client, generate a refresh token, copy the numeric GA4 Property ID into Outloop, and run a first proof through your agent. Outloop stores the credential locally and uses it through the API Bridge — the agent never sees the Google refresh token or access token.

Security rule. Never record, screenshot, paste, or publish a real client_secret, refresh_token, access_token, Authorization header, or Bearer token. Their only destination is the Outloop Mac app — never Outloop Cloud, the website, chat, docs, or .env files.

What you need before starting

Which Google account connects what

Three separate identities — keep them apart

Most failed Google Analytics GA4 setups are one confusion: assuming the Google account that manages the Cloud project is also the account that can open the client's GA4 property. It does not have to be, and often should not be.

  1. 1

    The Google Cloud project and OAuth app

    This owns the Client ID and Client Secret. It can belong to your agency or to your client — Outloop does not care which, and cannot tell the difference.

    cloud-admin@agency.example — manages the Google Cloud project

  2. 2

    The connected Google account

    This is the account you pick in Google's own chooser during the browser sign-in. It is the account that must actually own or be able to open the client's GA4 property.

    data-owner@client.example — is chosen at sign-in because it owns the client's GA4 property

  3. 3

    Outloop workspace access

    This decides which workspace may use the stored credential, which resources it may reach, and which capabilities agents get. It is set in the Access Profile, after the sign-in succeeds.

In that example, cloud-admin@agency.example created the OAuth app once, and every connector after it reuses that app — but the account you actually sign in as is data-owner@client.example, because that is the identity Google Analytics GA4 will check when an agent asks for a file.

The connected account still has to be allowed in. Four things can block it, and all four are set on the OAuth app, not in Outloop:
  • If the app's audience is External and it is still in Testing, the account must be added as a Test user first.
  • If the audience is Internal, only accounts inside that Google Workspace organisation can sign in at all.
  • The Google Analytics Data API must be enabled in the Google Cloud project the app belongs to.
  • The account must genuinely have access to the client's GA4 property. A successful sign-in proves identity, not reach.

1. Enable the two GA4 APIs

In Google Cloud Console, open APIs & Services → Library, search Google Analytics Admin API, and click Enable. This is the configuration API (account and property summaries).

Google Cloud product details page for the Google Analytics Admin API with the Enable button highlighted.

Go back to the Library, search Google Analytics Data API, and click Enable. This is the report-data API.

Google Cloud product details page for the Google Analytics Data API with the Enable button highlighted.

2. Create an OAuth client (once, for all Google connectors)

In Google Auth Platform → Clients, create a new OAuth client. Choose Application type: Web application, name it Outloop GA4 OAuth, leave Authorized JavaScript origins empty, and under Authorized redirect URIs add the OAuth Playground URL:

https://developers.google.com/oauthplayground
Create OAuth client ID form named Outloop GA4 OAuth with the OAuth Playground redirect URI added.

Click Create, then copy the Client ID and Client secret from the dialog.

OAuth client created dialog in Google Cloud with the client ID and client secret redacted.
Important. You will not be able to view the client secret again after closing this dialog — copy it now and store it securely. Do not screenshot or publish the secret.

3. Find the numeric GA4 Property ID

Outloop needs the numeric Property ID — not the G-… Measurement ID. In Google Analytics, open Admin → Property details. The numeric PROPERTY ID is at the top right — click the copy icon to copy it.

Google Analytics Admin Property details page with the numeric PROPERTY ID and copy icon at the top right (value redacted).
Correct (numeric Property ID):  540642806
Wrong (Measurement ID):         G-XXXXXXXXXX
Do not use the Measurement ID. If you are in Data streams → Web stream details you will see a G-… Measurement ID — that belongs to the web stream tag, not the API. Go to Property details and copy the numeric Property ID instead.
GA4 Web stream details screen showing the G- Measurement ID that should not be used as the Property ID.

4. Add Google Analytics GA4 in Outloop

In Outloop, open API Access → Add an API key and choose Google Analytics GA4. Use Agency-global / shared when the same Google user can access multiple GA4 properties and you want to grant workspaces over time — tick the workspace that should use it. Outloop still pins runtime use to the specific numeric GA4 Property ID you enter.

You only enter the Google OAuth app once

The first Google connector you set up asks for the Client ID and Client Secret from your Google Cloud OAuth client. Tick save as my default Google OAuth app and every later Google connector — Gmail, Drive, Sheets, Search Console and Google Ads — picks it from the Google OAuth app dropdown with no Client Secret to re-enter. When a saved profile supplies the app, Outloop shows “Using <client-id> — no Client Secret needed. This connector still signs in separately and gets its own access.”

Reusing the app does not mean sharing one login. Each connector still opens its own browser sign-in and gets its own refresh token, its own scopes and its own connected account — so you can revoke or re-authenticate one connector without touching the others.

Shared agency app or workspace-dedicated?

Which setup should I choose?

There are two reasonable answers for Google Analytics GA4, and the right one depends on who owns the Google Cloud infrastructure — not on how many clients you have.

Agency-global (shared OAuth app)

One OAuth app your agency owns, reused by every Google connector you add. This is the default and the right choice for most agencies.

  • Client ID and Client Secret entered once, then picked from a dropdown.
  • Every connector still runs its own Google sign-in.
  • Each one gets its own scopes, its own refresh token, its own connected account and its own revocation.
  • Reusing the app grants no data access by itself — workspace grants and Access Profiles stay explicit.

Workspace-dedicated

A separate OAuth client — or a separate Google Cloud project — for one workspace or one client.

  • The client owns the Google Cloud infrastructure and wants to keep owning it.
  • They need stronger administrative separation, or their own consent branding and audience rules.
  • They want separate quotas and their own lifecycle control.
  • The client owns the GA4 property and their analytics lead wants the OAuth app inside their own Google Cloud project.

A separate Google Cloud project is the strongest operational separation. A separate OAuth client inside the same project is lighter separation — useful, but the project is still shared.

Outloop cannot verify which you chose. It sees a Client ID and a Client Secret. It has no way to infer — and no way to enforce — how you organised your Google Cloud projects. If the separation matters to a client contract, it has to be real on the Google side; Outloop enforces the workspace boundary, not the Cloud-project boundary.
Sharing a stored credential is a third, different thing. Reusing the OAuth app is not the same as granting one stored Google Analytics GA4 credential to several workspaces. You can do the latter deliberately — but then replacing that credential affects every workspace assigned to it. When Outloop says a credential will be stored in the shared slot and replaces whatever is already there, read that line before you continue, not after. Granting the app to a workspace does not automatically grant it data access either — that is still the Access Profile's job.

5. Connect the account in your browser

The panel opens on Connect in your browser, with the Cloud Console detail tucked into the collapsed Setup details — Google Cloud OAuth client, scopes and caveats and Before you connect disclosures. Under Access to request from Google, pick the level agents should have — the full option is preselected with (recommended) in its label, and read-only is offered but never preselected. Check the Google OAuth app dropdown; a saved profile supplies the app with no Client Secret to re-enter.

Read the storage line before you continue. Where Outloop says the credential will be stored in the SHARED slot, it also warns that it replaces whatever is already there. If another workspace relies on that slot, change the scope before connecting rather than after.

Click Connect Google Analytics GA4 in your browser. Google's own sign-in opens, you sign in with the account that can read the property, and you approve the consent screen there. Outloop mints and stores the refresh token host-side — nothing to copy, nothing on your clipboard.

6. Confirm the account and capabilities

Outloop shows Connected as the Google account you used — check it before an agent pulls a client report. Under Agents will be able to (change any time in the Access profile), practical capabilities are pre-checked and destructive ones are prefixed and left unchecked. Click Confirm — this is the approved account.

macOS Keychain. macOS may ask permission to let Outloop read the stored credential from Keychain — click Always Allow. This is local Keychain access; the credential is not uploaded to Outloop Cloud.

7. View the stored key

OAuth is not the finish line — the Access Profile is

When Google Analytics GA4 hands you back to Outloop, the connector is authenticated but not yet authorized. Agents cannot use it until you make the authorization decision yourself:

  1. OAuth connected
  2. Confirm the account
  3. Open the Access Profile
  4. Approve the GA4 Property ID
  5. Choose capabilities
  6. Save the Access Profile
  7. Copy the proof prompt

In the Access Profile you set two things. Reach — the one approved entry under Property ID that this workspace may use. And capabilities — what agents may actually do inside it, with anything destructive left off unless you turn it on.

“Copy workspace run prompt” does not become available until you save. If it looks inactive, nothing is broken — the Access Profile has not been saved yet. Open the Access Profile, make the two choices below, and click Save Access Profile; the run prompt becomes available once the authorization is recorded.
The capability set is never chosen for you. Outloop enables nothing on your behalf and this guide recommends no shortcut. What agents may do in a client's Google Analytics GA4 account is an authorization decision that belongs to you — grant the narrowest set the work actually needs.

Outloop confirms the credential is stored in macOS Keychain with secret_exposed: false. Click View in stored keys to open the key row and copy the workspace run prompt.

Outloop confirmation that the Google Analytics GA4 credential was stored locally, with View in stored keys highlighted.

8. Run the first proof

Paste the workspace run prompt into your agent. The first proof verifies GA4 access through Outloop with a read of your account and property summaries:

GET /v1beta/accountSummaries

A successful, verified Outloop proof looks like this:

decision / code: allow / OK
HTTP status: 200
service: google_analytics
secret_exposed: false
GA identity: accountSummaries[].propertySummaries[].property = properties/PROPERTY_ID
runtime-verified: yes
Outloop Google Analytics GA4 runtime proof showing allow, OK, HTTP 200, service google_analytics, and secret_exposed false.

The setup is complete when the proof shows runtime-verified: yes and secret_exposed: false. Your agent can now use Google Analytics GA4 through Outloop; the Google OAuth credential stays in macOS Keychain, and the agent never sees the refresh token or access token.

Advanced — manual refresh token

Skip this if the browser connect worked. It stays documented because it still works, and because some teams prefer to mint the refresh token themselves. In the Outloop panel it sits behind the collapsed Advanced — manual refresh token disclosure.

Get a refresh token from the OAuth Playground

Open developers.google.com/oauthplayground, click the gear icon, and set: OAuth flow Server-side, Access type Offline, Force prompt Consent Screen, and check Use your own OAuth credentials. Paste the Client ID and Client secret (do not screenshot the pasted secret).

Google OAuth Playground configuration with Server-side flow, Offline access, and Consent Screen prompt. Google OAuth Playground with Use your own OAuth credentials enabled and empty client ID and secret fields.

In Step 1, paste the Analytics scopes into Input your own scopes and click Authorize APIs:

https://www.googleapis.com/auth/analytics.readonly   (read-only, recommended for the first proof)

# or, for approved GA4 Admin writes:
https://www.googleapis.com/auth/analytics.edit
https://www.googleapis.com/auth/analytics
Scope note. Read-only is recommended for the first proof. Use analytics.edit + analytics only if you want approved GA4 Admin write actions. Outloop still keeps deletes and Measurement Protocol blocked by runtime policy.

After approving the Google consent screen, OAuth Playground returns to Step 2. Click Exchange authorization code for tokens and copy the refresh_token (do not screenshot or publish it).

OAuth Playground Exchange authorization code for tokens step with the token values redacted.

Paste the values into Outloop

Paste the values you collected, then click Save pasted refresh token:

Outloop Google Analytics GA4 OAuth setup form with the client ID and Property ID redacted and the client secret and refresh token masked.
macOS Keychain. macOS may ask permission to let Outloop read the stored credential from Keychain — click Always Allow. This is local Keychain access; the credential is not uploaded to Outloop Cloud.

Changing the account or the credential later

Changing the account or the credential later

Three controls on the Google Analytics GA4 connector look similar and do different things. Picking the wrong one is the most common way a working connector gets broken on purpose.

Re-authenticate

Reuses the OAuth app you already selected and refreshes the authorization for the account that is already connected.

When: Use it when the refresh token expired or was revoked and you want the same account back.

Safety: It must not quietly become an account switch. If Outloop finds a different account at the other end, it reports the mismatch and keeps the previous token.

Connect as a different Google account

Keeps the same Client ID and Client Secret and opens Google's account chooser so you can pick another identity.

When: Use it when the wrong account was connected, or when the client moved the data to a different Google account.

Safety: The stored token is replaced only after Outloop positively verifies that the newly connected identity is the one you intended. A mismatch, a missing identity, a failed verification or a cancelled sign-in all leave the previous credential exactly as it was.

Replace the full credential

Swaps the OAuth app itself — a different Google Cloud project, Client ID or Client Secret.

When: Use it when the OAuth app is changing hands, or a client is moving the connector onto their own Cloud project.

Safety: This is not the same as choosing another Google data account. Confirm with "Sign in and replace" only when you actually mean to change the app.

Disconnecting does not delete your saved OAuth app. Removing a Google Analytics GA4 service credential clears that credential — but the saved Google OAuth app profile is a separate, reusable object and stays. So when you reconnect, Outloop may never ask for the Client ID and Client Secret again. That is the reuse working as designed, not evidence that a stale credential was silently kept. To use a different app, pick another saved profile from the Google OAuth app dropdown, or create a new one and save it alongside the existing one.

Verified vs not claimed yet

GA4 API through Outloop vs the Google Analytics MCP

Google publishes a Google Analytics MCP server and titles it Experimental — Google's own word, not ours. It covers both the Admin API and the Data API, including run_report, and it is read-only: its credentials use the analytics.readonly scope. For an analyst exploring one account conversationally, that is a genuinely useful tool.

The difference that matters for agency work is scope. The MCP server reaches whatever the credential you configure can reach, and Google's setup guidance is simply to make sure that credential "has access to your Google Analytics accounts or properties." One agency login usually reaches every client property at once. Outloop narrows it deliberately: the workspace is pinned to one numeric Property ID, so a report request cannot quietly resolve to a different client. The MCP server exposes the capability; Outloop decides which client's property it may be used on.

API bridge: Live now Read proof verified here Audited Secret-safe Property-pinned
MCP: Official MCP exists Experimental (Google's label) Read-only Not connected here
Google Analytics MCP facts are from Google's own repository, checked 14 August 2026. Only the Outloop read proof is marked verified — it is the one call actually run and audited here.
Dimension GA4 API through OutloopGoogle Analytics MCP (official)
Status here Read proof verified accountSummaries returned HTTP 200, decision allow, audited, secret_exposed:false. Not connected here Published by Google and titled Experimental; not connected or tested in this workspace.
Credential handling Never seen by the agent Client secret and refresh token stay in the macOS Keychain; access tokens minted host-side. Local server config Runs locally against Application Default Credentials you configure.
Which client property is used Pinned per workspace Workspace is pinned to one numeric GA4 Property ID. Whatever the credential reaches Bounded by the configured credential’s Google Analytics access; no per-workspace pinning.
Write operations Permitted under policy Admin writes allowed under the wider analytics.edit scope when authorized; not runtime-verified here. Read-only Uses the analytics.readonly scope.
Audit trail Local audit log Every request written locally with decision, HTTP status, and secret_exposed:false. Not per-workspace No local per-client audit of which property an agent queried.
Important: this comparison is intentionally conservative and is not a claim that APIs beat MCP. The Google Analytics MCP server is official and useful for read-only analysis; it is simply not connected in this workspace, so nothing in its column is marked verified. Facts checked against Google's repository on 14 August 2026; re-check before relying on them.

Troubleshooting

Google shows an account chooser

Expected. Outloop asks Google for the chooser on purpose, so a sign-in can never silently reuse whichever account your browser happened to be logged into. Pick the account that owns or can open the client's GA4 property — which is often not the account that manages the Google Cloud project.

“Google hasn’t verified this app”

This appears because the OAuth app is your own and has not been through Google's verification. If it is your app and you trust it, expand Advanced and continue. If you do not know who owns the app, stop — that warning is doing its job, and clicking past an unknown app is not a routine step.

Which audience the app uses decides who can get that far at all. An External app in Testing only admits accounts added as Test users. An Internal app only admits accounts inside its Google Workspace organisation. For customer-facing production use, complete Google's verification rather than living in Testing.

The wrong Google account got connected

Use Connect as a different Google account on the connector. It keeps the same Client ID and Client Secret and reopens Google's chooser. The stored token is only replaced once Outloop verifies the new identity is the intended one — if it does not match, Outloop reports the mismatch and keeps the previous credential. Nothing is lost by trying.

A credential that works but sits on the wrong account is deliberately not marked runtime-verified for that workspace. Working and correct are different things.

BACKEND_AUTH_FAILED during connect

Google rejected the sign-in, so the new credential failed Outloop's safe verification. The important part: the previous credential is unchanged. Do not delete the connector, the OAuth app or the workspace as a first move. Check, in this order — that you signed in as the account that can reach the client's GA4 property; that the account is admitted by the app's audience (a Test user on an External+Testing app); and that the API is enabled in the right Cloud project. Then try the connect again.

Reconnecting never asked for the Client ID and Secret

Expected. Disconnecting a Google Analytics GA4 credential does not delete your saved Google OAuth app profile — that is a separate object, kept on purpose so later connectors do not re-enter a Client Secret. Outloop reused it. If you specifically want a different app, pick another saved profile from the Google OAuth app dropdown, or create a new one and save it alongside. This is reuse working, not a stale credential silently retained.

“Copy workspace run prompt” is not available

The Access Profile has not been saved yet. Open the Access Profile, choose the reach and the capabilities, and click Save Access Profile — the run prompt becomes available once the authorization is recorded. OAuth succeeding is not the same as the workspace being authorized, and this is the step that closes the gap.

The connection stops working after about a week

If the OAuth app's audience is External and its publishing status is still Testing, Google expires refresh tokens for that app after roughly seven days. Two honest options: publish the app to In production, or use an Internal audience if everyone signing in is inside your Google Workspace organisation. Publishing may require Google's verification review depending on the scopes the app requests — that is Google's process and its outcome and timing are not ours to promise.

I pasted a value that starts with G-

That is the Measurement ID, not the GA4 Property ID. Go to Admin → Property details and copy the numeric Property ID (e.g. 540642806).

I do not see a refresh token

In the OAuth Playground, confirm Use your own OAuth credentials is checked, Access type is Offline, Force prompt is Consent Screen, and the redirect URI in Google Cloud is exactly https://developers.google.com/oauthplayground. Then authorize again.

The proof returns 403

Usually the Google user who created the refresh token does not have access to that GA4 property, or the wrong OAuth scope was authorized. Confirm the user's GA4 access and that the scope in Outloop matches the scope you authorized in the OAuth Playground.

The proof shows a config issue

Check that both the Admin API and the Data API are enabled, the client ID and secret are correct, the refresh token is pasted, the Property ID is numeric, and the scope in Outloop matches the scope authorized in the OAuth Playground.

Adding another GA4 property

Reuse the same Google Cloud project and OAuth client if the same Google user has access. In Outloop, add another Google Analytics GA4 entry or assign the shared connector to the right workspace, and always pin the correct numeric GA4 Property ID.

Rotate or revoke access

Official Google documentation

Outloop is available with guided onboarding for agency teams. Outloop is an independent tool and is not affiliated with or endorsed by Google. See the security model, the Google Search Console setup guide, or the Google Ads API setup guide.

Summarize this setup guide with AI ChatGPTClaudePerplexity

Once the read proof succeeds, your agent can use Google Analytics GA4 through Outloop — without seeing the OAuth token.

Outloop is available with guided onboarding for AI agencies, operators, and dev shops.

Frequently Asked Questions

Google Analytics GA4 API + Outloop — FAQ