PLACEMENT SYSTEM 6 Ocak 2026

Dinamik Placement Sistemi

Neyi Nerede Göstereceğiz? - Spotify Business Pattern

📝 Basit Anlatım (Herkes İçin)

Ne İstiyoruz?

Spotify Business'ın yaptığı gibi: Farklı sayfalarda farklı koleksiyonlar göstermek!

Örnek:
  • Anasayfa: "Editör Seçkisi", "Premium Özel", "Yeni Çıkanlar"
  • Cafe Sayfası: "Recommended cafe playlists", "Popular cafe playlists", "Family-friendly"
  • Gym Sayfası: "Workout Energy", "Cardio Hits", "Cool Down"

Nasıl Çalışacak?

  1. 1
    Admin panel'den koleksiyon oluştururken:
    "Bu koleksiyonu hangi sayfalarda göster?" seçilir
  2. 2
    Kullanıcı o sayfaya girdiğinde:
    Backend otomatik olarak o sayfa için olan koleksiyonları getirir
  3. 3
    Saat/Gün/Abonelik kontrolü:
    Sadece uygun olanlar gösterilir (önceki sistemle aynı)

Spotify Business - Cafe Sayfası Analizi

Ekran Görüntüsünde Görülenler:

1. Sayfa: Cafe
URL: spotify.com/business/genre/cafe
2. Tag Filters (Üstte)
Discover All Acoustic Bossa nova Instrumental Pop
3. Collection: "Recommended cafe playlists"
6 playlist, horizontal scroll
4. Collection: "Popular cafe playlists"
Subtitle: "Barista favourites", 6 playlist
5. Collection: "Family-friendly music for cafes"
6 playlist, horizontal scroll

Bizim Sistemde Nasıl Yaparız?

✅ TAM OLARAK AYNI ŞEKİLDE!
placement_rules JSON field ekleyeceğiz
Cafe Sayfası için:
{
  "placement_rules": {
    "pages": ["sector_show"],
    "sector_ids": [1],
    "position": 1
  }
}
Anasayfa için:
{
  "placement_rules": {
    "pages": ["home"],
    "sector_ids": null,
    "position": 2
  }
}
Tüm Sektör Sayfalarında:
{
  "placement_rules": {
    "pages": ["sector_show"],
    "sector_ids": null,
    "position": 3
  }
}

🔧 Teknik Detaylar (Geliştiriciler İçin)

Database Schema Güncelleme

Mevcut (v3):
muzibu_content_collections:
  - display_rules JSON
  - visibility_conditions JSON
  - priority INT
Yeni (v4 - Placement):
muzibu_content_collections:
  - display_rules JSON
  - visibility_conditions JSON
  - placement_rules JSON ⭐ YENİ!
  - priority INT

placement_rules JSON Schema

{
  "pages": ["home", "sector_show", "sector_index", "playlists_index"],
  "sector_ids": [1, 2, 3],  // null = tüm sektörler
  "category_ids": [5, 6],   // null = tüm kategoriler
  "tag_ids": [2, 3],        // null = tüm taglar
  "position": 1,            // Sayfa içinde sıralama (1,2,3...)
  "zone": "main"            // "main", "sidebar", "footer"
}
pages (Array)
• home (Anasayfa)
• sector_show (Cafe sayfası)
• sector_index (Tüm sektörler)
• playlists_index (Playlist listesi)
• albums_index (Album listesi)
sector_ids (Array|null)
• [1] = Sadece Cafe
• [1,2] = Cafe + Restaurant
• null = Tüm sektörler
position (Int)
• 1 = En üstte
• 2 = İkinci sıra
• 3 = Üçüncü sıra

SmartRecommendationService.php (Güncellenmiş)

public function getCollectionsForPage(
    string $page,
    $sectorId = null,
    $categoryId = null,
    $tagId = null,
    $user = null
): Collection {
    $now = now();
    $dayOfWeek = $now->format('D');
    $currentTime = $now->format('H:i');

    return ContentCollection::where('is_active', true)
        ->get()
        ->filter(function($collection) use (
            $page, $sectorId, $categoryId, $tagId,
            $user, $dayOfWeek, $currentTime
        ) {
            // 1. Placement Rules Check ⭐ YENİ!
            if (!$this->checkPlacementRules(
                $collection,
                $page,
                $sectorId,
                $categoryId,
                $tagId
            )) {
                return false;
            }

            // 2. Display Rules Check (mevcut)
            if (!$this->checkDisplayRules(
                $collection,
                $dayOfWeek,
                $currentTime,
                $sectorId
            )) {
                return false;
            }

            // 3. Visibility Conditions Check (mevcut)
            if (!$this->checkVisibilityConditions(
                $collection,
                $user
            )) {
                return false;
            }

            return true;
        })
        ->sortBy(function($collection) {
            return $collection->placement_rules['position'] ?? 999;
        });
}

