FUTIA
OTOMASYON8 dk okuma

WordPress Cron ile Otomatik İçerik Yayınlama: 2025 Kod Rehberi

WordPress'te cron job kullanarak içerik otomasyonu kurmak, manuel işi %90 azaltıyor. Bu rehberde gerçek kod örnekleri ve production hatalarını paylaşıyorum.

WordPress Cron ile Otomatik İçerik Yayınlama: 2025 Kod Rehberi
Miraç Eroğlu
9 Mayıs 2026

WordPress'in kendi cron sistemi, server cron'dan farklı çalışır ve bunu bilmeden kurulan otomasyonlar %60 ihtimalle başarısız oluyor. Ben FUTIA'da kamupersonelhaber.com için günde 50+ ilan yayınlarken, wp-cron.php'nin ziyaretçi trafiğine bağlı olduğunu öğrendim ve sistemin tamamını yeniden yazmak zorunda kaldım. WordPress cron ile otomatik içerik yayınlama kurarken, temel mantığı anlamak teknik detaylardan daha kritik. Bu rehberde, 6 yıldır sosyal medya pazarlamacısıyken AI otomasyonuna geçişimde edindiğim pratik bilgileri, gerçek kod örnekleriyle paylaşacağım. Siz de manuel içerik yayınlamaktan kurtulmak istiyorsanız, WordPress'in zamanlama mantığını doğru anlamanız gerekiyor.

WordPress Cron Sistemi Nasıl Çalışır

WordPress'in wp-cron.php dosyası, klasik server cron job'larından tamamen farklı çalışır. Her sayfa yüklendiğinde WordPress, "zamanı gelen bir görev var mı?" diye kontrol eder ve varsa arka planda çalıştırır. Bu yaklaşım, paylaşımlı hosting ortamlarında cron erişimi olmayan kullanıcılar için tasarlandı ama ciddi performans sorunları yaratıyor.

Trafiği düşük bir sitede, wp-cron.php saatlerce tetiklenmeyebilir. Ben italyanmutfagi.com'da 618 tarif otomasyonu kurarken, gece 03:00'te yayınlanması gereken içeriklerin sabah 09:00'da yayınlandığını fark ettim. Sebep basitti: gece kimse siteyi ziyaret etmediği için cron tetiklenmiyordu.

WordPress cron'u devre dışı bırakıp gerçek server cron kullanmak, production ortamlarında neredeyse zorunlu. wp-config.php dosyasına şu satırı ekleyerek WordPress'in kendi cron sistemini kapatabilirsiniz:

define('DISABLE_WP_CRON', true);

Ardından server'ınızın crontab ayarlarına şu komutu ekleyin (her 5 dakikada bir çalışır):

*/5 * * * * wget -q -O - https://siteniz.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1

Bu değişiklik, kamupersonelhaber.com'da ilan yayınlama güvenilirliğini %95'e çıkardı. Artık trafik olsun olmasın, cron job'lar zamanında tetikleniyordu.

WordPress Cron vs Server Cron Farkları

WordPress cron pseudo-cron olarak adlandırılır çünkü gerçek bir daemon değil, HTTP request tetiklemeli bir sistem. Server cron ise işletim sistemi seviyesinde, zaman bazlı kesin çalışır. Düşük trafikli sitelerde WordPress cron güvenilmez, yüksek trafikli sitelerde ise her sayfa yüklenişinde cron kontrolü yapıldığı için gereksiz overhead yaratır.

FUTIA'da tüm müşteri projelerinde DISABLE_WP_CRON aktif. Çünkü doktorbul.com gibi 79.000 sayfa olan bir sitede, her ziyaretçi wp-cron.php kontrolüne sebep olursa, database sorgularında darboğaz oluşuyor.

Basit Cron Job ile İçerik Yayınlama Kodu

