How Each Data Source Connects
The exact connection method per live Donovan / Hatfield source: a one-click OAuth login vs. a pasted API key.
Verified against code 2026-06-02 · full citations in docs/connection-methodology.md
OAuth login (consent screen)
API key (manual entry)
Live & pulling data
Connected, not yet fetching
M
Meta Ads
Facebook + Instagram
OAuth
Live
How you connect
1Click Connect
2Facebook login + consent screen
3Grant permissions
4Pick an ad account
You provide
Just your Facebook login and consent, then select the ad account. No keys typed.
Permissions
ads_read ads_management email
Tokens
Browser only builds the URL. The 60-day token swap and refresh run server-side in the Edge Function. Tokens never reach the browser.
FB vs IG
One connection covers both; platform / placement split stored in breakdown tables.
First backfill
36 months. FB + IG ad data → metric_snapshots; IG / page organic → meta_page_snapshots.
Daily update
Cron every 4 hours (0 1-23/4 * * *), 2-day overlap, dedup upsert. Rate limits honored with backoff + retry.
G
Google Search Console
Organic search
OAuth
Live
How you connect
1Click Connect
2Google consent screen
3Grant read access
4Pick a verified site
You provide
Google login and consent, then select which verified site / property. No keys typed.
Permissions
webmasters.readonly (read-only)
Tokens
Shares the Google OAuth client with Google Ads. Code exchange and refresh run server-side in the Edge Function; secrets in env only.
Property pick
Data-driven: sites come from the live GSC /sites API. Nothing hardcoded.
First backfill
16 months (480 days). POST query with dimensions date, query, page, country, device. 1k rows / page, 25k cap per sync → gsc_metric_snapshots.
Daily update
Cron daily 11:00 UTC (0 11 * * *). Token refreshed via stored refresh_token; 5-day overlap, dedup upsert.
B
Basis
Programmatic display (DSP)
API key
Not yet fetching
How you connect
1Open the Basis credentials modal
2Paste an API key + Seat / Advertiser ID
3Save
You provide
An API key and Seat ID, typed in by hand. No OAuth screen, no seat auto-discovery.
Tokens
Key stored as the connection secret, seat as the account id. No refresh (there is no token). Read server-side at sync.
First backfill
90 days per client → basis_metric_snapshots. Cron daily 04:00 UTC (placeholder cadence, to be tuned to Basis docs).
Current state: the connect flow, storage, and daily sync schedule are real, but the actual data fetch is a stub that returns nothing. No Basis numbers will populate until the live API endpoint and schema are wired. A wrong key currently looks like a silent success with zero rows.
In one line: two of the three connect with a one-click OAuth login (Meta, GSC), where the user only logs in and picks an account. Basis connects with a pasted API key and is not yet fetching live data.