private function checkPlacementRules(
    $collection,
    $page,
    $sectorId,
    $categoryId,
    $tagId
): bool {
    $rules = $collection->placement_rules;

    // Page check
    if (isset($rules['pages']) && !in_array($page, $rules['pages'])) {
        return false;
    }

    // Sector check
    if (isset($rules['sector_ids']) && $rules['sector_ids'] !== null) {
        if ($sectorId && !in_array($sectorId, $rules['sector_ids'])) {
            return false;
        }
    }

    // Category check
    if (isset($rules['category_ids']) && $rules['category_ids'] !== null) {
        if ($categoryId && !in_array($categoryId, $rules['category_ids'])) {
            return false;
        }
    }

    // Tag check
    if (isset($rules['tag_ids']) && $rules['tag_ids'] !== null) {
        if ($tagId && !in_array($tagId, $rules['tag_ids'])) {
            return false;
        }
    }

    return true;
}

Gerçek Senaryolar (Admin Panel'den Oluşturma)

Senaryo 1: "Recommended cafe playlists"

Admin Panel Input:
Koleksiyon: "Recommended cafe playlists"
Tip: editorial
İçerik: 15 playlist seçildi
Kurallar (3 Tab):
Display Rules: Her zaman göster
Visibility: Herkes
Placement: pages=["sector_show"], sector_ids=[1], position=1
Sonuç:
Cafe sayfasına (muzibu.com/sectors/cafe) girince EN ÜSTTE görünür!

Senaryo 2: "Premium Özel Seçkiler" (Anasayfa)

Admin Panel Input:
Koleksiyon: "👑 Premium Seçkiler"
Tip: editorial
İçerik: 20 premium playlist
Kurallar (3 Tab):
Display Rules: Her zaman
Visibility: subscription_types=["premium"]
Placement: pages=["home"], position=1
Sonuç:
Anasayfada EN ÜSTTE, SADECE premium kullanıcılara gösterilir!

Senaryo 3: "☀️ Güne Enerjik Başla" (Tüm Sektörler)

Admin Panel Input:
Koleksiyon: "☀️ Güne Enerjik Başla"
Tip: time_based
İçerik: 15 playlist (tüm sektörler)
Kurallar (3 Tab):
Display Rules: 06:00-12:00, Mon-Fri
Visibility: Herkes
Placement: pages=["home","sector_show"], sector_ids=null, position=2
Sonuç:
• Anasayfa + TÜM sektör sayfalarında gösterilir
• SADECE 06:00-12:00 arası, hafta içi
• Position=2 → "Recommended" altında gösterilir

Admin Panel Güncelleme (v2 → v4)

Mevcut (v2 - 5 Tab):

1 Temel Bilgiler
2 Görünürlük Kuralları (display_rules)
3 Kullanıcı Koşulları (visibility_conditions)
4 İçerik Seçimi (collection_items)
5 Önizleme (JSON + Frontend)

Yeni (v4 - 6 Tab): ⭐

1 Temel Bilgiler
2 Görünürlük Kuralları
3 Kullanıcı Koşulları
4 Sayfa Yerleşimi (placement_rules) ⭐ YENİ!
5 İçerik Seçimi
6 Önizleme

Tab 4: Sayfa Yerleşimi (Mockup)

1 = En üstte, 2 = İkinci sıra, vb.
Oluşturulan JSON:
{
  "placement_rules": {
    "pages": ["home", "sector_show"],
    "sector_ids": [1],
    "position": 1,
    "zone": "main"
  }
}

Cafe Sayfası Layout (Spotify Business Pattern)

Cafe

Cafe işletmeniz için özel seçilmiş müzikler

Recommended cafe playlists

Cafe için özel

Popular cafe playlists

Barista favourites

Family-friendly music for cafes

Dinamik Yerleşim: Bu 3 koleksiyon admin panel'den "pages=['sector_show'], sector_ids=[1], position=1/2/3" ayarlanarak otomatik olarak Cafe sayfasında gösterildi!
🎯

Evet! TAM Spotify Business Gibi Yapabiliriz!

placement_rules ile neyi nerede göstereceğimizi dinamik olarak kontrol ediyoruz

Dinamik
Admin panel'den hangi sayfalarda gösterileceğini seç
Çoklu Sayfa
Aynı koleksiyon birden fazla sayfada gösterilebilir
Sıralama
Position field ile sıralamayı kontrol et
Sonraki Adım: Uygulama
1. Migration: placement_rules JSON field ekle
2. Admin Panel: Tab 4 ekle (Sayfa Yerleşimi)
3. Service: getCollectionsForPage() method ekle
4. Controller: Sector sayfası için koleksiyonları getir
5. View: Sector page layout oluştur