WordPress functions.php ile Twitter Card Meta Etiketleri Ekleme

Sosyal medyada paylaşılan bir WordPress yazısının sade bir link yerine güzel bir önizleme kartı olarak görünmesi, tıklanma oranlarını ciddi ölçüde artırır. Twitter (artık X olarak biliniyor ama meta tag isimleri hala “twitter:” ile başlıyor) Card meta tagları tam olarak bunu sağlar. Bu yazıda, WordPress sitenize Twitter Card desteğini functions.php üzerinden nasıl ekleyeceğinizi, farklı içerik türleri için nasıl özelleştireceğinizi ve olası sorunları nasıl çözeceğinizi ele alacağız.

Twitter Card Meta Tagları Nedir ve Neden Önemli?

Twitter Card’lar, bir URL Twitter’da paylaşıldığında tweet’in altında görünen zengin önizleme bloklarıdır. Başlık, açıklama ve görsel içeren bu kartlar, sıradan bir link paylaşımına kıyasla çok daha fazla dikkat çeker.

Dört temel kart tipi vardır:

  • summary: Küçük önizleme görseli + başlık + açıklama
  • summary_large_image: Büyük önizleme görseli + başlık + açıklama
  • app: Mobil uygulama tanıtımı için
  • player: Video/audio içerik için

Sysadmin veya teknik blog yazıyorsanız genellikle summary_large_image tipi en iyi sonucu verir. WooCommerce ürün sayfaları için de aynı tip idealdir.

SEO eklentisi kullanmıyor musunuz? Yoast, RankMath gibi eklentiler bu tagları otomatik ekler. Ancak eklenti kullanmak istemiyorsanız, sitenizi hafif tutmak istiyorsanız veya mevcut eklentinin çıktısını özelleştirmeniz gerekiyorsa functions.php çözümü size tam kontrol sağlar.

Temel Yapı: Basit Bir Twitter Card Implementasyonu

Önce en temelden başlayalım. WordPress’te meta tagları wp_head action hook’una bağlayarak ekliyoruz.

// functions.php - Temel Twitter Card Meta Tagları
function add_twitter_card_meta_tags() {
    if ( is_singular() ) {
        global $post;

        // Başlık
        $title = get_the_title( $post->ID );

        // Açıklama: excerpt varsa kullan, yoksa içerikten oluştur
        if ( has_excerpt( $post->ID ) ) {
            $description = get_the_excerpt( $post->ID );
        } else {
            $description = wp_trim_words( strip_tags( $post->post_content ), 30, '...' );
        }

        // Öne çıkan görsel
        $image = '';
        if ( has_post_thumbnail( $post->ID ) ) {
            $image = get_the_post_thumbnail_url( $post->ID, 'large' );
        }

        echo '<meta name="twitter:card" content="summary_large_image">' . "n";
        echo '<meta name="twitter:title" content="' . esc_attr( $title ) . '">' . "n";
        echo '<meta name="twitter:description" content="' . esc_attr( $description ) . '">' . "n";

        if ( ! empty( $image ) ) {
            echo '<meta name="twitter:image" content="' . esc_url( $image ) . '">' . "n";
        }
    }
}
add_action( 'wp_head', 'add_twitter_card_meta_tags' );

Bu temel implementasyon işe yarasa da gerçek dünyada daha fazlasına ihtiyaç duyarsınız. Site hesabını eklemek, farklı sayfa tiplerini handle etmek ve fallback görseller belirlemek gerekecektir.

Gelişmiş Implementasyon: Site Geneli Tam Kapsamlı Çözüm

Şimdi production ortamında kullanabileceğiniz, tüm durumları kapsayan bir fonksiyon yazalım.

