Sosyal Paylaşım Butonu Ekleyen WordPress Eklentisi Nasıl Yapılır

WordPress eklenti geliştirme dünyasına ilk adım atanlar için sosyal paylaşım butonu eklentisi mükemmel bir başlangıç projesidir. Hem yeterince basit hem de gerçek dünyada kullanılabilir bir çıktı ortaya koyduğu için motivasyonu yüksek tutar. Ben bu eklentiyi ilk kez bir müşteri projesi için yazmak zorunda kaldım; hazır eklentiler ya çok şişmandı ya da tam ihtiyaç duyulan sosyal ağları desteklemiyordu. O günden bu yana bu örneği onlarca kişiye anlattım ve her seferinde farklı bir şey öğrettim. Şimdi sıra sizde.

Eklentinin Temel Yapısını Anlamak

WordPress eklentileri aslında çok basit bir prensiple çalışır: WordPress’in belirli noktalarda tetiklediği kancalara (hook) fonksiyon bağlarsınız, o fonksiyonlar çalışır, sonuç sayfaya yansır. Sosyal paylaşım butonu eklentisi de tam olarak bunu yapar.

Yapacağımız eklenti şu özelliklere sahip olacak:

  • Twitter, Facebook, LinkedIn ve WhatsApp için paylaşım butonları
  • Her yazı sayfasının altına otomatik eklenen butonlar
  • Yönetim panelinden hangi butonların gösterileceğini seçme imkanı
  • Özel CSS ile şekillendirme
  • Kısa kod (shortcode) desteği

Başlamadan önce klasör yapısını oluşturalım:

wp-content/plugins/sosyal-paylasim/
├── sosyal-paylasim.php
├── includes/
│   ├── class-sosyal-paylasim-butonlar.php
│   └── class-sosyal-paylasim-ayarlar.php
├── assets/
│   ├── css/
│   │   └── sosyal-paylasim.css
│   └── js/
│       └── sosyal-paylasim.js
└── languages/
    └── sosyal-paylasim-tr_TR.po

Ana Eklenti Dosyası

Her WordPress eklentisi bir ana PHP dosyasıyla başlar. Bu dosyanın en üstündeki yorum bloğu kritik önem taşır; WordPress bu bloğu okuyarak eklentinizi tanır.