WordPress'te otomatik içerik yayınlamak için önce bir cron event tanımlamanız gerekiyor. Ben memuratamalari.com için Claude Haiku API'den çektiğe içerikleri otomatik yayınlarken şu yapıyı kullandım:

// functions.php veya özel plugin dosyanıza ekleyin
function futia_schedule_content_publish() {
    if (!wp_next_scheduled('futia_auto_publish_event')) {
        wp_schedule_event(time(), 'hourly', 'futia_auto_publish_event');
    }
}
add_action('wp', 'futia_schedule_content_publish');

function futia_auto_publish_content() {
    $args = array(
        'post_status' => 'draft',
        'post_type' => 'post',
        'posts_per_page' => 5,
        'meta_query' => array(
            array(
                'key' => '_futia_auto_publish',
                'value' => '1',
                'compare' => '='
            )
        )
    );
    
    $drafts = get_posts($args);
    
    foreach ($drafts as $draft) {
        wp_update_post(array(
            'ID' => $draft->ID,
            'post_status' => 'publish',
            'post_date' => current_time('mysql'),
            'post_date_gmt' => current_time('mysql', 1)
        ));
        
        delete_post_meta($draft->ID, '_futia_auto_publish');
        
        // Log tutmak için
        error_log('FUTIA Auto-publish: ' . $draft->ID . ' - ' . $draft->post_title);
    }
}
add_action('futia_auto_publish_event', 'futia_auto_publish_content');

Bu kod saatte bir çalışır ve _futia_auto_publish meta değeri 1 olan taslak içerikleri yayınlar. Kamupersonelhaber.com'da ilan.gov.tr API'den çektiğim ilanları bu yöntemle otomatik yayınlıyorum. Her saat 5 ilan yayınlanıyor, böylece Google'ın "sudden content spike" algılaması önleniyor.

Custom Cron Interval Tanımlama

WordPress varsayılan olarak hourly, twicedaily, daily interval'ları sunuyor. Ancak ben daha spesifik aralıklar kullanmak istediğimde (örneğin her 2 saatte bir), custom interval tanımlıyorum:

function futia_custom_cron_intervals($schedules) {
    $schedules['every_two_hours'] = array(
        'interval' => 7200,
        'display' => __('Her 2 Saatte')
    );
    
    $schedules['every_six_hours'] = array(
        'interval' => 21600,
        'display' => __('Her 6 Saatte')
    );
    
    return $schedules;
}
add_filter('cron_schedules', 'futia_custom_cron_intervals');

Diolivo.com.tr'de sepet kurtarma e-postalarını her 6 saatte tetiklemek için bu yöntemi kullandım. CartBounty entegrasyonuyla birlikte, %340 trafik artışına katkı sağlayan otomasyon sisteminin bir parçası oldu.

API'den İçerik Çekip Otomatik Yayınlama

Gerçek dünya senaryolarında, içerik genelde harici bir kaynaktan gelir. Ben kamupersonelhaber.com'da ilan.gov.tr API'sini kullanıyorum. İşte basitleştirilmiş versiyonu:

function futia_fetch_and_publish_api_content() {
    $api_url = 'https://api.example.com/content?limit=10';
    
    $response = wp_remote_get($api_url, array(
        'timeout' => 30,
        'headers' => array(
            'Authorization' => 'Bearer YOUR_API_KEY'
        )
    ));
    
    if (is_wp_error($response)) {
        error_log('FUTIA API Error: ' . $response->get_error_message());
        return;
    }
    
    $body = wp_remote_retrieve_body($response);
    $data = json_decode($body, true);
    
    if (empty($data['items'])) {
        return;
    }
    
    foreach ($data['items'] as $item) {
        // Daha önce yayınlanmış mı kontrol et
        $existing = get_posts(array(
            'post_type' => 'post',
            'meta_key' => '_futia_external_id',
            'meta_value' => $item['id'],
            'post_status' => 'any',
            'posts_per_page' => 1
        ));
        
        if (!empty($existing)) {
            continue; // Zaten var, atla
        }
        
        $post_id = wp_insert_post(array(
            'post_title' => sanitize_text_field($item['title']),
            'post_content' => wp_kses_post($item['content']),
            'post_status' => 'publish',
            'post_author' => 1,
            'post_category' => array(get_cat_ID('Haberler'))
        ));
        
        if ($post_id) {
            update_post_meta($post_id, '_futia_external_id', $item['id']);
            update_post_meta($post_id, '_futia_source', 'api');
            
            // Featured image varsa
            if (!empty($item['image_url'])) {
                futia_set_featured_image_from_url($post_id, $item['image_url']);
            }
        }
    }
}
add_action('futia_api_sync_event', 'futia_fetch_and_publish_api_content');

