NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages

Every create, update and lifecycle transition dispatches an event you can listen to. Each wraps the affected model in a public $advertisement property:

use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Advertisements\Events\AdvertisementCreated;
use RoundlyConsulting\Advertisements\Events\AdvertisementUpdated;
use RoundlyConsulting\Advertisements\Events\AdvertisementPublished;
use RoundlyConsulting\Advertisements\Events\AdvertisementUnpublished;
use RoundlyConsulting\Advertisements\Events\AdvertisementExpired;
use RoundlyConsulting\Advertisements\Events\AdvertisementArchived;
use RoundlyConsulting\Advertisements\Events\AdvertisementDeleted;

Event::listen(AdvertisementPublished::class, function (AdvertisementPublished $event): void {
    $event->advertisement; // the published Advertisement
});
EventFired byPayload
AdvertisementCreatedcreate()$advertisement
AdvertisementUpdatedupdate()$advertisement
AdvertisementPublishedpublish() — now or scheduled$advertisement
AdvertisementUnpublishedunpublish()$advertisement
AdvertisementExpiredexpire() — now or a future instant$advertisement
AdvertisementArchivedarchive()$advertisement
AdvertisementDeleteddelete() — facade, action or model — and every ad model:prune removes$advertisement
ImpressionRecordedtrack()->impression() — inline or in the queued job$event (AdvertisementEvent)
ClickRecordedtrack()->click() — inline or in the queued job$event (AdvertisementEvent)

Tracking events

ImpressionRecorded and ClickRecorded carry the persisted AdvertisementEvent in a public $event property — fired inline, or inside the queued job when tracking is buffered:

use Illuminate\Support\Facades\Event;
use RoundlyConsulting\Advertisements\Events\ClickRecorded;
use RoundlyConsulting\Advertisements\Events\ImpressionRecorded;

Event::listen(ClickRecorded::class, function (ClickRecorded $event): void {
    $event->event;                  // the persisted AdvertisementEvent
    $event->event->advertisement;   // the clicked Advertisement
    $event->event->country_code;    // stamped viewer country, or null
});

All events live in RoundlyConsulting\Advertisements\Events. Pruning (model:prune) force-deletes expired ads one by one, so AdvertisementDeleted fires for each pruned ad like for any other delete.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.