WooCommerce Hesabım Sayfasına Özel Sekme Ekleme

Müşterileriniz WooCommerce’in varsayılan “Hesabım” sayfasını kullanırken, siz de muhtemelen “Keşke buraya özel bir sekme ekleyebilsem” diye düşünmüşsünüzdür. Sipariş geçmişi var, adresler var, hesap detayları var… ama sizin özel içeriğiniz için yer yok. İşte bu yazıda tam olarak bunu çözeceğiz. functions.php dosyasına yazacağımız birkaç fonksiyonla “Hesabım” sayfasına istediğiniz sekmeleri ekleyecek, özel içerikler gösterecek ve hatta kullanıcı bazlı dinamik veriler sunacaksınız.

Neden Özel Sekme Ekleme İhtiyacı Duyulur?

Gerçek dünya senaryolarına bakalım. Bir üyelik sitesi işletiyorsunuz ve kullanıcıların indirdiği lisans anahtarlarını göstermek istiyorsunuz. Ya da B2B bir e-ticaret siteniz var ve kurumsal müşterilerinize özel fiyat listelerini hesap panelinden sunmak istiyorsunuz. Belki de sadakat puanlarını, referans kodlarını veya özel destek talep formunu “Hesabım” sayfasına entegre etmek istiyorsunuz.

WooCommerce bu ihtiyaçları karşılamak için hook sistemi sunuyor. woocommerce_account_menu_items ve woocommerce_account_{endpoint}_endpoint hook’larını kullanarak bu işi çok temiz bir şekilde halledebilirsiniz.

Temel Yapıyı Anlamak

WooCommerce “Hesabım” sayfası aslında bir endpoint sistemi üzerine kurulu. Her sekme bir endpoint’e karşılık geliyor. Örneğin /hesabim/siparisler/ URL’si orders endpoint’ini tetikliyor. Biz de kendi endpoint’imizi tanımlayarak bu sisteme dahil olacağız.

Üç temel adım var:

  • Endpoint kaydetmek: WordPress’e yeni URL yapısını tanıtmak
  • Menüye eklemek: Sol menüde sekmemizin görünmesini sağlamak
  • İçerik göstermek: Sekmeye tıklandığında ne görüntüleneceğini belirlemek

Bunlara ek olarak rewrite rules’u flush etmek gerekiyor ki URL’ler düzgün çalışsın.

İlk Adım: Basit Bir Sekme Eklemek

functions.php dosyanıza bu kodu ekleyerek başlayalım:

<?php
// 1. Endpoint'i kaydet
function custom_add_my_account_endpoint() {
    add_rewrite_endpoint( 'ozel-icerik', EP_ROOT | EP_PAGES );
}
add_action( 'init', 'custom_add_my_account_endpoint' );

// 2. Menüye sekme ekle
function custom_add_my_account_menu_items( $items ) {
    // Çıkış yap linkinden önce ekle
    $logout = $items['customer-logout'];
    unset( $items['customer-logout'] );
    
    $items['ozel-icerik'] = 'Özel İçerik';
    $items['customer-logout'] = $logout;
    
    return $items;
}
add_filter( 'woocommerce_account_menu_items', 'custom_add_my_account_menu_items' );

// 3. İçeriği göster
function custom_ozel_icerik_endpoint_content() {
    echo '<h3>Özel İçeriğiniz</h3>';
    echo '<p>Buraya istediğiniz içeriği ekleyebilirsiniz.</p>';
}
add_action( 'woocommerce_account_ozel-icerik_endpoint', 'custom_ozel_icerik_endpoint_content' );

Kodu ekledikten sonra WordPress yönetici paneli > Ayarlar > Kalıcı Bağlantılar sayfasına girip kaydetmeniz gerekiyor. Bu işlem rewrite rules’u yeniler ve yeni endpoint’iniz aktif hale gelir.

Endpoint Adlandırma Kuralları

Dikkat etmeniz gereken önemli bir nokta var. Endpoint adında Türkçe karakter kullanmayın. URL yapısında sorun çıkarır. Ancak menü etiketinde Türkçe karakter kullanabilirsiniz.