Bu kod, API'den gelen içerikleri duplicate kontrolü yaparak yayınlar. _futia_external_id meta field'ı, aynı içeriğin birden fazla kez yayınlanmasını önlüyor. Kamupersonelhaber.com'da günde 50+ ilan yayınlarken, bu kontrol sayesinde hiç duplicate içerik problemi yaşamadım.

Featured Image Otomasyonu

API'den gelen görselleri otomatik featured image olarak eklemek için:

function futia_set_featured_image_from_url($post_id, $image_url) {
    require_once(ABSPATH . 'wp-admin/includes/media.php');
    require_once(ABSPATH . 'wp-admin/includes/file.php');
    require_once(ABSPATH . 'wp-admin/includes/image.php');
    
    $tmp = download_url($image_url);
    
    if (is_wp_error($tmp)) {
        return false;
    }
    
    $file_array = array(
        'name' => basename($image_url),
        'tmp_name' => $tmp
    );
    
    $id = media_handle_sideload($file_array, $post_id);
    
    if (is_wp_error($id)) {
        @unlink($file_array['tmp_name']);
        return false;
    }
    
    set_post_thumbnail($post_id, $id);
    return true;
}

İtalyanmutfagi.com'da 618 tarif için görselleri bu fonksiyonla otomatik ekledim. Schema.org Recipe markup'ıyla birlikte, Google'da zengin sonuçlar almamızı sağladı.

Zamanlı Yayınlama ve Kuyruklama Sistemi

İçerikleri anında yayınlamak yerine, belirli aralıklarla kuyruktan çıkararak yayınlamak SEO açısından daha mantıklı. Google, ani içerik patlamalarını spam olarak algılayabiliyor.

function futia_queue_content_for_publishing($post_data) {
    global $wpdb;
    
    $table_name = $wpdb->prefix . 'futia_publish_queue';
    
    $wpdb->insert(
        $table_name,
        array(
            'post_title' => $post_data['title'],
            'post_content' => $post_data['content'],
            'post_category' => $post_data['category'],
            'scheduled_time' => $post_data['publish_time'],
            'status' => 'pending',
            'created_at' => current_time('mysql')
        ),
        array('%s', '%s', '%d', '%s', '%s', '%s')
    );
}

function futia_process_publish_queue() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'futia_publish_queue';
    
    $items = $wpdb->get_results(
        "SELECT * FROM $table_name 
         WHERE status = 'pending' 
         AND scheduled_time <= NOW() 
         LIMIT 3"
    );
    
    foreach ($items as $item) {
        $post_id = wp_insert_post(array(
            'post_title' => $item->post_title,
            'post_content' => $item->post_content,
            'post_status' => 'publish',
            'post_category' => array($item->post_category)
        ));
        
        if ($post_id) {
            $wpdb->update(
                $table_name,
                array('status' => 'published', 'post_id' => $post_id),
                array('id' => $item->id),
                array('%s', '%d'),
                array('%d')
            );
        }
    }
}
add_action('futia_queue_process_event', 'futia_process_publish_queue');

