Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Posters Laravel Package

baks-dev/posters

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps to First Ad Display

  1. Install and Publish

    composer require baks-dev/posters
    php artisan vendor:publish --provider="BaksDev\Posters\PostersServiceProvider" --tag="posters-config"
    

    Verify config/posters.php exists with default settings.

  2. Configure Ad Slots Edit config/posters.php to define your first slot:

    'slots' => [
        'header' => [
            'width' => 728,
            'height' => 90,
            'pages' => ['home', 'blog/*'],
        ],
    ],
    
  3. Create a Migration for Ad Campaigns Since the package is minimal, manually create a migration for ad_campaigns:

    php artisan make:migration create_ad_campaigns_table
    

    Define schema with campaign_id, name, image_url, click_url, and impressions.

  4. Display a Banner in Blade Add this to your template (e.g., resources/views/layouts/app.blade.php):

    @if(config('posters.enabled') && in_array(Request::path(), config('posters.slots.header.pages')))
        <div class="posters-slot" data-slot="header"></div>
        @push('scripts')
            <script>
                document.addEventListener('DOMContentLoaded', function() {
                    const slot = document.querySelector('.posters-slot');
                    if (slot) {
                        fetch('/api/posters/header')
                            .then(response => response.text())
                            .then(html => slot.innerHTML = html);
                    }
                });
            </script>
        @endpush
    @endif
    
  5. Create a Controller Endpoint Add to routes/api.php:

    Route::get('/api/posters/{slot}', [PostersController::class, 'render']);
    

    Implement PostersController to fetch and render the ad:

    public function render($slot)
    {
        $ad = AdCampaign::where('slot', $slot)
            ->where('active', true)
            ->inRandomOrder()
            ->first();
    
        return response()->view('posters::ad', ['ad' => $ad]);
    }
    
  6. Test the Flow

    • Visit a page with the slot (e.g., /home).
    • Verify the ad renders and logs an impression (check storage/logs/laravel.log).

Implementation Patterns

Core Workflows

1. Ad Slot Management

  • Dynamic Slot Registration: Extend the package by adding slot definitions via a service provider:
    // app/Providers/PostersServiceProvider.php
    public function register()
    {
        $this->app->singleton('posters.slots', function () {
            return [
                'sidebar' => [
                    'width' => 300,
                    'height' => 600,
                    'pages' => ['blog/*'],
                    'priority' => 10,
                ],
            ];
        });
    }
    
  • Conditional Slots: Use middleware to enable/disable slots based on user roles or geolocation:
    // app/Http/Middleware/EnablePosters.php
    public function handle(Request $request, Closure $next)
    {
        if (auth()->check() && auth()->user()->is_premium) {
            config(['posters.enabled' => false]);
        }
        return $next($request);
    }
    

2. Ad Rendering Strategies

  • Blade Directives: Create a custom Blade directive for ad slots:
    // app/Providers/BladeServiceProvider.php
    Blade::directive('adSlot', function ($expression) {
        return "<?php echo \\BaksDev\\Posters\\AdRenderer::slot({$expression}); ?>";
    });
    
    Usage:
    @adSlot('header')
    
  • API-Driven Rendering: For SPAs or headless setups, expose an API endpoint:
    Route::get('/posters/render/{slot}', function ($slot) {
        return response()->json([
            'html' => AdRenderer::slot($slot),
            'impression_id' => Str::uuid(),
        ]);
    });
    

3. Tracking and Analytics

  • Event-Based Tracking: Dispatch events for impressions/clicks:
    // After rendering an ad
    event(new AdImpression($ad->id, $slot));
    
    // Listen for clicks
    AdClick::created(function ($click) {
        Log::info("Ad clicked: {$click->ad_id}", ['user_id' => auth()->id()]);
    });
    
  • Third-Party Integration: Forward tracking data to Google Analytics:
    AdImpression::created(function ($impression) {
        $client = new \Google\Analytics\Data\V1beta\BetaAnalyticsDataClient();
        $client->runReport([
            'property' => 'properties/YOUR_PROPERTY_ID',
            'dateRanges' => [new \Google\Analytics\Data\V1beta\DateRange(['start_date' => now()->toDateString(), 'end_date' => now()->toDateString()])],
            'dimensions' => [new \Google\Analytics\Data\V1beta\Dimension(['name' => 'pagePath'])],
            'metrics' => [new \Google\Analytics\Data\V1beta\Metric(['name' => 'sessions'])],
        ]);
    });
    

4. A/B Testing

  • Slot-Based Testing: Extend the AdCampaign model to support variants:
    // database/migrations/...
    Schema::table('ad_campaigns', function (Blueprint $table) {
        $table->string('variant')->nullable();
        $table->integer('variant_weight')->default(1);
    });
    
    Update the renderer to select variants by weight:
    $ad = AdCampaign::where('slot', $slot)
        ->where('active', true)
        ->whereIn('variant', ['control', 'variant_a'])
        ->inRandomOrder()
        ->first();
    

Integration Tips

Laravel Ecosystem

  • Queue Jobs for Tracking: Offload impression/click tracking to queues:
    // After rendering an ad
    TrackImpression::dispatch($ad->id, $slot);
    
    // app/Jobs/TrackImpression.php
    public function handle()
    {
        $impression = new AdImpression([
            'ad_id' => $this->adId,
            'slot' => $this->slot,
            'ip' => request()->ip(),
        ]);
        $impression->save();
    }
    
  • Cache Ad Slots: Cache rendered ad HTML for 5 minutes:
    $html = Cache::remember("ad_slot_{$slot}", 300, function () use ($slot) {
        return AdRenderer::slot($slot);
    });
    

Frontend

  • Lazy-Load Ads: Use Intersection Observer to load ads only when visible:
    const observer = new IntersectionObserver((entries) => {
        entries.forEach(entry => {
            if (entry.isIntersecting) {
                fetch(`/api/posters/${entry.target.dataset.slot}`)
                    .then(response => response.text())
                    .then(html => entry.target.innerHTML = html);
                observer.unobserve(entry.target);
            }
        });
    });
    document.querySelectorAll('.posters-slot').forEach(slot => observer.observe(slot));
    
  • Ad Styling: Override default styles in your CSS:
    .posters-ad {
        max-width: 100%;
        height: auto;
    }
    .posters-ad img {
        display: block;
        width: 100%;
    }
    

Database

  • Optimize for Performance: Add indexes to ad_campaigns:
    Schema::table('ad_campaigns', function (Blueprint $table) {
        $table->index(['slot', 'active']);
        $table->index('variant');
    });
    
  • Archive Old Data: Create a scheduled job to archive impressions older than 6 months:
    // app/Console/Commands/ArchiveAdImpressions.php
    public function handle()
    {
        AdImpression::where('created_at', '<=', now()->subMonths(6))
            ->update(['archived' => true]);
    }
    

Gotchas and Tips

Pitfalls

1. Missing Database Schema

  • Issue: The package assumes you’ve created tables for ad_campaigns, ad_slots, and tracking. Without migrations, you’ll get ClassNotFound errors.
  • Fix: Manually create migrations or extend the package’s PostersServiceProvider to register migrations:
    public function boot()
    {
        $this->loadMigrationsFrom(__DIR__.'/../database/migrations');
    }
    

2. **Blade Directive Conflic

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
ilhamsyabani/laravel-volt-starter
thethunderturner/filament-latex
ghostcompiler/laravel-querybuilder
webrek/laravel-telescope-mongodb
anousss007/blatui
zatona-eg/zatona-eg-api
cocosmos/filament-sticky-save-bar
patrickbussmann/oauth2-apple
3brs/enterprise-security-bundle
anousss007/vigilance
supportpal/eloquent-model
ardenexal/fhir-models
laravel-at/laravel-image-sanitize
romalytar/yammi-audit-log-laravel
ardenexal/fhir-validation
arshaviras/weather-widget
laravel-chronicle/core
sunchayn/nimbus
daikazu/eloquent-salesforce-objects
unseen-codes/chat