WordPress’te Yazı Altına Yazar Kutusu Ekleme: Bio ve Sosyal Medya Linkleri
Blog yazılarında yazar bilgisini göstermek, okuyucularla güven bağı kurmanın en doğal yollarından biri. Ziyaretçi bir yazıyı okuyunca “Bu kim yazdı, neden dinlemeliyim?” diye düşünür. İşte tam bu noktada yazar kutusu devreye giriyor. WordPress’in varsayılan yapısında bu özellik yok ya da çok kısıtlı kalıyor. Plugin yüklemek yerine doğrudan functions.php üzerinden bu işi halletmek hem daha temiz hem de sitenizin performansını etkilemiyor.
Bu yazıda sıfırdan bir yazar kutusu sistemi kuracağız. Yazar profil fotoğrafı, biyografi, sosyal medya linkleri ve birden fazla yazar senaryosunu ele alacağız. Kod örnekleri gerçek projelerde kullandığım yapılar, doğrudan kopyalayıp kullanabilirsiniz.
Temel Yaklaşım: Ne Yapmak İstiyoruz?
Hedef şu: Her blog yazısının altına, o yazıyı yazan kişinin kısa biyografisini, profil fotoğrafını ve sosyal medya butonlarını gösteren bir kutu eklemek. Bunu yaparken:
- WordPress kullanıcı profil alanlarını kullanacağız
- Ekstra profil alanları ekleyeceğiz (Twitter, LinkedIn, GitHub vs.)
- Yazar kutusunu otomatik olarak tek yazı sayfalarına ekleyeceğiz
- CSS ile şekillendireceğiz
- Çok yazarlı sitelerde sorunsuz çalışmasını sağlayacağız
Tüm bu iş için tek bir plugin bile kurmak zorunda değilsiniz.
Kullanıcı Profiline Sosyal Medya Alanları Ekleme
WordPress’in varsayılan kullanıcı profil sayfasında sadece “Web Sitesi” alanı var. Twitter, LinkedIn, GitHub gibi alanlar yok. Bunları functions.php ile ekleyebiliriz.
// functions.php'ye ekleyin
function custom_user_profile_fields( $user ) {
?>
<h3>Sosyal Medya Bilgileri</h3>
<table class="form-table">
<tr>
<th><label for="twitter">Twitter / X</label></th>
<td>
<input type="text" name="twitter" id="twitter"
value="<?php echo esc_attr( get_the_author_meta( 'twitter', $user->ID ) ); ?>"
class="regular-text" placeholder="https://twitter.com/kullanici" />
</td>
</tr>
<tr>
<th><label for="linkedin">LinkedIn</label></th>
<td>
<input type="text" name="linkedin" id="linkedin"
value="<?php echo esc_attr( get_the_author_meta( 'linkedin', $user->ID ) ); ?>"
class="regular-text" placeholder="https://linkedin.com/in/kullanici" />
</td>
</tr>
<tr>
<th><label for="github">GitHub</label></th>
<td>
<input type="text" name="github" id="github"
value="<?php echo esc_attr( get_the_author_meta( 'github', $user->ID ) ); ?>"
class="regular-text" placeholder="https://github.com/kullanici" />
</td>
</tr>
<tr>
<th><label for="youtube">YouTube</label></th>
<td>
<input type="text" name="youtube" id="youtube"
value="<?php echo esc_attr( get_the_author_meta( 'youtube', $user->ID ) ); ?>"
class="regular-text" placeholder="https://youtube.com/@kanal" />
</td>
</tr>
</table>
<?php
}
add_action( 'show_user_profile', 'custom_user_profile_fields' );
add_action( 'edit_user_profile', 'custom_user_profile_fields' );
Bu kodu ekledikten sonra WordPress admin panelinde Kullanıcılar > Profiliniz bölümüne gittiğinizde sosyal medya alanlarını göreceksiniz. Ama bu alanları kaydetmek için ayrı bir fonksiyon gerekiyor.
Sosyal Medya Alanlarını Kaydetme
Alanları göstermek yeterli değil, kaydetmek de gerekiyor. Güvenlik açısından nonce kontrolü ve capability kontrolü şart.
function save_custom_user_profile_fields( $user_id ) {
// Yetki kontrolü
if ( ! current_user_can( 'edit_user', $user_id ) ) {
return false;
}
// Her alanı tek tek kaydet
$social_fields = array( 'twitter', 'linkedin', 'github', 'youtube' );
foreach ( $social_fields as $field ) {
if ( isset( $_POST[ $field ] ) ) {
update_user_meta(
$user_id,
$field,
sanitize_url( $_POST[ $field ] )
);
}
}
}
add_action( 'personal_options_update', 'save_custom_user_profile_fields' );
add_action( 'edit_user_profile_update', 'save_custom_user_profile_fields' );
sanitize_url() fonksiyonunu kullanmak önemli çünkü kullanıcıdan gelen URL verisi doğrudan veritabanına kaydediliyor. Bu şekilde zararlı içerik girişini engelliyoruz.
Yazar Kutusu HTML Yapısını Oluşturma
Şimdi asıl meseleye geliyoruz. Yazar kutusunu oluşturacak fonksiyon biraz uzun ama her parçasını açıklayacağım.
function get_author_box( $author_id = null ) {
// Yazar ID belirtilmemişse mevcut yazının yazarını al
if ( null === $author_id ) {
$author_id = get_the_author_meta( 'ID' );
}
// Yazar bilgilerini topla
$author_name = get_the_author_meta( 'display_name', $author_id );
$author_bio = get_the_author_meta( 'description', $author_id );
$author_url = get_author_posts_url( $author_id );
$author_avatar = get_avatar( $author_id, 96 );
// Sosyal medya linkleri
$social_links = array(
'twitter' => get_user_meta( $author_id, 'twitter', true ),
'linkedin' => get_user_meta( $author_id, 'linkedin', true ),
'github' => get_user_meta( $author_id, 'github', true ),
'youtube' => get_user_meta( $author_id, 'youtube', true ),
'website' => get_the_author_meta( 'user_url', $author_id ),
);
// Biyografi yoksa kutuyu gösterme
if ( empty( $author_bio ) ) {
return '';
}
// HTML oluşturmaya başla
$output = '<div class="author-box" itemscope itemtype="https://schema.org/Person">';
$output .= '<div class="author-box-avatar">';
$output .= '<a href="' . esc_url( $author_url ) . '">' . $author_avatar . '</a>';
$output .= '</div>';
$output .= '<div class="author-box-content">';
$output .= '<h4 class="author-box-name" itemprop="name">';
$output .= '<a href="' . esc_url( $author_url ) . '">' . esc_html( $author_name ) . '</a>';
$output .= '</h4>';
$output .= '<p class="author-box-bio" itemprop="description">' . wp_kses_post( $author_bio ) . '</p>';
// Sosyal medya ikonları
$social_icons = array(
'twitter' => 'Twitter',
'linkedin' => 'LinkedIn',
'github' => 'GitHub',
'youtube' => 'YouTube',
'website' => 'Web Sitesi',
);
$social_html = '';
foreach ( $social_links as $platform => $url ) {
if ( ! empty( $url ) ) {
$social_html .= '<a href="' . esc_url( $url ) . '" class="author-social-link author-social-' . esc_attr( $platform ) . '" target="_blank" rel="noopener noreferrer">';
$social_html .= esc_html( $social_icons[ $platform ] );
$social_html .= '</a>';
}
}
if ( ! empty( $social_html ) ) {
$output .= '<div class="author-box-social">' . $social_html . '</div>';
}
$output .= '</div>'; // .author-box-content
$output .= '</div>'; // .author-box
return $output;
}
Burada itemscope ve itemtype kullandığımıza dikkat edin. Schema.org markup’ı arama motorlarının yazarı doğru tanımasına yardımcı oluyor ve bazı durumlarda arama sonuçlarında zengin snippet’lere katkı sağlıyor.
Yazar Kutusunu Otomatik Ekleme
Kutuyu oluşturduk ama nereye ekleyeceğiz? İki yöntem var: hook kullanmak ya da template dosyasına doğrudan yazmak. Hook yöntemi daha temiz çünkü tema değiştirseniz bile çalışmaya devam eder.
function add_author_box_to_posts( $content ) {
// Sadece tek yazı sayfalarında ve ana döngüde çalışsın
if ( is_single() && is_main_query() && in_the_loop() && get_post_type() === 'post' ) {
$author_box = get_author_box();
if ( ! empty( $author_box ) ) {
$content = $content . $author_box;
}
}
return $content;
}
add_filter( 'the_content', 'add_author_box_to_posts' );
is_main_query() ve in_the_loop() kontrollerini es geçmeyin. Bunlar olmadan yazar kutusu sidebar widget’larında, sayfa başlıklarında veya başka beklenmedik yerlerde de görünebilir. Bu hatayı bizzat yaşadım, sayfanın tam ortasında yazar kutusu belirince sorunun ne olduğunu bulmak biraz zaman aldı.
CSS ile Stil Verme
Fonksiyonel kısım tamamdı, şimdi görsel tarafı halledelim. Bu CSS’i temanızın style.css dosyasına veya functions.php üzerinden enqueue edebilirsiniz.
function author_box_styles() {
if ( is_single() ) {
$css = '
.author-box {
display: flex;
gap: 20px;
padding: 25px;
margin: 40px 0;
background: #f8f9fa;
border: 1px solid #e9ecef;
border-radius: 8px;
border-left: 4px solid #0073aa;
}
.author-box-avatar img {
border-radius: 50%;
width: 96px;
height: 96px;
object-fit: cover;
}
.author-box-content {
flex: 1;
}
.author-box-name {
margin: 0 0 10px 0;
font-size: 18px;
}
.author-box-name a {
color: #0073aa;
text-decoration: none;
}
.author-box-bio {
margin: 0 0 15px 0;
color: #555;
line-height: 1.6;
}
.author-box-social {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.author-social-link {
display: inline-block;
padding: 5px 12px;
border-radius: 4px;
font-size: 13px;
font-weight: 600;
text-decoration: none;
color: #fff;
transition: opacity 0.2s;
}
.author-social-link:hover {
opacity: 0.85;
color: #fff;
}
.author-social-twitter { background: #1da1f2; }
.author-social-linkedin { background: #0077b5; }
.author-social-github { background: #333; }
.author-social-youtube { background: #ff0000; }
.author-social-website { background: #0073aa; }
@media (max-width: 600px) {
.author-box {
flex-direction: column;
align-items: center;
text-align: center;
}
.author-box-social {
justify-content: center;
}
}
';
wp_add_inline_style( 'wp-block-library', $css );
}
}
add_action( 'wp_enqueue_scripts', 'author_box_styles' );
CSS’i sadece is_single() koşulunda yüklüyoruz. Ana sayfa, kategori sayfaları ve diğer arşiv sayfalarında bu stili yüklemek gereksiz. Performans açısından önemsiz görünse de bu tarz küçük optimizasyonlar birikirken fark yaratıyor.
Shortcode ile Manuel Kullanım
Bazen yazar kutusunu yazının ortasına ya da farklı bir konuma manuel olarak eklemek isteyebilirsiniz. Shortcode bu iş için biçilmiş kaftan.
function author_box_shortcode( $atts ) {
$atts = shortcode_atts(
array(
'id' => null,
'user' => null,
),
$atts,
'author_box'
);
$author_id = null;
// ID ile çağrıldıysa
if ( ! empty( $atts['id'] ) ) {
$author_id = intval( $atts['id'] );
}
// Kullanıcı adı ile çağrıldıysa
if ( ! empty( $atts['user'] ) ) {
$user = get_user_by( 'login', sanitize_user( $atts['user'] ) );
if ( $user ) {
$author_id = $user->ID;
}
}
return get_author_box( $author_id );
}
add_shortcode( 'author_box', 'author_box_shortcode' );
Kullanım örnekleri:
[author_box]– Mevcut yazının yazarını gösterir[author_box id="5"]– ID’si 5 olan kullanıcıyı gösterir[author_box user="ahmet"]– Kullanıcı adı “ahmet” olan kişiyi gösterir
Bu özellikle misafir yazarlar veya birden fazla yazarın katkı verdiği makalelerde işe yarıyor. Diyelim ki üç farklı kişi bir yazıya katkı verdi, üç tane shortcode koyarak hepsinin kutusunu gösterebilirsiniz.
Çok Yazarlı Site Senaryosu
Birden fazla yazarı destekleyen bir site yönetiyorsanız, her yazara ait bilgilerin doğru görünmesi kritik. Aynı zamanda bazı yazarlara yazar kutusu göstermek istemeyebilirsiniz. Bunu kontrol etmek için kullanıcı meta alanı ekleyelim.
// Profil sayfasına "Yazar kutusu göster" seçeneği ekle
function add_show_author_box_option( $user ) {
$show_box = get_user_meta( $user->ID, 'show_author_box', true );
?>
<h3>Yazar Kutusu Ayarları</h3>
<table class="form-table">
<tr>
<th><label for="show_author_box">Yazar Kutusu</label></th>
<td>
<label>
<input type="checkbox"
name="show_author_box"
id="show_author_box"
value="1"
<?php checked( $show_box, '1' ); ?> />
Yazılarımın altında yazar kutumu göster
</label>
</td>
</tr>
</table>
<?php
}
add_action( 'show_user_profile', 'add_show_author_box_option' );
add_action( 'edit_user_profile', 'add_show_author_box_option' );
function save_show_author_box_option( $user_id ) {
if ( ! current_user_can( 'edit_user', $user_id ) ) {
return false;
}
$value = isset( $_POST['show_author_box'] ) ? '1' : '0';
update_user_meta( $user_id, 'show_author_box', $value );
}
add_action( 'personal_options_update', 'save_show_author_box_option' );
add_action( 'edit_user_profile_update', 'save_show_author_box_option' );
Sonra get_author_box fonksiyonumuza bu kontrolü ekleyelim. Fonksiyonun başındaki biyografi kontrolünden hemen önce şunu ekleyin:
// show_author_box kontrolü - get_author_box fonksiyonu içinde kullanın
$show_box = get_user_meta( $author_id, 'show_author_box', true );
// Varsayılan olarak göster, açıkça kapatılmışsa gösterme
if ( $show_box === '0' ) {
return '';
}
Bu yaklaşımla her yazar kendi profilinden yazar kutusunu açıp kapatabilir. Admin panelinden de herhangi bir kullanıcının kutusunu yönetebilirsiniz.
Widget Alanı ile Sidebar’da Yazar Bilgisi
Tek yazı sayfasının yanında sidebar’da da yazar bilgisi göstermek isteyebilirsiniz. Bunun için basit bir widget fonksiyonu yazalım.
function author_info_widget() {
if ( ! is_single() ) {
return;
}
$author_id = get_the_author_meta( 'ID' );
$author_name = get_the_author_meta( 'display_name' );
$author_bio = get_the_author_meta( 'description' );
$author_avatar = get_avatar( $author_id, 64 );
$post_count = count_user_posts( $author_id, 'post' );
if ( empty( $author_bio ) ) {
return;
}
echo '<div class="sidebar-author-widget">';
echo '<div class="sidebar-author-avatar">' . $author_avatar . '</div>';
echo '<h4>' . esc_html( $author_name ) . '</h4>';
echo '<p class="author-post-count">' . intval( $post_count ) . ' yazı</p>';
echo '<p>' . wp_kses_post( wp_trim_words( $author_bio, 20 ) ) . '</p>';
echo '<a href="' . esc_url( get_author_posts_url( $author_id ) ) . '">Tüm yazıları gör</a>';
echo '</div>';
}
wp_trim_words() fonksiyonu ile biyografiyi 20 kelimeye kısaltıyoruz. Sidebar dar bir alan olduğu için tam biyografi yerine özet göstermek daha mantıklı.
Gerçek Dünya Senaryosu: Teknoloji Blogu
Diyelim ki birden fazla yazarın katkı verdiği bir teknoloji blogu yönetiyorsunuz. Yazarların bir kısmı frontend geliştirici, bir kısmı backend, bir kısmı da sistem yöneticisi. Her yazarın uzmanlık alanını profilinde göstermek istiyorsunuz.
Bu senaryo için ek bir profil alanı ekleyelim:
// Uzmanlık alanı ve unvan alanları - show_user_profile ve edit_user_profile hook'larına bağlayın
function add_expertise_fields( $user ) {
$expertise = get_user_meta( $user->ID, 'expertise', true );
$job_title = get_user_meta( $user->ID, 'job_title', true );
?>
<h3>Profesyonel Bilgiler</h3>
<table class="form-table">
<tr>
<th><label for="job_title">Unvan / Pozisyon</label></th>
<td>
<input type="text" name="job_title" id="job_title"
value="<?php echo esc_attr( $job_title ); ?>"
class="regular-text"
placeholder="Örn: Senior Backend Developer" />
</td>
</tr>
<tr>
<th><label for="expertise">Uzmanlık Alanları</label></th>
<td>
<input type="text" name="expertise" id="expertise"
value="<?php echo esc_attr( $expertise ); ?>"
class="regular-text"
placeholder="Örn: PHP, MySQL, Linux, Docker" />
<p class="description">Virgülle ayırarak yazın</p>
</td>
</tr>
</table>
<?php
}
add_action( 'show_user_profile', 'add_expertise_fields' );
add_action( 'edit_user_profile', 'add_expertise_fields' );
function save_expertise_fields( $user_id ) {
if ( ! current_user_can( 'edit_user', $user_id ) ) {
return false;
}
if ( isset( $_POST['job_title'] ) ) {
update_user_meta( $user_id, 'job_title', sanitize_text_field( $_POST['job_title'] ) );
}
if ( isset( $_POST['expertise'] ) ) {
update_user_meta( $user_id, 'expertise', sanitize_text_field( $_POST['expertise'] ) );
}
}
add_action( 'personal_options_update', 'save_expertise_fields' );
add_action( 'edit_user_profile_update', 'save_expertise_fields' );
Bu alanları get_author_box() fonksiyonunuzda kullanmak için yazar adından hemen sonra şu satırları ekleyebilirsiniz:
// get_author_box fonksiyonu içinde, author_name satırından sonra kullanın
$job_title = get_user_meta( $author_id, 'job_title', true );
$expertise = get_user_meta( $author_id, 'expertise', true );
// HTML kısmında unvan gösterimi
if ( ! empty( $job_title ) ) {
$output .= '<p class="author-job-title">' . esc_html( $job_title ) . '</p>';
}
// Uzmanlık etiketleri
if ( ! empty( $expertise ) ) {
$tags = array_map( 'trim', explode( ',', $expertise ) );
$output .= '<div class="author-expertise">';
foreach ( $tags as $tag ) {
$output .= '<span class="expertise-tag">' . esc_html( $tag ) . '</span>';
}
$output .= '</div>';
}
Performans Notları
Yazar kutusunu her sayfa yüklemesinde veritabanından çekmek, yüksek trafikli sitelerde küçük bir yük oluşturabilir. Object cache kullanıyorsanız sorun yok zaten, değilseniz transient ile cache ekleyebilirsiniz:
function get_author_box_cached( $author_id = null ) {
if ( null === $author_id ) {
$author_id = get_the_author_meta( 'ID' );
}
$cache_key = 'author_box_' . $author_id;
$cached = get_transient( $cache_key );
if ( false !== $cached ) {
return $cached;
}
$box = get_author_box( $author_id );
// 12 saat cache'le
set_transient( $cache_key, $box, 12 * HOUR_IN_SECONDS );
return $box;
}
// Kullanıcı profili güncellendiğinde cache'i temizle
function clear_author_box_cache( $user_id ) {
delete_transient( 'author_box_' . $user_id );
}
add_action( 'profile_update', 'clear_author_box_cache' );
Profil güncellendiğinde cache’i temizlemek kritik. Bunu yapmadan yazarlar profillerini güncellediğinde değişiklikler 12 saat sonrasına kadar görünmeyebilir. profile_update hook’u tam bu iş için var.
Sonuç
Tüm bu kodları bir araya getirdiğinizde hiçbir plugin kurmadan tam özellikli bir yazar kutusu sisteminiz oluyor. Özetlersek:
- Profil alanları: Twitter, LinkedIn, GitHub, YouTube linkleri ve unvan/uzmanlık alanları ekledik
- Yazar kutusu fonksiyonu: Schema.org markup ile arama motoru dostu HTML ürettik
- Otomatik ekleme:
the_contentfiltresi ile tek yazı sayfalarına otomatik bağladık - Shortcode desteği: Manuel yerleştirme için
[author_box]shortcode’u ekledik - Çok yazar desteği: Her yazarın kutusunu açıp kapatabileceği tercih ekledik
- Cache mekanizması: Transient ile veritabanı sorgularını azalttık
Bu yapının güzel yanı tamamen modüler olması. İhtiyacınıza göre parçaları alıp kullanabilirsiniz. Sadece sosyal medya alanları mı istiyorsunuz, sadece o bölümü kopyalayın. Tam sistemi mi kuracaksınız, kodları sırayla functions.php’ye ekleyin ve hazır.
Child tema kullanıyorsanız tüm bu kodları child temanın functions.php dosyasına ekleyin. Ana tema güncellemelerinde değişiklikleriniz korunur. Eğer bu kodlar zamanla büyürse, ayrı bir inc/author-box.php dosyası oluşturup functions.php‘den require_once ile dahil etmek daha düzenli bir yapı sağlar.
