Documentation · Platforms.

Connect Meta and Google Ads to Admaxxer — without App Review.

Admaxxer's paste-token model is the v1 default. You bring your own credentials, we encrypt them with AES-256-GCM, monitor expiry on a daily cron, and rotate keys without breaking existing connections. No Facebook App Review. No multi-week Google Ads developer-token wait. Connect in five minutes and ship revenue attribution today.

Open Integrations Back to docs

Overview — why paste-token, why now

Most attribution and ad-ops tools require a Meta App Review pass, a Google Ads standard-access developer token, or both. That gate is a 4–12 week back-and-forth before you ship a single feature. The reviewer wants a recorded demo, screenshots, a privacy policy, a data-deletion flow, and proof that your callbacks are reachable. By the time you pass, your roadmap has shifted twice. Admaxxer skips that loop entirely with a paste-token model: you generate credentials in your own developer accounts and paste them into Integrations. Admaxxer holds them encrypted, rotates them, monitors expiry, and calls the public APIs on your behalf. Account safety is rule #1 — we respect every documented rate limit and back off aggressively rather than risk a flagged ad account or a revoked developer token.

The trade-off is real. With a paste-token model, the user is responsible for generating the token in the first place. We compensate by making the generation step the simplest possible UX: short instructions, a copy-paste field, a live GET /me validator that fails before persistence. For users who already manage tokens (developers, agencies, in-house ad-ops teams), this is faster than OAuth. For users who don't, the OAuth path is supported as well — we don't force a single flow.

The v1 model has three properties worth calling out:

This document covers the full lifecycle — connect, encrypt, monitor, rotate, disconnect — and the safeguards that make it production-grade. If you're integrating with Admaxxer's API, the connection model also affects the public REST surface (see Developer / REST API).

Meta Ads connection

Two paths are supported, and both end with a live GET /me Graph API call before the credential is persisted — invalid tokens fail fast at connect time, not on the next cron run.

Path A — Paste a long-lived token (primary)

The primary, working connect path. Users paste a long-lived user token (e.g. issued from a Meta Business Manager System User) plus the ad-account ID directly. A System User token is ideal: it doesn't expire on the ~60-day cadence and it survives password changes by individual users, so you paste once and you're set. This is well suited to agencies provisioning multiple workspaces from a single Business Manager, and to engineering-led integrations. The paste flow runs a live GET /me validator before persistence, so an invalid token fails fast at connect time. Generation requires a Meta Business account with admin privileges; the Marketing API system-user docs walk through the steps.

Path B — One-click "Connect with Facebook" (coming soon — app review in progress)

A one-click OAuth flow that runs the Facebook OAuth dialog with PKCE and a signed state parameter, exchanges the short-lived authorization code for a long-lived (~60 day) user token, and ends with an account picker. This flow is fully built, but the one-click sign-in is coming soon — it's pending Meta's app review. Until that approval lands, use the paste-a-token path above; it gives you the same long-lived connection in about two minutes.

Required permissions and limits

Meta Ads — required scopes, API version, and rate limits
ItemValue
OAuth scopesads_management, ads_read
Graph API versionv21.0
Rate limit~200 calls/hour/user-token (auto-backoff on 17/32/613)
Multi-account ceilingUnlimited active connections per workspace on every paid plan (a generous safety ceiling guards against runaway automation)
Liveness checkGET /me before persistence

Source of truth — internal + allowlisted external

The Meta documentation Admaxxer builds against is Meta's own published Marketing API reference: Marketing API overview, Get started, Business SDK, and the v25.0 reference. Field names, enum values, edge shapes, and endpoint paths come from the v25.0 reference specifically — this prevents drift across Meta API version semantics.

Google Ads connection

Google Ads connects via one-click OAuth. Google approved Basic Access on Admaxxer's own developer token, so Admaxxer owns the developer token, the OAuth client ID, and the OAuth client secret — you never paste a developer token, build a Google Cloud OAuth client, or mint a refresh token in OAuth Playground. The flow: click Connect Google Ads in Integrations → Google's consent screen asks for the single https://www.googleapis.com/auth/adwords scope (no Gmail, Drive, or Calendar) → on approval Admaxxer calls listAccessibleCustomers and shows every account your Google login can reach → you pick the account to track. MCC / manager users pick the manager account, then the target child account — Admaxxer stores the manager as login_customer_id and the child as customer_id so requests resolve through the manager hierarchy.

The endpoint chain is GET /api/integrations/google-ads/authorize → OAuth callback → account picker → POST .../finalize. Before persisting anything, Admaxxer runs a live GAQL probe against the chosen account — so a connection that shows "Connected" is genuinely working, never a green badge over a dead credential. Once validated, Admaxxer backfills the last 90 days and syncs daily. The only secret stored is the encrypted refresh_token (plus the clear-text customer_id and optional login_customer_id); the developer token and OAuth client come from Admaxxer's environment, not the user.

After connecting, open the Claude agent (⌘J) and ask things like "What's my Google Ads ROAS this week?" or "Which Google Ads campaigns have the worst cost per conversion?"

GAQL — Google Ads Query Language

Admaxxer batches campaign, ad-group, and keyword reads via GAQL. GAQL is Google's SQL-flavored query language for the Ads API; it lets you select fields from a logical resource (campaign, ad_group, keyword_view, etc.) with WHERE filters and segments. A representative query:

SELECT campaign.id, campaign.name
FROM campaign
WHERE campaign.status != 'REMOVED'

All cost values come back as cost_micros; we divide by 1,000,000 to get the account currency (USD for most US accounts, native currency otherwise). Conversion values, click counts, and impression counts are first-class GAQL fields — no second roundtrip required. We always select cost_micros rather than constructing a derived "spend" field because the micros version is the canonical Google representation; rounding to dollars happens in the presentation layer.

For richer reporting (date-segmented insights, cross-account roll-ups, keyword performance over a window), Admaxxer issues batched GAQL queries against the relevant resource (campaign, ad_group, keyword_view) and joins the results in our own pipeline. We don't rely on Google's reporting API for derived metrics — every metric used in our dashboards is computed from the raw GAQL columns, which means we can re-derive history any time a definition changes.

Token cache, refresh policy, and quotas

Google Ads — token cache, refresh, and quota
ItemValue
Access-token cache50 min in-memory, per connection
Refresh policyOn 401, exactly one refresh attempt before failing the request
Daily quota15,000 ops / day (default standard access)
REST versionv23
Required scopehttps://www.googleapis.com/auth/adwords

Source of truth — internal + external

Admaxxer builds against Google's own published documentation: Google Ads API getting started. GAQL queries are validated against the Google-published GAQL reference; we always remember to divide cost_micros by 1e6 — that's the most common mistake when integrating Google Ads.

Token storage — AES-256-GCM with scrypt key derivation

Every credential — your Meta access token, your Google refresh token, OAuth secrets, and any manager-account identifiers — is encrypted with AES-256-GCM before it is ever written to our database. AES-256-GCM is the industry-standard authenticated encryption mode; it gives us confidentiality (AES-256) and tamper-detection (the authentication tag) in a single primitive. The key we encrypt your credentials with is derived from a high-entropy secret using scrypt, which is deliberately memory-hard and slow to brute-force; a copy of the stored data alone never yields a usable key. An attacker would need both the encrypted credential and the live encryption key — and that key is never written to disk.

Each stored credential gets a fresh, random initialization value per encryption, and a built-in authentication tag means any tampering causes decryption to fail loudly rather than silently. Reading a token always means decrypting it on the way out — your credentials are never stored in plaintext anywhere, so even our database backups only ever contain encrypted bytes.

Plaintext lifetime

The decrypted token only exists in memory for the brief moment an outbound call to Meta or Google is in flight. It is never written to our logs (our logging redacts known credential fields), never written to disk, never sent to any third party, and never returned over a public Admaxxer API. Restarts wipe it from memory; the only path back to a usable token is through the live encryption key. We've audited our codebase to confirm no log line, serialized response, or error trace can ever leak a token.

Why application-level encryption?

We encrypt and decrypt your credentials inside the application rather than relying on database-level encryption, for two reasons: (1) the encryption key never leaves the running application, so even someone with direct read access to the database can't decrypt your tokens; (2) we can rotate the key without rewriting every stored record in place (see Key source and rotation below). The cost is one extra step in application code, which is negligible next to the network round-trip to Meta or Google.

Key source and rotation

The key we encrypt your stored credentials with is supplied to the application as a securely-managed secret, never checked into code and never exposed to customers. Admaxxer can roll this key on demand without any reconnect on your side.

Zero-downtime key rotation

During a rotation, both the previous key and the new key can decrypt your existing credentials, so nothing breaks while the changeover happens. Newly-stored credentials always use the new key, and existing ones are quietly re-encrypted under it in the background — so the old key naturally retires itself as your data is migrated forward. From your perspective, a key rotation is completely invisible.

Token expiry monitoring

Long-lived Meta user tokens last ~60 days. We check every active connection once a day, and as soon as a token is within a week of expiring we email you a reminder — at most once per day per connection, so you're never bombarded.

Once a token has expired, calls into Meta start failing. The connection is flagged as needing attention, the app surfaces a clear banner, and you're prompted to reconnect. The check is forgiving but never silent: every time a connection slips into a failed state, you get exactly one email.

Decrypt failure handling