Bu sistemde, içerikler önce kuyruğa alınıyor ve zamanı geldiğinde yayınlanıyor. Doktorbul.com'da 79.000 doktor profilini yayınlarken benzer bir kuyruk sistemi kullandım. Günde 200 profil yayınlayarak, 12 ayda tüm içeriği Google'a indeksletmiş olduk.

Hata Yönetimi ve Logging

Production ortamında cron job'lar sessizce başarısız olabilir. Ben her zaman detaylı logging yapıyorum:

function futia_log_cron_activity($message, $level = 'info') {
    $log_file = WP_CONTENT_DIR . '/futia-cron-logs.txt';
    $timestamp = current_time('Y-m-d H:i:s');
    $log_entry = "[$timestamp] [$level] $message" . PHP_EOL;
    
    error_log($log_entry, 3, $log_file);
    
    // Kritik hatalar için email gönder
    if ($level === 'error') {
        wp_mail(
            'info@futia.net',
            'FUTIA Cron Hatası',
            $message
        );
    }
}

function futia_safe_api_call() {
    try {
        $response = wp_remote_get('https://api.example.com/data');
        
        if (is_wp_error($response)) {
            throw new Exception($response->get_error_message());
        }
        
        $code = wp_remote_retrieve_response_code($response);
        if ($code !== 200) {
            throw new Exception("API HTTP $code döndü");
        }
        
        futia_log_cron_activity('API çağrısı başarılı', 'info');
        return json_decode(wp_remote_retrieve_body($response), true);
        
    } catch (Exception $e) {
        futia_log_cron_activity('API hatası: ' . $e->getMessage(), 'error');
        return false;
    }
}

Kamupersonelhaber.com'da ilan.gov.tr API bazen timeout veriyor. Bu logging sistemi sayesinde, hangi saatlerde API'nin yavaşladığını tespit edip cron zamanlamasını ona göre ayarlayabiliyorum.

Cron Job Sağlık Kontrolü

Cron job'larınızın düzgün çalışıp çalışmadığını kontrol etmek için:

function futia_cron_health_check() {
    $last_run = get_option('futia_last_cron_run');
    $current_time = time();
    
    // 2 saatten fazla çalışmamışsa uyarı
    if ($current_time - $last_run > 7200) {
        wp_mail(
            'info@futia.net',
            'FUTIA Cron Durdu',
            "Son çalışma: " . date('Y-m-d H:i:s', $last_run)
        );
    }
}

function futia_update_last_run() {
    update_option('futia_last_cron_run', time());
}
add_action('futia_auto_publish_event', 'futia_update_last_run');
add_action('wp_loaded', 'futia_cron_health_check');

Bu kod, cron job'ın son çalışma zamanını kaydediyor ve 2 saatten uzun süre çalışmamışsa e-posta uyarısı gönderiyor. Diolivo.com.tr'de sepet kurtarma sistemi bu şekilde monitör ediyorum.

Production'da Dikkat Edilmesi Gerekenler

WordPress cron otomasyonlarını canlıya alırken, birkaç kritik noktaya dikkat etmek gerekiyor. İlk olarak, server kaynaklarını aşırı kullanmamak. Ben her cron job'da maximum 10 içerik işliyorum, daha fazlası memory limit hatalarına sebep oluyor.

İkinci olarak, duplicate content kontrolü şart. API'den gelen içerikleri yayınlarken, her zaman unique identifier (external ID, hash vb.) kontrol ediyorum. Memuratamalari.com'da 40.400 aylık organik arama trafiği elde etmemizin bir sebebi, hiç duplicate content olmaması.

Üçüncü olarak, rate limiting. Harici API'lere dakikada 60'tan fazla istek atmamak için throttling uyguluyorum:

function futia_throttled_api_call($endpoint) {
    $last_call = get_transient('futia_api_last_call');
    $current_time = time();
    
    if ($last_call && ($current_time - $last_call) < 2) {
        sleep(2); // 2 saniye bekle
    }
    
    $response = wp_remote_get($endpoint);
    set_transient('futia_api_last_call', $current_time, 60);
    
    return $response;
}

