Why this matters
Support teams often need to ping a customer about an order status, a missing address detail, or delivery timing. Jumping between WooCommerce and chat apps wastes time and causes copy paste mistakes.
This tutorial adds a small but high impact improvement:
- A Quick Chat column in the Orders list that opens WhatsApp or Telegram for the customer
- Buttons in the Order Details screen to do the same
- A Telegram username field at checkout so Telegram links actually work
- Robust phone normalization so WhatsApp opens correctly
Important requirement
WhatsApp chat links only work reliably when the phone number includes a country code and contains digits only. Example: +1 415 555 0100
must become 14155550100
. We will enforce this automatically.
Telegram note
Telegram public deep links use usernames, not phone numbers. We will collect and store a Telegram username and link to https://t.me/username
.
What we will build
- A small plugin shell
- A phone normalizer that produces WhatsApp compatible digits
- URL builders for WhatsApp and Telegram
- SVG icons for neat buttons
- A column in the Orders list to start chats
- Buttons in the Order Details screen
- A checkout field for Telegram username and admin persistence
You can copy each step into your plugin file as you go. At the end, you will find the complete code in one piece.
Step 1. Create the plugin
Create a folder:
wp-content/plugins/woo-quick-messaging/
Create a file named:
wp-content/plugins/woo-quick-messaging/woo-quick-messaging.php
Add the plugin header and a default country code constant:
<?php
/**
* Plugin Name: Woo Quick Messaging
* Description: One click WhatsApp and Telegram chat from WooCommerce orders. Cleans phone numbers and adds country code if missing. Adds a Telegram username field.
* Version: 1.1.0
* Author: You
* License: GPL2
*/
if (!defined('ABSPATH')) exit;
// Set your store default. Use digits only, no plus. Example: 1 for USA, 44 for UK, 98 for Iran.
if (!defined('WQM_DEFAULT_COUNTRY_CODE')) {
define('WQM_DEFAULT_COUNTRY_CODE', '98');
}
Why we do this: the constant lets you control how local numbers are promoted to international format without editing code in multiple places.
Step 2. Normalize phone numbers for WhatsApp
WhatsApp’s phone
parameter accepts digits only and expects an international format. We will:
- Strip everything except digits
- Convert
00CC...
toCC...
- If the number starts with
0
, assume local and replace the leading0
withWQM_DEFAULT_COUNTRY_CODE
- If there is no country code but the pattern looks like a local mobile, prepend the default country code
/**
* Normalize a raw phone string into WhatsApp compatible digits.
* Output must be digits only, no plus.
*/
function wqm_normalize_phone_for_whatsapp($raw, $country_code = WQM_DEFAULT_COUNTRY_CODE) {
if (!$raw) return '';
$digits = preg_replace('/\D+/', '', trim($raw));
if ($digits === '') return '';
// 00CC... -> CC...
if (strpos($digits, '00') === 0) {
$digits = substr($digits, 2);
}
// Local format starts with a single 0
if (strpos($digits, '0') === 0) {
$digits = $country_code . substr($digits, 1);
}
// If it still does not start with CC, try typical local patterns
if (strpos($digits, $country_code) !== 0) {
// Example heuristics for a 10 digit mobile that begins with 9
if (preg_match('/^9\d{9}$/', $digits)) {
$digits = $country_code . $digits;
} elseif (preg_match('/^09\d{9}$/', $digits)) {
$digits = $country_code . substr($digits, 1);
}
}
return $digits;
}
You can adapt the regex for your region. The important idea is to always return digits that begin with a country code.
Step 3. Build deep links for WhatsApp and Telegram
/** WhatsApp Web or Desktop URL builder */
function wqm_whatsapp_web_url($digits_no_plus, $prefill_text = '') {
if (!$digits_no_plus) return '';
$base = 'https://web.whatsapp.com/send?phone=' . rawurlencode($digits_no_plus);
if ($prefill_text !== '') {
$base .= '&text=' . rawurlencode($prefill_text);
}
return $base;
}
/**
* Telegram uses usernames for public deep linking.
* We accept a username with or without a leading @ and return https://t.me/username
*/
function wqm_telegram_url_from_username($username) {
if (!$username) return '';
$username = ltrim(trim($username), '@');
if ($username === '') return '';
return 'https://t.me/' . rawurlencode($username);
}
Notes:
- On desktop,
web.whatsapp.com
is ideal. On mobile, browsers often hand off to the app. If you preferhttps://api.whatsapp.com/send
, swap the base. - Telegram cannot reliably start chats by phone number because of privacy settings. Username is the right approach.
Step 4. SVG icons for compact buttons
function wqm_svg_whatsapp($size = 18) {
$size = intval($size);
return '
<svg width="'.$size.'" height="'.$size.'" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" style="vertical-align:middle">
<path d="M19.11 17.12c-.3-.15-1.77-.87-2.05-.97-.28-.1-.49-.15-.7.15-.21.3-.8.97-.98 1.17-.18.2-.36.22-.66.07-.3-.15-1.27-.47-2.42-1.5-.9-.8-1.5-1.77-1.68-2.07-.17-.3-.02-.47.13-.62.13-.13.3-.36.44-.54.15-.18.2-.3.3-.5.1-.2.05-.37-.02-.52-.07-.15-.7-1.68-.96-2.3-.25-.6-.5-.5-.7-.5h-.6c-.2 0-.52.07-.8.37-.28.3-1.05 1.02-1.05 2.5s1.08 2.9 1.23 3.1c.15.2 2.13 3.25 5.15 4.55.72.31 1.28.49 1.72.63.72.23 1.38.2 1.9.12.58-.09 1.77-.72 2.02-1.42.25-.7.25-1.3.18-1.42-.07-.12-.25-.2-.55-.35z" />
<path d="M16 3C8.82 3 3 8.82 3 16c0 2.31.62 4.47 1.7 6.34L3 29l6.85-1.78C11.62 28.38 13.73 29 16 29c7.18 0 13-5.82 13-13S23.18 3 16 3zm0 23.6c-2.04 0-3.94-.6-5.53-1.63l-.4-.25-4.07 1.06 1.09-3.97-.26-.41A10.55 10.55 0 0 1 5.4 16C5.4 10.7 9.7 6.4 15 6.4S24.6 10.7 24.6 16 20.3 26.6 16 26.6z"/>
</svg>';
}
function wqm_svg_telegram($size = 18) {
$size = intval($size);
return '
<svg width="'.$size.'" height="'.$size.'" viewBox="0 0 240 240" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" style="vertical-align:middle">
<circle cx="120" cy="120" r="120" fill="#37AEE2"/>
<path d="M50 119l135-52c6-2 11 1 9 9l-23 108c-1 7-6 9-12 6l-35-26-17 16c-2 2-4 3-8 3l3-39 70-63c3-3-1-4-5-2l-86 54-37-12c-8-2-8-8 2-12z" fill="#fff"/>
</svg>';
}
Step 5. Add a Quick Chat column to Orders list
We will register a new column and render clickable icons. WhatsApp uses the billing phone. Telegram uses a username stored on the order or user profile.
/** Add a column header */
add_filter('manage_edit-shop_order_columns', function ($columns) {
$new = [];
foreach ($columns as $key => $label) {
$new[$key] = $label;
if ($key === 'order_total') $new['wqm_quickchat'] = 'Quick Chat';
}
if (!isset($new['wqm_quickchat'])) $new['wqm_quickchat'] = 'Quick Chat';
return $new;
}, 20);
/** Render the column cells */
add_action('manage_shop_order_posts_custom_column', function ($column, $post_id) {
if ($column !== 'wqm_quickchat') return;
$order = wc_get_order($post_id);
if (!$order) return;
$phone_raw = $order->get_billing_phone();
$wa_digits = $phone_raw ? wqm_normalize_phone_for_whatsapp($phone_raw) : '';
// Telegram username from order meta or user meta
$tg_username = $order->get_meta('_billing_telegram');
if (!$tg_username && $order->get_user_id()) {
$tg_username = get_user_meta($order->get_user_id(), 'billing_telegram', true);
if (!$tg_username) {
$tg_username = get_user_meta($order->get_user_id(), 'telegram_username', true);
}
}
$links = [];
if ($wa_digits) {
$wa_url = esc_url(wqm_whatsapp_web_url($wa_digits));
$links[] = '<a href="'.$wa_url.'" target="_blank" rel="noopener noreferrer" title="Open WhatsApp" style="display:inline-flex;align-items:center;gap:6px;text-decoration:none;margin-right:10px">'
. wqm_svg_whatsapp(18) . '<span style="font-size:12px">WhatsApp</span></a>';
}
if ($tg_username) {
$tg_url = esc_url(wqm_telegram_url_from_username($tg_username));
if ($tg_url) {
$links[] = '<a href="'.$tg_url.'" target="_blank" rel="noopener noreferrer" title="Open Telegram" style="display:inline-flex;align-items:center;gap:6px;text-decoration:none">'
. wqm_svg_telegram(18) . '<span style="font-size:12px">Telegram</span></a>';
}
}
echo $links ? implode('', $links) : '<span style="opacity:.6">No chat</span>';
}, 20, 2);
Step 6. Add buttons in the Order Details screen
These appear below the billing address inside a single order view.
add_action('woocommerce_admin_order_data_after_billing_address', function ($order) {
if (!$order instanceof WC_Order) return;
$phone_raw = $order->get_billing_phone();
$wa_digits = $phone_raw ? wqm_normalize_phone_for_whatsapp($phone_raw) : '';
$tg_username = $order->get_meta('_billing_telegram');
if (!$tg_username && $order->get_user_id()) {
$tg_username = get_user_meta($order->get_user_id(), 'billing_telegram', true);
if (!$tg_username) {
$tg_username = get_user_meta($order->get_user_id(), 'telegram_username', true);
}
}
echo '<p style="margin-top:8px;display:flex;gap:8px;flex-wrap:wrap">';
if ($wa_digits) {
$url = esc_url(wqm_whatsapp_web_url($wa_digits));
echo '<a href="'.$url.'" target="_blank" rel="noopener noreferrer" class="button" style="display:inline-flex;align-items:center;gap:8px">'
. wqm_svg_whatsapp(16) . '<span>WhatsApp Web</span></a>';
}
if ($tg_username) {
$tg_url = esc_url(wqm_telegram_url_from_username($tg_username));
if ($tg_url) {
echo '<a href="'.$tg_url.'" target="_blank" rel="noopener noreferrer" class="button" style="display:inline-flex;align-items:center;gap:8px">'
. wqm_svg_telegram(16) . '<span>Telegram</span></a>';
}
}
echo '</p>';
}, 20);
Step 7. Collect and persist Telegram username
Add a field at checkout, store it on the order, and copy to user meta for reuse.
// Add a checkout field
add_filter('woocommerce_checkout_fields', function ($fields) {
$fields['billing']['billing_telegram'] = [
'type' => 'text',
'label' => __('Telegram username', 'woo-quick-messaging'),
'placeholder' => __('username only, no @', 'woo-quick-messaging'),
'required' => false,
'class' => ['form-row-wide'],
'priority' => 125,
];
return $fields;
});
// Store on the order
add_action('woocommerce_checkout_create_order', function ($order, $data) {
if (!empty($data['billing_telegram'])) {
$username = ltrim(trim($data['billing_telegram']), '@');
$order->update_meta_data('_billing_telegram', $username);
}
}, 10, 2);
// Copy to user profile after checkout
add_action('woocommerce_checkout_update_order_meta', function ($order_id) {
$order = wc_get_order($order_id);
if (!$order) return;
$user_id = $order->get_user_id();
$username = $order->get_meta('_billing_telegram');
if ($user_id && $username) {
update_user_meta($user_id, 'billing_telegram', $username);
}
});
// Show the username in the admin order billing panel
add_action('woocommerce_admin_order_data_after_billing_address', function ($order) {
$username = $order->get_meta('_billing_telegram');
if ($username) {
echo '<p><strong>' . esc_html__('Telegram username', 'woo-quick-messaging') . ':</strong> ' . esc_html('@' . $username) . '</p>';
}
}, 5);
// Allow manual edit in admin
add_action('woocommerce_admin_order_data_after_order_details', function ($order) {
$username = $order->get_meta('_billing_telegram');
?>
<div class="address">
<p class="form-field form-field-wide">
<label for="wqm_billing_telegram"><?php esc_html_e('Telegram username', 'woo-quick-messaging'); ?></label>
<input type="text" class="short" style="min-width:300px" name="wqm_billing_telegram" id="wqm_billing_telegram"
value="<?php echo esc_attr($username); ?>"
placeholder="<?php esc_attr_e('username only, no @', 'woo-quick-messaging'); ?>" />
</p>
</div>
<?php
}, 30);
// Save the manual edit
add_action('woocommerce_process_shop_order_meta', function ($post_id) {
if (isset($_POST['wqm_billing_telegram'])) {
$username = ltrim(sanitize_text_field(wp_unslash($_POST['wqm_billing_telegram'])), '@');
update_post_meta($post_id, '_billing_telegram', $username);
$order = wc_get_order($post_id);
if ($order && $order->get_user_id() && $username) {
update_user_meta($order->get_user_id(), 'billing_telegram', $username);
}
}
}, 10);
Testing checklist
- Create a test order with a local style phone. Confirm WhatsApp opens and the number shows the country code.
- Create another order with a full international number that starts with a plus. Confirm the plus is removed and digits remain correct.
- Provide a Telegram username at checkout. Confirm the Orders list shows a Telegram button and links to
https://t.me/username
. - Remove the username and confirm the Telegram button disappears.
- Try in a private browser on desktop and on a phone to verify handoff to apps.
Wrap up
You now have a clean, minimal plugin that lets support agents open WhatsApp or Telegram directly from the WooCommerce Orders list and the Order Details page. WhatsApp will always work with the required country code. Telegram will work when the customer shares a username.
If you want a follow up, I can add:
- A settings page for the default country code and a WhatsApp prefill template
- Store level toggles to hide or show each network
- Country specific phone patterns for better normalization