<?php
// YANLIŞ kullanım - URL'de sorun çıkarır
add_rewrite_endpoint( 'özel-içerik', EP_ROOT | EP_PAGES );

// DOĞRU kullanım - URL temiz, etiket Türkçe
add_rewrite_endpoint( 'ozel-icerik', EP_ROOT | EP_PAGES );
$items['ozel-icerik'] = 'Özel İçerik'; // Etiket Türkçe olabilir

Ayrıca hook adında tire varsa PHP hook adında bu tire olduğu gibi kullanılır:

<?php
// Endpoint adı: ozel-icerik
// Hook adı: woocommerce_account_ozel-icerik_endpoint
add_action( 'woocommerce_account_ozel-icerik_endpoint', 'callback_fonksiyonu' );

Birden Fazla Sekme Eklemek

Gerçek projelerde genellikle birden fazla sekme gerekir. Hepsini düzenli bir şekilde yönetmek için array yapısı kullanalım:

<?php
/**
 * Birden fazla özel sekme yönetimi
 * Her sekme için endpoint, etiket ve callback tanımlanıyor
 */
function custom_register_account_endpoints() {
    $endpoints = custom_get_account_tabs();
    foreach ( $endpoints as $endpoint => $data ) {
        add_rewrite_endpoint( $endpoint, EP_ROOT | EP_PAGES );
    }
}
add_action( 'init', 'custom_register_account_endpoints' );

// Tüm özel sekmeleri merkezi olarak tanımlayan fonksiyon
function custom_get_account_tabs() {
    return array(
        'lisans-anahtarlari' => array(
            'label'    => 'Lisans Anahtarları',
            'callback' => 'custom_lisans_anahtarlari_content',
            'icon'     => '🔑',
        ),
        'sadakat-puanlari' => array(
            'label'    => 'Sadakat Puanları',
            'callback' => 'custom_sadakat_puanlari_content',
            'icon'     => '⭐',
        ),
        'destek-talepleri' => array(
            'label'    => 'Destek Talepleri',
            'callback' => 'custom_destek_talepleri_content',
            'icon'     => '🎫',
        ),
    );
}

// Menüye ekle
function custom_add_multiple_menu_items( $items ) {
    $tabs     = custom_get_account_tabs();
    $logout   = $items['customer-logout'];
    unset( $items['customer-logout'] );
    
    foreach ( $tabs as $endpoint => $data ) {
        $items[ $endpoint ] = $data['icon'] . ' ' . $data['label'];
    }
    
    $items['customer-logout'] = $logout;
    return $items;
}
add_filter( 'woocommerce_account_menu_items', 'custom_add_multiple_menu_items' );

// Her sekme için hook bağlantısını dinamik olarak kur
function custom_register_endpoint_actions() {
    $tabs = custom_get_account_tabs();
    foreach ( $tabs as $endpoint => $data ) {
        add_action(
            'woocommerce_account_' . $endpoint . '_endpoint',
            $data['callback']
        );
    }
}
add_action( 'init', 'custom_register_endpoint_actions' );

Gerçek Dünya Senaryosu: Lisans Anahtarları Sekmesi

Diyelim ki dijital ürün satıyorsunuz ve her kullanıcının satın aldığı ürünlere ait lisans anahtarlarını göstermek istiyorsunuz. Bu anahtarları bir meta key olarak siparişlerde sakladığınızı varsayıyorum:

<?php
function custom_lisans_anahtarlari_content() {
    $current_user_id = get_current_user_id();
    
    // Kullanıcının tamamlanmış siparişlerini al
    $orders = wc_get_orders( array(
        'customer_id' => $current_user_id,
        'status'      => array( 'wc-completed' ),
        'limit'       => -1,
    ) );
    
    if ( empty( $orders ) ) {
        echo '<div class="woocommerce-info">';
        echo 'Henüz tamamlanmış siparişiniz bulunmuyor.';
        echo '</div>';
        return;
    }
    
    echo '<h3>Lisans Anahtarlarınız</h3>';
    echo '<div class="custom-license-list">';
    
    $lisans_bulundu = false;
    
    foreach ( $orders as $order ) {
        foreach ( $order->get_items() as $item ) {
            // Her sipariş kaleminde lisans anahtarı ara
            $lisans_key = $item->get_meta( '_lisans_anahtari' );
            
            if ( $lisans_key ) {
                $lisans_bulundu = true;
                $product_name   = $item->get_name();
                $order_date     = $order->get_date_created()->date( 'd.m.Y' );
                
                echo '<div class="lisans-item" style="border:1px solid #ddd; padding:15px; margin:10px 0; border-radius:4px;">';
                echo '<strong>' . esc_html( $product_name ) . '</strong>';
                echo '<p>Satın Alma Tarihi: ' . esc_html( $order_date ) . '</p>';
                echo '<div class="lisans-key" style="background:#f5f5f5; padding:10px; font-family:monospace; font-size:14px;">';
                echo esc_html( $lisans_key );
                echo '</div>';
                echo '<button onclick="navigator.clipboard.writeText('' . esc_js( $lisans_key ) . '')" style="margin-top:8px; cursor:pointer;">Kopyala</button>';
                echo '</div>';
            }
        }
    }
    
    if ( ! $lisans_bulundu ) {
        echo '<div class="woocommerce-info">Lisans anahtarınız bulunmuyor.</div>';
    }
    
    echo '</div>';
}

Gerçek Dünya Senaryosu: Sadakat Puanları Sekmesi

Kullanıcı meta verisi olarak sakladığınız puanları gösteren bir sekme:

<?php
function custom_sadakat_puanlari_content() {
    $user_id       = get_current_user_id();
    $mevcut_puan   = (int) get_user_meta( $user_id, '_sadakat_puani', true );
    $puan_gecmisi  = get_user_meta( $user_id, '_puan_gecmisi', true );
    
    if ( ! is_array( $puan_gecmisi ) ) {
        $puan_gecmisi = array();
    }
    
    // TL karşılığı hesapla (örnek: 100 puan = 10 TL)
    $tl_karsiligi = number_format( $mevcut_puan / 10, 2 );
    
    echo '<div class="sadakat-ozet" style="background:#f0f8f0; padding:20px; border-radius:8px; margin-bottom:20px;">';
    echo '<h3 style="margin:0 0 10px;">Toplam Puanınız</h3>';
    echo '<div style="font-size:48px; font-weight:bold; color:#2e7d32;">' . esc_html( $mevcut_puan ) . '</div>';
    echo '<p>≈ ' . esc_html( $tl_karsiligi ) . ' TL değerinde</p>';
    echo '</div>';
    
    if ( ! empty( $puan_gecmisi ) ) {
        echo '<h4>Puan Geçmişi</h4>';
        echo '<ul style="list-style:none; padding:0;">';
        
        foreach ( array_reverse( $puan_gecmisi ) as $kayit ) {
            $renk = $kayit['miktar'] > 0 ? '#2e7d32' : '#c62828';
            $isaret = $kayit['miktar'] > 0 ? '+' : '';
            
            echo '<li style="display:flex; justify-content:space-between; padding:10px; border-bottom:1px solid #eee;">';
            echo '<span>' . esc_html( $kayit['aciklama'] ) . ' - ' . esc_html( $kayit['tarih'] ) . '</span>';
            echo '<strong style="color:' . $renk . ';">' . $isaret . esc_html( $kayit['miktar'] ) . ' puan</strong>';
            echo '</li>';
        }
        
        echo '</ul>';
    } else {
        echo '<p>Henüz puan işleminiz bulunmuyor.</p>';
    }
}

Kullanıcı Rolüne Göre Sekme Gösterme / Gizleme

B2B sitelerinde toptan müşterilerinize özel sekmeler göstermek, perakende müşterilere göstermemek isteyebilirsiniz:

<?php
function custom_conditional_menu_items( $items ) {
    $current_user = wp_get_current_user();
    
    // Toptan müşteri rolü kontrolü
    if ( in_array( 'toptan_musteri', (array) $current_user->roles ) ) {
        $logout = $items['customer-logout'];
        unset( $items['customer-logout'] );
        
        $items['toptan-fiyat-listesi'] = '📋 Toptan Fiyat Listesi';
        $items['kurumsal-fatura']      = '🏢 Kurumsal Fatura Bilgileri';
        
        $items['customer-logout'] = $logout;
    }
    
    // Premium üye kontrolü
    $is_premium = get_user_meta( get_current_user_id(), '_premium_uye', true );
    if ( $is_premium ) {
        $logout = $items['customer-logout'];
        unset( $items['customer-logout'] );
        
        $items['premium-icerikler'] = '👑 Premium İçerikler';
        
        $items['customer-logout'] = $logout;
    }
    
    return $items;
}
add_filter( 'woocommerce_account_menu_items', 'custom_conditional_menu_items' );