<?php
/**
 * Plugin Name: Sosyal Paylaşım Butonları
 * Plugin URI: https://siteniz.com/sosyal-paylasim
 * Description: Yazılarınıza Twitter, Facebook, LinkedIn ve WhatsApp paylaşım butonları ekler.
 * Version: 1.0.0
 * Requires at least: 5.8
 * Requires PHP: 7.4
 * Author: Sizin Adınız
 * Author URI: https://siteniz.com
 * License: GPL v2 or later
 * Text Domain: sosyal-paylasim
 * Domain Path: /languages
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit; // Doğrudan erişimi engelle
}

// Sabit tanımlamaları
define( 'SP_VERSION', '1.0.0' );
define( 'SP_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'SP_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
define( 'SP_PLUGIN_FILE', __FILE__ );

// Sınıfları dahil et
require_once SP_PLUGIN_DIR . 'includes/class-sosyal-paylasim-butonlar.php';
require_once SP_PLUGIN_DIR . 'includes/class-sosyal-paylasim-ayarlar.php';

// Eklentiyi başlat
function sp_basla() {
    new Sosyal_Paylasim_Butonlar();
    
    if ( is_admin() ) {
        new Sosyal_Paylasim_Ayarlar();
    }
}
add_action( 'plugins_loaded', 'sp_basla' );

// Aktivasyon hook'u
register_activation_hook( __FILE__, 'sp_aktive_et' );
function sp_aktive_et() {
    $varsayilan_ayarlar = array(
        'twitter'   => '1',
        'facebook'  => '1',
        'linkedin'  => '1',
        'whatsapp'  => '1',
        'pozisyon'  => 'altta',
        'renk_sema' => 'renkli',
    );
    add_option( 'sp_ayarlar', $varsayilan_ayarlar );
}

// Deaktivasyon hook'u
register_deactivation_hook( __FILE__, 'sp_deaktive_et' );
function sp_deaktive_et() {
    // Gerekirse temizleme işlemleri
}

ABSPATH kontrolü neden önemli? Çünkü birisi PHP dosyanıza doğrudan tarayıcıdan erişmeye çalışırsa bu satır onu durdurur. Güvenlik açısından bu basit önlem bile kritik fark yaratır.

Buton Sınıfını Oluşturmak

Şimdi eklentinin kalbi olan buton sınıfını yazalım. Bu sınıf, paylaşım URL’lerini oluşturur ve içeriği sayfaya ekler.

<?php
// includes/class-sosyal-paylasim-butonlar.php

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class Sosyal_Paylasim_Butonlar {

    private $ayarlar;

    public function __construct() {
        $this->ayarlar = get_option( 'sp_ayarlar', array() );
        
        // CSS ve JS dosyalarını yükle
        add_action( 'wp_enqueue_scripts', array( $this, 'varlik_yukle' ) );
        
        // İçeriğe butonları ekle
        add_filter( 'the_content', array( $this, 'icerige_ekle' ) );
        
        // Shortcode tanımla
        add_shortcode( 'sosyal_paylasim', array( $this, 'shortcode_calistir' ) );
    }

    public function varlik_yukle() {
        if ( is_singular( 'post' ) || is_page() ) {
            wp_enqueue_style(
                'sosyal-paylasim-css',
                SP_PLUGIN_URL . 'assets/css/sosyal-paylasim.css',
                array(),
                SP_VERSION
            );
            
            wp_enqueue_script(
                'sosyal-paylasim-js',
                SP_PLUGIN_URL . 'assets/js/sosyal-paylasim.js',
                array( 'jquery' ),
                SP_VERSION,
                true
            );
        }
    }

    public function paylasim_url_olustur( $ag ) {
        $sayfa_url   = urlencode( get_permalink() );
        $sayfa_baslik = urlencode( get_the_title() );
        
        $urllar = array(
            'twitter'  => 'https://twitter.com/intent/tweet?url=' . $sayfa_url . '&text=' . $sayfa_baslik,
            'facebook' => 'https://www.facebook.com/sharer/sharer.php?u=' . $sayfa_url,
            'linkedin' => 'https://www.linkedin.com/sharing/share-offsite/?url=' . $sayfa_url,
            'whatsapp' => 'https://wa.me/?text=' . $sayfa_baslik . '%20' . $sayfa_url,
        );
        
        return isset( $urllar[ $ag ] ) ? $urllar[ $ag ] : '#';
    }

    public function buton_html_olustur() {
        $aktif_aglar = array( 'twitter', 'facebook', 'linkedin', 'whatsapp' );
        $renk_sema   = isset( $this->ayarlar['renk_sema'] ) ? $this->ayarlar['renk_sema'] : 'renkli';
        
        $html  = '<div class="sp-buton-grubu sp-sema-' . esc_attr( $renk_sema ) . '">';
        $html .= '<span class="sp-baslik">' . __( 'Paylaş:', 'sosyal-paylasim' ) . '</span>';
        
        $etiketler = array(
            'twitter'  => 'Twitter',
            'facebook' => 'Facebook',
            'linkedin' => 'LinkedIn',
            'whatsapp' => 'WhatsApp',
        );
        
        foreach ( $aktif_aglar as $ag ) {
            if ( ! empty( $this->ayarlar[ $ag ] ) ) {
                $url  = $this->paylasim_url_olustur( $ag );
                $html .= sprintf(
                    '<a href="%s" class="sp-buton sp-buton-%s" target="_blank" rel="noopener noreferrer" aria-label="%s üzerinde paylaş">%s</a>',
                    esc_url( $url ),
                    esc_attr( $ag ),
                    esc_attr( $etiketler[ $ag ] ),
                    esc_html( $etiketler[ $ag ] )
                );
            }
        }
        
        $html .= '</div>';
        
        return $html;
    }

    public function icerige_ekle( $icerik ) {
        if ( ! is_singular( 'post' ) ) {
            return $icerik;
        }
        
        $butonlar    = $this->buton_html_olustur();
        $pozisyon    = isset( $this->ayarlar['pozisyon'] ) ? $this->ayarlar['pozisyon'] : 'altta';
        
        if ( 'ustte' === $pozisyon ) {
            return $butonlar . $icerik;
        } elseif ( 'ikisinde' === $pozisyon ) {
            return $butonlar . $icerik . $butonlar;
        }
        
        return $icerik . $butonlar;
    }

    public function shortcode_calistir( $atts ) {
        $atts = shortcode_atts(
            array(
                'pozisyon' => 'satir_ici',
            ),
            $atts,
            'sosyal_paylasim'
        );
        
        return $this->buton_html_olustur();
    }
}

Burada dikkat etmeniz gereken birkaç şey var. esc_url(), esc_attr() ve esc_html() fonksiyonlarını görmezden gelmeyin. Bunlar XSS saldırılarına karşı temel savunma hattınızdır. WordPress geliştirme dünyasında “escape et, sonra ekle” altın kuralı olarak geçer.

Ayarlar Sayfası Oluşturmak

Yönetim paneline bir ayarlar sayfası eklemek, eklentinizi gerçekten kullanılabilir kılar. WordPress Settings API bunu son derece sistematik bir şekilde yapmanızı sağlar.

<?php
// includes/class-sosyal-paylasim-ayarlar.php

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class Sosyal_Paylasim_Ayarlar {

    public function __construct() {
        add_action( 'admin_menu', array( $this, 'menu_ekle' ) );
        add_action( 'admin_init', array( $this, 'ayarlari_kaydet' ) );
    }

    public function menu_ekle() {
        add_options_page(
            'Sosyal Paylaşım Ayarları',
            'Sosyal Paylaşım',
            'manage_options',
            'sosyal-paylasim-ayarlar',
            array( $this, 'ayarlar_sayfasi_ciz' )
        );
    }

    public function ayarlari_kaydet() {
        register_setting(
            'sp_ayarlar_grubu',
            'sp_ayarlar',
            array( $this, 'ayarlari_dogrula' )
        );

        add_settings_section(
            'sp_ana_bolum',
            'Sosyal Ağ Seçenekleri',
            array( $this, 'bolum_aciklamasi_ciz' ),
            'sosyal-paylasim-ayarlar'
        );

        $alanlar = array(
            'twitter'   => 'Twitter',
            'facebook'  => 'Facebook',
            'linkedin'  => 'LinkedIn',
            'whatsapp'  => 'WhatsApp',
        );

        foreach ( $alanlar as $id => $etiket ) {
            add_settings_field(
                'sp_' . $id,
                $etiket . ' Butonu',
                array( $this, 'checkbox_ciz' ),
                'sosyal-paylasim-ayarlar',
                'sp_ana_bolum',
                array( 'id' => $id, 'etiket' => $etiket . ' paylaşım butonunu göster' )
            );
        }

        add_settings_field(
            'sp_pozisyon',
            'Buton Pozisyonu',
            array( $this, 'pozisyon_secici_ciz' ),
            'sosyal-paylasim-ayarlar',
            'sp_ana_bolum'
        );
    }

    public function bolum_aciklamasi_ciz() {
        echo '<p>Hangi sosyal ağ butonlarının gösterileceğini seçin.</p>';
    }

    public function checkbox_ciz( $args ) {
        $ayarlar = get_option( 'sp_ayarlar', array() );
        $kontrol = isset( $ayarlar[ $args['id'] ] ) ? checked( $ayarlar[ $args['id'] ], '1', false ) : '';
        
        printf(
            '<input type="checkbox" id="sp_%s" name="sp_ayarlar[%s]" value="1" %s />
            <label for="sp_%s">%s</label>',
            esc_attr( $args['id'] ),
            esc_attr( $args['id'] ),
            $kontrol,
            esc_attr( $args['id'] ),
            esc_html( $args['etiket'] )
        );
    }

    public function pozisyon_secici_ciz() {
        $ayarlar  = get_option( 'sp_ayarlar', array() );
        $secili   = isset( $ayarlar['pozisyon'] ) ? $ayarlar['pozisyon'] : 'altta';
        $secenekler = array(
            'altta'    => 'İçeriğin Altında',
            'ustte'    => 'İçeriğin Üstünde',
            'ikisinde' => 'Hem Üst Hem Alt',
        );
        
        echo '<select name="sp_ayarlar[pozisyon]">';
        foreach ( $secenekler as $deger => $metin ) {
            printf(
                '<option value="%s" %s>%s</option>',
                esc_attr( $deger ),
                selected( $secili, $deger, false ),
                esc_html( $metin )
            );
        }
        echo '</select>';
    }

    public function ayarlari_dogrula( $girdi ) {
        $temiz = array();
        $izinli_aglar = array( 'twitter', 'facebook', 'linkedin', 'whatsapp' );
        
        foreach ( $izinli_aglar as $ag ) {
            $temiz[ $ag ] = isset( $girdi[ $ag ] ) ? '1' : '0';
        }
        
        $izinli_pozisyonlar = array( 'altta', 'ustte', 'ikisinde' );
        $temiz['pozisyon']  = in_array( $girdi['pozisyon'], $izinli_pozisyonlar, true ) 
            ? $girdi['pozisyon'] 
            : 'altta';
        
        return $temiz;
    }

    public function ayarlar_sayfasi_ciz() {
        if ( ! current_user_can( 'manage_options' ) ) {
            return;
        }
        ?>
        <div class="wrap">
            <h1><?php echo esc_html( get_admin_page_title() ); ?></h1>
            <form method="post" action="options.php">
                <?php
                settings_fields( 'sp_ayarlar_grubu' );
                do_settings_sections( 'sosyal-paylasim-ayarlar' );
                submit_button( 'Kaydet' );
                ?>
            </form>
        </div>
        <?php
    }
}

CSS ile Butonları Şekillendirmek

Fonksiyonel ama çirkin bir eklenti kullanıcılar tarafından hemen reddedilir. Minimal ama şık bir tasarım yapalım.

/* assets/css/sosyal-paylasim.css */

