Zum Hauptinhalt springen

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

MethodParameterReturnBeschreibung
calculateDailyMetrics()?string $platform = nullintGrowth-Metriken für alle Profile berechnen
calculateTrendingScores()--intTrending-Scores basierend auf Growth berechnen
updateTrendingFlags()--intis_rising_star Flags setzen

Berechnete Metriken

MetrikBeschreibungBerechnung
followers_countAktueller Follower-StandLetzte SocialProfileDailyMetric
follower_growth_7dAbsolutes Wachstum 7 Tagecurrent - 7_days_ago
follower_growth_7d_pctRelatives Wachstum 7 Tage(current - 7d_ago) / 7d_ago * 100
follower_growth_30dAbsolutes Wachstum 30 Tagecurrent - 30_days_ago
follower_growth_30d_pctRelatives Wachstum 30 TageProzentual
trending_scoreTrending-IndikatorGewichteter Score aus kurz-/langfristigem Wachstum
follower_tierGrößenklassemicro, small, medium, large, mega
is_rising_starÜberdurchschnittliches WachstumWachstum > Tier-Durchschnitt
favorites_countAnzahl Favoriten-EinträgeCount aus favorite_watcher_sources

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:

  1. Das relative 7-Tage-Wachstum den Durchschnitt des eigenen Tiers überschreitet
  2. Mindestens 7 Datenpunkte vorliegen
  3. 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

  • SocialProfile Model, SocialProfileDailyMetric Model, SocialProfileExploreMetrics Model, DailySyncRun Model

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

MethodParameterReturnBeschreibung
calculateTrendingVideos()--intTrending-Scores für alle Videos berechnen
getTopTrending()int $limit = 50CollectionTop-Trending-Videos abrufen
MetrikBeschreibung
view_velocityViews pro Stunde in den letzten 24h
view_growth_24hAbsolute View-Zunahme in 24 Stunden
view_growth_24h_pctRelative View-Zunahme in 24 Stunden
trending_scoreGewichteter 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

  • YouTubeVideo Model, YouTubeVideoStat Model

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

MethodParameterReturnBeschreibung
detectCategories()int $chunkSize = 1000intAI-Kategorien für alle Profile synchronisieren

Ablauf

  1. Alle Profile mit tracking_enabled = true, followers_count >= 100, gesetzter ai_category und nicht blocked/sanitized/archived werden in Chunks geladen
  2. Für jedes Profil wird ai_category → Slug gemappt (via ExploreCategorySeeder::getSlugForAiCategory())
  3. Der Slug wird in explore_profile_metrics.primary_category geschrieben (nur tatsaechliche Updates werden gezaehlt)
  4. Am Ende werden die Profil-Counts pro Kategorie in explore_categories.profile_count aktualisiert

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)

MethodParameterReturnBeschreibung
getSlugForAiCategory()string $aiCategory?stringAI-Name → Slug (z.B. 'Technology''technology')
getAiCategoryForSlug()string $slug?stringSlug → AI-Name (z.B. 'beauty-fashion''Beauty & Fashion')

Location: database/seeders/ExploreCategorySeeder.php

Abhängigkeiten

  • ExploreCategory Model, SocialProfile Model, ExploreProfileMetric Model, ExploreCategorySeeder

Verwendet von

  • CalculateExploreMetrics-Command (--type=categories), Explore-Seite Kategorie-Filter