Bu kod, API çağrıları arasında minimum 2 saniye bekleme süresi koyuyor. Kamupersonelhaber.com'da ilan.gov.tr API'sinin rate limit'ine takılmamak için kullanıyorum.

Dördüncü olarak, timezone sorunları. WordPress'te current_time() kullanırken, GMT offset'i dikkate almak gerekiyor. Türkiye saatiyle çalışan bir sistemde, cron zamanlamalarını GMT+3 olarak ayarlamalısınız.

Database Temizliği

Otomatik içerik sistemleri zamanla database'i şişirebilir. Ben her ay çalışan bir temizlik cron'u kullanıyorum:

function futia_cleanup_old_queue_items() {
    global $wpdb;
    $table_name = $wpdb->prefix . 'futia_publish_queue';
    
    // 30 günden eski, yayınlanmış kayıtları sil
    $wpdb->query(
        "DELETE FROM $table_name 
         WHERE status = 'published' 
         AND created_at < DATE_SUB(NOW(), INTERVAL 30 DAY)"
    );
    
    // Transient'ları temizle
    $wpdb->query(
        "DELETE FROM {$wpdb->options} 
         WHERE option_name LIKE '_transient_futia_%' 
         OR option_name LIKE '_transient_timeout_futia_%'"
    );
}
add_action('futia_monthly_cleanup', 'futia_cleanup_old_queue_items');

İtalyanmutfagi.com'da 618 tarif otomasyonunda, bu temizlik sistemi database boyutunu %40 azalttı.

Cron Job Debug ve Test Etme

Geliştirme aşamasında, cron job'ları test etmek için WP-CLI kullanıyorum:

wp cron event list
wp cron event run futia_auto_publish_event
wp cron schedule list

WordPress admin panelinde cron job'ları manuel tetiklemek için de basit bir admin sayfası oluşturabilirsiniz:

function futia_cron_test_page() {
    if (!current_user_can('manage_options')) {
        return;
    }
    
    if (isset($_POST['run_cron'])) {
        do_action('futia_auto_publish_event');
        echo '<div class="notice notice-success"><p>Cron job çalıştırıldı!</p></div>';
    }
    
    echo '<div class="wrap">';
    echo '<h1>FUTIA Cron Test</h1>';
    echo '<form method="post">';
    submit_button('Cron Job Çalıştır', 'primary', 'run_cron');
    echo '</form>';
    
    // Son 10 log kaydını göster
    $logs = file_get_contents(WP_CONTENT_DIR . '/futia-cron-logs.txt');
    $log_lines = array_slice(explode(PHP_EOL, $logs), -10);
    
    echo '<h2>Son Loglar</h2><pre>';
    echo implode(PHP_EOL, $log_lines);
    echo '</pre></div>';
}

function futia_add_cron_menu() {
    add_management_page(
        'FUTIA Cron Test',
        'FUTIA Cron',
        'manage_options',
        'futia-cron-test',
        'futia_cron_test_page'
    );
}
add_action('admin_menu', 'futia_add_cron_menu');

Bu admin sayfası, cron job'ları manuel tetiklemenize ve son logları görüntülemenize olanak sağlıyor. Doktorbul.com'da 79.000 profil otomasyonunu test ederken, bu araç hayat kurtarıcıydı.

WordPress cron otomasyonları kurmak, başta karmaşık görünse de doğru yapı ile son derece güvenilir sistemler kurabilirsiniz. Ben FUTIA'da Hollanda'dan Türk markalarına tam bu tür otomasyonlar kuruyorum. Kamupersonelhaber.com'daki 50+ günlük ilan otomasyonundan, italyanmutfagi.com'daki 618 tarif sistemine kadar, tüm projelerimde bu rehberdeki prensipleri kullanıyorum.

