營收卡關?別只顧著投廣告!教你用 WooCommerce 自動化代碼喚醒「沉睡 90 天」的殭屍客群

2026/02/1 | WC 開發, WP 開發技巧, 數位行銷策略

工程師教戰:WooCommerce 90 天沉睡客群自動召回術

廣告效益低落,流量紅利不再?資深工程師 Eric 不談空泛理論,直接公開硬核程式碼!開發新客成本是挽回舊客的 5 到 25 倍,因此,誰能有效喚醒資料庫中「沉睡 90 天」的殭屍客戶,誰就是贏家。本文將教你如何利用 WordPress 與 WooCommerce 底層機制,在 functions.php 中埋入高效自動化代碼,精準發送專屬優惠券召回郵件。立即動手實戰,將你的網站轉化為 24 小時不間斷的自動印鈔機!

需要專業協助?

聯絡浪花專案團隊 →

營收卡關?別只顧著投廣告!資深工程師教你用 WooCommerce 自動化代碼喚醒「沉睡 90 天」的殭屍客群

嗨,我是 Eric,浪花科技的資深工程師。如果你的資料庫裡躺著好幾千筆會員資料,但每個月活躍下單的只有那幾百人,那你這篇文章真的要好好看。

每次開會聽到行銷部門喊著「廣告費越來越貴」、「ROAS(廣告投資報酬率)一直掉」,我心裡都會默默翻個白眼(工程師的內心戲)。大家總是拚命想把新流量倒進來,卻看著手上的舊名單像一灘死水。你知道嗎?開發一個新客戶的成本,是挽回舊客戶的 5 到 25 倍。在 2025 年這個流量紅利消失的年代,誰能喚醒「沈睡客群」,誰才是贏家。

今天我不談虛無縹緲的行銷理論,我們要來點硬核的。我會教你如何利用 WordPress 和 WooCommerce 的底層機制,寫一段自動化程式碼,精準偵測「90 天未互動」的殭屍客戶,並自動發送帶有優惠券的召回郵件。把這套機制埋進你的 `functions.php` 或自製外掛裡,你的網站就會變成一台 24 小時不休息的自動印鈔機。

為什麼是 90 天?RFM 模型中的黃金關鍵點

在寫 Code 之前,我們得先懂一點邏輯。為什麼我不設 30 天或 180 天?

  • 30 天: 客戶可能只是剛買完東西,還在體驗期,這時候發信騷擾只會增加退訂率。
  • 180 天: 客戶早就忘記你是誰了,這時候喚醒的難度極高,甚至可能被標記為垃圾信件。
  • 90 天(一季): 這是一個非常微妙的心理門檻。客戶對你的品牌還有印象,但購買習慣開始淡化。這時候用「專屬優惠」推一把,挽回的成功率最高。

這在數據分析領域被稱為 RFM 模型(Recency, Frequency, Monetary) 中的 Recency(最近一次消費)。我們的程式碼邏輯,就是要抓出 Recency > 90 days 的這群人。

技術實戰:如何找出沉睡客戶?

很多新手工程師會犯一個錯誤:直接用 PHP 迴圈跑所有的 `wc_get_orders()`。拜託,千萬別這樣做!如果你的網站有幾萬筆訂單,這種寫法會直接把你的伺服器記憶體吃光,導致網站掛掉 (504 Gateway Timeout)。

身為資深工程師,我們要用 SQL 查詢或是高效的 `WP_User_Query` 配合 `meta_query` 來精準打擊。

核心邏輯流程圖

  1. 排程觸發: 設定每日一次的 WP-Cron 排程(建議在半夜流量低峰期)。
  2. 撈取名單: 找出最後一次登入或購買時間在 90 天前的會員。
  3. 排除清單: 排除掉最近已經發送過喚醒信的人(避免重複騷擾)。
  4. 生成優惠: 動態建立一組專屬的 Coupon Code。
  5. 發送郵件: 寄出客製化 HTML 郵件。
  6. 寫入紀錄: 在 User Meta 標記「已發送」,並記錄日期。

Show Me The Code:支援經典編輯器的完整範例

這段程式碼可以直接放在你的子佈景主題的 `functions.php` 中,或者封裝成一個簡單的外掛。為了確保效能,我加了 `LIMIT` 限制,每次排程只處理 50 人,避免超時。


<?php
/**
 * 註冊排程事件
 */
add_action( 'wp', 'roamer_schedule_dormant_customer_recovery' );
function roamer_schedule_dormant_customer_recovery() {
    if ( ! wp_next_scheduled( 'roamer_daily_dormant_check' ) ) {
        wp_schedule_event( time(), 'daily', 'roamer_daily_dormant_check' );
    }
}

