Documentation menu: Laravel
Laravel integration
Add theBizness.ai analytics to your Laravel application with elegant Blade templates and environment configuration.
Setup time
5 minutes
Difficulty
Medium
Performance
Elegant
Choose your implementation method
Blade layout method
Step 1: Environment configuration
Add these variables to your .env file:
# .env
THEBIZNESS_ENABLED=true
THEBIZNESS_WEBSITE_ID=your-website-id
THEBIZNESS_DOMAIN=yourdomain.comStep 2: Create the config file
Create config/analytics.php:
<?php
// config/analytics.php
return [
'thebizness' => [
'enabled' => env('THEBIZNESS_ENABLED', false),
'website_id' => env('THEBIZNESS_WEBSITE_ID'),
'domain' => env('THEBIZNESS_DOMAIN'),
'script_url' => env('THEBIZNESS_SCRIPT_URL', 'https://thebizness.ai/js/script.js'),
// Route patterns the middleware should skip, for example ['admin/*', 'horizon*']
'exclude' => [],
],
];Step 3: Update the layout template
Update your main layout file:
{{-- resources/views/layouts/app.blade.php --}}
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>{{ config('app.name', 'Laravel') }}</title>
<!-- Scripts -->
@vite(['resources/css/app.css', 'resources/js/app.js'])
<!-- theBizness Analytics -->
@if(config('analytics.thebizness.enabled', false) && config('analytics.thebizness.website_id'))
<script
async
defer
data-website-id="{{ config('analytics.thebizness.website_id') }}"
data-domain="{{ config('analytics.thebizness.domain') ?: request()->getHost() }}"
src="https://thebizness.ai/js/script.js">
</script>
@endif
</head>
<body>
<div id="app">
@yield('content')
</div>
</body>
</html>- • Environment-based configuration
- • Conditional loading based on settings
- • Auto-detects domain from request
- • Easy to disable for development
Middleware implementation
Create the analytics middleware
<?php
// app/Http/Middleware/AnalyticsMiddleware.php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
class AnalyticsMiddleware
{
public function handle(Request $request, Closure $next)
{
$response = $next($request);
if (! $this->shouldInjectAnalytics($request, $response)) {
return $response;
}
// Streamed and file responses have no string body, so getContent() can return false
$content = $response->getContent();
if (! is_string($content)) {
return $response;
}
// Inject before closing head tag
$content = str_replace('</head>', $this->getAnalyticsScript() . '</head>', $content);
$response->setContent($content);
// Keep an existing Content-Length header accurate
if ($response->headers->has('Content-Length')) {
$response->headers->set('Content-Length', (string) strlen($content));
}
return $response;
}
private function shouldInjectAnalytics(Request $request, $response): bool
{
return config('analytics.thebizness.enabled', false) &&
// Only plain responses. StreamedResponse and BinaryFileResponse are not Illuminate\Http\Response
$response instanceof Response &&
$response->getStatusCode() === 200 &&
$request->route() &&
! $request->expectsJson() &&
// Skip the route patterns listed under 'exclude' in config/analytics.php
! $request->is(...(config('analytics.thebizness.exclude') ?? [])) &&
// Compressed bodies cannot be edited as text
! $response->headers->has('Content-Encoding') &&
str_contains($response->headers->get('Content-Type', ''), 'text/html');
}
private function getAnalyticsScript(): string
{
$websiteId = config('analytics.thebizness.website_id');
$domain = config('analytics.thebizness.domain') ?: request()->getHost();
$scriptUrl = config('analytics.thebizness.script_url');
if (!$websiteId) {
return '';
}
return sprintf(
'<script async defer data-website-id="%s" data-domain="%s" src="%s"></script>%s',
e($websiteId),
e($domain),
e($scriptUrl),
PHP_EOL
);
}
}Register the middleware
Laravel 11 and later: add the middleware to the web group in bootstrap/app.php:
<?php
// bootstrap/app.php (Laravel 11 and later)
use App\Http\Middleware\AnalyticsMiddleware;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Configuration\Middleware;
return Application::configure(basePath: dirname(__DIR__))
// ... keep your existing withRouting() and withExceptions() calls
->withMiddleware(function (Middleware $middleware) {
$middleware->web(append: [
AnalyticsMiddleware::class,
]);
})
->create();Laravel 10 and earlier: add App\Http\Middleware\AnalyticsMiddleware::class to the 'web' array in $middlewareGroups in app/Http/Kernel.php.
Blade component
Create the component
{{-- resources/views/components/analytics.blade.php --}}
@if(config('analytics.thebizness.enabled', false) && config('analytics.thebizness.website_id'))
<script
async
defer
data-website-id="{{ config('analytics.thebizness.website_id') }}"
data-domain="{{ config('analytics.thebizness.domain') ?: request()->getHost() }}"
src="{{ config('analytics.thebizness.script_url', 'https://thebizness.ai/js/script.js') }}">
</script>
@endif
{{-- Usage in layouts: --}}
{{-- <x-analytics /> --}}Helper class and Artisan command
Analytics helper class
<?php
// app/Helpers/AnalyticsHelper.php
namespace App\Helpers;
class AnalyticsHelper
{
public static function isEnabled(): bool
{
return config('analytics.thebizness.enabled', false) &&
!empty(config('analytics.thebizness.website_id'));
}
public static function getTrackingScript(): string
{
if (!self::isEnabled()) {
return '';
}
$websiteId = config('analytics.thebizness.website_id');
$domain = config('analytics.thebizness.domain') ?: request()->getHost();
$scriptUrl = config('analytics.thebizness.script_url', 'https://thebizness.ai/js/script.js');
return sprintf(
'<script async defer data-website-id="%s" data-domain="%s" src="%s"></script>',
e($websiteId),
e($domain),
e($scriptUrl)
);
}
}
// Add to composer.json autoload.files:
// "files": ["app/Helpers/AnalyticsHelper.php"]Artisan setup command
<?php
// app/Console/Commands/SetupAnalytics.php
namespace App\Console\Commands;
use Illuminate\Console\Command;
class SetupAnalytics extends Command
{
protected $signature = 'analytics:setup {website-id} {domain?}';
protected $description = 'Set up theBizness analytics configuration';
public function handle()
{
$websiteId = $this->argument('website-id');
$domain = $this->argument('domain') ?: parse_url(config('app.url'), PHP_URL_HOST);
// Update .env file
$this->updateEnvFile([
'THEBIZNESS_ENABLED' => 'true',
'THEBIZNESS_WEBSITE_ID' => $websiteId,
'THEBIZNESS_DOMAIN' => $domain,
]);
$this->info('Analytics configuration updated successfully!');
$this->info("Website ID: {$websiteId}");
$this->info("Domain: {$domain}");
}
private function updateEnvFile(array $values): void
{
$envFile = base_path('.env');
$envContent = file_get_contents($envFile);
foreach ($values as $key => $value) {
$pattern = "/^{$key}=.*/m";
$replacement = "{$key}={$value}";
if (preg_match($pattern, $envContent)) {
$envContent = preg_replace($pattern, $replacement, $envContent);
} else {
$envContent .= "\n{$replacement}";
}
}
file_put_contents($envFile, $envContent);
}
}Usage
# Setup analytics with Artisan command
php artisan analytics:setup your-website-id yourdomain.com
# Use in Blade templates
{!! AnalyticsHelper::getTrackingScript() !!}Verify installation
Development check
- 1. Run
php artisan serveto check that the page loads - 2. Visit your Laravel app
- 3. Check browser DevTools Network tab
- 4. Look for the script.js request. The console shows a "Tracking disabled on localhost" warning here, which is expected
Configuration check
- 1. Run
php artisan config:cache - 2. Check
config('analytics.thebizness') - 3. Verify environment variables
- 4. Test different routes
- • The tracker does nothing on localhost, *.local, *.test, private IP addresses or file:// pages. It logs a "Tracking disabled on localhost" warning in the console. Verify on a publicly reachable domain.
- • Use different configurations for different environments
- • Consider disabling analytics in local development
- • Cache config in production:
php artisan config:cache - • Test with both authenticated and guest users
- • If your site sends a Content-Security-Policy header, allow https://thebizness.ai in script-src and connect-src. Blocked requests show only as CSP errors in the browser console
Laravel integration complete
Your Laravel application is now tracking analytics with elegant configuration. Here's what to explore next:
Revenue attribution
Connect Stripe or send a purchase event from your order-complete page
Custom events
Send events from the browser with window.thebizness(...). See the API reference
Server-side reporting
Report sales from your backend with Laravel's HTTP client and your ingest secret as a Bearer token. Keep the secret in your .env file