Client Reporter
Multi-platform performance reports for agency clients — connects to GA4, Google Search Console, Meta Ads, and TikTok Ads, renders a white-label PDF in under a minute. Free, MIT-licensed, runs locally.
When to use this skill
Trigger this skill when the user:
- Asks for a weekly or monthly client performance report
- Says "pull last 30 days for client X" or similar phrasing
- Wants a multi-platform analytics roll-up (paid + organic)
- Mentions GA4, Google Search Console, Meta Ads, or TikTok Ads in a reporting context
- Asks to "send the client their numbers" or "prep the client review deck"
Don't trigger for:
- Single-platform reports (use the platform's native UI — too thin a use case)
- Real-time dashboards (this is for periodic batch reports)
What it produces
A single, branded PDF (typically 6–10 pages, ~2 MB) containing:
- Cover page with agency logo, client name, reporting period
- Executive summary — 3–5 key metrics with deltas vs. prior period
- GA4 section — sessions, users, conversions, revenue, top pages
- Search Console section — clicks, impressions, CTR, avg. position, top queries
- Meta Ads section — spend, ROAS, top creative, CPM trend
- TikTok Ads section — spend, video views, CPM, top videos
- Footer — "Powered by Recipes by WiseChef" (toggleable for white-label)
Setup
1. Install dependencies
cd skills/client-reporter
pip3 install -r requirements.txt
# OR explicitly:
pip3 install google-analytics-data google-api-python-client weasyprint jinja2 pyyaml
System dep for weasyprint:
# Ubuntu/Debian
sudo apt install -y libpango-1.0-0 libpangoft2-1.0-0
# macOS
brew install pango
2. Provision a Google service account
For GA4 + Search Console (one account works for both):
- Create a service account at console.cloud.google.com
- Enable Google Analytics Data API and Search Console API
- Download the JSON key
- In GA4 admin → Property → Property Access → add the service-account email with Viewer
- In Search Console → Settings → Users → add the service-account email with Restricted
Save the JSON to credentials/ga4-service-account.json (gitignored by default).
3. Configure
cp config.yaml.example config.yaml
# edit config.yaml with your client's IDs
Minimal config:
branding:
agency_name: "Your Agency"
logo_path: "./assets/agency-logo.png"
primary_color: "#FFD166"
cta_footer: true
connectors:
ga4:
credentials_file: "credentials/ga4-service-account.json"
property_id: "123456789"
search_console:
credentials_file: "credentials/ga4-service-account.json"
site_url: "https://yourclient.com"
report:
client_name: "Acme Corp"
period_days: 30
output_path: "./output/acme-2026-04.pdf"
4. Run
python3 skill.py --config config.yaml
# → ./output/acme-2026-04.pdf
For the agent driving this skill: tell the user "point me at the client's config slug and I'll run the report". The skill prints the output path to stdout — the agent reads that and surfaces it.
Usage examples
# One-shot run with explicit dates
python3 skill.py --config config.yaml \
--start 2026-04-01 --end 2026-04-30 \
--output ./output/acme-april-2026.pdf
# Last 7 days
python3 skill.py --config config.yaml --period-days 7
# Multi-client batch (one config per client)
for cfg in clients/*.yaml; do
python3 skill.py --config "$cfg"
done
# White-label mode (drop WiseChef footer)
python3 skill.py --config config.yaml --no-footer
Connector status
| Platform | Status | Auth method |
|---|---|---|
| Google Analytics 4 | ✅ Working | Service Account JSON |
| Google Search Console | ✅ Working | Service Account JSON |
| Meta Ads | 🔄 Stub (returns realistic mock data) | Access Token |
| TikTok Ads | 🔄 Stub (returns realistic mock data) | Access Token |
| LinkedIn Ads | 📋 Planned | OAuth2 |
| GoHighLevel | 📋 Planned | API Key |
Stubs return structurally-correct mock data so the PDF pipeline runs end-to-end while real connectors are being wired.
Pitfalls
- GA4 property ID vs. measurement ID. The skill needs the numeric property ID (e.g.
123456789), NOT the measurement IDG-XXXXXXXXXX. Find it in GA4 admin → Property → Property details. - GSC site URL format. For domain-verified properties use
sc-domain:yourclient.com. For URL-prefix properties use the full URL withhttps://. Mismatch → empty results, no error. - Service account permissions are silent. If the service account isn't added to GA4/GSC with view access, the API returns an empty result set, not an error. Always run a test query before assuming the connector is broken.
- Weasyprint font fallback. If the configured
branding.font_familyisn't installed, weasyprint silently falls back to a generic serif. Drop a.ttfintemplates/fonts/and reference it by family name. - Meta Ads token scopes. Token needs
ads_read(andads_managementfor the spend-by-campaign breakdown). Tokens generated in the test app rarely have both — check on first run. - TikTok rate limits. TikTok Ads API caps at 100 req/min per advertiser. The skill caches per-client, per-day at
~/.recipes/cache/tiktok-ads/. Delete the cache to force a refresh. - PDF size on long reports. A 90-day report with all four connectors can hit 8 MB. Use
--period-days 30for client deliverables; longer for internal reviews only.
Customising the output
The HTML template is at templates/report.html (Jinja2). Override sections by:
- Editing
templates/report.htmldirectly (simplest) - Setting
report.templatein config to point at your own template - Subclassing
lib.pdf.ReportBuilder(advanced)
Per-section data is passed in as {"ga4": {...}, "search_console": {...}, "meta_ads": {...}, "tiktok_ads": {...}, "branding": {...}, "client": {...}, "period": {...}}.
Output sample
A real run on a SaaS landing-page client typically reports:
GA4
Sessions: 5,213 (+18% MoM)
Users: 3,847 (+22%)
Goal completions: 142 (+11%)
Search Console
Clicks: 1,209 (+5%)
Impressions: 38,114 (+12%)
Avg position: 14.2 → 12.8
Meta Ads
Spend: €2,140 (+3%)
ROAS: 3.2x (vs 2.9x prior)
Top creative: "Founder talking head Q2 2026"
TikTok Ads
Spend: €890
Views: 412k
CPM: €2.16
License
MIT. See LICENSE at the repo root.
Want it run for you?
If you don't want to operate this skill yourself, WiseChef Framework ships managed AI employees that run Client Reporter end-to-end as a service, with calendar-driven cadence and Slack/email delivery. From €199/month.