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

The package works with zero configuration. The published config/advertisements.php, without its comment headers:

return [
    // Eloquent models the package resolves — override with your own subclasses.
    'model' => RoundlyConsulting\Advertisements\Models\Advertisement::class,

    // Key type of the polymorphic author column: 'bigint', 'uuid' or 'ulid'.
    'key_type' => env('ADVERTISEMENTS_KEY_TYPE', 'bigint'),

    'placement_model' => RoundlyConsulting\Advertisements\Models\Placement::class,
    'category_model' => RoundlyConsulting\Advertisements\Models\Category::class,
    'event_model' => RoundlyConsulting\Advertisements\Models\AdvertisementEvent::class,

    // Impression / click recording — inline, or buffered to the queue.
    'tracking' => [
        'buffered' => env('ADVERTISEMENTS_TRACKING_BUFFERED', false),
        'queue' => env('ADVERTISEMENTS_TRACKING_QUEUE'),
        'connection' => env('ADVERTISEMENTS_TRACKING_CONNECTION'),
    ],

    // Locale used when the active locale has no translation for an attribute.
    'fallback_locale' => env('ADVERTISEMENTS_FALLBACK_LOCALE', config('app.fallback_locale', 'en')),

    // Slugs (sluggable): keep retired advertisement slugs and 301 them to the current one.
    'slugs' => [
        'history' => env('ADVERTISEMENTS_SLUG_HISTORY', false),
    ],

    // Currency used by AdvertisementData::fromMinor() / ::fromDecimal() when none is given.
    'default_currency' => env('ADVERTISEMENTS_CURRENCY', 'EUR'),

    // Register the global Advertisements facade alias.
    'register_facade_alias' => env('ADVERTISEMENTS_FACADE_ALIAS', true),

    // Visual creatives (media-library): one single-file bucket per placement named
    // "{creative_bucket_prefix}:{placement-slug}" plus a generic "{fallback_bucket}".
    'media' => [
        'creative_bucket_prefix' => 'creative',
        'fallback_bucket' => 'creative',
        'disk' => env('ADVERTISEMENTS_MEDIA_DISK'), // null = media-library default
        'responsive_widths' => null,                // null = media-library default ladder
        'display_variant' => 'display',
        'use_fallback_bucket' => true,
        'text_ad_view' => 'advertisements::text-ad',
    ],

    // Geo-targeting & geo reporting (geolocation).
    'geo' => [
        'targeting_enabled' => env('ADVERTISEMENTS_GEO_TARGETING', true),
        'untargeted_match' => true,                 // ads with no targeting match every viewer
        'match_when_unknown' => 'untargeted_only',  // unknown viewer / unknown fact: 'untargeted_only' | 'all'
        'stamp_events' => env('ADVERTISEMENTS_GEO_STAMP', true),
    ],
];

Every key

KeyDefaultEnvPurpose
modelAdvertisement::class—The advertisement model: the packaged class or a subclass of it — anything else throws InvalidConfigurationException.
key_typebigintADVERTISEMENTS_KEY_TYPEKey type of the polymorphic author column: bigint, uuid or ulid (anything else throws InvalidConfigurationException). Read at migrate time; every author model must share it.
placement_modelPlacement::class—The placement (zone) model.
category_modelCategory::class—The category model.
event_modelAdvertisementEvent::class—The impression/click event model.
tracking.bufferedfalseADVERTISEMENTS_TRACKING_BUFFEREDDispatch recording to the queue instead of writing inline.
tracking.queuenullADVERTISEMENTS_TRACKING_QUEUEQueue for buffered recording (null or blank = default).
tracking.connectionnullADVERTISEMENTS_TRACKING_CONNECTIONQueue connection for buffered recording (null or blank = default).
fallback_localeapp.fallback_localeADVERTISEMENTS_FALLBACK_LOCALETranslation fallback, slug-binding fallback and the locale placement/category slugs are generated from. Not set (null or blank) means no translation fallback, and slugs use en.
slugs.historyfalseADVERTISEMENTS_SLUG_HISTORYRemember retired ad slugs and 301 them to the current one. Needs sluggable’s migration.
default_currencyEURADVERTISEMENTS_CURRENCYCurrency for AdvertisementData::fromMinor() / fromDecimal() when none is given; must be registered in money-for-laravel.
register_facade_aliastrueADVERTISEMENTS_FACADE_ALIASRegister the global Advertisements alias; false to opt out.
media.creative_bucket_prefixcreative—Prefix of the per-placement bucket name ({prefix}:{slug}).
media.fallback_bucketcreative—Generic, size-less creative bucket tried before the text ad.
media.disknullADVERTISEMENTS_MEDIA_DISKDisk for creatives (null or blank = media-library default).
media.responsive_widthsnull—Responsive width ladder (null = media-library default). Every width must be a positive integer; a bad or blank entry throws instead of being dropped.
media.display_variantdisplay—Variant name fit to the placement dimensions.
media.use_fallback_buckettrue—Try the generic creative bucket before the text ad.
media.text_ad_viewadvertisements::text-ad—Blade view rendering the text-ad fallback.
geo.targeting_enabledtrueADVERTISEMENTS_GEO_TARGETINGApply geo-targeting in targetedIn().
geo.untargeted_matchtrue—Ads with no targeting match every viewer.
geo.match_when_unknownuntargeted_only—What an unknown viewer gets — untargeted_only or all — and whether a rule the viewer lacks the country or coordinates for fails or passes. Anything else (ALL, everything) throws InvalidConfigurationException listing both.
geo.stamp_eventstrueADVERTISEMENTS_GEO_STAMPStamp the viewer’s country (+ region, city, coordinates) onto recorded events.

Environment

Eleven keys are env-backed, so you rarely need to publish the config at all:

ADVERTISEMENTS_CURRENCY=EUR
ADVERTISEMENTS_FALLBACK_LOCALE=en
ADVERTISEMENTS_KEY_TYPE=bigint
ADVERTISEMENTS_SLUG_HISTORY=true
ADVERTISEMENTS_TRACKING_BUFFERED=true
ADVERTISEMENTS_TRACKING_CONNECTION=redis
ADVERTISEMENTS_TRACKING_QUEUE=tracking
ADVERTISEMENTS_FACADE_ALIAS=true
ADVERTISEMENTS_MEDIA_DISK=s3
ADVERTISEMENTS_GEO_TARGETING=true
ADVERTISEMENTS_GEO_STAMP=true

Notes

  • default_currency must be registered in money-for-laravel’s currency registry — any ISO 4217 code by default.
  • key_type is only read by the migration: change it before migrating, not after.
  • The model keys must name the packaged model or a subclass of it; anything else throws — see Custom models.
  • Every bool key accepts true/false, 1/0, on/off or yes/no (from .env or the published file). Anything else throws an InvalidConfigurationException naming the key, so a typo never quietly becomes the default.
  • The other keys are just as strict: one that is not set — left out, null or blank ('' or whitespace, such as an ADVERTISEMENTS_FALLBACK_LOCALE= line) — takes its default; one set to the wrong shape throws an InvalidConfigurationException naming the key. The currency, locale, bucket names, display variant, text-ad view, disk and queue settings must be strings, and every responsive width a real width (a blank entry inside the list throws). php artisan about shows a broken setting as INVALID.
  • With register_facade_alias off, import RoundlyConsulting\Advertisements\Facades\Advertisements explicitly; the facade itself keeps working.

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.