// Toptan fiyat listesi içeriği
function custom_toptan_fiyat_listesi_content() {
    $current_user = wp_get_current_user();
    
    if ( ! in_array( 'toptan_musteri', (array) $current_user->roles ) ) {
        wp_redirect( wc_get_account_endpoint_url( 'dashboard' ) );
        exit;
    }
    
    // PDF veya tablo gösterimi
    $fiyat_listesi_url = get_option( 'toptan_fiyat_listesi_pdf' );
    
    echo '<h3>Toptan Fiyat Listeniz</h3>';
    
    if ( $fiyat_listesi_url ) {
        echo '<p><a href="' . esc_url( $fiyat_listesi_url ) . '" class="button" download>Fiyat Listesini İndir (PDF)</a></p>';
    }
    
    echo '<p>Fiyat listesi hakkında sorularınız için <a href="mailto:[email protected]">[email protected]</a> adresine yazabilirsiniz.</p>';
}
add_action( 'woocommerce_account_toptan-fiyat-listesi_endpoint', 'custom_toptan_fiyat_listesi_content' );

Form İçeren Sekme: Destek Talebi

Sekme içinde form gösterip AJAX veya normal POST ile işlem de yapabilirsiniz:

<?php
function custom_destek_talepleri_content() {
    // Form gönderildi mi kontrol et
    if ( isset( $_POST['destek_gonder'] ) && wp_verify_nonce( $_POST['_wpnonce'], 'destek_talebi' ) ) {
        $konu    = sanitize_text_field( $_POST['konu'] );
        $mesaj   = sanitize_textarea_field( $_POST['mesaj'] );
        $user_id = get_current_user_id();
        $user    = get_userdata( $user_id );
        
        // E-posta gönder
        $to      = get_option( 'admin_email' );
        $subject = 'Destek Talebi: ' . $konu;
        $body    = "Kullanıcı: " . $user->display_name . " (" . $user->user_email . ")nn";
        $body   .= "Konu: " . $konu . "nn";
        $body   .= "Mesaj:n" . $mesaj;
        
        $gonderildi = wp_mail( $to, $subject, $body );
        
        if ( $gonderildi ) {
            // Talebi veritabanına da kaydedelim
            $talepler = get_user_meta( $user_id, '_destek_talepleri', true );
            if ( ! is_array( $talepler ) ) {
                $talepler = array();
            }
            $talepler[] = array(
                'tarih'  => date( 'd.m.Y H:i' ),
                'konu'   => $konu,
                'durum'  => 'Açık',
            );
            update_user_meta( $user_id, '_destek_talepleri', $talepler );
            
            echo '<div class="woocommerce-message">Destek talebiniz başarıyla iletildi. En kısa sürede dönüş yapacağız.</div>';
        } else {
            echo '<div class="woocommerce-error">Bir hata oluştu. Lütfen tekrar deneyin.</div>';
        }
    }
    
    // Geçmiş talepler
    $user_id  = get_current_user_id();
    $talepler = get_user_meta( $user_id, '_destek_talepleri', true );
    
    if ( is_array( $talepler ) && ! empty( $talepler ) ) {
        echo '<h4>Geçmiş Talepleriniz</h4>';
        echo '<ul style="list-style:none; padding:0;">';
        foreach ( array_reverse( $talepler ) as $talep ) {
            echo '<li style="padding:10px; border-bottom:1px solid #eee;">';
            echo '<strong>' . esc_html( $talep['konu'] ) . '</strong> - ';
            echo '<small>' . esc_html( $talep['tarih'] ) . '</small> ';
            echo '<span style="color:orange;">' . esc_html( $talep['durum'] ) . '</span>';
            echo '</li>';
        }
        echo '</ul>';
    }
    
    // Yeni talep formu
    echo '<h4>Yeni Destek Talebi</h4>';
    echo '<form method="post">';
    wp_nonce_field( 'destek_talebi' );
    echo '<p><label>Konu<br><input type="text" name="konu" required style="width:100%;"></label></p>';
    echo '<p><label>Mesajınız<br><textarea name="mesaj" rows="5" required style="width:100%;"></textarea></label></p>';
    echo '<p><input type="submit" name="destek_gonder" value="Talebi Gönder" class="button"></p>';
    echo '</form>';
}
add_action( 'woocommerce_account_destek-talepleri_endpoint', 'custom_destek_talepleri_content' );

