---
title: "Creatives — Advertisements for Laravel | Roundly"
description: "Attach an image creative per placement, get a display variant sized to the zone, and render a responsive <img> or the text-ad fallback."
url: https://roundly-consulting.com/open-source/docs/advertisements-for-laravel/creatives
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Advertisements for Laravel](https://roundly-consulting.com/open-source/docs/advertisements-for-laravel.md)

# Creatives

Each placement has its own single-file creative bucket with a display variant fit (cover) to that placement’s width × height. Attach an image and read it back, or render it — an image when one exists, the text ad otherwise:

```php
// Attach (or replace) the creative for a placement — model, id, or slug.
$ad->addCreative($request->file('banner'), 'sidebar');   // an UploadedFile or a file path

$ad->creativeFor('sidebar');                 // ?Media (placement-specific, then generic)
$ad->creativeUrl('sidebar');                 // display-variant URL, or '' / fallback when empty
$ad->creativeUrl('sidebar', '');             // the original

// Responsive <img> when a creative exists, else the text-ad fallback (name + description + price).
echo Advertisements::render($ad, 'sidebar', ['class' => 'ad']);
echo $ad->renderCreative('sidebar', ['class' => 'ad']); // the same, from the model
```

## Buckets

Buckets are named {creative\_bucket\_prefix}:{placement-slug}, plus a generic, size-less {fallback\_bucket}. Each accepts JPEG, PNG, WebP, GIF and AVIF, keeps a single file (a new upload replaces the old one) and uses media.disk and media.responsive\_widths when set. A placement without dimensions gets a display variant with no resize.

```php
$ad->creativeBucketName('sidebar');   // "creative:sidebar"
$ad->fallbackCreativeBucket();        // "creative"
$ad->displayVariant();                // "display"

// A generic, size-less creative for any placement without its own image:
$ad->addMedia($request->file('banner'))->toMediaBucket($ad->fallbackCreativeBucket());
```

- creativeFor() — the placement-specific image, then the generic creative (when media.use\_fallback\_bucket is on), else null.
- creativeUrl() — the display-variant URL by default; pass another variant name, or '' for the original. Returns the bucket’s fallback URL or '' when nothing is attached.
- Advertisements::render($ad, $placement) — a responsive <img> with srcset (alt defaults to the ad’s name) when an image creative exists, otherwise the text ad. $ad->renderCreative() is sugar for the same call.

## Text-ad fallback

Without an image creative, render() renders the advertisements::text-ad Blade view: a div.advertisement-text-ad sized to the placement’s dimensions, with a data-advertisement attribute, holding the name, the description when filled and the price formatted in the active locale. Publish the view to restyle it, or point media.text\_ad\_view at your own view — a view that doesn’t exist fails loudly with an InvalidArgumentException.

```bash
php artisan vendor:publish --tag="advertisements-views"
# → resources/views/vendor/advertisements/text-ad.blade.php
```

- $advertisement — the Advertisement being rendered.
- $placement — the resolved ?Placement.
- $attributes — the array passed to render() or renderCreative().

## Render attributes

The text ad applies every attribute you pass to its <div>, escaped: class and style are appended to its own (class="advertisement-text-ad ad"), anything else is added or overrides. The image path hands them to media-library’s responsive <img>, which takes class, alt (defaulting to the ad’s name) and sizes.

## Custom renderer

Advertisements::render() goes through the bound RoundlyConsulting\\Advertisements\\Contracts\\CreativeRenderer. Bind your own to swap the whole resolution chain:

```php
use Illuminate\Support\HtmlString;
use RoundlyConsulting\Advertisements\Contracts\CreativeRenderer;
use RoundlyConsulting\Advertisements\Models\Advertisement;
use RoundlyConsulting\Advertisements\Models\Placement;

final class NativeAdRenderer implements CreativeRenderer
{
    public function render(Advertisement $advertisement, Placement|int|string $placement, array $attributes = []): HtmlString
    {
        return new HtmlString(view('ads.native', ['ad' => $advertisement])->render());
    }
}

// AppServiceProvider::register()
$this->app->bind(CreativeRenderer::class, NativeAdRenderer::class);
```

Creatives are media-library Media rows, so everything that package offers — variants, responsive srcset, private and temporary URLs — applies to them.

## 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](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## 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.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/advertisements-for-laravel.md)
