PM-Tracking: Ereignis-Log fuer Aufrufe + Shares (press_release_events)

- press_release_events (type view/share, channel, ohne Personenbezug):
  Model/Enums/Factory, Cascade-Delete an der PM
- Detailaufruf loggt View-Event zusaetzlich zum Legacy-hits-Zaehler
  (bleibt bewusst einfacher Page-Request-Zaehler, User-Vorgabe 10.07.)
- POST press-release/{slug}/share (throttle 30/min, nur archiv-sichtbare
  PMs des Portals) loggt Teilen-Klicks je Kanal (LinkedIn/X/E-Mail/Copy)
- Kundenpanel-PM-Seite: neue Kachel Geteilt mit Kanal-Aufschluesselung
- lang: web.detail.views (de/en)
- Tests: Web/PressReleaseTrackingTest (7)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Kevin Adametz 2026-07-10 09:56:42 +00:00
parent 60d0d9b103
commit 8f5970436b
14 changed files with 392 additions and 0 deletions

View file

@ -10,6 +10,7 @@ use App\Http\Controllers\Web\NewsroomDetailController;
use App\Http\Controllers\Web\NewsroomsController;
use App\Http\Controllers\Web\PreiseController;
use App\Http\Controllers\Web\ReleaseDetailController;
use App\Http\Controllers\Web\ReleaseShareTrackingController;
use App\Http\Controllers\Web\ReportFormController;
use App\Http\Controllers\Web\SitemapController;
use App\Http\Controllers\Web\SucheController;
@ -205,6 +206,12 @@ Route::prefix('{edition}')->whereIn('edition', SetEdition::EDITIONS)->group(func
// Detailseite einer Pressemitteilung (z.B. /de/press-release/ki-revolution)
Route::get('press-release/{slug}', ReleaseDetailController::class)->name('release.detail');
// Share-Tracking der Detailseite (Teilen-Buttons): loggt Kanal-Klicks
// als press_release_events, ohne Personenbezug.
Route::post('press-release/{slug}/share', ReleaseShareTrackingController::class)
->middleware('throttle:30,1')
->name('release.share');
// Preise / Tarife (datengetrieben: Plan + config/billing + config/credits)
Route::get('preise', PreiseController::class)->name('preise');