This page documents every KPI on the Funnel Overview and the product tables (Solar & Storage, Generators) of the FSP Marketing Dashboard, plus the Total / By Region / By Source dimensions and the drilldown / investigate queries. All numbers reproduce the fsp-bi-hub/f2p_2026 reports directly from HubSpot data using a handful of server-aggregated GROUP BY queries.

<aside> 💡

The shared base filters (new_contacts_base, contacted_leads_base, set_appointments_base, closed, cancelled), the product scopes (ProductScopes), the timezone bucketing (ReportingTimeZone), and the caching conventions are documented once on the Conventions & Shared Filters page. This page references them by name rather than repeating them in full.

</aside>

Code citations point at:


1. Data flow (controller → service → cache)

The React funnel table calls GET /api/v1/funnel with a set of query params. Api::V1::FunnelController#index renders cached_metrics, which wraps compute_metrics in Rails.cache.fetch (funnel_controller.rb:172-204).

Product routing (compute_metrics, funnel_controller.rb:177-204):

Params (all whitelisted in the controller; funnel_controller.rb:206-245):

Param Method Validated by Default
product product ProductScopes::ALL_PRODUCTS overview
scheduler scheduler ProductScopes.valid_scheduler all (Web / Call)
appt_type appt_type ProductScopes.valid_appt_type all (Sit / Virtual)
source_group source_group ProductScopes.valid_source_grouping cac_category
region region_filter ProductScopes.valid_region nil (no cross-filter)
source source_filter ProductScopes.valid_source_category nil (no cross-filter)
start_date start_date Date.parse, fallback 2026-01-01 Jan 1 2026 (F2P year)
end_date end_date Date.parse, fallback today (Central) ReportingTimeZone.current_date

Cache key & expiry (funnel_controller.rb:11-15, 247-250):