Explore Services
Die Explore-Services berechnen Growth-Metriken, Trending-Scores und Kategorie-Zuordnungen für die Explore-Ansicht. Sie laufen täglich als Batch-Berechnung und speichern ihre Ergebnisse in dedizierten Metriken-Tabellen.
ExploreMetricsCalculator
Location: app/Services/Explore/ExploreMetricsCalculator.php
Berechnet tägliche Growth-Metriken und Trending-Scores für alle getrackten Profile. Die Ergebnisse werden in der social_profile_explore_metrics-Tabelle gespeichert und bilden die Grundlage für Explore-Sortierung, Rising-Star-Erkennung und Kategorie-Filter.
Public Methods
| Method | Parameter | Return | Beschreibung |
|---|---|---|---|
calculateDailyMetrics() | ?string $platform = null | int | Growth-Metriken für alle Profile berechnen |
calculateTrendingScores() | -- | int | Trending-Scores basierend auf Growth berechnen |
updateTrendingFlags() | -- | int | is_rising_star Flags setzen |
Berechnete Metriken
| Metrik | Beschreibung | Berechnung |
|---|---|---|
followers_count | Aktueller Follower-Stand | Letzte SocialProfileDailyMetric |
follower_growth_7d | Absolutes Wachstum 7 Tage | current - 7_days_ago |
follower_growth_7d_pct | Relatives Wachstum 7 Tage | (current - 7d_ago) / 7d_ago * 100 |
follower_growth_30d | Absolutes Wachstum 30 Tage | current - 30_days_ago |
follower_growth_30d_pct | Relatives Wachstum 30 Tage | Prozentual |
trending_score | Trending-Indikator | Gewichteter Score aus kurz-/langfristigem Wachstum |
follower_tier | Größenklasse | micro, small, medium, large, mega |
is_rising_star | Überdurchschnittliches Wachstum | Wachstum > Tier-Durchschnitt |
favorites_count | Anzahl Favoriten-Einträge | Count aus favorite_watcher_sources |
Trending-Score-Berechnung
Der Trending-Score gewichtet kurzfristiges Wachstum stärker als langfristiges:
trending_score = (growth_7d_pct * 0.6) + (growth_30d_pct * 0.4)
Profile mit negativem Wachstum erhalten einen Trending-Score von 0.
Rising-Star-Erkennung
Ein Profil wird als Rising Star markiert, wenn:
- Das relative 7-Tage-Wachstum den Durchschnitt des eigenen Tiers überschreitet
- Mindestens 7 Datenpunkte vorliegen
- Das Profil nicht blocked, sanitized oder archived ist
DailySyncRun-Integration
Die Berechnung nutzt die DailySyncRun-Tabelle, um nur Tage mit vollständigen Sync-Daten zu berücksichtigen. Ein Tag gilt als "complete", wenn der Status des DailySyncRun-Eintrags complete ist. Tage mit partiellem oder fehlendem Sync werden bei der Growth-Berechnung übersprungen.
Fallback-Mechanismus: Wenn keine DailySyncRun-Einträge mit Status complete vorliegen, greift ein Fallback auf die tatsächlichen Datumseinträge in social_profile_daily_metrics. Dabei werden die letzten 4 verfügbaren Datumswerte als Berechnungsgrundlage verwendet. Wichtig: Der Date-Vergleich normalisiert sowohl Carbon-Objekte als auch Strings auf toDateString(), um Type-Mismatch-Fehler zu vermeiden (Bugfix 2026-02-22).
Ausschluss-Filter
Bei der Berechnung werden grundsätzlich gefiltert:
->whereNull('blocked_at')
->whereNull('sanitized_at')
->whereNull('archived_at')
Abhängigkeiten
SocialProfileModel,SocialProfileDailyMetricModel,SocialProfileExploreMetricsModel,DailySyncRunModel
Verwendet von
CalculateExploreMetrics-Command (täglich 03:00 UTC), Explore-Seite, Related Profiles
ExploreTrendingVideosCalculator
Location: app/Services/Explore/ExploreTrendingVideosCalculator.php
Berechnet Trending-Scores für YouTube-Videos basierend auf View-Velocity und View-Growth. Identifiziert Videos, die aktuell überdurchschnittlich schnell an Views gewinnen.
Public Methods
| Method | Parameter | Return | Beschreibung |
|---|---|---|---|
calculateTrendingVideos() | -- | int | Trending-Scores für alle Videos berechnen |
getTopTrending() | int $limit = 50 | Collection | Top-Trending-Videos abrufen |
Trending-Video-Metriken
| Metrik | Beschreibung |
|---|---|
view_velocity | Views pro Stunde in den letzten 24h |
view_growth_24h | Absolute View-Zunahme in 24 Stunden |
view_growth_24h_pct | Relative View-Zunahme in 24 Stunden |
trending_score | Gewichteter Score aus Velocity und Growth |
Berechnung
view_velocity = (views_now - views_24h_ago) / hours_since_publish
trending_score = normalize(view_velocity * 0.5 + view_growth_24h_pct * 0.3 + engagement_rate * 0.2)
Abhängigkeiten
YouTubeVideoModel,YouTubeVideoStatModel
Verwendet von
CalculateExploreMetrics-Command (--type=trending), Explore Trending Videos Seite
ExploreCategoryDetector
Location: app/Services/Explore/ExploreCategoryDetector.php
Synchronisiert AI-erkannte Kategorien aus social_profiles.ai_category nach explore_profile_metrics.primary_category. Die Kategorien werden durch den Gemini AI-Enhancer (DetectProfileLanguage-Job) gesetzt und als englische Namen gespeichert. Der Detector mappt diese über ExploreCategorySeeder::getSlugForAiCategory() auf Slugs.
Public Methods
| Method | Parameter | Return | Beschreibung |
|---|---|---|---|
detectCategories() | int $chunkSize = 1000 | int | AI-Kategorien für alle Profile synchronisieren |
Ablauf
- Alle Profile mit
tracking_enabled = true,followers_count >= 100, gesetzterai_categoryund nicht blocked/sanitized/archived werden in Chunks geladen - Für jedes Profil wird
ai_category→ Slug gemappt (viaExploreCategorySeeder::getSlugForAiCategory()) - Der Slug wird in
explore_profile_metrics.primary_categorygeschrieben (nur tatsaechliche Updates werden gezaehlt) - Am Ende werden die Profil-Counts pro Kategorie in
explore_categories.profile_countaktualisiert
Ausschluss-Filter
Die Query verwendet dieselben Filter wie der ExploreMetricsCalculator:
->whereNull('blocked_at')
->whereNull('sanitized_at')
->whereNull('archived_at')
Dadurch werden nur Profile kategorisiert, die tatsaechlich in Explore sichtbar sind. Ohne diese Filter entstanden Diskrepanzen zwischen AI-erkannten Kategorien (~150k) und tatsaechlich kategorisierten Explore-Profilen (~59k).
26 Kategorien
Alle Kategorien stammen 1:1 aus ChannelLanguageDetector::CATEGORIES:
Automotive, Beauty & Fashion, Comedy, Education, Finance & Business, Fitness & Health, Food & Cooking, Gaming, Lifestyle, Music, News, Politics, Pets & Animals, Science, Technology, Sports, Travel & Adventure, Kids & Family, Movies, TV & Anime, DIY, Crafts & Maker, Art & Design, Home & Garden, True Crime, ASMR & Relaxation, Podcasts & Interviews, Other
Helper-Methoden (ExploreCategorySeeder)
| Method | Parameter | Return | Beschreibung |
|---|---|---|---|
getSlugForAiCategory() | string $aiCategory | ?string | AI-Name → Slug (z.B. 'Technology' → 'technology') |
getAiCategoryForSlug() | string $slug | ?string | Slug → AI-Name (z.B. 'beauty-fashion' → 'Beauty & Fashion') |
Location: database/seeders/ExploreCategorySeeder.php
Abhängigkeiten
ExploreCategoryModel,SocialProfileModel,ExploreProfileMetricModel,ExploreCategorySeeder
Verwendet von
CalculateExploreMetrics-Command (--type=categories), Explore-Seite Kategorie-Filter