diff --git a/app/Enums/ContactMessageTopic.php b/app/Enums/ContactMessageTopic.php
index c220f979..f246ec09 100644
--- a/app/Enums/ContactMessageTopic.php
+++ b/app/Enums/ContactMessageTopic.php
@@ -5,6 +5,7 @@ namespace App\Enums;
enum ContactMessageTopic: string
{
case Contact = 'contact';
+ case Advertising = 'advertising';
case BugReport = 'bug_report';
case PressReleaseReport = 'press_release_report';
case Feedback = 'feedback';
@@ -16,6 +17,7 @@ enum ContactMessageTopic: string
{
return match ($this) {
self::Contact => 'Kontaktaufnahme',
+ self::Advertising => 'Werbeanfrage',
self::BugReport => 'Fehlermeldung',
self::PressReleaseReport => 'PM-Meldung',
self::Feedback => 'Feedback',
diff --git a/lang/de/web.php b/lang/de/web.php
index 2bc0089a..503bcf07 100644
--- a/lang/de/web.php
+++ b/lang/de/web.php
@@ -92,6 +92,15 @@ return [
'title' => 'Meistgelesen',
],
+ 'ad_slot' => [
+ 'label' => 'Anzeige',
+ 'end_label' => 'Ende Anzeige',
+ 'eyebrow' => 'Werbeplatz verfügbar',
+ 'title' => 'Hier könnte Ihre Werbung stehen',
+ 'text' => 'Erreichen Sie Entscheider aus dem DACH-Raum — direkt im redaktionellen Umfeld.',
+ 'cta' => 'Jetzt Werbeplatz anfragen',
+ ],
+
'newsrooms' => [
'title' => 'Aktive Newsrooms',
'today' => 'Heute',
@@ -189,6 +198,8 @@ return [
'intro' => 'Wählen Sie Ihr Anliegen — wir melden uns werktags schnellstmöglich zurück.',
'topic_contact' => 'Kontaktaufnahme',
'topic_contact_desc' => 'Allgemeine Frage oder Anfrage an uns',
+ 'topic_advertising' => 'Werbung buchen',
+ 'topic_advertising_desc' => 'Werbeplätze und Konditionen anfragen',
'topic_bug' => 'Fehler melden',
'topic_bug_desc' => 'Etwas funktioniert nicht wie erwartet',
'topic_press' => 'Pressemitteilung melden',
diff --git a/lang/en/web.php b/lang/en/web.php
index 1ad93d98..bf1c78a8 100644
--- a/lang/en/web.php
+++ b/lang/en/web.php
@@ -87,6 +87,15 @@ return [
'title' => 'Most read',
],
+ 'ad_slot' => [
+ 'label' => 'Advertisement',
+ 'end_label' => 'End of advertisement',
+ 'eyebrow' => 'Ad space available',
+ 'title' => 'Your advertising could be here',
+ 'text' => 'Reach decision-makers across the DACH region — right within the editorial environment.',
+ 'cta' => 'Enquire about this ad space',
+ ],
+
'newsrooms' => [
'title' => 'Active newsrooms',
'today' => 'Today',
@@ -184,6 +193,8 @@ return [
'intro' => 'Choose your topic — we will get back to you as soon as possible on business days.',
'topic_contact' => 'Get in touch',
'topic_contact_desc' => 'General question or inquiry',
+ 'topic_advertising' => 'Book advertising',
+ 'topic_advertising_desc' => 'Ask about ad placements and rates',
'topic_bug' => 'Report a bug',
'topic_bug_desc' => 'Something is not working as expected',
'topic_press' => 'Report a press release',
diff --git a/resources/views/components/web/ad-slot.blade.php b/resources/views/components/web/ad-slot.blade.php
new file mode 100644
index 00000000..c4ff8449
--- /dev/null
+++ b/resources/views/components/web/ad-slot.blade.php
@@ -0,0 +1,47 @@
+{{--
+ Werbeplatz-Hinweis (Eigenwerbung): dezenter „Anzeige"-Rahmen im Stil der
+ früheren Ad-Slots (focus-ad/feed-ad), solange die Fläche nicht vermarktet
+ ist. Klick öffnet das schwebende Kontakt-Widget mit vorgewähltem Thema
+ „Werbeanfrage" (Window-Event `open-contact-modal` + topic-Detail).
+
+ Varianten steuern nur die Außenabstände der jeweiligen Einbauorte:
+ - sidebar → Hero-Sidebar der Startseiten
+ - feed → Meldungs-Feed
+ - inline → Fließtext der PM-Detailseite
+--}}
+
+@props(['variant' => 'sidebar'])
+
+
$variant === 'sidebar',
+ 'my-6' => $variant === 'feed',
+ 'my-8 max-w-[680px]' => $variant === 'inline',
+])>
+
+
+ {{ __('web.ad_slot.label') }}
+
+
+
+
+
+
+
+ {{ __('web.ad_slot.end_label') }}
+
+
+
diff --git a/resources/views/components/web/contact-launcher.blade.php b/resources/views/components/web/contact-launcher.blade.php
index 4b3d5fad..79d209e4 100644
--- a/resources/views/components/web/contact-launcher.blade.php
+++ b/resources/views/components/web/contact-launcher.blade.php
@@ -25,6 +25,11 @@
'label' => __('web.launcher.topic_contact'),
'description' => __('web.launcher.topic_contact_desc'),
],
+ [
+ 'value' => \App\Enums\ContactMessageTopic::Advertising->value,
+ 'label' => __('web.launcher.topic_advertising'),
+ 'description' => __('web.launcher.topic_advertising_desc'),
+ ],
[
'value' => \App\Enums\ContactMessageTopic::BugReport->value,
'label' => __('web.launcher.topic_bug'),
@@ -50,7 +55,8 @@
topic: @js(old('topic')),
topicLabels: @js($launcherTopicLabels),
}"
- @open-contact-modal.window="open = true"
+ {{-- Optionales Event-Detail `topic` wählt das Anliegen direkt vor (z. B. Werbeplätze). --}}
+ @open-contact-modal.window="open = true; if ($event.detail?.topic && topicLabels[$event.detail.topic]) { topic = $event.detail.topic }"
@keydown.escape.window="open = false"
class="fixed bottom-5 right-5 z-50 flex flex-col items-end gap-3 print:hidden"
>
diff --git a/resources/views/components/web/focus-hero.blade.php b/resources/views/components/web/focus-hero.blade.php
index ac960d85..6edd48b2 100644
--- a/resources/views/components/web/focus-hero.blade.php
+++ b/resources/views/components/web/focus-hero.blade.php
@@ -88,6 +88,8 @@
@foreach ($sideReleases as $index => $release)
@endforeach
+
+
diff --git a/resources/views/livewire/web/press-release-feed.blade.php b/resources/views/livewire/web/press-release-feed.blade.php
index 31772d09..2e6add98 100644
--- a/resources/views/livewire/web/press-release-feed.blade.php
+++ b/resources/views/livewire/web/press-release-feed.blade.php
@@ -127,6 +127,11 @@ new class extends Component
@foreach ($rest as $release)
+
+ @if ($loop->index === 2)
+ {{-- Werbeplatz nach der dritten Feed-Meldung (Position der früheren feed-ad). --}}
+
+ @endif
@endforeach
@if ($releases->hasMorePages())
diff --git a/resources/views/web/release-detail.blade.php b/resources/views/web/release-detail.blade.php
index 417d2b66..cb49099f 100644
--- a/resources/views/web/release-detail.blade.php
+++ b/resources/views/web/release-detail.blade.php
@@ -353,6 +353,11 @@
@endif
+ {{-- Inline-Werbeplatz (Position der früheren Inline-Ad); in der privaten Vorschau ausgeblendet --}}
+ @unless ($isPreview)
+
+ @endunless
+
{{-- Pressekontakt --}}
@if ($contact)
diff --git a/tests/Feature/PressReleasePreviewTest.php b/tests/Feature/PressReleasePreviewTest.php
index dce50fe7..6527853e 100644
--- a/tests/Feature/PressReleasePreviewTest.php
+++ b/tests/Feature/PressReleasePreviewTest.php
@@ -62,7 +62,9 @@ test('preview renders the public release detail layout with preview banner and n
->assertSeeText('Vorschau')
->assertSeeText('So erscheint die Pressemitteilung nach der Veröffentlichung.')
->assertSeeText('Status: Entwurf')
- ->assertSeeText('Entwurf im Portal-Design');
+ ->assertSeeText('Entwurf im Portal-Design')
+ // Der Werbeplatz-Hinweis erscheint nur auf der öffentlichen Seite.
+ ->assertDontSeeText('Hier könnte Ihre Werbung stehen');
});
test('preview applies the theme of the target portal', function () {
diff --git a/tests/Feature/Web/ContactFormTest.php b/tests/Feature/Web/ContactFormTest.php
index 236d8308..b2d7a610 100644
--- a/tests/Feature/Web/ContactFormTest.php
+++ b/tests/Feature/Web/ContactFormTest.php
@@ -150,6 +150,34 @@ test('a widget submission stores topic and page url', function () {
});
});
+test('an advertising enquiry from the ad slot stores the advertising topic', function () {
+ /** @var TestCase $this */
+ Mail::fake();
+
+ $this->post('https://presseecho.test/de/kontakt', [
+ 'name' => 'Willi Werbung',
+ 'email' => 'willi@example.test',
+ 'message' => 'Ich interessiere mich für Werbeplätze auf Ihrem Portal.',
+ 'topic' => 'advertising',
+ 'page_url' => 'https://presseecho.test/de',
+ ])->assertSessionHas('contact-status');
+
+ $message = ContactMessage::query()->sole();
+
+ expect($message->topic)->toBe(ContactMessageTopic::Advertising)
+ ->and($message->portal)->toBe('presseecho');
+
+ Mail::assertSent(ContactRequestSubmitted::class, fn (ContactRequestSubmitted $mail) => $mail->topicLabel === 'Werbeanfrage');
+});
+
+test('the spoke pages offer the advertising topic in the contact launcher', function () {
+ /** @var TestCase $this */
+ $this->get('https://businessportal24.test/de/faq')
+ ->assertSuccessful()
+ ->assertSee('Werbung buchen')
+ ->assertSee('Werbeplätze und Konditionen anfragen');
+});
+
test('an unknown topic is rejected', function () {
/** @var TestCase $this */
Mail::fake();
diff --git a/tests/Feature/Web/PresseechoHomeTest.php b/tests/Feature/Web/PresseechoHomeTest.php
index 286c81db..3030bb96 100644
--- a/tests/Feature/Web/PresseechoHomeTest.php
+++ b/tests/Feature/Web/PresseechoHomeTest.php
@@ -50,6 +50,39 @@ test('presseecho homepage renders the editorial shell with real data', function
->assertSeeText('Heute im Fokus');
});
+test('presseecho homepage shows the ad slot self-promotion in the hero sidebar', function () {
+ /** @var TestCase $this */
+ $category = Category::factory()->create([
+ 'portal' => Portal::Presseecho,
+ ]);
+ $category->translations()->create([
+ 'locale' => 'de',
+ 'name' => 'Energie & Klima',
+ 'slug' => 'energie-klima',
+ ]);
+
+ $company = Company::factory()->presseecho()->create();
+
+ PressRelease::factory()
+ ->published()
+ ->forPortal(Portal::Presseecho)
+ ->for($category)
+ ->for($company)
+ ->create([
+ 'title' => 'Ad-Slot Hero Meldung',
+ 'slug' => 'ad-slot-hero-meldung',
+ 'published_at' => now()->subHour(),
+ ]);
+
+ $this->get('https://presseecho.test/de')
+ ->assertSuccessful()
+ ->assertSeeText('Hier könnte Ihre Werbung stehen')
+ ->assertSeeText('Jetzt Werbeplatz anfragen')
+ // Klick öffnet das Kontakt-Widget mit vorgewähltem Thema „Werbeanfrage".
+ ->assertSee('open-contact-modal', false)
+ ->assertSee("{ topic: 'advertising' }", false);
+});
+
test('presseecho homepage hides data sections and shows the empty feed state without content', function () {
/** @var TestCase $this */
$this->get('https://presseecho.test/de')
diff --git a/tests/Feature/Web/ReleaseDetailTest.php b/tests/Feature/Web/ReleaseDetailTest.php
index 3e5b6a54..740f84b3 100644
--- a/tests/Feature/Web/ReleaseDetailTest.php
+++ b/tests/Feature/Web/ReleaseDetailTest.php
@@ -128,6 +128,26 @@ test('release detail without chosen placeholder falls back to the generic hero',
->assertDontSee('images/press-release-placeholders/', false);
});
+test('release detail shows the ad slot self-promotion inline', function () {
+ /** @var TestCase $this */
+ // Werbeplatz-Hinweis (Eigenwerbung): Klick öffnet das Kontakt-Widget
+ // mit vorgewähltem Thema „Werbeanfrage".
+ [$category, $company] = detailCategoryAndCompany(Portal::Businessportal24);
+
+ $release = PressRelease::factory()
+ ->published()
+ ->forPortal(Portal::Businessportal24)
+ ->for($category)
+ ->for($company)
+ ->create(['slug' => 'meldung-mit-werbeplatz', 'published_at' => now()->subDay()]);
+
+ $this->get('https://businessportal24.test/de/press-release/'.$release->slug)
+ ->assertSuccessful()
+ ->assertSeeText('Hier könnte Ihre Werbung stehen')
+ ->assertSeeText('Jetzt Werbeplatz anfragen')
+ ->assertSee("{ topic: 'advertising' }", false);
+});
+
test('release detail shows prominent report links below the article', function () {
/** @var TestCase $this */
// T13 (Meldeverfahren): Die Melde-Links stehen sichtbar unter jeder