Andrea Caravello
← All projects

Case 02 / Reporting & decision support

GEO reporting dashboard

A dashboard is only as honest as its definitions. AI visibility, search and pipeline in one view, with what every number means written down.

My roleReporting & dashboard development¹
Evidence status · 28 Oct 2026Original application recorded · synthetic data

Outcome · self-reported scopeReporting scope: 226 inbound deals and 29 wins in three months, the pipeline this reporting covered, plus 800+ technical SEO fixes led (redirects, crawl errors, keyword gaps). Period results, self-reported; not exclusive SEO/GEO attribution or causal credit.

The challenge

Every week someone asks: where do we stand in AI-generated answers, and what do we do next? Visibility, search and pipeline data answer different questions, blur them and correlation gets sold as revenue. The dashboard answers the question and writes down what every number means.

My role

I built this dashboard and its reporting method: source definitions, metric boundaries, the weekly digest. My name is on the methodology, including its limits.

The approach

Seven views over the same sources, share of voice, AI attribution, keyword rankings, content opportunities, wins, digest, and every number carries a path back to the source that produced it. Code and a scheduled workflow prove the implementation; refreshes, adoption and business impact are claimed nowhere.

Product demo · original application · synthetic fixtures02
Your original application, with real filtering and reporting logic.The dashboard itself, recorded from the original application on invented datasets: share of voice, AI attribution, content opportunities, win log, digest, the app’s own data notice left visible, and a library warning mid-clip stays in (real behaviour). Silent; descriptive captions. Invalid legacy metrics excluded and disclosed below. The earlier 111s tab capture is preserved in the packages.Read the descriptive captionsDownload the demo

Data lineage

The four stages, in spec form
System illustration · not a screen recording02
Stage 01Corpus
  • 24 allowlisted source files
  • pinned commit edf6284
  • original repository unchanged
Stage 02Runtime
  • original application, invented data
  • 7 routes rendered
  • isolated venv
Stage 03Guard
  • application-level network guard
  • not an OS firewall
  • no live tool calls
Stage 04Lineage
  • quarter AI-share numerator can include outbound
  • denominator uses inbound
  • scope kept beside the number
Stage 05Test
  • 200% characterization test
  • reproduces a bug on purpose
  • shown as a bug, not a result
Stage 06States
  • empty alerts can be correct
  • legacy captions are not fixture measurements
Persistent synthetic disclosureAttribution limitations statedNo digest sending needed

Figures describe the rendered synthetic run. The 200% test shows a known bug, not performance, and legacy captions aren’t fixture measurements.

Visibility / search / CRMDistinct source systems
Processed datasetsDefined cohorts and reporting scope
Reporting viewsPipeline, visibility, opportunities, digest

Seven views: pipeline attribution, visibility, keywords, opportunities, reporting. A scheduled workflow configures Peec refreshes; current execution unverified.

The seven views are the real ones: Pipeline Attribution, GEO Share of Voice, AI Attribution, Keyword Rankings, Content Opportunities, Win Log, Digest & Alerts. Every number keeps a path back to the source I defined it from.

Attribution decisions

An AI-labelled deal is not proof that AI generated revenue. Even its share of pipeline can mislead: the synthetic test shows an outbound deal entering the numerator while the denominator counts inbound deals only. I use that defect to make the reporting boundary explicit, not to present the percentage as a valid result.

Explicit definitions make a dashboard less pretty and more honest: an attractive percentage can’t hide mismatched populations or stale data.

Synthetic validation

The test set, including the reproducible denominator defect

The fixture includes an AI-labelled outbound deal on purpose: 3 AI-labelled inbound of 8 → 37.5% honestly; counting every AI-labelled deal shows 50%, the defect, reproducible.

Other tests: empty denominators, conflicting sources, duplicate IDs, filters, stale snapshots, brand-prompt exclusion, designed criteria, not executed results.

No private code, CRM records or real company charts here. The recorded run used synthetic fixtures against the original application, reporting behaviour, not live refreshes, adoption or business impact.

The setup

Runs locally: a Streamlit application on 127.0.0.1:8501 over synthetic fixtures, seven views, one router. An application-level Python guard blocks live Peec, GSC, HubSpot and Slack traffic. The weekly digest is copy-ready output; nothing is auto-sent. The fixtures mirror the original sources. 24 allowlisted files pinned to a commit, so every render is reproducible, and empty alert states stay visible: empty can be the correct answer.

Results and limitations

¹ Personal implementation scope and AI assistance remain to be finalized. Employer publication clearance is separate from source access. No employer code, records or URLs here.

What it produces · rendered from synthetic fixtures02
Cello GEO/SEO Weekly Digest — Oct 23, 2026
CONTENT GAPS (top 3):
• "synthetic referral software" — 1,000 impressions, position 2.8
• "synthetic referral api" — 600 impressions, position 8.0
AI CITATIONS:
• No significant changes this week
PIPELINE:
• AI deal share: 66.7% in 2026-10 (+16.7pp vs prior month)
• Total AI-attributed deals: 7 (QP Live: 4)
rendered from synthetic fixturesAI deal share carries the known denominator defect, shown as rendered, not as a valid business metricSoV before 4 May 2026 includes archived prompts, indicative onlyempty alerts are a correct state
Inputs → lineage → priorities → digest: one copy-paste block, ready for Slack.Produced by the original application on invented data. Every figure is a synthetic fixture; the AI-share line carries its known denominator defect, the disclosure travels with the number.

What I learned

Decide what you’ll do with the number before you build the chart. Definitions first, even when it slows the dashboard down, trust is worth the extra click. Reporting that changes no decision is decoration.