「加入購物車」是 WooCommerce 商店裡被點擊次數最多的按鈕,卻常常是被忽略的一塊。預設文字千篇一律、點下去要不要跳頁、要不要直接帶到結帳,這些行為其實都能調整,而且多數不需要動到很深的程式碼。
問題在於,這顆按鈕在 WooCommerce 裡其實有好幾種樣貌:單一商品頁有一顆、商店列表頁每個商品各一顆、相關商品區又一顆,三個地方背後對應的是不同的 hook。如果搞不清楚這層結構,常常會發生「改了文字單頁有變、商店頁卻沒變」的情況。
這篇會把 WooCommerce 加入購物車按鈕的客製拆成三件事來講:改文字、調整 AJAX(點了不刷新頁面的非同步加入)、以及改變點擊後的行為(例如直接跳結帳)。每一段都附上可以直接貼進 functions.php 的程式碼,並提醒幾個官方教學很少提到的踩雷點。
加入購物車按鈕分散在哪幾個位置?
先弄清楚按鈕出現的位置,後面所有客製才有對象。WooCommerce 的加入購物車按鈕主要出現在三個地方,各自由不同的模板與 hook 控制。
- 單一商品頁的按鈕:使用者點進某個商品後看到的那顆,行為最完整,可以選數量、選規格(可變商品)再加入。
- 商店與彙整頁的按鈕:商店首頁、商品分類頁、標籤頁的列表中,每個商品縮圖底下的那顆。這顆預設是簡化版,多半只負責把商品丟進購物車。
- 相關商品與交叉銷售區的按鈕:商品頁下方「相關商品」或購物車頁「您可能也喜歡」帶出來的按鈕,本質上和彙整頁的列表按鈕共用同一套邏輯。
把這三類分開記住很重要,因為改文字、改連結時,單頁與列表用的是不同的 filter。只改其中一個,另一個不會跟著變,這是新手最常卡住的點。
WooCommerce 加入購物車按鈕的文字怎麼改?
改文字靠的是兩個 filter,單頁一個、列表頁一個,分開掛才會兩邊都生效。把程式碼放進子主題的 functions.php,或自建一個小外掛,盡量不要直接改佈景主題本體,免得更新時被覆蓋掉。
先處理單一商品頁,這顆對應 woocommerce_product_single_add_to_cart_text:
add_filter( 'woocommerce_product_single_add_to_cart_text', 'ez_single_add_to_cart_text' );
function ez_single_add_to_cart_text() {
return '立即購買';
}
再處理商店與彙整頁的列表按鈕,這顆對應 woocommerce_product_add_to_cart_text:
add_filter( 'woocommerce_product_add_to_cart_text', 'ez_loop_add_to_cart_text', 10, 2 );
function ez_loop_add_to_cart_text( $text, $product ) {
return '立即購買';
}
如果只想改文字、不想碰程式碼,還有兩條路。一是用翻譯外掛(例如 Loco Translate)把「Add to cart」這串字串改掉,缺點是它只能整站統一替換,沒辦法依商品類型給不同文字。二是裝專門做按鈕文字的外掛,後台會多出可視化的設定欄位,適合完全不想碰程式碼的人。
不同商品類型要顯示不同文字怎麼辦?
列表頁的 filter 帶有 $product 物件,這代表可以依商品類型給出不同文字,而不是全站一個樣。常見需求是組合商品顯示「組合優惠」、缺貨商品顯示「查看詳情」、預購商品顯示「立即預購」。
做法是在 filter 裡用 switch 判斷商品類型:
add_filter( 'woocommerce_product_add_to_cart_text', 'ez_text_by_type', 10, 2 );
function ez_text_by_type( $text, $product ) {
switch ( $product->get_type() ) {
case 'grouped':
return '查看組合';
case 'variable':
return '選擇規格';
case 'external':
return '前往購買';
default:
return $text;
}
}
這裡有個容易忽略的細節:可變商品(variable)和外部商品(external)在列表頁本來就不是「直接加入」的按鈕,它們會帶使用者跳到商品頁去選規格,或跳到外部連結。所以替換文字時要讓字面跟實際行為對得上,把可變商品寫成「立即加入」反而會誤導使用者。
加入購物車按鈕的 AJAX 行為要不要開?
AJAX 加入購物車指的是點擊後不重新整理頁面,商品在背景被丟進購物車,購物車數量即時更新。它的好處是使用者停留在原本的列表頁可以繼續逛,不會每加一件就被打斷一次。
要開啟這個行為,到 WooCommerce → 設定 → 商品 → 一般,勾選「在彙整頁啟用 AJAX 加入購物車按鈕」。這個官方選項只作用在商店與彙整頁的列表按鈕,單一商品頁的按鈕預設就會送出表單、刷新頁面,因為它要處理數量與規格,邏輯比列表按鈕複雜。
這是一個常見誤解:很多人勾了這個選項後,發現單一商品頁點下去還是會刷新,以為設定壞了。實際上官方的 AJAX 範圍本來就只涵蓋列表頁,單頁要做 AJAX 得另外寫程式。
自訂 AJAX 加入購物車按鈕要符合哪些條件?
如果要自己刻一顆 AJAX 按鈕,WooCommerce 內建的 add-to-cart.js 其實會幫忙處理大部分工作,前提是按鈕的結構要對。一顆能被內建腳本接管的 AJAX 按鈕,必須同時滿足兩個條件:
- 掛上指定的 class:按鈕要帶
add_to_cart_button與ajax_add_to_cart兩個 class,內建腳本是靠這兩個 class 來綁定點擊事件的。 - 提供商品 ID:用
data-product_id屬性把商品 ID 帶進去,腳本才知道要加哪個商品。
舉例來說,在彙整頁每個商品後面塞一顆「加 10 件」的按鈕,可以這樣寫:
add_action( 'woocommerce_after_shop_loop_item', function() {
$product_id = get_the_ID();
echo '<a href="?add-to-cart=' . $product_id . '&quantity=10"
data-quantity="10"
data-product_id="' . $product_id . '"
class="button add_to_cart_button ajax_add_to_cart">加 10 件入車</a>';
}, 99 );
幾個要點:data-quantity 可以指定一次加入的數量;href 裡的 ?add-to-cart= 是給關掉 JavaScript 的瀏覽器當備援用的,正常情況下不會走到那條路。
當內建按鈕滿足不了需求(例如要在加入前後切換載入動畫、或一次處理多個商品),就得自己寫 jQuery 呼叫 WooCommerce 的 AJAX 端點。關鍵是用 wc_add_to_cart_params.wc_ajax_url 組出端點網址,並在成功後手動觸發 added_to_cart 事件,購物車的 fragment 才會跟著更新:
jQuery( function( $ ) {
$( '#custom-add-to-cart' ).click( function( e ) {
e.preventDefault();
$.ajax({
type: 'POST',
url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'add_to_cart' ),
data: { product_id: 54, quantity: 2 },
success: function( res ) {
$( document.body ).trigger( 'added_to_cart', [ res.fragments, res.cart_hash ] );
}
});
});
});
漏掉最後那行 trigger( 'added_to_cart' ),會出現「商品其實加進去了,但畫面上的購物車數字沒動」的詭異狀況,這也是自訂 AJAX 按鈕最常見的疏漏。
點了加入購物車後要直接跳結帳怎麼設定?
讓使用者按下按鈕就直接到結帳頁,是縮短購買流程很常見的做法,特別適合單一主打商品或客單純粹的店。完整做起來不只是一行程式,要四個步驟配合才不會出狀況。
第一步、關掉彙整頁的 AJAX 加入購物車。既然要跳頁,就不能讓 AJAX 把使用者留在原地。回到 WooCommerce → 設定 → 商品,把「在彙整頁啟用 AJAX 加入購物車按鈕」取消勾選。
第二步、設定跳轉到結帳頁。核心是 woocommerce_add_to_cart_redirect 這個 filter,回傳結帳頁網址即可:
add_filter( 'woocommerce_add_to_cart_redirect', 'ez_redirect_to_checkout' );
function ez_redirect_to_checkout( $url ) {
return wc_get_checkout_url();
}
這裡用 wc_get_checkout_url() 取得結帳頁網址,比自己拼網址安全,因為它會去讀 WooCommerce 設定裡實際指定的結帳頁,搬站或改頁面時不會跑掉。
第三步、把按鈕文字改成符合情境的字。既然點了就跳結帳,按鈕還寫「加入購物車」就名實不符,搭配前面的文字 filter 改成「立即結帳」或「直接購買」比較合理。
第四步、移除「已加入購物車」的提示訊息。直接跳結帳的情境下,那行「商品已加入購物車」的提示顯得多餘,可以用 wc_add_to_cart_message_html 把它清掉:
add_filter( 'wc_add_to_cart_message_html', '__return_empty_string' );
設成單一商品也能加入時為什麼會跳錯誤?
把商品設成「單獨銷售」(sold individually)後,跳結帳的設定會出現一個邊界狀況:當商品已經在購物車裡,使用者再點一次按鈕,會收到「此商品已在購物車中」的錯誤訊息,沒辦法順利進結帳。
解法是攔截按鈕的網址,判斷商品如果已經在購物車裡,就把按鈕網址直接換成結帳頁,跳過「再加一次」這個動作:
add_filter( 'woocommerce_product_add_to_cart_url', 'ez_fix_individual', 10, 2 );
function ez_fix_individual( $url, $product ) {
if ( $product->is_sold_individually()
&& WC()->cart->find_product_in_cart( WC()->cart->generate_cart_id( $product->get_id() ) ) ) {
$url = wc_get_checkout_url();
}
return $url;
}
這類邊界狀況官方教學很少提,但只要你的店有設定單獨銷售的商品,遲早會遇到。
如果整套程式碼對你來說門檻太高,市面上有「加入購物車後跳轉」類型的外掛可以裝,後台勾選就能把目的地設成結帳頁或自訂網址。涉及收款流程的部分(金流串接、結帳欄位)屬於另一個主題,這裡先不展開。
客製按鈕該寫程式還是裝外掛?
判斷標準很單純,看你要客製的深度,以及未來要不要常常調整。
- 只是改文字、改跳轉目的地:需求單純又不常動,用程式碼最乾淨,幾行 filter 就解決,不用為了一個小功能多裝一支外掛拖慢網站。
- 要依商品類型給不同文字、處理單獨銷售的邊界狀況:這類需要
switch判斷或攔截網址的邏輯,程式碼比外掛更靈活,外掛的設定欄位往往涵蓋不到。 - 完全不想碰程式碼、需要可視化設定:交給專門的按鈕外掛,後台點一點就好,代價是多一支外掛要維護,且彈性受限於它提供的選項。
不論走哪條路,改完都要實際測一輪:單頁、商店列表頁、相關商品區三個位置的按鈕文字與行為是否如預期,AJAX 開關下的購物車數字有沒有即時更新,跳結帳的流程會不會被「單獨銷售」之類的設定卡住。
把加入購物車按鈕當成一個可以調整的轉換環節,而不是預設長怎樣就接受,往往能在不改商品、不改價格的前提下,讓使用者更願意把商品送進結帳。先確認你要改的是哪一個位置的按鈕,再決定動文字、動 AJAX 還是動行為,三件事釐清了,客製就只是把對應的 filter 掛上去而已。