If a stored credential can't be read for any reason, Admaxxer returns a clear "credentials need reconnecting" error rather than failing in a confusing way, and the app deep-links you straight to the reconnect screen. There is no silent fallback to stale data — we'd rather show you a clean, actionable error.

Disconnect lifecycle — soft-delete with audit

Disconnect is a soft-delete with three guarantees: (a) we attempt to revoke access on the platform side, (b) we tombstone your stored credential so no one can resurrect it, and (c) we keep the connection record for your audit history.

  1. Best-effort revoke (Meta). We ask Meta to revoke our access on its side. If that call fails (for example, the token was already invalid), it doesn't block the rest of the teardown — we treat it as best-effort because the platform sometimes rejects an already-revoked token.
  2. Tombstone the credential. We overwrite your stored token with a tombstone value. Even with the live encryption key, the original token is gone for good.
  3. Keep the record for audit. The connection record is marked disconnected and retained for your history, while only active connections show up in your dashboard.

Workspace isolation — every connection scoped

Every connection belongs to exactly one workspace. Every request — read or write — verifies that the connection it's touching belongs to your active workspace before doing anything. There is no cross-workspace path; even an Admaxxer operator can't accidentally route a request through another customer's token. The Claude agent inherits your active workspace from your session, so chat-driven actions are scoped identically.

This check runs on every request, not just at the storage layer, so an oversight in one place can't leak a token across customers. Any new feature that touches connections inherits the same workspace check by default — there are no exceptions — and an automated guardrail in our build pipeline blocks anything that would skip it.

Multi-tenant safety extends to the agent. The Claude agent can list, inspect, and (with your explicit confirmation) modify campaigns — but only within your active workspace. There is no "operator override" path and no cross-workspace path. If you belong to multiple workspaces (agencies often do), you explicitly switch workspace before chatting, and the agent only ever sees the one you're currently in.

This same per-workspace boundary applies to the cached insights layer that powers your dashboards — cached results are never shared across workspaces.

What can the agent do with my connections?

The Claude AI agent (Sonnet, prompt-cached, streaming SSE) inherits the user's active workspace and reads from the same connection set the dashboard uses. The agent has six tools split across two surfaces:

This means the connection layer effectively gates every agent action. If your Meta token is expired and the connection is flagged as needing attention, the agent's read-only Meta tools fail with a clear error pointing you to reconnect — not a confusing partial response. For the full agent surface and tool schemas, see Claude AI Agent.

Frequently asked

Do I need Facebook App Review or Google Ads developer-token approval?
No. The v1 paste-token model means you supply your own credentials — your long-lived Meta user token, or your Google OAuth refresh token plus your already-approved developer token. Admaxxer never goes through Meta App Review or asks you to wait on Google's developer-token approval queue.
How are my Meta and Google tokens stored?
AES-256-GCM with scrypt key derivation. Ciphertext is packed as iv:tag:ciphertext (base64). Plaintext only exists in memory during outbound API calls and is never written to logs, never sent to a third party, and never persisted to disk in plaintext form.
What happens when my Meta token expires?
Long-lived Meta user tokens are valid ~60 days. We check every connection daily and email you a reminder once a token is within a week of expiring (at most one reminder per day per connection, so you're never spammed). Once a token has expired the connection is flagged as needing attention and the app prompts you to reconnect in a couple of clicks.
How do you handle Meta and Google rate limits?
Meta Marketing API: ~200 calls/hour/user-token. We auto-backoff on rate-limit error codes (17/32/613) and never spam. Google Ads: 15,000 ops/day default; access tokens cache for 50 minutes in-memory, and a 401 triggers exactly one refresh before failing the request. Ad-account safety is the #1 priority — we err on the side of caution every time.
Can Admaxxer rotate its encryption key without breaking my existing connections?
Yes. Admaxxer can roll the key it encrypts your stored credentials with while keeping both the old and new key able to decrypt during the changeover — so your connections keep working and get quietly re-encrypted under the new key in the background. You never have to reconnect because of a key rotation.
What does Admaxxer do when I disconnect an ad account?
Soft-delete. We ask the platform to revoke access on its side (best-effort), then overwrite your stored token with a tombstone value so it can never be recovered — even by us. The connection record stays for your audit history, but the credential itself is permanently unreadable.
How many Meta or Google accounts can I connect per workspace?
Every paid plan ships unlimited ad-account connections. We apply a generous safety ceiling per workspace to guard against runaway automation, but in practice you can connect as many Meta and Google accounts as your team manages.
Can the Claude agent see or use my ad-platform connections?
Yes — every connection is scoped to your workspace, and the Claude agent inherits that workspace context. Read tools (list_campaigns, get_account_insights) require an active connection. Destructive tools (update_campaign, pause_all_low_roas) require both an active connection AND explicit user confirmation before they fire.

Next steps