Data Client
GA4 Reports reads Google Analytics data through GA4ReportsDataClientInterface, persists daily and page metrics, then renders admin widgets from stored rows. The package binds a real client when config is complete and a null client when it is not.
Config Keys
Section titled “Config Keys”| Key | Use |
|---|---|
capell-ga4-reports.enabled | Enables sync and admin reporting. |
capell-ga4-reports.property_id | GA4 property ID. |
capell-ga4-reports.credentials_path | Service account credentials path. |
capell-ga4-reports.sync_days | Default lookback window for sync actions. |
capell-ga4-reports.route_slug | Admin route slug. |
capell-ga4-reports.tables.* | Table-name overrides and protected table registration. |
Prefer settings UI values when a host app exposes them; config is still the package fallback.
Swap the Data Client
Section titled “Swap the Data Client”Use the contract for tests, local demos, or a different analytics backend.
use Capell\GA4Reports\Contracts\GA4ReportsDataClientInterface;use Capell\GA4Reports\Data\GA4ReportsDailyMetricData;use Capell\GA4Reports\Data\GA4ReportsPageMetricData;use Capell\GA4Reports\Data\GA4ReportsWindowData;
final class DemoGA4ReportsDataClient implements GA4ReportsDataClientInterface{ public function isConfigured(): bool { return true; }
public function dailyMetrics(GA4ReportsWindowData $window): array { return [ new GA4ReportsDailyMetricData( propertyId: $window->propertyId, metricDate: $window->startsAt, totalUsers: 12, sessions: 18, screenPageViews: 42, engagedSessions: 10, engagementRate: 0.56, averageSessionDuration: 38.5, eventCount: 64, conversions: 1, ), ]; }
public function pageMetrics(GA4ReportsWindowData $window): array { return [ new GA4ReportsPageMetricData( propertyId: $window->propertyId, metricDate: $window->startsAt, pagePath: '/about', pageTitle: 'About', totalUsers: 5, sessions: 7, screenPageViews: 11, eventCount: 14, conversions: 0, ), ]; }}
$this->app->singleton(GA4ReportsDataClientInterface::class, DemoGA4ReportsDataClient::class);Return empty arrays when the backend has no data. Throw GA4ReportsApiException only for failures operators need to see.
Verification
Section titled “Verification”vendor/bin/pest packages/ga4-reports/tests --configuration=phpunit.xml