The Google UA Property is going away from July 2023. Google is implementing the Google Analytics V4. Universal Analytics will no longer process new data in standard properties beginning on 1 July 2023. Prepare now by setting up and switching over to a Google Analytics 4 property. Learn More
The Google Analytics data will only be available through the GCP API.
Genlytics is a powerful Google Analytics 4 (GA4) package for Laravel, completely rewritten following SOLID principles with Repository pattern, Event-driven architecture, and performance optimizations. The package integrates seamlessly with your Laravel application, providing intelligent caching, background job processing, and real-time analytics updates.
- Repository Pattern - Abstracted data access layer for easy testing and extension
- Event-Driven - Decoupled event system for extensibility
- Intelligent Caching - Automatic cache management with configurable TTL (90%+ API call reduction)
- Background Jobs - Non-blocking analytics queries for better performance
- Real-Time Updates - Automatic refresh scheduling for live dashboards
- Type Safety - Full type hints and comprehensive PHPDoc
- Error Handling - Robust error handling with logging
- Comprehensive Tests - 52 test cases with 83+ assertions
- Backward Compatible - Existing code works without changes
- Single Responsibility - Each class has one clear purpose
- Dependency Inversion - Dependencies on abstractions, not concretions
- Interface Segregation - Focused, specific interfaces
- Open/Closed - Extensible via interfaces without modification
- PHP 8.1 or higher
- Laravel 9.0 or higher
- Google Analytics 4 (GA4) property
- Google Cloud Platform project with Analytics Data API enabled
- Service account with Analytics access
Install the package via Composer:
composer require zfhassaan/genlyticsThe package supports Laravel's auto-discovery, so the service provider and facade will be automatically registered. No manual configuration needed!
If you prefer manual registration, add to config/app.php:
'providers' => [
// ...
zfhassaan\genlytics\provider\AnalyticsServiceProvider::class,
],
'aliases' => [
// ...
'Genlytics' => zfhassaan\genlytics\facades\AnalyticsFacade::class,
],php artisan vendor:publish --tag=genlytics-configOr publish everything:
php artisan vendor:publish --provider="zfhassaan\genlytics\provider\AnalyticsServiceProvider"Add to your .env file:
# Required
GENLYTICS_PROPERTY_ID=your-property-id-here
GENLYTICS_CREDENTIALS=storage/app/analytics/service-account.json
# Optional - Cache Configuration
GENLYTICS_ENABLE_CACHE=true
GENLYTICS_CACHE_LIFETIME=1440
# Optional - Background Jobs
GENLYTICS_USE_BACKGROUND_JOBS=true
GENLYTICS_QUEUE_CONNECTION=redis
GENLYTICS_QUEUE_NAME=default
# Optional - Real-Time Updates
GENLYTICS_ENABLE_REALTIME_UPDATES=true
GENLYTICS_REALTIME_CACHE_LIFETIME=30- Create GA4 Property - Create a Google Analytics 4 property
- Enable Analytics Data API - Enable in Google Cloud Console
- Create Service Account - Create service account in GCP
- Generate JSON Key - Download service account JSON key
- Grant Analytics Access - Add service account email to GA4 property with Viewer/Analyst role
See Installation Guide for detailed steps.
use zfhassaan\genlytics\Genlytics;
$analytics = new Genlytics();Or use the facade:
use Genlytics;
$result = Genlytics::runReports(...);Or dependency injection:
use zfhassaan\genlytics\Genlytics;
class AnalyticsController extends Controller
{
public function __construct(
protected Genlytics $analytics
) {}
}$period = [
'start_date' => '7daysAgo',
'end_date' => 'today'
];
$dimensions = [['name' => 'country']];
$metrics = [['name' => 'activeUsers']];
$result = $analytics->runReports($period, $dimensions, $metrics);$dimensions = [
['name' => 'country'],
['name' => 'city'],
['name' => 'deviceCategory'],
];
$metrics = [
['name' => 'activeUsers'],
['name' => 'sessions'],
['name' => 'bounceRate'],
];
$result = $analytics->runReports($period, $dimensions, $metrics);$options = [
'limit' => 100,
'offset' => 0,
'orderBys' => [
[
'metric' => [
'metricName' => 'activeUsers'
],
'desc' => true
]
]
];
$result = $analytics->runReports($period, $dimensions, $metrics, $options);$result = $analytics->runReports(
$period,
$dimensions,
$metrics,
[],
true // Force refresh from API
);$dimensions = [['name' => 'country']];
$metrics = [['name' => 'activeUsers']];
$result = $analytics->runRealTime($dimensions, $metrics);$period = [
'start_date' => '30daysAgo',
'end_date' => 'today'
];
// Single dimension
$result = $analytics->runDimensionReport($period, 'country');
// Multiple dimensions
$result = $analytics->runDimensionReport($period, ['country', 'city']);{
"data": [
{
"dimensions": {
"country": "United States",
"city": "New York"
},
"metrics": {
"activeUsers": "1250",
"sessions": "1500"
}
}
],
"metadata": {
"count": 1,
"timestamp": "2024-01-01T00:00:00Z"
}
}Genlytics automatically caches analytics data to reduce API calls:
// Cache is enabled by default
// Configure in config/analytics.php or .env
GENLYTICS_ENABLE_CACHE=true
GENLYTICS_CACHE_LIFETIME=1440 // 24 hours in minutesBenefits:
- 90%+ reduction in API calls
- Faster response times
- Lower API quota usage
Process analytics queries in the background:
// Enable in config
GENLYTICS_USE_BACKGROUND_JOBS=true
// Requires queue worker
php artisan queue:workBenefits:
- Non-blocking requests
- Better user experience
- Automatic cache refresh
Automatic real-time data refresh:
// Enable in config
GENLYTICS_ENABLE_REALTIME_UPDATES=true
GENLYTICS_REALTIME_CACHE_LIFETIME=30 // secondsListen to analytics events:
use zfhassaan\genlytics\Events\AnalyticsDataFetched;
use Illuminate\Support\Facades\Event;
Event::listen(AnalyticsDataFetched::class, function ($event) {
Log::info('Analytics data fetched', [
'type' => $event->reportType,
'from_cache' => $event->fromCache,
'data_count' => count($event->data),
]);
});Available Events:
-
AnalyticsDataRequested- Fired when data is requested -
AnalyticsDataFetched- Fired when data is successfully fetched -
AnalyticsCacheUpdated- Fired when cache is updated -
AnalyticsQueryFailed- Fired when query fails
For advanced usage, access the repository:
use zfhassaan\genlytics\Contracts\AnalyticsRepositoryInterface;
$repository = app(AnalyticsRepositoryInterface::class);
$response = $repository->runReport(
$dateRange,
$dimensions,
$metrics,
$options
);Publish test cases to your application for customization:
php artisan vendor:publish --tag=genlytics-testsThis publishes:
-
tests/Genlytics/TestCase.php- Base test case -
tests/Genlytics/Unit/- Unit tests -
tests/Genlytics/Feature/- Feature tests -
tests/Genlytics/Integration/- Integration tests
See PUBLISHING.md for details.
Run the test suite:
composer testOr with coverage:
composer test-coverageTest Coverage:
- 52 test cases
- 83+ assertions
- All major components tested
- Mocks for external dependencies (no real API calls needed)
php artisan genlytics:refresh-cache --clearphp artisan genlytics:refresh-cache --type=report
php artisan genlytics:refresh-cache --type=realtimeuse zfhassaan\genlytics\Contracts\CacheManagerInterface;
$cacheManager = app(CacheManagerInterface::class);
// Clear specific cache
$cacheManager->forget('report:abc123');
// Clear all cache
$cacheManager->clear();class DashboardController extends Controller
{
public function analytics(Genlytics $analytics)
{
$period = [
'start_date' => '30daysAgo',
'end_date' => 'today'
];
$metrics = [['name' => 'activeUsers']];
$users = $analytics->runReports($period, [], $metrics);
return view('dashboard.analytics', [
'users' => $users->getData(true)
]);
}
}public function liveVisitors(Genlytics $analytics)
{
$metrics = [['name' => 'activeUsers']];
$result = $analytics->runRealTime([], $metrics);
return response()->json([
'visitors' => $result->getData(true)['data'][0]['metrics']['activeUsers'] ?? 0
]);
}public function topCountries(Genlytics $analytics)
{
$period = ['start_date' => '30daysAgo', 'end_date' => 'today'];
$dimensions = [['name' => 'country']];
$metrics = [['name' => 'activeUsers']];
$options = [
'orderBys' => [
[
'metric' => ['metricName' => 'activeUsers'],
'desc' => true
]
],
'limit' => 10
];
return $analytics->runReports($period, $dimensions, $metrics, $options);
}try {
$result = $analytics->runReports($period, $dimensions, $metrics);
} catch (\Exception $e) {
Log::error('Analytics error', [
'error' => $e->getMessage(),
]);
return response()->json([
'error' => 'Failed to fetch analytics data'
], 500);
}- Intelligent Caching - Reduces API calls by 90%+
- Background Processing - Non-blocking requests
- Query Optimization - Efficient parameter handling
- Real-Time Scheduling - Automatic refresh management
- Installation Guide - Step-by-step setup
- Configuration Guide - All configuration options
- Usage Guide - Usage examples and best practices
- Troubleshooting - Common issues and solutions
- How to Release - Release process
- Contributing - Contribution guidelines
- Architecture - Architecture documentation
- Migration Guide - Migration from v1.x to v2.0
See CHANGELOG.md for all changes.
- Complete rewrite following SOLID principles
- Repository pattern implementation
- Event-driven architecture
- Intelligent caching system
- Background job processing
- Real-time updates
- Comprehensive test suite
- Enhanced error handling
- Full backward compatibility
The MIT License (MIT). Please see License File for more information.
- Author: Hassaan Ali
- Email: zfhassaan@gmail.com
Made with ❤️ for the Laravel community
