{
 "id": "18.3",
 "title": "Google",
 "department": "Integrations and ecosystem",
 "department_slug": "integrations-and-ecosystem",
 "direction": null,
 "branded": false,
 "status": "draft",
 "owner": "Param",
 "last_verified": "2026-10-26",
 "holds": "OAuth verification, scopes, Ads and GA4 access",
 "urls": {
  "html": "https://handbook.joinsquareup.com/integrations-and-ecosystem/google",
  "markdown": "https://handbook.joinsquareup.com/integrations-and-ecosystem/google.md",
  "json": "https://handbook.joinsquareup.com/integrations-and-ecosystem/google.json"
 },
 "other_directions": [],
 "tldr": {
  "headline": "Google is done: verified 21 Oct for Ads and Analytics, read only",
  "points": [
   {
    "icon": "check",
    "text": "The OAuth app was verified after two rejections, and the warning is gone."
   },
   {
    "icon": "lock",
    "text": "Only two sensitive scopes, so any new scope re-opens review."
   },
   {
    "icon": "link",
    "text": "Brands connect by one-click sign in, or GA4 by property ID with a Viewer."
   },
   {
    "icon": "warn",
    "text": "Two past rejections came from stray scopes: never add include_granted_scopes back."
   },
   {
    "icon": "clock",
    "text": "Whether Ads Basic access came through is not recorded since 16 Oct."
   }
  ],
  "stat": {
   "value": "2",
   "label": "sensitive scopes verified"
  },
  "decide": "Did Ads Basic access come through?",
  "mood": "solid"
 },
 "sources": [
  "brew origin/main: connectors/google.js:1-35, 95-110; docs/connectors-approvals.md:10, 19-24; tools/prod-env.sh:9; deploy.sh:41; docs/production.md:119-121",
  "memory brew-google-oauth-scopes, brew-real-connectors, treg-catalog-for-brew",
  "handbook content/engineering/connectors.md, read for consistency"
 ],
 "open_questions": [
  "**Did Ads Basic access come through?** No source after 16 Oct. Proposal: Param checks the API Center today; until then the developer token keeps reading as it does.",
  "**Search Console as a connector.** Treg's catalog lists it as connected and free, but no Brew connector reads it [src: memory treg-catalog-for-brew]. Proposal: add it in v2 together with any other new scope, in one review.",
  "**One project for Brew and the old cockpit.** Proposal: keep sharing it, because the developer token is tied to this project, and retire the cockpit's Google connect instead."
 ],
 "parts": {
  "Answer": "Google is the one platform where Brew's approval is done: the OAuth app for project squareup-492617 was verified on 21 October 2026 for exactly two sensitive scopes, Ads and Analytics read only, and the rule is that any new scope re-opens review, so none is added without a reason Param accepts.",
  "Today": "### The project and the clients\n\n| Fact | Value | Source |\n|---|---|---|\n| Project | squareup-492617, shared by Brew and the old SquareUp cockpit | [src: memory brew-google-oauth-scopes] |\n| Brew's connect client | \"SquareUp Ads API Ingestion\", 223432117369-g6k9… | [src: memory brew-google-oauth-scopes] |\n| Local MCP client | \"Claude MCP\" Desktop client 223432117369-ot3d…, behind `~/.config/google-mcp/adc.json`, re-minted with Ads and Analytics only | [src: memory brew-google-oauth-scopes] |\n| Developer token | `GOOGLE_ADS_DEVELOPER_TOKEN`, tied to this one project; it reads real accounts already | [src: brew/connectors/google.js:17] [src: brew/docs/connectors-approvals.md:22-24] |\n| Ads API version | `GOOGLE_ADS_API_VERSION`, default v26; v21 was retired and answered 404 | [src: brew/connectors/google.js:14-16] |\n| Callbacks | `/auth/google/callback` and `/connect/<id>/callback` on both sites | [src: brew/docs/production.md:119-121] |\n\n### Scopes\n\n| Scope | Why | Source |\n|---|---|---|\n| openid, email, profile | Sign in | [src: memory brew-google-oauth-scopes] |\n| `adwords` | Google Ads read through GAQL searchStream | [src: brew/connectors/google.js:1-3, 18] |\n| `analytics.readonly` | GA4 through the Data API runReport | [src: brew/connectors/google.js:3, 18] |\n\nThe five old cockpit scopes, calendar, events, Meet, Drive and Gmail, are not Brew's and were removed from the consent screen [src: memory brew-google-oauth-scopes].\n\n### Verification history\n\n| Date | What happened | Source |\n|---|---|---|\n| 16 Oct | Verification and Ads Basic access submitted; `GOOGLE_OAUTH=1` on, with the unverified warning and a 100 user cap | [src: memory brew-real-connectors] [src: brew/docs/connectors-approvals.md:19-23] |\n| 19 Oct | Rejected: `cloud-platform` requested but not configured; cause was the local MCP client minted by `gcloud auth application-default login`; re-minted | [src: memory brew-google-oauth-scopes] |\n| 21 Oct | Rejected again: the consent screen showed a third line; cause was `include_granted_scopes=true` in google.js, removed in 1afb9ba | [src: memory brew-google-oauth-scopes] |\n| 21 Oct evening | Verified: branding and data access, `adwords` and `analytics.readonly`; the unverified warning is gone | [src: memory brew-google-oauth-scopes] |\n\nAds Basic access was applied for on 16 Oct; no source records Google's answer [src: memory brew-real-connectors].\n\n### How a brand connects\n\n| Route | Review needed | Source |\n|---|---|---|\n| One-click Google sign in for Ads and GA4, `GOOGLE_OAUTH=1` on both sites | Done, verified | [src: brew/tools/prod-env.sh:9] [src: brew/deploy.sh:41] |\n| GA4 by property ID, with `brew-runtime@squareup-492617.iam.gserviceaccount.com` added as Viewer | None | [src: brew/docs/connectors-approvals.md:10] [src: brew/connectors/google.js:5-6] |\n| A manager account: the ad accounts under it are listed and read through the manager | Done, same sign in | [src: brew/connectors/google.js:104-108] |\n\nA GA4 property used by another brand, or whose web stream is not the brand's site, is refused unless staff override [src: handbook engineering/connectors]. Google Ads is read every 6 hours, GA4 every 6 [src: handbook engineering/connectors].",
  "Tomorrow": "| Item | Version | Tag |\n|---|---|---|\n| `adwords` and `analytics.readonly`, read only | v1 | Stays |\n| Search Console read for the brand's own search terms | v2 | New, adds a scope and a review |\n| Google Merchant Center read | v3 | New, adds a scope and a review |\n| Ads changes such as pausing or budgets | v4 | Changes the use of `adwords`, needs a new justification and a person's yes per action |\n\nThe v2 to v4 rows are proposals for Param, not decisions.",
  "How we do it": "1. Never re-run `gcloud auth application-default login` with the Claude MCP client: it adds `cloud-platform` and brings the discrepancy back [src: memory brew-google-oauth-scopes].\n2. Never add `include_granted_scopes` back to google.js [src: memory brew-google-oauth-scopes].\n3. Before adding any scope, write the reason in this document's Open part and wait for Param's yes; then record a new demo video whose consent screen shows exactly the permission lines asked for [src: memory brew-google-oauth-scopes].\n4. When Google sends an Ads API sunset email, bump the version and redeploy:\n\n```bash\nGOOGLE_ADS_API_VERSION=v27 ./deploy.sh   # the number from Google's email\n```\n\n[src: brew/connectors/google.js:14-16]\n\n5. To re-record a consent video, first remove SquareUp at myaccount.google.com/connections for the recording account [src: memory brew-google-oauth-scopes].",
  "Numbers": "| Metric | Definition | Where measured |\n|---|---|---|\n| Scopes on the consent screen | Count of scopes in Data Access, target 5 | Google Auth Platform, Proposed |\n| Live Google connections | Google Ads and GA4 connections in state live | `connections` on production, Proposed |\n| Ads reads failing | Google Ads reads that fail in a day | Server log `[google]`, Proposed |",
  "Open": "1. **Did Ads Basic access come through?** No source after 16 Oct. Proposal: Param checks the API Center today; until then the developer token keeps reading as it does.\n2. **Search Console as a connector.** Treg's catalog lists it as connected and free, but no Brew connector reads it [src: memory treg-catalog-for-brew]. Proposal: add it in v2 together with any other new scope, in one review.\n3. **One project for Brew and the old cockpit.** Proposal: keep sharing it, because the developer token is tied to this project, and retire the cockpit's Google connect instead."
 }
}