前言
在 WooCommerce 後台商品列表中,管理者常需要快速取得商品的「加入購物車」連結以便分享或推廣。這段程式碼實作了在商品列表中新增一欄「複製課程連結」按鈕,點擊後可彈出視窗讓使用者輸入優惠券代碼,並將優惠券參數附加到連結中,最後將完整連結複製到剪貼簿。這對於需要快速產生帶優惠券的購物車連結的電商管理者非常實用。
新增自訂欄位顯示複製按鈕
利用 manage_edit-product_columns 過濾器新增一欄「複製課程連結」,並透過 manage_product_posts_custom_column 動作在該欄位輸出一個帶有商品加入購物車 URL 的按鈕。URL 是以網站首頁 URL 加上 /cart/?add-to-cart=商品ID 組成。
add_filter('manage_edit-product_columns', 'add_copy_link_column');
function add_copy_link_column($columns) {
$columns['copy_add_to_cart'] = __('複製課程連結', 'woocommerce');
return $columns;
}
add_action('manage_product_posts_custom_column', 'show_copy_link_column_content', 10, 2);
function show_copy_link_column_content($column, $post_id) {
if ($column === 'copy_add_to_cart') {
$product_id = (int) $post_id;
$site_url = my_copy_cart_site_url();
$add_to_cart_url = $site_url . '/cart/?add-to-cart=' . $product_id;
echo '<button type="button" class="button copy-cart-link" data-url="' . esc_attr($add_to_cart_url) . '" title="點擊複製連結">複製</button>';
}
}
客製化 JavaScript 處理複製邏輯與優惠券輸入
在後台商品列表頁尾插入 JavaScript 和 CSS,當使用者點擊「複製」按鈕時:
- 透過
window.prompt詢問是否輸入優惠券代碼,可留空。 - 根據輸入結果組合最終 URL,若有優惠券則加上
&wt_coupon=優惠券代碼。 - 使用 Clipboard API 複製連結,若不支援則使用傳統
execCommand備援。 - 複製成功會顯示成功提示,失敗則顯示錯誤提示並提供手動複製。
function buildFinalUrl(baseUrl) {
var coupon = window.prompt('是否要加入優惠券?\n(可留空,直接按確定即可)', '');
if (coupon === null) return baseUrl;
coupon = String(coupon || '').trim();
if (!coupon) return baseUrl;
var joiner = (baseUrl.indexOf('?') === -1) ? '?' : '&';
return baseUrl + joiner + 'wt_coupon=' + encodeURIComponent(coupon);
}
$(document).on('click', '.copy-cart-link', function(e) {
e.preventDefault();
var button = $(this);
var baseUrl = button.data('url');
var originalHtml = button.html();
if (button.hasClass('copying')) return;
button.addClass('copying');
var finalUrl = buildFinalUrl(baseUrl);
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(finalUrl).then(function() {
showCopySuccess(button, originalHtml);
}).catch(function() {
fallbackCopyTextToClipboard(finalUrl, button, originalHtml);
});
} else {
fallbackCopyTextToClipboard(finalUrl, button, originalHtml);
}
});
快速動作連結整合
除了欄位按鈕外,也在商品標題下方的快速動作連結加入「複製購物車連結」,提升操作便利性。此連結同樣帶有商品加入購物車的 URL,並套用相同的 JavaScript 行為。
add_filter('post_row_actions', 'add_copy_link_quick_action', 10, 2);
function add_copy_link_quick_action($actions, $post) {
if ($post->post_type === 'product') {
$product_id = (int) $post->ID;
$site_url = my_copy_cart_site_url();
$add_to_cart_url = $site_url . '/cart/?add-to-cart=' . $product_id;
$actions['copy_cart_link'] = '<a href="#" class="copy-cart-link" data-url="' . esc_attr($add_to_cart_url) . '" style="color:#0073aa;">📋 複製購物車連結</a>';
}
return $actions;
}
實務應用與優化建議
此功能適合需要快速產生帶優惠券的購物車連結的 WooCommerce 商店管理員,方便推廣或客服回覆。未來可優化:
- 將網站 URL 改為動態取得,避免硬編碼。
- 增加複製成功的視覺動畫提升 UX。
- 支援多種優惠券參數或其他自訂參數。
- 對於大量商品列表,可考慮優化前端效能。
完整程式碼
<?php
/**
* WooCommerce 後台商品列表添加複製 add-to-cart 連結的功能 + 可選優惠券
* 適用於 WPCode(PHP Snippet / Run Everywhere 或 Admin Only)
*
* 功能:
* - 商品列表新增一欄「複製課程連結」
* - 點按後彈出視窗詢問優惠券(可留空)
* - 若有填,複製的 URL 會加上:&wt_coupon=COUPON
* - 同時支援「快速動作」複製
*/
/** 你網站的網域(建議改成動態,不用寫死) */
function my_copy_cart_site_url() {
return home_url();
}
// 在商品列表中添加自定義列
add_filter('manage_edit-product_columns', 'add_copy_link_column');
function add_copy_link_column($columns) {
$columns['copy_add_to_cart'] = __('複製課程連結', 'woocommerce');
return $columns;
}
// 顯示列內容
add_action('manage_product_posts_custom_column', 'show_copy_link_column_content', 10, 2);
function show_copy_link_column_content($column, $post_id) {
if ($column === 'copy_add_to_cart') {
$product_id = (int) $post_id;
$site_url = my_copy_cart_site_url();
$add_to_cart_url = $site_url . '/cart/?add-to-cart=' . $product_id;
echo '<button type="button" class="button copy-cart-link" data-url="' . esc_attr($add_to_cart_url) . '" title="點擊複製連結">
複製
</button>';
}
}
// 添加 JavaScript 和 CSS
add_action('admin_footer', 'copy_link_admin_script');
function copy_link_admin_script() {
$screen = get_current_screen();
if (!$screen || $screen->id !== 'edit-product') {
return;
}
?>
<style>
.copy-cart-link {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 4px 8px;
font-size: 12px;
line-height: 1.4;
border-radius: 3px;
cursor: pointer;
transition: all 0.3s ease;
}
.copy-cart-link:hover {
background-color: #000000;
color: white;
transform: translateY(-1px);
}
.copy-cart-link .dashicons {
font-size: 14px;
width: 14px;
height: 14px;
}
.column-copy_add_to_cart {
width: 110px;
text-align: center;
}
@media screen and (max-width: 782px) {
.copy-cart-link {
padding: 6px 10px;
font-size: 13px;
}
}
</style>
<script type="text/javascript">
jQuery(document).ready(function($) {
// 組裝最終要複製的 URL(可選 wt_coupon)
function buildFinalUrl(baseUrl) {
// 1) 詢問優惠券(可留空)
var coupon = window.prompt('是否要加入優惠券?\n(可留空,直接按確定即可)', '');
// 使用者按取消 -> 仍照原本複製(你也可以改成 return null 代表不複製)
if (coupon === null) {
return baseUrl;
}
coupon = String(coupon || '').trim();
if (!coupon) {
return baseUrl;
}
// 2) 已有 ?add-to-cart=...,直接加 &wt_coupon=
// 若未來 baseUrl 可能沒有 query,這裡也做保險處理
var joiner = (baseUrl.indexOf('?') === -1) ? '?' : '&';
return baseUrl + joiner + 'wt_coupon=' + encodeURIComponent(coupon);
}
$(document).on('click', '.copy-cart-link', function(e) {
e.preventDefault();
var button = $(this);
var baseUrl = button.data('url');
var originalHtml = button.html();
if (button.hasClass('copying')) return;
button.addClass('copying');
var finalUrl = buildFinalUrl(baseUrl);
// 若你希望「按取消就不複製」,把 buildFinalUrl 的取消行為改成 return null
// 然後這裡加上:
// if (!finalUrl) { button.removeClass('copying'); return; }
if (navigator.clipboard && window.isSecureContext) {
navigator.clipboard.writeText(finalUrl).then(function() {
showCopySuccess(button, originalHtml);
}).catch(function(err) {
console.error('Copy failed: ', err);
fallbackCopyTextToClipboard(finalUrl, button, originalHtml);
});
} else {
fallbackCopyTextToClipboard(finalUrl, button, originalHtml);
}
});
function fallbackCopyTextToClipboard(text, button, originalHtml) {
var textArea = document.createElement("textarea");
textArea.value = text;
textArea.style.top = "0";
textArea.style.left = "0";
textArea.style.position = "fixed";
textArea.style.opacity = "0";
textArea.style.pointerEvents = "none";
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
var successful = document.execCommand('copy');
if (successful) {
showCopySuccess(button, originalHtml);
} else {
showCopyError(button, originalHtml, text);
}
} catch (err) {
console.error('Copy failed: ', err);
showCopyError(button, originalHtml, text);
}
document.body.removeChild(textArea);
}
function showCopySuccess(button, originalHtml) {
button.removeClass('copying').addClass('copied');
button.html('<span class="dashicons dashicons-yes"></span> 已複製');
setTimeout(function() {
button.removeClass('copied');
button.html(originalHtml);
}, 2500);
}
function showCopyError(button, originalHtml, text) {
button.removeClass('copying');
var tooltip = $('<div class="copy-error-tooltip" style="position:absolute;background:#333;color:#fff;padding:8px 12px;border-radius:4px;font-size:12px;z-index:9999;max-width:320px;word-break:break-all;">複製失敗,請手動複製:<br>' + text + '</div>');
$('body').append(tooltip);
var buttonOffset = button.offset();
tooltip.css({
top: buttonOffset.top - tooltip.outerHeight() - 5,
left: buttonOffset.left
});
setTimeout(function() { tooltip.remove(); }, 5000);
tooltip.on('click', function() {
if (navigator.clipboard) navigator.clipboard.writeText(text);
$(this).remove();
});
}
});
</script>
<?php
}
// 可選:添加快速動作連結(在商品名稱下方)
add_filter('post_row_actions', 'add_copy_link_quick_action', 10, 2);
function add_copy_link_quick_action($actions, $post) {
if ($post->post_type === 'product') {
$product_id = (int) $post->ID;
$site_url = my_copy_cart_site_url();
$add_to_cart_url = $site_url . '/cart/?add-to-cart=' . $product_id;
$actions['copy_cart_link'] = '<a href="#" class="copy-cart-link" data-url="' . esc_attr($add_to_cart_url) . '" style="color:#0073aa;">📋 複製購物車連結</a>';
}
return $actions;
}