---
id: "18.2"
title: "Meta"
dept: integrations-and-ecosystem
status: draft
owner: Param
branded: false
last_verified: 2026-10-26
sources:
  - "brew origin/main: connectors/meta.js:1-26, 90, 130; docs/connectors-approvals.md:25-29, 38-47; tools/prod-env.sh:9; deploy.sh:41; connectors/protected.js"
  - "memory brew-meta-app-review, brew-real-connectors, brew-meta-connector-qa, never-disconnect-arata-meta, brew-shopify-connector-qa, brew-live-stores"
  - "handbook content/engineering/connectors.md, read for consistency"
---

# Meta

## Answer

Brew reads Meta Ads through one SquareUp Meta app with Facebook Login for Business, read only; any brand outside the app's roles waits on two gates, Business Verification and then App Review for read permissions, and the review draft is filled but cannot be submitted until verification passes and two screencasts are uploaded.

## Today

### The app

| Fact | Value | Source |
|---|---|---|
| App | SquareUp app 1675538196856449, in the SquareUp business portfolio | [src: memory brew-real-connectors] [src: memory brew-meta-app-review] |
| Login configuration | "Brew Ads Read" 2157080375167128, set as `META_ADS_CONFIG_ID` on both sites | [src: brew/tools/prod-env.sh:9] [src: brew/deploy.sh:41] [src: memory brew-real-connectors] |
| Graph version | v26.0, the newest Meta answered on 22 Oct | [src: brew/connectors/meta.js:9-11] |
| Access tier | `development_access` until App Review passes: only people with a role on the app can connect | [src: memory brew-meta-connector-qa] [src: brew/docs/connectors-approvals.md:29] |
| What a sign in grants | `ads_read`, `business_management` and `pages_show_list`; `promote_pages` comes back empty, so the brand's Page is found from its own ads | [src: memory brew-meta-connector-qa] |
| Sign in life | About 60 days, no refresh token; Brew renews where Meta allows and warns owners and admins a week ahead | [src: brew/connectors/meta.js:23-26] |
| Accounts | One or more ad accounts per brand, summed; an agency account counts only the ads for the brand's Page | [src: brew/connectors/meta.js:3-5, 130] |

### The two gates

| Gate | State | Source |
|---|---|---|
| Business Verification, portfolio 898394269362946, Yellow Monk Technologies LLP | Submitted 16 Oct as Registered with the incorporation certificate; still In review on 24 Oct | [src: memory brew-real-connectors] [src: memory brew-meta-app-review] |
| Access verification as a Tech Provider | Can only start once Business Verification passes | [src: memory brew-meta-app-review] |
| App Review, submission 1689993865410882 | Draft filled 24 Oct; Submit blocked | [src: memory brew-meta-app-review] |

### What the review draft asks for

| Permission | Kept | Source |
|---|---|---|
| `ads_read`, `business_management`, `public_profile`, Marketing API Access Tier | Requested; the 500 call bar was already met | [src: memory brew-meta-app-review] |
| `ads_management`, WhatsApp, Pages, Threads, catalog | Removed | [src: memory brew-meta-app-review] |

- Use case text and allowed usage agreements are saved for all four [src: memory brew-meta-app-review].
- Data handling: processor Google LLC, Google Cloud, India and the US; controller Yellow Monk Technologies LLP, India; national security requests No; public authority policy "None of the above", Param's choice [src: memory brew-meta-app-review].
- App settings: privacy and data deletion URLs are both brew.joinsquareup.com/privacy; a Website platform for brew.joinsquareup.com with reviewer testing instructions; reviewers email hello@ to be added to Cozy Snugglet [src: memory brew-meta-app-review].

### The screencasts

Two are missing, one for `ads_read` and one for `business_management` [src: memory brew-meta-app-review]. The script on file:
1. Open brew.joinsquareup.com and sign in with Google.
2. Open a brand, Connectors, Connect Meta Ads, Facebook Login for Business, pick the ad account.
3. Show what Brew read: spend, return on spend and frequency, all read only.
4. Show the card built from it, seen only by the brand's team.
5. Show Disconnect removing the token.
[src: brew/docs/connectors-approvals.md:38-47]