Eğer siteniz için otomatik içerik yayınlama sistemi kurmak istiyorsanız, benimle WhatsApp üzerinden +90 532 491 17 05 numarasından veya info@futia.net adresinden iletişime geçebilirsiniz. Site + otomasyon + aylık bakım paketlerimiz, manuel işlerinizi %90 azaltabiliyor.

Sıkça Sorulanlar

WordPress cron ve server cron arasındaki fark nedir?

WordPress cron (wp-cron.php), ziyaretçi trafiğine bağlı pseudo-cron sistemidir. Her sayfa yüklendiğinde tetiklenir ve düşük trafikli sitelerde güvenilmez çalışır. Server cron ise işletim sistemi seviyesinde, zaman bazlı kesin çalışır. Production ortamlarında DISABLE_WP_CRON aktif edip gerçek server cron kullanmak önerilir. Ben FUTIA projelerinde her zaman server cron kullanıyorum çünkü kamupersonelhaber.com gibi düzenli yayın gerektiren sitelerde güvenilirlik kritik.

Otomatik içerik yayınlarken duplicate content nasıl önlenir?

API'den veya harici kaynaklardan gelen içerikleri yayınlamadan önce, unique identifier kontrolü yapmalısınız. Ben _futia_external_id gibi custom meta field kullanarak, içeriğin daha önce yayınlanıp yayınlanmadığını kontrol ediyorum. wp_insert_post çağrısından önce get_posts ile meta_value sorgusu yaparak, duplicate içerik engelleniyor. İtalyanmutfagi.com'da 618 tarif yayınlarken, bu yöntemle hiç duplicate içerik problemi yaşamadık.

WordPress cron job'ları ne sıklıkla çalıştırmalıyım?

Sıklık, içerik hacmine ve API rate limit'lerine bağlı. Ben genelde saatlik (hourly) veya 2 saatlik custom interval kullanıyorum. Çok sık çalıştırmak (örneğin her 5 dakika) server kaynaklarını tüketir, çok seyrek çalıştırmak (günlük) ise içerik akışını bozar. Kamupersonelhaber.com'da günde 50+ ilan yayınlamak için saatlik cron yeterli oluyor. Her çalışmada 3-5 içerik yayınlayarak, Google'ın spam algılamasını önlüyorum.

Cron job hatalarını nasıl monitör edebilirim?

Detaylı logging sistemi kurmak şart. Ben her cron çalışmasında timestamp, işlem detayı ve hata mesajlarını WP_CONTENT_DIR altında log dosyasına yazıyorum. Kritik hatalar için wp_mail ile e-posta uyarısı gönderiyorum. Ayrıca last_run timestamp'i tutarak, cron job'ın 2 saatten uzun süre çalışmadığını tespit edip uyarı gönderen bir health check sistemi kullanıyorum. Diolivo.com.tr'deki sepet kurtarma otomasyonunu bu şekilde monitör ediyorum.

API'den gelen görselleri otomatik featured image yapmak güvenli mi?

Evet ama dikkatli olmalısınız. media_handle_sideload fonksiyonu, görseli WordPress media library'sine indirir ve doğru şekilde işler. Ancak timeout ve memory limit sorunlarına karşı try-catch kullanmalısınız. Ben görselleri indirmeden önce boyutunu kontrol ediyorum (max 2MB) ve timeout değerini 30 saniyeye çıkarıyorum. İtalyanmutfagi.com'da 618 tarif için görselleri bu yöntemle otomatik ekledik ve Schema.org markup ile birlikte Google'da zengin sonuçlar aldık.

YAZAR HAKKINDA
Miraç Eroğlu

Hacettepe mezunu, 6 yıldır sosyal medya, 2 yıldır AI otomasyon.

Daha fazla bilgi →

Bu yazıdaki tekniklerden birini uygulamak ister misiniz? Kısa bir form doldurun, 48 saat içinde ücretsiz ön inceleme raporu mailinize düşsün.