/**
 * 核心邏輯:喚醒沉睡客戶
 */
add_action( 'roamer_daily_dormant_check', 'roamer_process_dormant_customers' );
function roamer_process_dormant_customers() {
    global $wpdb;

    // 設定沉睡天數閾值
    $days_inactive = 90;
    $cutoff_date = date( 'Y-m-d H:i:s', strtotime( "-{$days_inactive} days" ) );

    // 1. 找出潛在目標:最後一次活躍時間早於 90 天前,且沒有被標記過「已喚醒」的客戶
    // 注意:這裡簡化邏輯,假設我們用 WooCommerce 的最後訂單時間作為判斷依據
    // 為了效能,每次只抓 20 人
    
    $args = array(
        'role'    => 'customer',
        'number'  => 20, 
        'meta_query' => array(
            'relation' => 'AND',
            array(
                'key'     => '_last_order_date', // 需確保你的系統有記錄這個欄位,若無則需透過 hook 在訂單完成時寫入
                'value'   => $cutoff_date,
                'compare' => '<',
                'type'    => 'DATETIME'
            ),
            array(
                'key'     => '_roamer_dormant_email_sent',
                'compare' => 'NOT EXISTS' // 排除已經發過信的人
            )
        )
    );

    $user_query = new WP_User_Query( $args );
    $customers = $user_query->get_results();

    if ( empty( $customers ) ) {
        return;
    }

    $mailer = WC()->mailer();

    foreach ( $customers as $customer ) {
        // 2. 雙重檢查:確認該客戶真的在 90 天內沒有任何新訂單 (避免 User Meta 更新延遲)
        if ( roamer_check_recent_orders( $customer->ID, $days_inactive ) ) {
            continue; // 如果最近有單,跳過並更新 Meta
        }

        // 3. 生成專屬優惠券 (譬如 9 折)
        $coupon_code = 'COMEBACK-' . strtoupper( wp_generate_password( 6, false ) );
        $amount = '10'; // 10% off
        $discount_type = 'percent';

        $coupon = array(
            'post_title' => $coupon_code,
            'post_content' => '自動喚醒優惠券',
            'post_status' => 'publish',
            'post_author' => 1,
            'post_type' => 'shop_coupon'
        );

        $new_coupon_id = wp_insert_post( $coupon );
        update_post_meta( $new_coupon_id, 'discount_type', $discount_type );
        update_post_meta( $new_coupon_id, 'coupon_amount', $amount );
        update_post_meta( $new_coupon_id, 'individual_use', 'yes' );
        update_post_meta( $new_coupon_id, 'usage_limit', '1' );
        update_post_meta( $new_coupon_id, 'expiry_date', date( 'Y-m-d', strtotime( '+7 days' ) ) ); // 7天後過期
        update_post_meta( $new_coupon_id, 'customer_email', array( $customer->user_email ) );

        // 4. 發送 Email
        $subject = '嘿 ' . $customer->display_name . ',我們好久不見了!(內含專屬優惠)';
        $message = "<p>親愛的 {$customer->display_name},</p>";
        $message .= "<p>我們發現您已經有一段時間沒回來看看了。為了表達想念,這是您的專屬優惠碼:<strong>{$coupon_code}</strong></p>";
        $message .= "<p>結帳時輸入可享 9 折優惠,限時 7 天有效!</p>";
        
        // 使用 WooCommerce 的郵件樣式發送
        $email_heading = '我們想念你';
        $content = $mailer->wrap_message( $email_heading, $message );
        $mailer->send( $customer->user_email, $subject, $content );

        // 5. 標記已發送,避免重複寄信
        update_user_meta( $customer->ID, '_roamer_dormant_email_sent', time() );
    }
}

/**
 * 輔助函式:檢查最近是否有訂單
 */
function roamer_check_recent_orders( $user_id, $days ) {
    $orders = wc_get_orders( array(
        'customer_id' => $user_id,
        'limit' => 1,
        'date_after' => date( 'Y-m-d', strtotime( "-{$days} days" ) ),
        'return' => 'ids',
    ) );
    
    if ( ! empty( $orders ) ) {
        // 如果發現其實有訂單,更新一下 Meta 資料,避免下次誤判
        update_user_meta( $user_id, '_roamer_dormant_email_sent', 'active' );
        return true;
    }
    return false;
}

