Insights — Improvement & Growth Plan
Package: capell-app/insights · Kind: extension (admin + frontend) · Tier: premium · Product group: Capell Growth · Bundle: growth · Status: Complete
1. Snapshot
Section titled “1. Snapshot”Insights is a first-party, consent-aware web-analytics extension for Capell. The frontend surface ships a vanilla JS tracker and overrideable consent banner injected via a RenderHookLocation::BodyEnd hook (src/Support/RenderHooks/RegisterInsightsTrackerHook.php) plus two public POST endpoints (src/Http/Controllers/InsightsBeaconController.php, InsightsConsentController.php) backed by Actions (RecordInsightsEventsAction, ValidateInsightsBeaconRequestAction, UpdateInsightsConsentAction, CreateInsightsVisitAction, MirrorInsightsConsentToPrivacyCenterAction). The admin surface adds an InsightsPage, seven dashboard widgets, three overview stats, daily aggregate rollups, and a settings schema, fed by Build*QueryAction aggregates over four tables (insights_visits, insights_consents, insights_events, insights_daily_rollups). Deps: lorisleiva/laravel-actions, spatie/laravel-data, spatie/laravel-package-tools; requires capell-app/admin|core|frontend, supports capell-app/privacy-center.
Current marketplace summary (verbatim): “Cookie-light, GDPR-aware web analytics built into your Capell admin — page views, clicks, visitor journeys, and consent, with no third-party scripts and no data leaving your server.” The manifest now lists the extension card, the settings screen, and two styled route-backed public fixture screenshots proving the frontend tracker and packaged consent banner render through the Insights BodyEnd hook. The blank dashboard/widget captures remain committed runner evidence but are no longer promoted as buyer-facing media until analytics demo data produces populated Capell widgets.
2. Improvements (existing functionality)
Section titled “2. Improvements (existing functionality)”- Done/Shipped: JS tracker bootstraps a visit on the first recordable hit. The beacon action now creates a visit when no
visit_idis supplied, the server-resolved region is outside UK/Europe, consent is not required for all regions, and the batch contains at least one non-ignored event. The events endpoint returns the freshvisit_id, the tracker forces fetch instead ofsendBeaconfor that first flush, and then stores the id for later beacon batches. Focused coverage documents outside-region creation, consent-required suppression, and the first-flush JS response path. —src/Actions/RecordInsightsEventsAction.php,src/Http/Controllers/InsightsBeaconController.php,resources/js/capell-insights.js— M - Closed: derive
hash_saltfromAPP_KEYby default —ResolveInsightsHashSaltActionnow treats empty, whitespace-only, and legacy publiccapell-insightssalts as placeholders, derives the visitor hash salt from a usableAPP_KEY, and falls back to the public legacy salt only when no usable app key exists.InsightsHealthCheckfails that unsafe fallback state without exposing configured secrets in diagnostics. — privacy hardening —src/Actions/ResolveInsightsHashSaltAction.php,src/Actions/CreateInsightsVisitAction.php,src/Actions/UpdateInsightsConsentAction.php,src/Health/InsightsHealthCheck.php— S - Done/Shipped:
ConsentRegionResolveris wired server-side.InsightsConsentControllerignores the client-suppliedregionfor trust decisions and passesResolveConsentRegionAction::run()intoUpdateInsightsConsentAction; the beacon endpoint now uses the same server-side region resolution before creating first visits. — fixes attacker-controllable GDPR jurisdiction + removes dead code —src/Http/Controllers/InsightsConsentController.php,src/Http/Controllers/InsightsBeaconController.php,src/Actions/CreateInsightsVisitAction.php,src/Support/Consent/ConsentRegionResolver.php— M - Done/Shipped: chunked retention purge.
PurgeInsightsDataAction::handlenow deletes eligible events, consents, and visits through bounded ID batches instead of unbounded table deletes. Batch size defaults topurge_batch_sizeand can be overridden when the Action is called, keeping the purge command behavior stable while reducing lock/replication risk on high-write installs. —src/Actions/PurgeInsightsDataAction.php,config/capell-insights.php— S - Done/Shipped: cache dashboard aggregates. Dashboard aggregate Actions now remember materialized results behind stable keys that include locale/window/site/language/limit inputs, using
dashboard_cache_ttl_secondsand theinsightscache tag when the current store supports tags. Event recording, consent updates, and retention purge writes flush the tagged dashboard cache on tag-capable stores; non-tag stores still get bounded TTL protection. —src/Actions/RememberInsightsDashboardAggregateAction.php,src/Actions/Build*QueryAction.php,src/Actions/RecordInsightsEventsAction.php,src/Actions/PurgeInsightsDataAction.php— M - Done/Shipped: Reconcile registered vs on-disk migrations —
InsightsServiceProvider::configurePackagenow registers only the four migration files present indatabase/migrations/, andInsightsMigrationsTestasserts every registered migration name has a file on disk. — fresh-install hazard closed —src/Providers/InsightsServiceProvider.php,tests/Feature/Database/InsightsMigrationsTest.php— S - Done/Shipped: Flesh out the health check.
InsightsHealthChecknow reports storage-table presence, beacon route registration, frontend tracker render-hook output, monthly retention purge scheduling, and non-default visitor hash secret diagnostics, with pass/fail coverage. — Diagnostics value —src/Health/InsightsHealthCheck.php,tests/Feature/Health/InsightsHealthCheckTest.php— M - Done/Shipped: session boundaries for journeys.
RecordInsightsEventsActionnow rotates a persistent visit cookie into a freshInsightsVisitwhenlast_seen_atis older thansession_timeout_minutes(30 minutes by default). The new visit preserves consent region/status and receives the queued cookie, so event sequences restart per session and journey widgets no longer merge returning visitor activity into one historical timeline. —src/Actions/RecordInsightsEventsAction.php,config/capell-insights.php,capell.json— M - Done/Shipped: daily rollups for long-range reports. The package now owns an
insights_daily_rollupstable plusRebuildInsightsDailyRollupsActionandinsights:rollups:rebuildcommand, scheduled daily. Popular and trending page reports use day/path/type aggregate rows for day-aligned windows and fall back to raw events until aggregates exist, keeping fresh installs correct while reducing long-range dashboard scans. —database/migrations/2026_06_06_000001_create_insights_daily_rollups_table.php,src/Actions/RebuildInsightsDailyRollupsAction.php,src/Actions/BuildPopularPagesQueryAction.php,src/Actions/BuildTrendingPagesQueryAction.php— L - Done/Shipped: digest and CSV export seam.
BuildInsightsDigestActionassembles overview stats, popular pages, acquisition sources, and funnel conversion data for a window;ExportInsightsDigestCsvActionserializes the digest without reintroducing public render work or admin query coupling. —src/Actions/BuildInsightsDigestAction.php,src/Actions/ExportInsightsDigestCsvAction.php— M
3. Missing Features (gaps)
Section titled “3. Missing Features (gaps)”Tied to capabilities[] = insights, insights-admin, insights-frontend, insights-consent-banner, insights-acquisition-reports, insights-conversion-funnels, insights-traffic-filtering, insights-session-journeys, insights-daily-rollups, insights-privacy-signals, insights-privacy-center-mirror, beacon, cache-blocking.
- Done/Shipped: consent banner / opt-in UI. The BodyEnd hook now renders an overrideable
capell-insights::components.consent-bannerview by default, gated byconsent_banner_enabled. The tracker shows it when no current-policy consent decision is stored, supports accept/reject/granular choices, posts to the consent endpoint, stores the decision locally withpolicy_version, and hides the banner after a successful response. —resources/views/components/consent-banner.blade.php,resources/js/capell-insights.js,config/capell-insights.php - Done/Shipped: Referrer & UTM analytics.
BuildAcquisitionSourcesQueryActionnow surfaces storedutm_source,utm_medium,utm_campaign, andreferrer_urldata in an Acquisition Sources dashboard widget. The report groups visits by campaign, referrer host, or direct traffic; it is cache-keyed by the dashboard window and declared asinsights-acquisition-reportsin the manifest. —src/Actions/BuildAcquisitionSourcesQueryAction.php,src/Filament/Widgets/AcquisitionSourcesWidget.php,capell.json - Done/Shipped: pre-aggregated rollups / retention tiers (differentiator). Daily rollups now aggregate path × day × type counts for popular/trending page dashboards, with raw-event fallback until aggregates exist. Deeper separate retention tiers for raw-vs-aggregate data remain future depth.
- Done/Shipped: funnels & conversions (differentiator). Companion packages can now call
RecordConversionActionto record typed conversion events with source package/value/currency metadata, andBuildFunnelConversionReportActionsummarizes named event steps by unique visits and conversion rate. The beacon metadata contract also allows conversion metadata keys for browser/custom integrations. —src/Actions/RecordConversionAction.php,src/Actions/BuildFunnelConversionReportAction.php,src/Data/InsightsEventMetadataData.php - Done/Shipped: bot / self-traffic filtering.
RecordInsightsEventsActionnow suppresses ignored IPs and user-agent patterns before creating first visits or appending events to existing visits. The package config ships default bot, crawler, monitor, Lighthouse, PageSpeed, Pingdom, GTmetrix, and headless-browser patterns, withignored_ipsavailable for agency/staff office traffic. —src/Actions/RecordInsightsEventsAction.php,config/capell-insights.php,capell.json - Visit duration / bounce / entry-exit (table-stakes).
started_at/last_seen_atexist on the visit but no engaged-time, bounce-rate, or entry/exit-page metrics are computed. - Done/Shipped: consent expiry & re-prompt. Browser decisions are stored with
policy_version, the packaged banner reappears when the configured policy version changes, and the server refuses analytics recording in consent-required regions when the latest consent is for an old policy or older thanconsent_expires_days. - Done/Shipped: server-side event API surface for other packages.
RecordConversionActiongives seo-suite/campaign-studio style packages an explicit in-process analytics contract without exposing a public unauthenticated write API.BuildFunnelConversionReportActionprovides the matching reporting surface for bundle dashboards. - Done/Shipped: digest/export reporting. First-party analytics can now be summarized as a typed digest and exported as CSV, giving GA4 Reports, Campaign Studio, Email Studio, and future scheduled report consumers a consistent report seam.
- Done/Shipped: Do-Not-Track / Global Privacy Control honoring and server-side re-consent (differentiator).
honor_privacy_signalsnow defaults on. The browser tracker exits before registering listeners whennavigator.globalPrivacyControl,navigator.doNotTrack, ornavigator.msDoNotTrackis active, and the beacon endpoint returns no-content without validation/persistence forSec-GPC: 1,DNT: 1, orX-Do-Not-Track: 1. Consent-required regions now record analytics only when the latest consent matches the configuredpolicy_versionand remains insideconsent_expires_days. —resources/js/capell-insights.js,resources/views/tracker.blade.php,src/Actions/ValidateInsightsBeaconRequestAction.php,src/Actions/RecordInsightsEventsAction.php
4. Issues / Risks
Section titled “4. Issues / Risks”- Done/Shipped: first-visit data loss is fixed for no-consent-required regions. See §2 item 1. The no-visit beacon path now creates a visit, records the first non-ignored event, returns a visit id, and refuses to create visits when the server region still requires consent.
- Done/Shipped: GDPR region is resolved server-side.
InsightsConsentControllerand the first-visit beacon path both useResolveConsentRegionAction; client-supplied region remains accepted as request shape only, not as the trust source for consent enforcement. - Reversible visitor hashes (PII). Closed for default installs: empty or legacy
hash_saltvalues now derive fromAPP_KEY, and Diagnostics fails if the package would fall back to the public legacy salt. Remaining risk is limited to installs running without a usableAPP_KEYand without a privatehash_salt. - Cache-safety of the beacon: OK. The render hook output is static config + a file-read script cached
rememberForeverkeyed by file mtime (src/Actions/GetInsightsTrackerScriptAction.php); the blade does no DB query and leaks no model IDs/labels/permissions (resources/views/tracker.blade.php) — consistent withcacheSafety.cacheable:false, sensitiveOutput:false. The render hook now suppresses tracker output on configuredignored_pathssuch as/admin*, matching the server-side beacon ignore policy and avoiding admin/Livewire script emission. —src/Support/RenderHooks/RegisterInsightsTrackerHook.php,tests/Feature/Frontend/InsightsRenderHookTest.php - Closed: migration drift.
InsightsMigrationsTestnow asserts all registered migration names exist on disk, and the provider no longer references phantom06/site-FK migrations. - Closed: core manifest mismatches.
capell.jsonnow declaresCapell\Insights\Settings\InsightsSettings, the generated Shield page permissionView:InsightsPage, and the shipped marketplace screenshot set.ManifestRequirementsTestasserts those declarations and the screenshot files.commands.doctorremainsnullbecause no package command ships; Diagnostics consumes the health-check class directly. - Closed: single-event and legacy import Actions retained intentionally. The single-event family is not on the browser beacon request path, but it remains a supported server-side integration path:
RecordConversionActioncallsRecordCustomActionAction,docs/tracking-and-consent.mddocuments custom server-side events, andImportLegacyPageViewsActionis the migration-owned idempotent importer for legacypage_views. Removing these would regress package integrations and fresh-upgrade migration behavior. - Performance budget realism.
frontendRenderBudgetMs:20is plausible (cached script), short-TTL dashboard aggregate caching reduces repeated widget scans, and daily rollups now replace raw page-event scans for day-aligned popular/trending dashboards. High write volume oninsights_eventsremains the principal scaling risk for live and custom-event reports. - i18n. Strings are translated via
capell-insights::keys (good), but the config keytrack_form-buildercontains a hyphen and is mirrored as a setting/label key — brittle and inconsistent with snake_case siblings (config/capell-insights.php,src/Filament/Settings/InsightsSettingsSchema.php:34). - Test gaps. First-visit auto-creation, consent-required suppression, server-side region resolution, manifest declarations, render-hook banner output, admin-path render-hook suppression, health-check render/schedule probes, JS banner primitives, chunked retention purge behavior, dashboard cache helper behavior, and acquisition-source grouping have focused coverage. Remaining gaps: browser-level consent-banner interaction coverage and deeper long-window rollup coverage.
5. Marketplace & Selling
Section titled “5. Marketplace & Selling”Critique. The manifest summary and package description now lead with the buyer benefit (first-party, GDPR-aware analytics without third-party scripts). The gallery references the extension card, settings screen, and two styled package-owned public fixture captures for the active tracker and consent-banner flow. Remaining media upside is optional: recapture populated dashboard/widgets before promoting admin analytics screenshots, and promote dark admin alternates only if Marketplace wants explicit dark-mode gallery entries.
Improved 1-sentence summary. “Cookie-light, GDPR-aware web analytics built into your Capell admin — page views, clicks, visitor journeys, and consent, with no third-party scripts and no data leaving your server.”
Improved 3–4 sentence description. “Insights gives Capell sites first-party traffic analytics that respect privacy by default: it records page views, clicks, and visitor journeys server-side, hashes visitor identifiers, and gates UK/EU tracking behind consent. Dashboards for popular pages, trending pages, top actions, and recent journeys live right inside the admin Marketing Studio — no Google Analytics, no cookie soup, no tag manager. Retention windows and an automatic purge keep data lean and compliant. When Privacy Center is installed, consent decisions are mirrored into your central consent ledger automatically.”
Media gaps. Marketplace now references only the buyer-worthy settings and public fixture captures. The overview/dashboard widget PNGs were demoted after visual inspection showed mostly blank Insights admin pages rather than populated analytics widgets. The previous frontend tracker image was demoted and deleted because visual inspection showed a mostly blank Demo page; the replacement fixture is guarded behind CAPELL_INSIGHTS_SCREENSHOT_FIXTURES_ENABLED and is enabled by the screenshot wrapper only for captures. Dark alternates remain available in docs/screenshots/ but are not yet promoted.
Pricing / tier / bundle positioning. Premium tier in the growth bundle is now more defensible because first-visit recording and the packaged consent banner are in place. Insights is the natural data backbone of the bundle: position seo-suite and campaign-studio as dependents that record conversions/funnels through an Insights server-side contract (cross-sell), and lean on the existing supports: capell-app/privacy-center mirror as a compliance upsell. Bundle messaging: “Insights measures it, Campaign Studio acts on it, SEO Suite ranks for it.”
Differentiators / value props / target buyer. Differentiators: privacy-first (no third-party scripts, hashed identifiers, consent-gated, Privacy Center mirror), fully in-admin, multi-site/locale aware. Target buyer: privacy-conscious agencies and site owners on Capell who want GA-style insight without GA’s compliance and cookie overhead.
Keywords/tags (8–12). web-analytics, privacy-friendly-analytics, gdpr, cookie-consent, first-party-tracking, page-views, click-tracking, visitor-journeys, marketing-studio, consent-management, filament, capell.
6. Prioritized Roadmap
Section titled “6. Prioritized Roadmap”| Item | Bucket | Effort | Impact | Section ref |
|---|---|---|---|---|
| Done/Shipped: Fix first-visit visit creation so default traffic is actually recorded | Done | M | High | §2, §4 |
Done/Shipped: Resolve consent region server-side (wire ConsentRegionResolver) | Done | M | High | §2, §4 |
hash_salt from APP_KEY; enforce non-default in health check | Done | S | High | §2, §4 |
| Reconcile registered-vs-missing migrations and README persistence docs | Done | S | High | §2, §4 |
Fix manifest: populate settings[], permissions[], and shipped screenshots | Done | S | Med | §4, §5 |
| Done/Shipped: Ship a themable consent banner / frontend component | Done | M | High | §3 |
| Done/Shipped: Chunk the retention purge | Done | S | Med | §2, §4 |
Done/Shipped: Cache dashboard aggregates (TTL + insights tag) | Done | M | High | §2, §4 |
| Done/Shipped: Expand health check with render-hook and purge-schedule probes | Done | S | Med | §2, §4 |
| Done/Shipped: Add referrer + UTM / channel reports (data already captured) | Done | M | High | §3 |
| Done/Shipped: Add bot + admin/self-traffic filtering | Done | M | Med | §3 |
| Done/Shipped: Per-session journey boundaries (sequence reset) | Done | M | Med | §2 |
| Done/Shipped: Daily rollup table + retention tiers for fast long-range reports | Done | L | High | §3 |
| Done/Shipped: Funnels & conversion reporting + server-side event contract for bundle packages | Done | L | High | §3, §5 |
| Done/Shipped: Add a route-backed public screenshot fixture that renders Insights BodyEnd hooks, then capture/promote tracker and consent-banner PNGs | Done | S | Med | §5 |
Closed 2026-06-06: confirmed single-event Action family / ImportLegacyPageViews are live integration and migration contracts, not dead code | Done | S | Low | §4 |
| Done/Shipped: Honor DNT / GPC; server-side consent expiry/re-prompt | Done | M | Med | §3 |
| Done/Shipped: Add Insights digest builder and CSV export seam | Done | M | Med | §2, §3 |
| Recapture populated Capell analytics dashboard/widget screenshots before promoting them as buyer-facing media | Future | S | Med | §5 |
Completion Review
Section titled “Completion Review”Completed 2026-06-08. Every current manifest-backed roadmap row is closed, including the retained single-event Action family / legacy importer, tracker/banner privacy controls, dashboard aggregate/rollup surfaces, server-side conversion contract, admin-path tracker suppression, and the new digest/export seam. Populated admin dashboard recapture remains optional future media polish rather than an active completion blocker.