Weave 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

Advertising Bundle Laravel Package

idmarinas/advertising-bundle

A Symfony/PHP bundle for managing advertising campaigns and banners, with configurable ad zones, impression and click tracking, and performance reporting. Integrates into Symfony apps to help schedule, serve, and monitor ads through a straightforward, maintainable workflow.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and enable. The bundle is a Symfony bundle, so the whole install is three commands and one config file:

composer require idmarinas/advertising-bundle
# Flex registers it; otherwise add to config/bundles.php
php bin/console debug:config idmarinas_advertising

That last command is your first stop, not the README. Bundle config trees drift between releases, and debug:config gives you the real, version-accurate key names (networks, adsense.client_id, per-slot definitions, etc.) instead of whatever the GitHub docs last showed.

Where to look first, in this order:

  1. DependencyInjection/Configuration.php — the definitive list of what you can configure. Faster than reading prose.
  2. src/Twig/ — the runtime extension. This is the actual public API you'll call from templates; function names and argument order live here, and they're what you'll use 95% of the time.
  3. Resources/config/ (or config/) — the service definitions, which tell you what's injectable into your own services.
  4. Entity/ + Repository/ — only if you're using the Doctrine-backed ad/slot management rather than static config.

First use case. Configure the AdSense network with your client ID, define one ad unit, then drop the bundle's Twig render call into templates/base.html.twig in a sidebar or below-content slot. That gets you a working ad in about ten minutes and validates the whole chain (network → config → Twig → rendered <ins>/<script> markup) before you invest in slot management.

Laravel developer's mental model: the bundle is a service-provider + config + Blade-directive package, renamed. config/packages/idmarinas_advertising.yaml is your config/advertising.php. The Twig extension is your @ad('slot') directive. The Doctrine entities are an Eloquent model + repository. Once you map those three, nothing here is exotic.

Implementation Patterns

Layout slots, not page-by-page calls. Define ad slots once in config (or as DB-backed rows), then render by slot key from the base layout. Page templates shouldn't know about ad networks at all — they request 'sidebar-top' and the bundle decides which network fills it. This is the single biggest maintainability win: swapping AdSense for a house-ad campaign becomes a config change, not a template sweep.

Separate "selection" from "rendering." The useful architecture is a thin service that picks which ad should fill a slot (active dates, weight, frequency cap, page targeting) and a renderer that turns that selection into HTML. If the bundle's built-in resolution is too static, write your own selector service, inject the repository, and call the bundle's render helper with the resolved entity. Don't fork the bundle to add targeting logic.

Generic network for house ads and fallbacks. The AdSense network is a fixed adapter; the generic network is where you plug in your own markup. Use it for: internal promos, sponsor banners, and — importantly — a fallback when AdSense returns no fill, so slots don't collapse and cause layout shift.

Consent gating in one place. Wrap ad rendering in a single Twig partial or a small service that checks the consent state before emitting any network script. If you scatter consent checks across templates you will miss one, and that's a compliance bug, not a cosmetic one.

Cache the rendered markup, not the query. Ad HTML is expensive to assemble (entity lookups + targeting) and cheap to store. Cache the rendered string per (slot, consent-state, device-class) for a few minutes. Invalidate on ad-entity save via a Doctrine listener. Do not cache ad markup inside a full-page cache without varying on consent — that's how you serve a personalized ad to someone who declined tracking.

Test with a mock network. In test env, point the config at the generic network with a static fixture string. Then functional tests can assert "the slot rendered" without hitting Google, and you get deterministic HTML for snapshot tests.

Gotchas and Tips

This is Symfony. There is no Laravel bridge. If you're evaluating it from a Laravel codebase, you cannot composer require it and get a facade — there's no service provider, no Blade directive, and the entities assume Doctrine. Either run it in a Symfony app, or (more realistically) read the source as a design reference and reimplement the ~200 lines of slot resolution + rendering you actually need. The concept is worth stealing; the package is not portable.

Doctrine mapping is the #1 install failure. If you use the entity-backed mode, the bundle's mappings must be registered (auto-mapping, or an explicit doctrine.orm.mappings entry). Symptom: "The class X was not found in the chain configured namespaces." Then run doctrine:migrations:diff and review the generated migration — don't blindly migrate on a production database with existing ad tables.

Client IDs and env vars. AdSense client IDs differ per environment and you must not ship a real one to dev (you'll pollute your AdSense account with junk impressions and possibly get flagged). Set the ID via env with a blank/dev placeholder that renders nothing in dev.

Server-side rendering means no hydration, but real CLS. The bundle emits markup during the request, so you don't fight client-side rendering — but an empty slot that fills late shifts your layout. Reserve the slot dimensions in CSS (fixed min-height per slot key) rather than letting the ad define them.

Ad blockers make local debugging confusing. A blank slot in dev is ambiguous: config error, no fill, or uBlock. Render a visible placeholder in dev env (e.g., a dashed box with the slot name) so you can distinguish "not wired up" from "blocked."

Extension points, in order of preference: (1) custom network adapter implementing the bundle's network interface; (2) Twig template overrides for the ad markup; (3) a decorator service around the renderer. Forking the bundle should be last — with 0 dependents and a small star count, you are the maintenance team if you patch it.

Version pinning matters here. Last release is dated 2026 and the project is small; the API surface is not stability-guaranteed by a large community. Pin to a caret constraint you've tested and read the changelog before minor bumps, because Twig function signatures are the kind of thing that changes quietly in a 0.x-to-0.y jump. Check the composer.json PHP/Symfony constraints against your app before installing — a modern Symfony requirement will silently fail on an older LTS.

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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect