Context
lib/analytics/{meta,tiktok,youtube}.ts all return seeded deterministic mock numbers from piece_id. Real analytics fetching does not exist.
Goal
Real adapters that pull insights from each platform's API and write to data/analytics.jsonl in the schema documented in DESIGN.md § Data Flow.
Acceptance criteria
Meta (lib/analytics/meta.ts:25-38): uses Graph API; reads META_ACCESS_TOKEN, META_PAGE_ID; fetches reach, impressions, saves, shares, comments, profile_visits for IG + FB
TikTok (lib/analytics/tiktok.ts:25-38): uses TikTok Business API; reads TIKTOK_ACCESS_TOKEN; same metrics shape
YouTube (lib/analytics/youtube.ts:25-38): uses YouTube Data + Analytics APIs; reads YOUTUBE_API_KEY, YOUTUBE_CHANNEL_ID; metric shape + watch_time_s
All three return { piece_id, platform, reach, impressions, saves, shares, comments, profile_visits, ctr, watch_time_s?, captured_at } matching DESIGN.md
Each writes one line per fetch to data/analytics.jsonl
.ralph/analytics-pull.sh calls the real fetchers when DRY_RUN=false, keeps synthetic mode when true
.env.example adds the new keys with comments on how to obtain them
E2E specs with mocked HTTP for each adapter
Files
lib/analytics/{meta,tiktok,youtube}.ts
.ralph/analytics-pull.sh
.env.example
Context
lib/analytics/{meta,tiktok,youtube}.tsall return seeded deterministic mock numbers frompiece_id. Real analytics fetching does not exist.Goal
Real adapters that pull insights from each platform's API and write to
data/analytics.jsonlin the schema documented in DESIGN.md § Data Flow.Acceptance criteria
lib/analytics/meta.ts:25-38): uses Graph API; readsMETA_ACCESS_TOKEN,META_PAGE_ID; fetches reach, impressions, saves, shares, comments, profile_visits for IG + FBlib/analytics/tiktok.ts:25-38): uses TikTok Business API; readsTIKTOK_ACCESS_TOKEN; same metrics shapelib/analytics/youtube.ts:25-38): uses YouTube Data + Analytics APIs; readsYOUTUBE_API_KEY,YOUTUBE_CHANNEL_ID; metric shape +watch_time_s{ piece_id, platform, reach, impressions, saves, shares, comments, profile_visits, ctr, watch_time_s?, captured_at }matching DESIGN.mddata/analytics.jsonl.ralph/analytics-pull.shcalls the real fetchers whenDRY_RUN=false, keeps synthetic mode whentrue.env.exampleadds the new keys with comments on how to obtain themFiles
lib/analytics/{meta,tiktok,youtube}.ts.ralph/analytics-pull.sh.env.example