Özel CSS Eklemek

Sekmelerinizin diğerlerine uyumlu görünmesi için WooCommerce stil sistemini kullanın:

<?php
function custom_account_tab_styles() {
    if ( is_account_page() ) {
        echo '<style>
        .custom-license-list .lisans-item {
            transition: box-shadow 0.2s;
        }
        .custom-license-list .lisans-item:hover {
            box-shadow: 0 2px 8px rgba(0,0,0,0.1);
        }
        .woocommerce-MyAccount-navigation ul li.is-active a {
            font-weight: bold;
        }
        .sadakat-ozet {
            text-align: center;
        }
        @media (max-width: 768px) {
            .lisans-key {
                word-break: break-all;
            }
        }
        </style>';
    }
}
add_action( 'wp_head', 'custom_account_tab_styles' );

Sık Karşılaşılan Sorunlar ve Çözümleri

404 Hatası Alıyorum

Endpoint’i ekledikten sonra kalıcı bağlantıları yenilemek zorunlu. Bunu functions.php‘ye ekleyerek otomatik hale getirebilirsiniz:

<?php
function custom_flush_rewrite_on_activate() {
    custom_add_my_account_endpoint();
    flush_rewrite_rules();
}
register_activation_hook( __FILE__, 'custom_flush_rewrite_on_activate' );

// Geliştirme sürecinde manuel tetiklemek için:
// Yönetici paneli > Ayarlar > Kalıcı Bağlantılar > Kaydet

Sekme Aktif Görünmüyor

WooCommerce aktif sekmeyi tespit etmek için query var kullanıyor. Eğer sekmeniz aktif görünmüyorsa:

<?php
function custom_fix_active_endpoint( $endpoint ) {
    // Endpoint adınızın query var olarak tanındığından emin olun
    global $wp_query;
    
    if ( isset( $wp_query->query_vars['ozel-icerik'] ) ) {
        // Bu endpoint aktif
    }
}

İçerik Görünmüyor Ama Hata da Yok

Hook adının endpoint adıyla tam eşleştiğini kontrol edin. Tire karakteri dahil her şey birebir aynı olmalı:

<?php
// Endpoint: destek-talepleri
// Hook: woocommerce_account_destek-talepleri_endpoint
// Sondaki _endpoint ifadesini unutmayın!
add_action( 'woocommerce_account_destek-talepleri_endpoint', 'callback' );

Sonuç

WooCommerce “Hesabım” sayfasına özel sekme eklemek, doğru hook’ları bildiğinizde oldukça basit bir işlem. woocommerce_account_menu_items filter’ı ile menüye ekliyorsunuz, woocommerce_account_{endpoint}_endpoint action’ı ile içeriği gösteriyorsunuz. Aradaki tek kritik nokta kalıcı bağlantıları yenilemek.

Bu sistemi kullanarak müşterilerinize çok daha zengin bir hesap deneyimi sunabilirsiniz. Lisans anahtarları, sadakat puanları, destek talepleri, referans programları, özel belgeler… bunların hepsini WooCommerce’in mevcut arayüzüne entegre ederek tutarlı bir kullanıcı deneyimi yaratabilirsiniz.

Kodları bir plugin’e taşımayı da düşünebilirsiniz. Özellikle birden fazla sekme yönetiyorsanız, functions.php‘de tutmak yerine küçük bir must-use plugin olarak ayırmak hem yönetimi kolaylaştırır hem de tema değişikliklerinden etkilenmemenizi sağlar.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir