Search by

zfhassaan / genlytics

zfhassaan

Genlytics is a powerful Google Analytics Composer package that allows for easy data collection, analysis, and visualization. Optimized for SEO, it helps improve website performance and drive more organic traffic.

Package info

github.com/zfhassaan/genlytics

pkg:composer/zfhassaan/genlytics

Statistics

Installs: 133

Dependents: 0

Suggesters: 0

Stars: 5

Open Issues: 0

v1.0.5 2026-10-25 12:11 UTC

This package is auto-updated.

Last update: 2026-10-25 15:46:22 UTC


README

Genlytics

Latest Version on Packagist MIT Licensed Tests Total Downloads Laravel 10–13 PHP 8.0–8.6 Coverage

Disclaimer

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.

About

Genlytics is a powerful Google Analytics 4 (GA4) package for Laravel, completely rewritten 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.

Key Features

  • 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 - 160 test cases with 484 assertions (90.4% code coverage, 100% pass rate)
  • Backward Compatible - Existing code works without changes

Architecture Highlights

  • 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

Requirements

  • PHP: ^8.0 || ^8.1 || ^8.2 || ^8.3 || ^8.4 || ^8.5 || ^8.6
  • Laravel Framework: 10.x, 11.x, 12.x, and 13.x
  • Google Analytics 4 (GA4) property
  • Google Cloud Platform project with Analytics Data API enabled
  • Service account with Analytics access

Installation

Install the package via Composer:

composer require zfhassaan/genlytics

Auto-Discovery

The package supports Laravel's auto-discovery, so the service provider and facade will be automatically registered. No manual configuration needed!

Manual Registration (Optional)

If you prefer manual registration, add to config/app.php:

'providers' => [
    // ...
    zfhassaan\genlytics\provider\AnalyticsServiceProvider::class,
],

'aliases' => [
    // ...
    'Genlytics' => zfhassaan\genlytics\facades\AnalyticsFacade::class,
],

Configuration

Publish Configuration

php artisan vendor:publish --tag=genlytics-config

Or publish everything:

php artisan vendor:publish --provider="zfhassaan\genlytics\provider\AnalyticsServiceProvider"

Environment Variables

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

Google Analytics Setup

  1. Create GA4 Property - Create a Google Analytics 4 property
  2. Enable Analytics Data API - Enable in Google Cloud Console
  3. Create Service Account - Create service account in GCP
  4. Generate JSON Key - Download service account JSON key
  5. Grant Analytics Access - Add service account email to GA4 property with Viewer/Analyst role

See Installation Guide for detailed steps.

Usage

🚀 Eloquent-Style Fluent Query Builder (Recommended)

Genlytics provides a fluent, expressive query builder modeled after Laravel's Eloquent ORM:

use zfhassaan\genlytics\facades\AnalyticsFacade as Genlytics;

// 1. Fluent queries with pre-defined date macros
$data = Genlytics::query()
    ->last7Days()
    ->dimensions(['country', 'city'])
    ->metrics(['activeUsers', 'sessions'])
    ->orderByDesc('activeUsers')
    ->limit(10)
    ->remember(3600) // Cache query for 1 hour
    ->get();

// 2. Direct Strongly-Typed DTO Casting
$pageDtos = Genlytics::query()->last30Days()->toPageDto();
foreach ($pageDtos as $page) {
    echo "{$page->path}: {$page->views} views
";
}

// 3. Direct Standardized Laravel API Resource Casting (with SemVer envelope)
return Genlytics::query()->last7Days()->toPageResource();

🛒 E-Commerce & Conversion Funnel Pipelines

Analyze GA4 multi-step conversion funnels, top products, and categories with zero boilerplate:

// Default GA4 purchase funnel (view_item -> add_to_cart -> checkout -> purchase)
$funnel = Genlytics::ecommerceFunnel('30daysAgo');
echo "Overall conversion: {$funnel->overallConversionRate}%
";

// Top products by revenue
$products = Genlytics::topProducts(limit: 10, period: 'last30Days');

// Top product categories
$categories = Genlytics::topCategories(limit: 10, period: 'last30Days');

⚡ Batch Multi-Reporting API

Fetch multiple distinct widget queries in a single HTTP request to eliminate GA4 quota overhead:

$batch = Genlytics::getBatchReports([
    'top_pages' => [
        'period' => 'last7Days',
        'dimensions' => ['pagePath'],
        'metrics' => ['screenPageViews'],
        'limit' => 5
    ],
    'top_countries' => [
        'period' => 'last7Days',
        'dimensions' => ['country'],
        'metrics' => ['activeUsers'],
        'limit' => 5
    ]
]);

Basic / Direct Usage

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
    ) {}
}

Running Reports

Basic Report

$period = [
    'start_date' => '7daysAgo',
    'end_date' => 'today'
];

$dimensions = [['name' => 'country']];
$metrics = [['name' => 'activeUsers']];

$result = $analytics->runReports($period, $dimensions, $metrics);

Multiple Dimensions and Metrics

$dimensions = [
    ['name' => 'country'],
    ['name' => 'city'],
    ['name' => 'deviceCategory'],
];

$metrics = [
    ['name' => 'activeUsers'],
    ['name' => 'sessions'],
    ['name' => 'bounceRate'],
];

$result = $analytics->runReports($period, $dimensions, $metrics);

