Connecting Google sources
One Google sign-in covers GA4 (traffic), GTM (read-only tag audit), and Google Ads (spend). Funnelkeeper asks for read scopes only and stores the refresh token encrypted.
From the dashboard
Integrations → Connect with Google → consent → pick your property/container → done.
From a terminal or agent
The browser step can’t be skipped — Google requires a human consent screen. The flow hands the URL out and polls:
POST /connect/google/start {"product_slug":"demo-product","kinds":["ga4","gtm"],"client":"cli"}
→ {"state":"…","auth_url":"https://accounts.google.com/o/oauth2/v2/auth?…","expires_at":"…"}
Give auth_url to the human. Then poll (bearer required; the state is bound to your
account and expires after 10 minutes):
GET /connect/google/status?state=…
→ {"status":"pending"} keep polling (2s, then 5s)
→ {"status":"complete","results":[…],"options":{"ga4_properties":[…],"gtm_containers":[…]}}
→ {"status":"error","error":"access_denied"}
When options holds more than one property or container, ask the human which, then:
POST /connect/google/select {"state":"…","ga4_property_id":"4210…","gtm_container_path":"accounts/…/containers/…"}
→ {"ok":true,"activated":["ga4","gtm"]}
Exactly one option? Pass it straight through — no need to ask.
What GTM is for
Nothing is ever written to your container. The Keeper reads the live version weekly and answers one question: is the GA4 tag this product expects present and unpaused? If spend is running while the answer is no, you get an alert card — because every funnel number under-counts until the tag is fixed.
Google Ads
Spend sync activates automatically once Funnelkeeper’s Google Ads developer token is approved; until then your customer id is stored and the CSV bridge covers spend imports.