WordPress Favicon ve App Icon Programatik Tanımlama
WordPress sitenizin favicon ve uygulama ikonlarını yönetmek için WordPress yönetim paneline girmek zorunda olmadığınızı biliyor muydunuz? Çoğu geliştirici bu işlemi WordPress Customizer üzerinden ya da tema ayarlarından yapıyor, ancak bu yaklaşım bazı ciddi sorunlara yol açabiliyor. Özellikle çoklu site kurulumlarında, staging-production geçişlerinde ya da CI/CD pipeline’ı olan projelerde, veritabanına bağımlı ayarlar baş ağrısına dönüşebiliyor. Bu yazıda, favicon ve app icon tanımlamalarını tamamen functions.php üzerinden programatik olarak nasıl yöneteceğinizi ele alacağız.
Sorunun Kökü: Neden Veritabanı Bağımlılığından Kaçınmalıyız?
WordPress’te favicon ayarları varsayılan olarak site_icon seçeneği adıyla veritabanında saklanıyor. Bu medya attachment ID’si, farklı ortamlar arasında tutarsız oluyor. Yani geliştirme ortamında ID 47 olan görsel, production’da bambaşka bir ID alıyor. Bu durumu yaşayan her geliştirici bilir: Staging’de mükemmel görünen favicon, canlı ortama geçince kayboluyor.
Bunun yanı sıra şu senaryoları düşünün:
- Versiyon kontrolü: Kodunuzu Git’te tutuyorsunuz ama favicon ayarı veritabanında. Değişikliği takip etmek imkansız.
- Çoklu site (Multisite): Her alt site için ayrı ayrı yönetim paneline girip favicon ayarlamak hem zaman kaybı hem de hata riski.
- Headless WordPress: REST API veya WPGraphQL kullanan projelerde ikonların doğru dönmesi için özel tanımlama gerekiyor.
- Müşteri projeleri: Müşterinin yanlışlıkla favicon’u silmesini ya da değiştirmesini önlemek istiyorsunuz.
WordPress’in Favicon Sistemi Nasıl Çalışır?
WordPress, wp_site_icon() fonksiyonu aracılığıyla bölümüne favicon ve app icon etiketlerini ekliyor. Bu fonksiyon wp_head kancasına bağlı ve get_site_icon_url() fonksiyonunu kullanarak veritabanındaki attachment ID’sini çözümleyip URL’e dönüştürüyor.
Biz bu sistemi tamamen bypass etmeyeceğiz, bunun yerine mevcut kancaları ve filtrelerini kullanarak kendi kontrolümüzü oluşturacağız. Bu sayede hem WordPress çekirdeğiyle uyumlu kalacağız hem de istediğimiz esnekliği kazanacağız.
Temel Kavramlar
Favicon ve app icon konusunda iki farklı dünya var:
- Klasik Favicon:
favicon.icoveya küçük PNG dosyaları, tarayıcı sekmesinde gösterilen ikon. - Apple Touch Icons: iOS cihazlarda ana ekrana eklendiğinde kullanılan ikonlar, genellikle 180×180 piksel.
- Android / PWA Icons:
manifest.jsondosyasıyla tanımlanan, Android cihazlar ve PWA uygulamaları için ikonlar. - MS Tiles: Windows cihazlar için özel meta etiketleri.
- OG Image ile Fark: Open Graph görseli favicon ile karıştırılmamalı, farklı amaçlara hizmet ediyor.
Yöntem 1: wp_head ile Manuel Ekleme
En basit ve doğrudan yaklaşım, WordPress’in kendi favicon çıktısını devre dışı bırakıp yerine kendi etiketlerimizi eklemek. Bunun için önce wp_site_icon aksiyonunu kaldırıyoruz, ardından kendi fonksiyonumuzu ekliyoruz.
<?php
/**
* WordPress'in varsayılan favicon çıktısını devre dışı bırak
* ve programatik favicon tanımlaması yap
*/
// WordPress'in varsayılan site icon fonksiyonunu kaldır
remove_action( 'wp_head', 'wp_site_icon', 99 );
// Admin paneli için de kaldır (opsiyonel)
remove_action( 'admin_head', 'wp_site_icon' );
/**
* Özel favicon ve app icon etiketlerini ekle
*/
function custom_favicon_tags() {
$icon_path = get_template_directory_uri() . '/assets/images/icons/';
?>
<!-- Klasik Favicon -->
<link rel="icon" type="image/x-icon" href="<?php echo esc_url( $icon_path . 'favicon.ico' ); ?>">
<link rel="icon" type="image/png" sizes="32x32" href="<?php echo esc_url( $icon_path . 'favicon-32x32.png' ); ?>">
<link rel="icon" type="image/png" sizes="16x16" href="<?php echo esc_url( $icon_path . 'favicon-16x16.png' ); ?>">
<!-- Apple Touch Icons -->
<link rel="apple-touch-icon" sizes="180x180" href="<?php echo esc_url( $icon_path . 'apple-touch-icon.png' ); ?>">
<link rel="apple-touch-icon" sizes="152x152" href="<?php echo esc_url( $icon_path . 'apple-touch-icon-152x152.png' ); ?>">
<!-- Android / PWA -->
<link rel="manifest" href="<?php echo esc_url( get_template_directory_uri() . '/site.webmanifest' ); ?>">
<!-- MS Tiles -->
<meta name="msapplication-TileColor" content="#2b5797">
<meta name="msapplication-TileImage" content="<?php echo esc_url( $icon_path . 'mstile-144x144.png' ); ?>">
<meta name="theme-color" content="#ffffff">
<?php
}
add_action( 'wp_head', 'custom_favicon_tags', 1 );
add_action( 'admin_head', 'custom_favicon_tags', 1 );
Bu yaklaşımda dikkat etmeniz gereken kritik nokta: remove_action çağrısını doğru öncelik değeriyle yapmanız gerekiyor. WordPress wp_site_icon fonksiyonunu 99 önceliğiyle ekliyor, bu yüzden remove_action çağrısında da 99 kullanmalısınız.
Yöntem 2: get_site_icon_url Filtresi
Eğer WordPress’in kendi mekanizmasını kullanmak ama URL’i değiştirmek istiyorsanız, get_site_icon_url filtresi tam size göre. Bu yöntem daha temiz çünkü WordPress’in HTML yapısını koruyor, sadece URL’leri override ediyorsunuz.
<?php
/**
* site_icon URL'ini dinamik olarak değiştir
* WordPress'in kendi HTML çıktısını korur, sadece URL override edilir
*
* @param string $url Mevcut site icon URL'i
* @param int $size İstenen ikon boyutu
* @param int $blog_id Blog ID (multisite için)
* @return string Yeni ikon URL'i
*/
function override_site_icon_url( $url, $size, $blog_id ) {
$icon_base = get_template_directory_uri() . '/assets/icons/';
// Boyuta göre farklı dosya döndür
if ( $size >= 512 ) {
return $icon_base . 'icon-512x512.png';
} elseif ( $size >= 192 ) {
return $icon_base . 'icon-192x192.png';
} elseif ( $size >= 180 ) {
return $icon_base . 'apple-touch-icon.png';
} elseif ( $size >= 32 ) {
return $icon_base . 'favicon-32x32.png';
} else {
return $icon_base . 'favicon-16x16.png';
}
}
add_filter( 'get_site_icon_url', 'override_site_icon_url', 10, 3 );
Bu filtrenin güzelliği şu: WordPress REST API üzerinden site ikonunu sorgulayan uygulamalar da doğru URL’i alıyor. Headless projelerde bu önemli bir avantaj.
Yöntem 3: Multisite İçin Dinamik Favicon Yönetimi
Multisite kurulumlarında her alt sitenin kendi faviconunu olması gerekebilir. Bunu hem veritabanından okuyarak hem de tema dosya yapısından okuyarak yönetebilirsiniz.
<?php
/**
* Multisite ortamında her blog için dinamik favicon
* Önce blog-specific dizini kontrol eder, yoksa varsayılana döner
*/
function multisite_dynamic_favicon() {
$blog_id = get_current_blog_id();
$blog_slug = get_blog_details( $blog_id )->path;
$blog_slug = trim( $blog_slug, '/' );
// Blog'a özel ikon dizini
$specific_dir = get_template_directory() . '/assets/icons/sites/' . $blog_id . '/';
$specific_uri = get_template_directory_uri() . '/assets/icons/sites/' . $blog_id . '/';
// Varsayılan ikon dizini
$default_uri = get_template_directory_uri() . '/assets/icons/default/';
// Blog'a özel favicon varsa onu kullan, yoksa default'a düş
$favicon_uri = file_exists( $specific_dir . 'favicon.ico' ) ? $specific_uri : $default_uri;
// Renk şemasını blog meta'dan al (önceden set edilmiş olmalı)
$theme_color = get_blog_option( $blog_id, 'site_theme_color', '#ffffff' );
$tile_color = get_blog_option( $blog_id, 'site_tile_color', '#2b5797' );
?>
<link rel="icon" type="image/x-icon" href="<?php echo esc_url( $favicon_uri . 'favicon.ico' ); ?>">
<link rel="icon" type="image/png" sizes="32x32" href="<?php echo esc_url( $favicon_uri . 'favicon-32x32.png' ); ?>">
<link rel="apple-touch-icon" sizes="180x180" href="<?php echo esc_url( $favicon_uri . 'apple-touch-icon.png' ); ?>">
<meta name="theme-color" content="<?php echo esc_attr( $theme_color ); ?>">
<meta name="msapplication-TileColor" content="<?php echo esc_attr( $tile_color ); ?>">
<?php
}
Yöntem 4: Ortama Göre Favicon Değiştirme
Bu en kullanışlı senaryolardan biri. Development, staging ve production ortamlarında farklı faviconlar göstermek, hangi ortamda çalıştığınızı anında anlamanızı sağlar. Özellikle birden fazla tarayıcı sekmesinde farklı ortamları açık tuttuğunuzda hayat kurtarıcı.
<?php
/**
* Ortama göre favicon tanımla
* Development: Kırmızı kenarlıklı ikon
* Staging: Turuncu kenarlıklı ikon
* Production: Normal ikon
*/
function environment_aware_favicon() {
// Ortam tespiti - wp-config.php'de WP_ENVIRONMENT_TYPE tanımlı olmalı
$env = defined( 'WP_ENVIRONMENT_TYPE' ) ? WP_ENVIRONMENT_TYPE : 'production';
$icon_base = get_template_directory_uri() . '/assets/icons/';
switch ( $env ) {
case 'development':
case 'local':
$favicon_dir = $icon_base . 'env/dev/';
$theme_color = '#e74c3c'; // Kırmızı - dikkat çekici
break;
case 'staging':
$favicon_dir = $icon_base . 'env/staging/';
$theme_color = '#f39c12'; // Turuncu - uyarı
break;
default: // production
$favicon_dir = $icon_base;
$theme_color = '#ffffff';
break;
}
// Ortam etiketi ekle (sadece non-production)
if ( $env !== 'production' ) {
echo '<!-- Environment: ' . esc_html( strtoupper( $env ) ) . ' -->' . "n";
}
?>
<link rel="icon" type="image/x-icon" href="<?php echo esc_url( $favicon_dir . 'favicon.ico' ); ?>">
<link rel="icon" type="image/png" sizes="32x32" href="<?php echo esc_url( $favicon_dir . 'favicon-32x32.png' ); ?>">
<link rel="icon" type="image/png" sizes="16x16" href="<?php echo esc_url( $favicon_dir . 'favicon-16x16.png' ); ?>">
<link rel="apple-touch-icon" sizes="180x180" href="<?php echo esc_url( $favicon_dir . 'apple-touch-icon.png' ); ?>">
<meta name="theme-color" content="<?php echo esc_attr( $theme_color ); ?>">
<?php
}
// Varsayılan favicon çıktısını kaldır ve kendi fonksiyonumuzu ekle
remove_action( 'wp_head', 'wp_site_icon', 99 );
add_action( 'wp_head', 'environment_aware_favicon', 1 );
wp-config.php dosyanıza şunu ekleyin:
// wp-config.php
define( 'WP_ENVIRONMENT_TYPE', 'staging' ); // local, development, staging, production
Yöntem 5: CDN ile Favicon Sunumu
Yüksek trafikli sitelerde statik dosyaları CDN üzerinden sunmak standart bir pratik. Favicon dosyaları küçük olsa da her sayfa yüklemesinde çağrıldığı için CDN’e taşınması mantıklı.
<?php
/**
* Favicon ve icon URL'lerini CDN üzerinden sun
* CDN URL'i wp-config.php'de tanımlı olmalı
*/
function cdn_favicon_tags() {
// CDN URL yapılandırması
$cdn_url = defined( 'CDN_URL' ) ? CDN_URL : get_template_directory_uri();
$icon_version = defined( 'ICON_VERSION' ) ? ICON_VERSION : '1.0.0';
// Cache busting için version parametresi
$v = '?v=' . $icon_version;
$icons = $cdn_url . '/assets/icons/';
?>
<link rel="icon" type="image/x-icon" href="<?php echo esc_url( $icons . 'favicon.ico' . $v ); ?>">
<link rel="icon" type="image/png" sizes="96x96" href="<?php echo esc_url( $icons . 'favicon-96x96.png' . $v ); ?>">
<link rel="icon" type="image/png" sizes="32x32" href="<?php echo esc_url( $icons . 'favicon-32x32.png' . $v ); ?>">
<link rel="icon" type="image/png" sizes="16x16" href="<?php echo esc_url( $icons . 'favicon-16x16.png' . $v ); ?>">
<link rel="apple-touch-icon" sizes="180x180" href="<?php echo esc_url( $icons . 'apple-touch-icon.png' . $v ); ?>">
<link rel="apple-touch-icon" sizes="152x152" href="<?php echo esc_url( $icons . 'apple-touch-icon-152x152.png' . $v ); ?>">
<link rel="apple-touch-icon" sizes="120x120" href="<?php echo esc_url( $icons . 'apple-touch-icon-120x120.png' . $v ); ?>">
<meta name="msapplication-config" content="<?php echo esc_url( $icons . 'browserconfig.xml' . $v ); ?>">
<?php
}
wp-config.php tarafında:
// wp-config.php
define( 'CDN_URL', 'https://cdn.siteniz.com' );
define( 'ICON_VERSION', '2.1.0' ); // İkon setini güncellerken bu değeri artır
WooCommerce Mağazaları için Özel Senaryolar
WooCommerce kullanan sitelerde, özellikle multi-vendor yapısında ya da kategori bazlı alt markalarda dinamik favicon yönetimi çok işe yarıyor.
<?php
/**
* WooCommerce product/category sayfalarında kategori bazlı favicon
* Farklı departmanlar için farklı marka ikonları göster
*/
function woocommerce_category_favicon() {
if ( ! function_exists( 'is_woocommerce' ) ) {
return;
}
$icon_base = get_template_directory_uri() . '/assets/icons/';
$custom_icon = false;
// Ürün kategorisi sayfasında
if ( is_product_category() ) {
$term = get_queried_object();
if ( $term ) {
// Kategori meta'dan özel ikon URL al
$category_icon = get_term_meta( $term->term_id, '_category_favicon', true );
if ( ! empty( $category_icon ) ) {
$custom_icon = esc_url( $category_icon );
}
}
}
// Tekil ürün sayfasında
if ( is_product() ) {
$product = wc_get_product( get_the_ID() );
if ( $product ) {
$category_ids = $product->get_category_ids();
// İlk kategorinin ikonunu kullan
if ( ! empty( $category_ids ) ) {
$cat_icon = get_term_meta( $category_ids[0], '_category_favicon', true );
if ( ! empty( $cat_icon ) ) {
$custom_icon = esc_url( $cat_icon );
}
}
}
}
// Özel ikon varsa kullan, yoksa varsayılan
$favicon_url = $custom_icon ? $custom_icon : $icon_base . 'favicon-32x32.png';
echo '<link rel="icon" type="image/png" sizes="32x32" href="' . $favicon_url . '">' . "n";
echo '<link rel="apple-touch-icon" sizes="180x180" href="' . esc_url( $icon_base . 'apple-touch-icon.png' ) . '">' . "n";
}
remove_action( 'wp_head', 'wp_site_icon', 99 );
add_action( 'wp_head', 'woocommerce_category_favicon', 5 );
Web App Manifest Dinamik Üretimi
Modern PWA gereksinimlerini karşılamak için site.webmanifest dosyasını statik tutmak yerine dinamik olarak üretebilirsiniz. Bu özellikle markanın tema renklerini WordPress Customizer’dan yönettiğiniz durumlarda faydalı.
<?php
/**
* Web App Manifest'i dinamik olarak üret
* WordPress Customizer değerlerini manifest'e yansıt
*/
function register_dynamic_manifest_endpoint() {
add_rewrite_rule(
'site.webmanifest$',
'index.php?custom_manifest=1',
'top'
);
add_rewrite_tag( '%custom_manifest%', '([^&]+)' );
}
add_action( 'init', 'register_dynamic_manifest_endpoint' );
function serve_dynamic_manifest() {
if ( get_query_var( 'custom_manifest' ) !== '1' ) {
return;
}
$icon_base = get_template_directory_uri() . '/assets/icons/';
// Customizer değerlerinden renk al
$theme_color = get_theme_mod( 'brand_primary_color', '#2271b1' );
$background_color = get_theme_mod( 'brand_background_color', '#ffffff' );
$app_name = get_bloginfo( 'name' );
$short_name = get_theme_mod( 'app_short_name', substr( $app_name, 0, 12 ) );
$manifest = array(
'name' => $app_name,
'short_name' => $short_name,
'description' => get_bloginfo( 'description' ),
'start_url' => '/',
'display' => 'standalone',
'background_color' => $background_color,
'theme_color' => $theme_color,
'icons' => array(
array(
'src' => $icon_base . 'android-chrome-192x192.png',
'sizes' => '192x192',
'type' => 'image/png',
),
array(
'src' => $icon_base . 'android-chrome-512x512.png',
'sizes' => '512x512',
'type' => 'image/png',
),
),
);
header( 'Content-Type: application/manifest+json; charset=utf-8' );
header( 'Cache-Control: public, max-age=86400' ); // 24 saat cache
echo wp_json_encode( $manifest, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES );
exit;
}
add_action( 'template_redirect', 'serve_dynamic_manifest' );
Admin Paneli Favicon’unu da Değiştirme
Müşteri projelerinde admin panelinde de kendi logonuzu göstermek, white-label çalışmalar için önemli. Bunun için admin_head kancasını kullanıyoruz.
<?php
/**
* WordPress admin paneli favicon'unu değiştir
* White-label projeler için ideal
*/
function custom_admin_favicon() {
$icon_url = get_template_directory_uri() . '/assets/icons/admin-favicon.ico';
?>
<link rel="shortcut icon" href="<?php echo esc_url( $icon_url ); ?>" type="image/x-icon">
<?php
}
add_action( 'admin_head', 'custom_admin_favicon' );
// Login sayfası favicon'u için de ayrıca ekle
add_action( 'login_head', 'custom_admin_favicon' );
Önbellek Yönetimi ve Cache Busting
Favicon değişikliklerinin kullanıcılara hemen yansıması için cache busting stratejisi uygulamak gerekiyor. Tarayıcılar favicon’ları agresif şekilde önbelleğe aldığından bu konu çok önemli.
<?php
/**
* Otomatik cache busting için tema versiyon numarası kullan
* style.css versiyonunu veya custom sabit değeri kullan
*/
function versioned_favicon_tags() {
// Tema versiyon numarasını al
$theme = wp_get_theme();
$version = $theme->get( 'Version' );
// Veya manuel versiyon tanımlayabilirsiniz
// $version = defined( 'FAVICON_VERSION' ) ? FAVICON_VERSION : '1.0';
$icons = get_template_directory_uri() . '/assets/icons/';
$v = '?ver=' . $version;
?>
<link rel="icon" type="image/x-icon" href="<?php echo esc_url( $icons . 'favicon.ico' . $v ); ?>">
<link rel="icon" type="image/png" sizes="32x32" href="<?php echo esc_url( $icons . 'favicon-32x32.png' . $v ); ?>">
<link rel="icon" type="image/png" sizes="16x16" href="<?php echo esc_url( $icons . 'favicon-16x16.png' . $v ); ?>">
<link rel="apple-touch-icon" sizes="180x180" href="<?php echo esc_url( $icons . 'apple-touch-icon.png' . $v ); ?>">
<meta name="theme-color" content="#ffffff">
<?php
}
Dikkat Edilmesi Gereken Noktalar
Kodlarınızı yazarken şu konulara özellikle dikkat edin:
- Çift tanımlama sorunu: Hem
wp_site_iconhem de kendi fonksiyonunuz aktif kalırsa,bölümünde favicon etiketleri iki kez görünür.remove_actionçağrısını yapmayı unutmayın. - Plugin çakışmaları: SEO eklentileri (Yoast, RankMath) ve bazı güvenlik eklentileri de favicon etiketlerine müdahale edebilir. Bu durumda öncelik sıralamasını (priority) doğru ayarlayın.
- Child tema kullanımı:
get_template_directory_uri()yerineget_stylesheet_directory_uri()kullanmak, child tema dosyalarını doğru çözümler. Hangi temada çalıştığınıza göre karar verin. - HTTPS zorunluluğu: Favicon URL’lerinin site HTTPS kullanıyorsa
https://ile başladığından emin olun.esc_url()fonksiyonu bu konuda yardımcı olsa da manuel URL’lerde dikkatli olun. - Dosya varlık kontrolü: Özellikle dinamik yöntemlerde, dosyanın fiziksel olarak sunucuda mevcut olduğunu
file_exists()ile doğrulayın.
Sonuç
WordPress’te favicon ve app icon yönetimini programatik hale getirmek, bir kez kurduğunuzda size büyük kolaylık sağlayan bir yatırım. Özellikle versiyon kontrol sistemleri kullanan, çoklu ortam yöneten ya da müşteri projelerinde white-label çalışan geliştiriciler için bu yaklaşım neredeyse zorunlu hale geliyor.
Bu yazıda ele aldığımız yöntemler arasında projenize en uygun olanı seçin. Basit bir tek site kurulum için Yöntem 1 yeterli. Staging/production geçişlerini sık yapıyorsanız ortam bazlı favicon değiştirme (Yöntem 4) hayat kurtarır. Multisite ya da WooCommerce multi-vendor projelerinde ise dinamik yaklaşımlar kaçınılmaz.
Son olarak şunu hatırlatmakta fayda var: Favicon dosyalarınızı üretmek için realfavicongenerator.net gibi araçları kullanın. Bu araçlar tüm platform ve boyutlar için gerekli dosyaları tek seferde üretiyor ve bunu iyi bir başlangıç noktası olarak kullanıp dosyaları temanızın assets/icons/ dizinine yerleştirmeniz yeterli oluyor.
