Your ASA lab notebook — every theory, the change that tests it, and the verdict.
This is the layer Apple's console and a plain dashboard don't have: a hypothesis ledger that survives the ~24h reporting lag and a 7-day runway, and turns each finding into a reusable rule.
🌱 Learnings & rules adopted
The durable knowledge experiments leave behind — these constrain every future recommendation.
Campaigns
One row per campaign. Click a header to sort.
→
TOTALS is the account total, not the sum of the rows above — Apple masks low-volume terms, so per-campaign rows can under-count. — means we hold no data for that cell; 0 means we hold data and it is zero. Columns up to Spend are Apple; Tracked onward are RevenueCat, and Tracked is never the same number as Inst.
Purchases
Every RevenueCat purchase, newest first, with the campaign each is attributed to.
→
unattributed — resolving is the honest label while AdServices has not
answered yet — it self-fills once the install resolves (or stays, for an organic payer). A
sandbox row is a test purchase: visible here so testing is verifiable end-to-end, but
never counted as revenue. Dates are inclusive UTC days.
Keywords
Last 7 days · band by TTR · click a header to sort.
🟢 ≥4% 🟡 2–4% 🔴 <2% TTR. Rows under ~100 impressions are directional only. CPA shown where installs > 0.
Search Terms
What people actually typed — the source of negative-keyword discovery.
Reports
Pick a dimension, a window and a timezone; filter it; sort any column. Save it and it comes back.
→
TOTALS is the account total, not the sum of the rows above — Apple masks low-volume terms, so per-entity rows can under-count. — means we hold no data for that cell; 0 means we hold data and it is zero. TTR, CR, CPA and CPT are re-derived from the summed counts, never averaged from the daily rows.
All reports
A saved report stores the query, never the numbers — opening one re-runs it against today's data.
Timeline
Every account change on one axis — so you can read results against the change that caused them.
Blended TTR, with change marker
Change log
AI Usage
Every call we made to a model, what it cost, and why.
Cost is computed at the moment of the call and stored — never re-derived from today's price list, so a price change cannot rewrite what you already paid. Shown to six decimals because a single call routinely costs less than a cent.
Data & Sync
Where this account's data came from, and when.
Sync history
Every run this account has made — scheduled and manual alike.
One tick of the schedule writes four rows — sync, eval, experiment eval, alert — so “did we pull fresh data?” and “did we form suggestions?” stay separately answerable. Rows is what that job wrote: metrics for a sync, suggestions for an eval, alerts for an alert.
The pipeline
① Apple Ads API v5
Read-only pull: campaigns, ad groups, keywords, search-term reports.
→
② MySQL
Per-day metrics, reconciled against Apple's own grand totals before they land.
→
③ Evaluate
Deterministic rules form suggestions and raise alerts. No model is called in this phase.
→
④ This view
Briefing, experiment ledger, scorecard.
Webhook deliveries
Every inbound RevenueCat delivery, newest first — and what Sift did with it.
Admin-only. A rejected (401) delivery is logged with no body — so
a mis-set REVENUECAT_WEBHOOK_SECRET shows up here, not only in the server logs. The
Payload of an accepted delivery is the body as received, secret-scrubbed. Rows past the
retention window are swept nightly.
Settings
API reference for Claude Code
A single Markdown file describing every Sift endpoint and the conventions a client needs —
auth, money units, the report filter grammar, rate limits, and what it can and cannot do.
Hand it to the Claude Code CLI so it can drive Sift over HTTP instead of guessing.
New experiment
A theory is only real once it's written down with the change that tests it.