.sp-buton-grubu {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 10px;
    margin: 20px 0;
    padding: 15px;
    border-top: 1px solid #e0e0e0;
}

.sp-baslik {
    font-weight: 700;
    font-size: 14px;
    color: #444;
    margin-right: 5px;
}

.sp-buton {
    display: inline-flex;
    align-items: center;
    padding: 8px 16px;
    border-radius: 4px;
    font-size: 14px;
    font-weight: 600;
    text-decoration: none;
    color: #fff;
    transition: opacity 0.2s ease, transform 0.1s ease;
    cursor: pointer;
}

.sp-buton:hover {
    opacity: 0.85;
    transform: translateY(-1px);
    color: #fff;
    text-decoration: none;
}

/* Renkli tema */
.sp-sema-renkli .sp-buton-twitter  { background-color: #1da1f2; }
.sp-sema-renkli .sp-buton-facebook { background-color: #1877f2; }
.sp-sema-renkli .sp-buton-linkedin { background-color: #0a66c2; }
.sp-sema-renkli .sp-buton-whatsapp { background-color: #25d366; }

/* Mobil uyumluluk */
@media ( max-width: 480px ) {
    .sp-buton-grubu {
        flex-direction: column;
        align-items: flex-start;
    }
    
    .sp-buton {
        width: 100%;
        justify-content: center;
    }
}

JavaScript ile Tıklama Takibi

Gerçek projelerde analitik verisi toplamak önemlidir. Hangi butonun kaç kez tıklandığını görmek isteyebilirsiniz.

// assets/js/sosyal-paylasim.js

( function( $ ) {
    'use strict';

    $( document ).ready( function() {
        // Paylaşım butonlarına tıklama takibi ekle
        $( '.sp-buton' ).on( 'click', function( e ) {
            var $buton   = $( this );
            var ag       = '';
            var sınıflar = $buton.attr( 'class' ).split( ' ' );
            
            // Ağ adını class listesinden çıkar
            $.each( sınıflar, function( i, sinif ) {
                if ( sinif.indexOf( 'sp-buton-' ) === 0 && sinif !== 'sp-buton' ) {
                    ag = sinif.replace( 'sp-buton-', '' );
                }
            } );
            
            // Google Analytics 4 entegrasyonu (varsa)
            if ( typeof gtag !== 'undefined' ) {
                gtag( 'event', 'share', {
                    'method'       : ag,
                    'content_type' : 'article',
                    'item_id'      : window.location.pathname
                } );
            }
            
            // Konsol logu (geliştirme modunda)
            if ( window.location.hostname === 'localhost' || 
                 window.location.hostname === '127.0.0.1' ) {
                console.log( 'Paylaşım butonu tıklandı:', ag );
            }
        } );
    } );

} )( jQuery );

Uninstall Dosyası Eklemek

Profesyonel bir eklentinin mutlaka uninstall.php dosyası olmalıdır. Kullanıcı eklentiyi sildiğinde veritabanını temizler.

<?php
// uninstall.php

// WordPress tarafından çağrılmadıysa çalıştırma
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
    exit;
}

// Eklenti ayarlarını veritabanından sil
delete_option( 'sp_ayarlar' );

// Çok siteli kurulumlar için
if ( is_multisite() ) {
    $siteler = get_sites( array( 'fields' => 'ids' ) );
    
    foreach ( $siteler as $site_id ) {
        switch_to_blog( $site_id );
        delete_option( 'sp_ayarlar' );
        restore_current_blog();
    }
}

Bu dosyayı es geçmek büyük bir hata. WordPress.org eklenti direktörüne eklenti göndermek istiyorsanız bu dosya olmadan geçemezsiniz inceleme sürecini. Daha önemlisi, kullanıcıların güvenini kazanmak için eklentinizin arkasını temiz bırakması gerekir.

Shortcode Kullanımı ve Gerçek Dünya Senaryosu

Diyelim ki bir site sahibi belirli bir sayfanın sadece belirli bir bölümünde paylaşım butonları görmek istiyor. İçerik filtresi yerine shortcode bu durumda devreye girer.

Editörde şunu yazmak yeterli:

<!-- Sayfa editöründe kullanım -->
[sosyal_paylasim]

<!-- Widget alanında kullanım -->
[sosyal_paylasim pozisyon="satir_ici"]

<!-- PHP ile tema dosyasında kullanım -->
<?php echo do_shortcode( '[sosyal_paylasim]' ); ?>

Bir gerçek dünya vakasından bahsedeyim: Bir e-ticaret sitesi için çalışırken müşteri, ürün sayfalarında değil yalnızca blog yazılarında paylaşım butonları görmek istedi. icerige_ekle fonksiyonundaki is_singular('post') kontrolü tam bu yüzden orada. WooCommerce ürün sayfaları da singular sayılır ama post_type‘ı product‘tır. Bu kontrolü eklememek, ürün sayfalarına da butonların gelmesine yol açar; müşteri neden ürün paylaşım butonlarında fiyat bilgisi yok diye sorar, siz de kendinizi debug yaparken bulursunuz.

Eklentiyi Test Etmek

Geliştirme ortamında şu adımları izleyin:

# WP-CLI ile eklentiyi aktive etme
wp plugin activate sosyal-paylasim

# Ayarları kontrol etme
wp option get sp_ayarlar

# Ayarları komut satırından güncelleme (test için)
wp option update sp_ayarlar '{"twitter":"1","facebook":"0","linkedin":"1","whatsapp":"1","pozisyon":"altta"}' --format=json

# Debug logunu izleme
tail -f wp-content/debug.log

# Eklentiyi deaktive ve sil
wp plugin deactivate sosyal-paylasim
wp plugin delete sosyal-paylasim

wp-config.php dosyanızda geliştirme sırasında şu sabitlerin açık olduğundan emin olun:

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
define( 'SCRIPT_DEBUG', true );

SCRIPT_DEBUG sabiti özellikle önemlidir. Bu sabit açıkken WordPress, CSS ve JavaScript dosyalarının .min sürümü yerine tam sürümünü yükler. Geliştirme sırasında minify edilmiş dosyalarla uğraşmak gereksiz zaman kaybıdır.

Performans Optimizasyonu

Eklentiyi yalnızca ihtiyaç duyulan sayfalarda yüklemek için varlik_yukle fonksiyonundaki koşullu yükleme mantığını hatırlayın. Ama bunu bir adım daha ileri götürebilirsiniz.

// Sadece tekil yazı sayfalarında ve sayfalarda CSS/JS yükle
public function varlik_yukle() {
    if ( ! is_singular() ) {
        return;
    }
    
    // Ayarlardan en az bir ağ aktifse yükle
    $aktif_ag_var = false;
    $aglar = array( 'twitter', 'facebook', 'linkedin', 'whatsapp' );
    
    foreach ( $aglar as $ag ) {
        if ( ! empty( $this->ayarlar[ $ag ] ) ) {
            $aktif_ag_var = true;
            break;
        }
    }
    
    if ( ! $aktif_ag_var ) {
        return;
    }
    
    wp_enqueue_style(
        'sosyal-paylasim-css',
        SP_PLUGIN_URL . 'assets/css/sosyal-paylasim.css',
        array(),
        SP_VERSION
    );
    
    wp_enqueue_script(
        'sosyal-paylasim-js',
        SP_PLUGIN_URL . 'assets/js/sosyal-paylasim.js',
        array( 'jquery' ),
        SP_VERSION,
        true // Footer'a ekle, performans için
    );
}

true parametresine dikkat edin. Script’i footer’a eklemek sayfa yüklenme hızını artırır çünkü tarayıcı HTML’i parse etmeye devam eder, script indirilmesini beklemez.

Sonuç

Bu eklenti birkaç yüz satır kodla şunları başardı: güvenli URL oluşturma, Settings API ile temiz yönetim arayüzü, koşullu varlık yükleme ile performans optimizasyonu, shortcode desteği ve temiz kaldırma mekanizması. Bunların hepsi profesyonel WordPress geliştirmenin temel taşları.

Bu projeyi tamamladıktan sonra yapabileceğiniz geliştirmeler sonsuz. Pinterest ve Reddit desteği ekleyebilirsiniz. Her yazı için paylaşım sayacı tutabilirsiniz. REST API endpoint’i ile AJAX tabanlı sayaç güncellemesi yapabilirsiniz. Blok editörü (Gutenberg) için özel bir blok yazabilirsiniz.

WordPress eklenti geliştirmede en kritik alışkanlık, her çıktıyı escape etmek ve her girdiyi validate etmektir. Geri kalanı zaman içinde gelir. Kodu yazdıktan sonra WordPress Coding Standards’ı takip edip etmediğinizi kontrol etmek için PHP_CodeSniffer ve phpcs --standard=WordPress komutunu kullanmayı da ihmal etmeyin. Kod kalitesi sonradan değil, başından beri inşa edilir.

Bir yanıt yazın

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