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

The Advertisements facade

RoundlyConsulting\Advertisements\Facades\Advertisements is the recommended entry point. Its root is RoundlyConsulting\Advertisements\AdvertisementManager, which resolves an action from the container for every operation — so a host binding for an action applies to the facade too. The lifecycle verbs are flat:

use RoundlyConsulting\Advertisements\DataTransferObjects\AdvertisementData;
use RoundlyConsulting\Advertisements\Facades\Advertisements;
use RoundlyConsulting\Money\Money;

$ad = Advertisements::create(new AdvertisementData(
    name: 'Vintage road bike',
    price: Money::ofMajor('250.00', 'EUR'),
    category: 'bikes',
    author: $user,                  // any Eloquent model (polymorphic author)
));

Advertisements::publish($ad);                  // live now → AdvertisementPublished
Advertisements::publish($ad, now()->addWeek()); // scheduled → AdvertisementPublished
Advertisements::unpublish($ad);                // back to draft → AdvertisementUnpublished
Advertisements::expire($ad);                   // → AdvertisementExpired
Advertisements::archive($ad);                  // → AdvertisementArchived
Advertisements::delete($ad);                   // soft delete → AdvertisementDeleted

Serving is flat as well; everything about one ad — its placements and its tracking — hangs off the for($ad) handle:

// Serving
Advertisements::in('sidebar')->get();                 // active ads in a placement
Advertisements::targetedIn('sidebar', request())->get(); // … that target the viewer
Advertisements::random('sidebar');                    // ?Advertisement
echo Advertisements::render($ad, 'sidebar');          // the creative, or the text ad

// One ad's scoped API
Advertisements::for($ad)->placements()->sync(['sidebar', 'header']);
Advertisements::for($ad)->runsIn('sidebar');          // true
Advertisements::for($ad)->track('sidebar')->impression();

Every method

MethodReturnsWhat it does
create($data)AdvertisementCreate an ad from an AdvertisementData.
update($ad, $data)AdvertisementOverwrite the ad from an AdvertisementData.
publish($ad, ?$at = null)AdvertisementPublish now, or schedule for a future instant.
unpublish($ad)AdvertisementBack to draft; clears published_at.
expire($ad, ?$at = null)AdvertisementExpire now, or set a future expiry.
archive($ad)AdvertisementArchive without deleting.
delete($ad)boolSoft delete.
query()BuilderA fresh builder for the configured model.
active()Builderquery()->active().
in($placement)BuilderActive ads in a placement (model, id or slug).
targetedIn($placement, $viewer = null)BuilderActive ads in a placement that match the viewer’s location.
random($placement = null)?AdvertisementOne random active ad, optionally per placement.
render($ad, $placement, $attributes = [])HtmlStringThe creative for a placement, or the text ad.
for($ad)AdvertisementHandleOne ad’s scoped API — placements and tracking.
for($ad)->placements()->attach / detach / sync($placements)AdvertisementAdd, remove or replace placements; the ad comes back with placements reloaded.
for($ad)->runsIn($placement)boolWhether the ad is attached to the placement.
for($ad)->track(?$placement)->impression(?$data) / ->click(?$data)?AdvertisementEventRecord an impression or a click of a live ad; null when buffered.
fake()AdvertisementsFakeSwap in the recording fake for tests.
  • for($ad)->track() refuses an ad that isn’t live right now — draft, scheduled, expired or archived — with AdvertisementNotActive, and track($placement) refuses a placement the ad doesn’t run in with AdvertisementNotInPlacement. track() with no placement records without one.
  • Recording returns the persisted AdvertisementEvent, or null when tracking.buffered queues it.
  • render() goes through the bound CreativeRenderer — a responsive <img> when an image creative exists, the text ad otherwise.
  • The model methods — $ad->publish(), unpublish(), expire(), archive(), delete() and renderCreative() — are sugar over the same manager, so they fire the same events and Advertisements::fake() records them.

The facade alias is registered globally unless register_facade_alias is false; the facade class itself always works.

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.