// functions.php - Gelişmiş Twitter Card Sistemi
function sysadmin_twitter_card_meta() {

    // Yoast veya RankMath aktifse çakışmayı önle
    if ( defined( 'WPSEO_VERSION' ) || defined( 'RANK_MATH_VERSION' ) ) {
        return;
    }

    $twitter_site    = '@sitenizin_twitter_hesabi'; // Buraya kendi hesabınızı yazın
    $default_image   = get_template_directory_uri() . '/assets/images/default-og.jpg';
    $card_type       = 'summary_large_image';
    $title           = '';
    $description     = '';
    $image           = '';

    // Ana Sayfa
    if ( is_front_page() || is_home() ) {
        $title       = get_bloginfo( 'name' ) . ' - ' . get_bloginfo( 'description' );
        $description = get_bloginfo( 'description' );
        $image       = $default_image;

    // Tekil yazı/sayfa
    } elseif ( is_singular() ) {
        global $post;
        $title = get_the_title( $post->ID );

        if ( has_excerpt( $post->ID ) ) {
            $description = wp_strip_all_tags( get_the_excerpt( $post->ID ) );
        } else {
            $description = wp_trim_words(
                wp_strip_all_tags( $post->post_content ),
                25,
                '...'
            );
        }

        if ( has_post_thumbnail( $post->ID ) ) {
            $image = get_the_post_thumbnail_url( $post->ID, 'large' );
        } else {
            $image = $default_image;
        }

    // Kategori/Etiket arşiv sayfaları
    } elseif ( is_category() || is_tag() || is_tax() ) {
        $term        = get_queried_object();
        $title       = $term->name . ' - ' . get_bloginfo( 'name' );
        $description = ! empty( $term->description )
                       ? wp_strip_all_tags( $term->description )
                       : $term->name . ' kategorisindeki tüm yazılar.';
        $image       = $default_image;

    // Yazar sayfası
    } elseif ( is_author() ) {
        $author      = get_queried_object();
        $title       = $author->display_name . ' - ' . get_bloginfo( 'name' );
        $description = $author->description
                       ? wp_strip_all_tags( $author->description )
                       : $author->display_name . ' tarafından yazılan içerikler.';
        $image       = get_avatar_url( $author->ID, array( 'size' => 400 ) );
        $card_type   = 'summary'; // Yazar sayfası için küçük kart daha uygun

    // Arama sonuçları
    } elseif ( is_search() ) {
        $title       = '"' . get_search_query() . '" için arama sonuçları';
        $description = get_bloginfo( 'name' ) . ' üzerinde yapılan arama sonuçları.';
        $image       = $default_image;

    } else {
        return; // Diğer sayfa tipleri için bir şey ekleme
    }

    // Güvenlik: Tüm değerleri temizle
    $title       = esc_attr( $title );
    $description = esc_attr( wp_html_excerpt( $description, 200, '...' ) );
    $image       = esc_url( $image );
    $card_type   = esc_attr( $card_type );

    // Meta tagları yazdır
    ?>
    <meta name="twitter:card" content="<?php echo $card_type; ?>">
    <meta name="twitter:site" content="<?php echo esc_attr( $twitter_site ); ?>">
    <meta name="twitter:title" content="<?php echo $title; ?>">
    <meta name="twitter:description" content="<?php echo $description; ?>">
    <meta name="twitter:image" content="<?php echo $image; ?>">
    <?php
}
add_action( 'wp_head', 'sysadmin_twitter_card_meta', 5 );

Burada add_action çağrısında önceliği 5 olarak ayarladık. WordPress’in varsayılan önceliği 10‘dur, biz biraz önce ekliyoruz. Bu, bazı eklentilerin daha sonra müdahale etmesine imkan tanır.

WooCommerce Ürün Sayfaları için Özel Twitter Card

E-ticaret siteniz varsa, ürün sayfalarının sosyal medyada düzgün görünmesi doğrudan satışa etki eder. WooCommerce ürünleri için ayrı bir fonksiyon yazalım.

// functions.php - WooCommerce Ürün Twitter Card
function sysadmin_woocommerce_twitter_card() {

    // WooCommerce aktif değilse çık
    if ( ! class_exists( 'WooCommerce' ) ) {
        return;
    }

    // Sadece ürün sayfalarında çalış
    if ( ! is_product() ) {
        return;
    }

    global $post;
    $product = wc_get_product( $post->ID );

    if ( ! $product ) {
        return;
    }

    // Ürün adı
    $title = $product->get_name();

    // Ürün açıklaması: kısa açıklama öncelikli
    $short_desc = $product->get_short_description();
    if ( ! empty( $short_desc ) ) {
        $description = wp_trim_words( wp_strip_all_tags( $short_desc ), 25, '...' );
    } else {
        $description = wp_trim_words(
            wp_strip_all_tags( $product->get_description() ),
            25,
            '...'
        );
    }

    // Fiyatı açıklamaya ekle (isteğe bağlı ama etkili)
    $price = $product->get_price_html();
    if ( ! empty( $price ) ) {
        $clean_price = wp_strip_all_tags( $price );
        $description .= ' Fiyat: ' . $clean_price;
    }

    // Ürün görseli
    $image_id = $product->get_image_id();
    if ( $image_id ) {
        $image_data = wp_get_attachment_image_src( $image_id, 'large' );
        $image      = $image_data ? $image_data[0] : '';
    } else {
        $image = wc_placeholder_img_src( 'large' );
    }

    // Stok durumuna göre label
    $label = $product->is_in_stock() ? 'Stokta Var' : 'Stokta Yok';

    ?>
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:site" content="@sitenizin_twitter_hesabi">
    <meta name="twitter:title" content="<?php echo esc_attr( $title ); ?>">
    <meta name="twitter:description" content="<?php echo esc_attr( $description ); ?>">
    <meta name="twitter:image" content="<?php echo esc_url( $image ); ?>">
    <meta name="twitter:label1" content="Fiyat">
    <meta name="twitter:data1" content="<?php echo esc_attr( wp_strip_all_tags( $price ) ); ?>">
    <meta name="twitter:label2" content="Stok Durumu">
    <meta name="twitter:data2" content="<?php echo esc_attr( $label ); ?>">
    <?php
}
add_action( 'wp_head', 'sysadmin_woocommerce_twitter_card', 5 );

twitter:label1, twitter:data1 gibi taglar Twitter’ın “App Card” formatında çalışır ve ürün bilgilerini structured data gibi gösterir.

Özel Post Type Desteği Ekleme

Sysadmin bloglarında sıkça “tutorial”, “tool” veya “snippet” gibi özel post tipleri olur. Bunlar için de Twitter Card desteği eklemek gerekir.

// functions.php - Custom Post Type için Twitter Card
function sysadmin_cpt_twitter_card() {

    // Hangi post tiplerini kapsasın?
    $supported_types = array( 'tutorial', 'tool', 'snippet', 'kb_article' );

    if ( ! is_singular( $supported_types ) ) {
        return;
    }

    global $post;
    $post_type = get_post_type( $post->ID );

    // Post tipine göre prefix ekle
    $type_labels = array(
        'tutorial'   => 'Rehber',
        'tool'       => 'Araç',
        'snippet'    => 'Kod Snippet',
        'kb_article' => 'Bilgi Bankası',
    );

    $prefix = isset( $type_labels[ $post_type ] )
              ? '[' . $type_labels[ $post_type ] . '] '
              : '';

    $title = $prefix . get_the_title( $post->ID );

    // ACF veya custom field'dan açıklama çekmeye çalış
    $meta_desc = get_post_meta( $post->ID, '_custom_meta_description', true );
    if ( empty( $meta_desc ) ) {
        $meta_desc = has_excerpt( $post->ID )
                     ? get_the_excerpt( $post->ID )
                     : wp_trim_words( wp_strip_all_tags( $post->post_content ), 25, '...' );
    }

    $image = has_post_thumbnail( $post->ID )
             ? get_the_post_thumbnail_url( $post->ID, 'large' )
             : get_template_directory_uri() . '/assets/images/default-og.jpg';

    ?>
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:site" content="@sitenizin_twitter_hesabi">
    <meta name="twitter:creator" content="@<?php echo esc_attr( get_the_author_meta( 'twitter', $post->post_author ) ); ?>">
    <meta name="twitter:title" content="<?php echo esc_attr( $title ); ?>">
    <meta name="twitter:description" content="<?php echo esc_attr( $meta_desc ); ?>">
    <meta name="twitter:image" content="<?php echo esc_url( $image ); ?>">
    <meta name="twitter:image:alt" content="<?php echo esc_attr( get_the_title( $post->ID ) ); ?>">
    <?php
}
add_action( 'wp_head', 'sysadmin_cpt_twitter_card', 5 );

twitter:creator tagını burada kullandık. Bu tag, içeriği yazan kişinin Twitter hesabını belirtir. Bunun çalışması için yazar profilindeki “twitter” alanının dolu olması gerekir.

Görsel Boyut Kontrolü ve Optimizasyon

Twitter, card görsellerinde minimum 300×157 piksel, maximum 4096×4096 piksel ve 5MB boyut sınırı koyar. Yanlış boyutta görsel kullanmak kartın hiç görünmemesine yol açabilir.