Record on Cozy, never Arata [src: memory brew-meta-app-review] [src: memory never-disconnect-arata-meta].

### Portfolio cleanup, 24 Oct

- Removed the Officer Harry Page, @officerharrypreps and a pending invite [src: memory brew-meta-app-review].
- Kept every Cozy asset and the SquareUp Ads India ad account on purpose [src: memory brew-meta-app-review].
- The Harry, Donna and Archived datasets cannot be removed; Harry and Donna still receive pixel and CAPI events [src: memory brew-meta-app-review].

### Live connections

| Brand | State | Source |
|---|---|---|
| Arata | act_2942894532542334 connected 22 Oct; protected in code by `PROTECTED_CONNECTIONS=arata-in`; never disconnected, reconnected or re-selected | [src: memory never-disconnect-arata-meta] [src: brew/tools/prod-env.sh:9] |
| Cozy Snugglet, our test brand | SquareUp Ads India, only the Cozy Page's ads counted; disconnect tests run here | [src: memory brew-real-connectors] [src: memory brew-live-stores] |

Meta behaviour worth knowing: 200 ads per page fails, 100 works; throttles are retried; the 90 day data access limit counts as expiry [src: memory brew-meta-connector-qa] [src: memory brew-shopify-connector-qa]. Never call `DELETE /me/permissions`: one grant may serve several brands [src: memory brew-meta-connector-qa].

## Tomorrow

| Item | Version | Tag |
|---|---|---|
| `ads_read` and `business_management` only, read only | v1 | Stays |
| Any brand connects without an app role, after App Review | v1 | Changes |
| Graph version bumped when Meta announces a newer one | v1 | Stays |
| Pages and Instagram read for the brand's own posts | v2 | New, needs a new review |
| `ads_management` to pause or change budgets | v4 | New, needs a new review and a person's yes per action |

Rows from v2 on are proposals for Param, not decisions.

## How we do it

1. Check Business Verification in Meta Business Settings for portfolio 898394269362946. When it passes, start Access verification as a Tech Provider [src: memory brew-meta-app-review].
2. Record the two screencasts on Cozy with the script above, upload them to submission 1689993865410882, and press Submit. The built-in browser is signed in to Meta; Claude in Chrome is not [src: memory brew-meta-app-review].
3. Until approval, a design partner's Meta admin gets a role on the app, App roles then Testers or Analysts, and connects with one click [src: brew/docs/connectors-approvals.md:29].
4. Audit a brand read only:

```bash
node tools/meta-audit.mjs <slug>   # needs FEED_VAULT_KEY and the Meta app secrets
```

[src: memory brew-meta-connector-qa]

5. Any script that touches `private/vault/meta.json`, `connections.json` or disconnect skips `arata-in` [src: memory never-disconnect-arata-meta].

## Numbers

| Metric | Definition | Where measured |
|---|---|---|
| Days in verification | Days from 16 Oct submission to Business Verification passing | This document, Proposed |
| Days in App Review | Days from Submit to the answer | This document, Proposed |
| Live Meta connections | Meta connections in state live | `connections` table on production, Proposed |
| Sign ins near expiry | Meta connections within 7 days of their end | `connectors/index.js` warning emails, Proposed |

## Open

1. **Has Business Verification passed since 24 Oct?** No later source. Proposal: Param checks today and notes the date here.
2. **`pages_show_list` is granted at sign in but not in the review list.** Proposal: drop it from the login configuration before Submit, since the Page is now found from the ads.
3. **Who records the screencasts?** Proposal: Param, on Cozy, the same day verification passes.
4. **The old Harry and Donna datasets still take events.** Proposal: switch off their pixel and CAPI senders at the source so the portfolio carries only live products.