// 確保每次訂單完成時,更新使用者的 _last_order_date
add_action( 'woocommerce_order_status_completed', 'roamer_update_last_order_date' );
function roamer_update_last_order_date( $order_id ) {
    $order = wc_get_order( $order_id );
    if ( $user_id = $order->get_user_id() ) {
        update_user_meta( $user_id, '_last_order_date', date( 'Y-m-d H:i:s' ) );
        // 清除喚醒標記,以便未來再次進入循環
        delete_user_meta( $user_id, '_roamer_dormant_email_sent' );
    }
}
?>

程式碼解析 (工程師的小囉嗦)

這段程式碼有幾個眉角要注意:

  • User Meta 的重要性: 我使用 `_last_order_date` 作為判斷依據。這意味著你需要一個機制(如代碼最後一段)在每次訂單完成時去更新這個欄位。如果不這樣做,單純靠 query 所有訂單來排序,資料庫會哭出來。
  • Batch Processing (批次處理): 注意到了嗎?我在 `WP_User_Query` 裡設了 `’number’ => 20`。這是為了保護你的伺服器。每天跑一次排程,每次處理 20-50 人,細水長流,總比一次發 5000 封信然後被 Gmail 封鎖 IP 來得好。
  • 優惠券過期機制: 我設定了 `expiry_date`。這很重要,「稀缺性」是行銷轉換的關鍵。如果不設期限,客戶就會想「下次再買」,然後就沒有下次了。

進階優化:搭配 CRM 與 AI 讓自動化更有溫度

上面的程式碼是一個標準的「規則基礎 (Rule-based)」自動化。但在 2025 年,我們可以用更聰明的方法。

如果你的 WordPress 有串接 CRM(如 HubSpot 或 Salesforce),或是透過 n8n 串接了 OpenAI,你可以做更多事:

  • AI 生成主旨: 根據該客戶過去買過的產品(例如「貓飼料」),用 GPT-4 生成相關的信件主旨:「家裡的貓咪餓了嗎?90 天補貨優惠來了!」絕對比罐頭訊息有效。
  • 多渠道觸發: 不只發 Email。如果系統偵測到 Email 開信率低,可以改用 LINE 官方帳號發送 Flex Message 通知(前提是有串接)。

結論:資料庫是資產,別讓它變遺產

很多老闆以為網站架好、廣告投了就有業績,殊不知真正的金礦就在後台的「使用者列表」裡。這段程式碼雖然不長,但它實現了電商最核心的價值——客戶終身價值 (CLV) 的最大化

寫程式不只是為了修 bug,而是為了解決商業問題。把你手上的殭屍名單喚醒,你會發現,這比再去投 Facebook 廣告便宜太多了。

如果你覺得這段程式碼對你來說有點太硬核,或者你的會員數量已經大到需要更複雜的架構(例如搭配 Redis Queue 或專屬的行銷自動化伺服器),不要硬幹,這時候你需要專業的技術團隊來幫你規劃。

不想讓寶貴的客戶名單繼續沉睡?

無論是 WooCommerce 自動化開發、CRM 深度串接,還是企業級的資料庫優化,浪花科技都能為你量身打造最適合的技術解方。別讓你的資料庫變成數位垃圾場。

立即填寫表單聯繫 Eric

延伸閱讀

常見問題 (FAQ)

Q1: 為什麼我的自動喚醒郵件沒有寄出?

這通常跟 WordPress 的 Cron Job 機制有關。WordPress 的預設排程是「有人訪問網站時才會觸發」。如果你的網站流量較低,排程可能不會準時執行。建議在伺服器端(如 Cloudways 或 cPanel)設定系統級的 Crontab 來觸發 `wp-cron.php`,確保每分鐘都能穩定執行任務。

Q2: 這段程式碼會讓網站變慢嗎?

如果在 SQL 查詢時沒有做好限制(例如忘記加 `LIMIT`),或者在迴圈內做太多複雜運算,確實會影響效能。本文提供的範例使用了批次處理(每次只抓 20 人),並針對特定 Meta Key 查詢,對伺服器的負擔極小。但若會員數超過 10 萬,建議改用 Action Scheduler 進行非同步處理。

Q3: 發送的 Email 容易進垃圾信箱怎麼辦?

直接使用 WordPress 的 `wp_mail()` 發信很容易被擋。建議搭配 SMTP 外掛(如 WP Mail SMTP)並串接專業的郵件發送服務(如 SendGrid, Mailgun 或 AWS SES),並確保你的網域已設定好 SPF, DKIM 和 DMARC 驗證,這樣才能保證高送達率。

 
立即諮詢,索取免費1年網站保固