// functions.php - Görsel boyut kontrolü ile Twitter Card
function sysadmin_get_twitter_card_image( $post_id ) {

    $image_url = '';
    $min_width = 300;
    $min_height = 157;

    if ( has_post_thumbnail( $post_id ) ) {
        $thumb_id   = get_post_thumbnail_id( $post_id );
        $image_data = wp_get_attachment_image_src( $thumb_id, 'full' );

        if ( $image_data ) {
            $width  = $image_data[1];
            $height = $image_data[2];

            // Boyut yeterli mi?
            if ( $width >= $min_width && $height >= $min_height ) {
                // Önce 'twitter-card' boyutunu dene, yoksa 'large' kullan
                $twitter_size = wp_get_attachment_image_src( $thumb_id, 'twitter-card' );
                $image_url    = $twitter_size
                                ? $twitter_size[0]
                                : $image_data[0];
            } else {
                // Görsel çok küçükse default'a düş
                $image_url = get_template_directory_uri() . '/assets/images/default-og.jpg';
                // Opsiyonel: Admin'e uyarı logla
                if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
                    error_log( "Twitter Card: Post #{$post_id} thumbnail too small ({$width}x{$height})" );
                }
            }
        }
    }

    if ( empty( $image_url ) ) {
        $image_url = get_template_directory_uri() . '/assets/images/default-og.jpg';
    }

    return $image_url;
}

// Twitter Card görsel boyutunu WordPress'e kaydet
function sysadmin_register_twitter_card_image_size() {
    add_image_size( 'twitter-card', 1200, 628, true );
}
add_action( 'after_setup_theme', 'sysadmin_register_twitter_card_image_size' );

add_image_size ile twitter-card adında özel bir görsel boyutu kaydettik. Yeni yüklenen görseller bu boyutta otomatik kırpılacaktır. Mevcut görseller için Regenerate Thumbnails eklentisini çalıştırmanız gerekir.

Çakışma Kontrolü ve Debug Modu

Birden fazla fonksiyon veya eklenti aynı meta tagları eklemeye çalışırsa, sayfada duplicate meta tag’lar oluşur. Twitter bunu hata olarak işaretler.

// functions.php - Duplicate kontrolü ve debug modu
function sysadmin_twitter_card_with_duplicate_check() {

    // SEO eklentileri zaten eklediyse çık
    if (
        defined( 'WPSEO_VERSION' )      || // Yoast SEO
        defined( 'RANK_MATH_VERSION' )  || // Rank Math
        defined( 'SQ_VERSION' )         || // Squirrly SEO
        class_exists( 'All_in_One_SEO_Pack' ) // AIOSEO
    ) {
        if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
            error_log( 'Twitter Card: SEO eklentisi algılandı, custom fonksiyon devre dışı.' );
        }
        return;
    }

    // Sadece tekil sayfalarda devam et
    if ( ! is_singular() ) {
        return;
    }

    global $post;

    // Bu post için meta tag eklemeyi devre dışı bırakma imkanı
    $disable = get_post_meta( $post->ID, '_disable_twitter_card', true );
    if ( $disable ) {
        return;
    }

    // Post'a özel override değerleri
    $custom_title = get_post_meta( $post->ID, '_twitter_card_title', true );
    $custom_desc  = get_post_meta( $post->ID, '_twitter_card_description', true );
    $custom_image = get_post_meta( $post->ID, '_twitter_card_image', true );

    $title = ! empty( $custom_title )
             ? $custom_title
             : get_the_title( $post->ID );

    $description = ! empty( $custom_desc )
                   ? $custom_desc
                   : ( has_excerpt( $post->ID )
                       ? get_the_excerpt( $post->ID )
                       : wp_trim_words( wp_strip_all_tags( $post->post_content ), 25, '...' ) );

    $image = ! empty( $custom_image )
             ? $custom_image
             : sysadmin_get_twitter_card_image( $post->ID );

    // Debug modunda konsola bilgi yaz
    if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
        echo "n<!-- Twitter Card Debug:n";
        echo "Title: " . esc_html( $title ) . "n";
        echo "Description length: " . strlen( $description ) . " charsn";
        echo "Image: " . esc_url( $image ) . "n";
        echo "-->n";
    }

    ?>
    <meta name="twitter:card" content="summary_large_image">
    <meta name="twitter:site" content="@sitenizin_twitter_hesabi">
    <meta name="twitter:creator" content="@<?php echo esc_attr( get_the_author_meta( 'twitter', $post->post_author ) ); ?>">
    <meta name="twitter:title" content="<?php echo esc_attr( $title ); ?>">
    <meta name="twitter:description" content="<?php echo esc_attr( wp_html_excerpt( $description, 200 ) ); ?>">
    <meta name="twitter:image" content="<?php echo esc_url( $image ); ?>">
    <meta name="twitter:image:alt" content="<?php echo esc_attr( get_the_title( $post->ID ) ); ?>">
    <?php
}
add_action( 'wp_head', 'sysadmin_twitter_card_with_duplicate_check', 5 );