With Options

$options = [
    'limit' => 100,
    'offset' => 0,
    'orderBys' => [
        [
            'metric' => [
                'metricName' => 'activeUsers'
            ],
            'desc' => true
        ]
    ]
];

$result = $analytics->runReports($period, $dimensions, $metrics, $options);

Force Refresh (Bypass Cache)

$result = $analytics->runReports(
    $period,
    $dimensions,
    $metrics,
    [],
    true // Force refresh from API
);

Real-Time Reports

$dimensions = [['name' => 'country']];
$metrics = [['name' => 'activeUsers']];

$result = $analytics->runRealTime($dimensions, $metrics);

Dimension Reports

$period = [
    'start_date' => '30daysAgo',
    'end_date' => 'today'
];

// Single dimension
$result = $analytics->runDimensionReport($period, 'country');

// Multiple dimensions
$result = $analytics->runDimensionReport($period, ['country', 'city']);

Response Format

{
    "data": [
        {
            "dimensions": {
                "country": "United States",
                "city": "New York"
            },
            "metrics": {
                "activeUsers": "1250",
                "sessions": "1500"
            }
        }
    ],
    "metadata": {
        "count": 1,
        "timestamp": "2024-01-01T00:00:00Z"
    }
}

Advanced Features

Caching

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 minutes

Benefits:

  • 90%+ reduction in API calls
  • Faster response times
  • Lower API quota usage

Background Jobs

Process analytics queries in the background:

// Enable in config
GENLYTICS_USE_BACKGROUND_JOBS=true

// Requires queue worker
php artisan queue:work

Benefits:

  • Non-blocking requests
  • Better user experience
  • Automatic cache refresh

Real-Time Updates

Automatic real-time data refresh:

// Enable in config
GENLYTICS_ENABLE_REALTIME_UPDATES=true
GENLYTICS_REALTIME_CACHE_LIFETIME=30  // seconds

Events

Listen 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

Using Repository Directly

For advanced usage, access the repository:

use zfhassaan\genlytics\Contracts\AnalyticsRepositoryInterface;

$repository = app(AnalyticsRepositoryInterface::class);

$response = $repository->runReport(
    $dateRange,
    $dimensions,
    $metrics,
    $options
);

Publishing Test Cases

Publish test cases to your application for customization:

php artisan vendor:publish --tag=genlytics-tests

This 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.

Testing & Code Coverage

Run the comprehensive test suite (160 tests, 484 assertions across 19 test suites with 90.4% code coverage):

# Run all tests
php packages/zfhassaan/genlytics/test-runner.php
# or with composer:
composer test:genlytics

# Run with testdox output
php packages/zfhassaan/genlytics/test-runner.php --testdox

# Run specific suite or test
php packages/zfhassaan/genlytics/test-runner.php --filter QuotaManagerTest

# Run code coverage report in terminal
php -d xdebug.mode=coverage packages/zfhassaan/genlytics/test-runner.php --coverage-text
# or:
composer test:genlytics:coverage

# Generate HTML code coverage report
php -d xdebug.mode=coverage packages/zfhassaan/genlytics/test-runner.php --coverage-html coverage
# or:
composer test:genlytics:coverage-html

Test Coverage Highlights:

  • 160 automated tests with 484 assertions (100% pass rate, 0 failures, 0 errors)
  • 90.43% line code coverage (1,692 / 1,871 lines covered)
  • Full isolation & mocks for external Google Analytics Data API calls
  • 100% coverage on Commands, Events, Realtime listeners, DTOs, Exceptions, and API Resources
  • Full test coverage for PST timezone midnight calculations, concurrency locks, and quota modes (consume_all, maximum_utilization)

Cache Management

Clear Cache

php artisan genlytics:refresh-cache --clear

Refresh Specific Cache

php artisan genlytics:refresh-cache --type=report
php artisan genlytics:refresh-cache --type=realtime

Programmatic Cache Management

use zfhassaan\genlytics\Contracts\CacheManagerInterface;

$cacheManager = app(CacheManagerInterface::class);

// Clear specific cache
$cacheManager->forget('report:abc123');

// Clear all cache
$cacheManager->clear();

Common Use Cases

Dashboard Widget

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)
        ]);
    }
}

Real-Time Visitor Count

public function liveVisitors(Genlytics $analytics)
{
    $metrics = [['name' => 'activeUsers']];
    $result = $analytics->runRealTime([], $metrics);
    
    return response()->json([
        'visitors' => $result->getData(true)['data'][0]['metrics']['activeUsers'] ?? 0
    ]);
}

Top Countries Report

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);
}

Error Handling

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);
}

Performance Optimizations

  1. Intelligent Caching - Reduces API calls by 90%+
  2. Background Processing - Non-blocking requests
  3. Query Optimization - Efficient parameter handling
  4. Real-Time Scheduling - Automatic refresh management

Documentation

Changelog

See CHANGELOG.md for all changes.

v2.0.0 - Major Rewrite

  • Complete rewrite with modern architecture
  • Repository pattern implementation
  • Event-driven architecture
  • Intelligent caching system
  • Background job processing
  • Real-time updates
  • Comprehensive test suite
  • Enhanced error handling
  • Full backward compatibility

Support

License

The MIT License (MIT). Please see License File for more information.

Author

Made with ❤️ for the Laravel community