Hızlı Test Yöntemi

Yazdığınız kodun doğru çalışıp çalışmadığını test etmenin birkaç yolu var.

# Sayfa kaynak kodunu curl ile kontrol et
curl -s https://siteniz.com/bir-yaziniz/ | grep -i "twitter:"

# Daha okunabilir çıktı için
curl -s https://siteniz.com/bir-yaziniz/ | grep -i "twitter:" | sed 's/^[[:space:]]*//'

# Belirli bir meta tag'ın değerini çek
curl -s https://siteniz.com/bir-yaziniz/ | grep 'twitter:image' | 
  sed 's/.*content="([^"]*)".*/1/'

# SSL sertifikası sorununu atlayarak test
curl -sk https://siteniz.com/bir-yaziniz/ | grep "twitter:"

Daha görsel bir test için Twitter Card Validator aracını kullanabilirsiniz: cards-dev.twitter.com/validator. URL yapıştırıp “Preview Card” diyorsunuz, kartın nasıl görüneceğini anında görüyorsunuz.

Dikkat edilmesi gereken noktalar:

  • twitter:title en fazla 70 karakter olmalı
  • twitter:description en fazla 200 karakter olmalı
  • Görsel URL’si mutlaka HTTPS olmalı
  • Görsel dosyası gerçekten erişilebilir olmalı (404 dönmemeli)
  • Twitter bot’unun görseli cache’lemesi birkaç dakika alabilir

Sık Yapılan Hatalar

Gerçek dünyadan karşılaşılan tipik sorunları listeleyelim.

  • Görsel görünmüyor: Çoğunlukla görsel URL’sinin HTTP (S’siz) olmasından kaynaklanır. HTTPS’ye yönlendirme olsa bile Twitter bot bazen bunu takip etmez, direkt HTTPS URL kullanın.
  • Eski içerik önizleme gösteriyor: Twitter, card önizlemelerini agresif şekilde cache’ler. Twitter Card Validator’ı ziyaret ederek cache’i temizleyebilirsiniz, farklı tweet’lerde yeni cache oluşturulur.
  • Duplicate meta tag uyarısı: Kaynak kodu incelediğinizde aynı twitter:card tagının iki kez göründüğünü görürseniz, büyük ihtimalle aktif bir SEO eklentisi de ekliyordur. Fonksiyonun başına eklenti kontrolü koyun.
  • Açıklama boş geliyor: get_the_excerpt() bazı durumlarda boş döner, özellikle excerpt’i manuel girmeyen yazılarda. post_content‘ten trim eden fallback’i mutlaka ekleyin.
  • WooCommerce ürünlerinde görsel yok: Ürüne atanmış featured image yoksa get_the_post_thumbnail_url() false döner. WooCommerce’in kendi placeholder görselini fallback olarak kullanın.

Sonuç

Twitter Card meta taglarını functions.php üzerinden yönetmek, sitenizi eklenti bağımlılığından kurtarır ve tam kontrol sağlar. Bu yazıda ele aldığımız yöntemleri özetlemek gerekirse:

  • Temel implementasyonla başlayıp ihtiyaca göre genişletin
  • WooCommerce ürünleri için ayrı fonksiyon yazın, twitter:label taglarıyla ürün bilgilerini zenginleştirin
  • Custom post type’larınızda twitter:creator tagını unutmayın
  • Görsel boyut kontrolü ekleyerek bozuk kartların önüne geçin
  • SEO eklenti çakışmalarını her zaman başta kontrol edin
  • WP_DEBUG modunda loglama ekleyerek sorunları erken yakalayın

Production’a almadan önce mutlaka Twitter Card Validator ile test edin ve curl komutuyla kaynak kodu doğrulayın. Tek bir yanlış karakter bile kartın hiç görünmemesine yol açabilir.

Bir yanıt yazın

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