# Connect your website to Telegram for order and form alerts

- آدرس: https://di9.ir/blog/en/connect-website-telegram-order-notifications
- نویسنده: danidiba
- انتشار: 2026-09-24T22:40:00+03:30
- به‌روزرسانی: 2026-09-24T22:40:00+03:30
- دسته: Telegram
- برچسب‌ها: PHP، اتصال سایت به تلگرام، اعلان سفارش، ربات تلگرام، ووکامرس

> With a bot and a few lines of code you can send every new order or contact form straight to a private Telegram group or channel. This guide gives safe code for WordPress and WooCommerce, a Laravel example, and tips for storing the token.

A store manager who refreshes the orders page every few minutes, or a contact form whose email lands in spam, are two classic cases. The simpler way is for the site itself to send a message to Telegram. With a bot and a few lines of PHP this is doable. The key is to store the bot token properly and make sure a problem with Telegram never causes a problem with an order.

This article is part of the [complete Telegram guide](https://di9.ir/blog/%D8%B1%D8%A7%D9%87%D9%86%D9%85%D8%A7%DB%8C-%DA%A9%D8%A7%D9%85%D9%84-%D8%AA%D9%84%DA%AF%D8%B1%D8%A7%D9%85). Before you start, you need to have created a bot and have its token; for that step see [creating a Telegram bot](https://di9.ir/blog/%D8%B3%D8%A7%D8%AE%D8%AA-%D8%B1%D8%A8%D8%A7%D8%AA-%D8%AA%D9%84%DA%AF%D8%B1%D8%A7%D9%85).

## A simple architecture

The flow works like this:

1. An event happens on the site (a new order or a form submission).
2. The site's code sends an HTTPS request to the Telegram API.
3. The bot posts the message in the admins' group or a private channel.

You need three things: the bot token, the chat ID (`chat_id`) and outbound access from your server to `api.telegram.org`. Some services restrict access by country, and some hosts limit outbound connections; if messages don't arrive, first ask your hosting provider about outbound connectivity.

For the destination, create a private admin group, add the bot and send a message. Find the ID with `getUpdates`. For a channel, the bot must be an admin.

## Rule one: keep the token in configuration

The token must not be in files reachable from the web or in a public database. In WordPress, the best place is the `wp-config.php` file:

```php
// wp-config.php (above the line "That's all, stop editing!")
define( 'DI9_TG_TOKEN', 'your-bot-token-here' );
define( 'DI9_TG_CHAT_ID', '-1001234567890' );
```

If your host allows it, put the values in environment variables and read them with `getenv()`. Do not write the token inside a plugin file that you commit to a code repository.

## Sending messages safely from WordPress

Put this code in a small plugin (not in the theme's functions.php, because it disappears when you change themes). The base function sends an HTML message and logs errors without revealing the token:

```php
<?php
/**
 * Plugin Name: Site Telegram Notifications
 */

defined( 'ABSPATH' ) || exit;

function di9_tg_send( string $html ): bool {
    if ( ! defined( 'DI9_TG_TOKEN' ) || ! defined( 'DI9_TG_CHAT_ID' ) ) {
        return false;
    }

    $response = wp_remote_post(
        'https://api.telegram.org/bot' . DI9_TG_TOKEN . '/sendMessage',
        array(
            'timeout' => 5,
            'body'    => array(
                'chat_id'                  => DI9_TG_CHAT_ID,
                'text'                     => $html,
                'parse_mode'               => 'HTML',
                'disable_web_page_preview' => true,
            ),
        )
    );

    if ( is_wp_error( $response ) ) {
        error_log( 'Telegram notify failed: ' . $response->get_error_code() );
        return false;
    }

    if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
        error_log( 'Telegram notify HTTP ' . wp_remote_retrieve_response_code( $response ) );
        return false;
    }

    return true;
}

function di9_tg_esc( string $text ): string {
    return htmlspecialchars( $text, ENT_NOQUOTES, 'UTF-8' );
}
```

A few points in this code matter:

- The `timeout` is short so a slow Telegram does not hold up the page.
- The log contains only the error code, not the full URL. The request URL includes the token and must not go into logs.
- `htmlspecialchars` makes dynamic text safe for Telegram's HTML mode. Without it, a customer name containing `<` would break the message.

## WooCommerce new order alert

If you run WooCommerce, hook into the checkout order-processed action:

```php
add_action( 'woocommerce_checkout_order_processed', 'di9_tg_new_order', 10, 1 );

function di9_tg_new_order( int $order_id ): void {
    $order = wc_get_order( $order_id );
    if ( ! $order ) {
        return;
    }

    $lines   = array();
    $lines[] = '<b>New order #' . di9_tg_esc( (string) $order->get_order_number() ) . '</b>';
    $lines[] = 'Customer: ' . di9_tg_esc( $order->get_formatted_billing_full_name() );
    $lines[] = 'Total: ' . di9_tg_esc( wp_strip_all_tags( $order->get_formatted_order_total() ) );
    $lines[] = 'Status: ' . di9_tg_esc( wc_get_order_status_name( $order->get_status() ) );

    di9_tg_send( implode( "\n", $lines ) );
}
```

Send only the information the manager needs. Don't push phone numbers, addresses and payment details to Telegram for no reason; the group may have many members and messages stay on third-party servers. For setting up the store itself, see [setting up a store with WooCommerce](https://di9.ir/blog/%D8%B1%D8%A7%D9%87-%D8%A7%D9%86%D8%AF%D8%A7%D8%B2%DB%8C-%D9%81%D8%B1%D9%88%D8%B4%DA%AF%D8%A7%D9%87-%D9%88%D9%88%DA%A9%D8%A7%D9%85%D8%B1%D8%B3).

## A simple example for a contact form

If you have a custom form, send the message after validation and a nonce check:

```php
add_action( 'admin_post_nopriv_di9_contact', 'di9_handle_contact' );
add_action( 'admin_post_di9_contact', 'di9_handle_contact' );

function di9_handle_contact(): void {
    if ( ! isset( $_POST['_wpnonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ), 'di9_contact' ) ) {
        wp_die( 'Invalid request', '', array( 'response' => 403 ) );
    }

    $name    = isset( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : '';
    $message = isset( $_POST['message'] ) ? sanitize_textarea_field( wp_unslash( $_POST['message'] ) ) : '';

    if ( '' === $name || '' === $message ) {
        wp_safe_redirect( wp_get_referer() ?: home_url( '/' ) );
        exit;
    }

    di9_tg_send( '<b>New message from the contact form</b>' . "\n" . di9_tg_esc( $name ) . "\n" . di9_tg_esc( mb_substr( $message, 0, 500 ) ) );

    wp_safe_redirect( add_query_arg( 'sent', '1', wp_get_referer() ?: home_url( '/' ) ) );
    exit;
}
```

The HTML form needs a hidden `action` field with the value `di9_contact` and `wp_nonce_field( 'di9_contact' )`, and must submit to `admin-post.php`. A public form is a spam target; in practice add anti-spam such as a CAPTCHA or a rate limiter, otherwise spam bots will flood your group.

## Laravel

In Laravel, put the token in `.env` and read it through a config file:

```php
// config/services.php
'telegram' => [
    'token'   => env('TELEGRAM_BOT_TOKEN'),
    'chat_id' => env('TELEGRAM_CHAT_ID'),
],
```

```php
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;

function notifyTelegram(string $html): void
{
    $token = config('services.telegram.token');
    $chat  = config('services.telegram.chat_id');

    if (! $token || ! $chat) {
        return;
    }

    try {
        $response = Http::timeout(5)->asForm()->post(
            "https://api.telegram.org/bot{$token}/sendMessage",
            [
                'chat_id'    => $chat,
                'text'       => $html,
                'parse_mode' => 'HTML',
            ]
        );

        if ($response->failed()) {
            Log::warning('Telegram notify failed', ['status' => $response->status()]);
        }
    } catch (\Throwable $e) {
        Log::warning('Telegram notify exception', ['class' => $e::class]);
    }
}
```

For a high-traffic site, run this function inside a queued Job so the user's request does not wait for Telegram. Make dynamic text safe with `e()` or `htmlspecialchars`. Keep the `.env` file out of Git, and the public `public` folder must not expose it.

## After setup

- Test the site: place a test order and check that the message arrives.
- Keep Telegram's sending limits in mind and don't send in bulk.
- If the token leaks, revoke it in BotFather and put the new value in your configuration.
- For scheduled jobs such as a daily report, use cron on your host.

## Testing and troubleshooting

After installing the code, place a test order. If no message arrives, check these in order:

1. Are the constants in `wp-config.php` defined correctly? One wrong character is enough to break it.
2. Is the bot in the group, and an admin of the channel?
3. Is the chat ID correct? Group IDs are usually negative.
4. Did the PHP error log or the WordPress log record anything? Enabling `WP_DEBUG_LOG` on a staging site helps. Don't leave it on longer than necessary on a live site.
5. Does the server have outbound access to `api.telegram.org`? Some hosts restrict outbound connections.

For building a clean, safe plugin, [building a WordPress plugin from scratch](https://di9.ir/blog/%D8%B3%D8%A7%D8%AE%D8%AA-%D8%A7%D9%81%D8%B2%D9%88%D9%86%D9%87-%D9%88%D8%B1%D8%AF%D9%BE%D8%B1%D8%B3-%D8%A7%D8%B2-%D8%B5%D9%81%D8%B1) is a good foundation. For overall site security, also review the [WordPress security checklist](https://di9.ir/blog/%DA%86%DA%A9-%D9%84%DB%8C%D8%B3%D8%AA-%D8%A7%D9%85%D9%86%DB%8C%D8%AA-%D9%88%D8%B1%D8%AF%D9%BE%D8%B1%D8%B3).

## What not to send

No sensitive data should be in the message: passwords, card details, verification codes, or anything that would cause serious harm if leaked. An alert should only say "something happened" and give the order number; the manager sees the details in the site's admin panel. If a message must contain customer information, keep the group private and limit its members to the people who need it.

## Alternative: a ready-made plugin

If you don't want to write code, there are ready-made plugins that send forms or orders to Telegram. Before installing, check a few things: is it still maintained? Where does it store the token? Does it send more information than needed to an outside service? A plugin that asks for several unnecessary permissions for a simple job, or has not been updated for a long time, is not a good choice. Remember that every extra plugin increases the attack surface; for a simple need, the few lines of code above are more under your control.

## Summary

- The site sends a message to the bot's API with one HTTPS request; you need the token, the chat ID and outbound access.
- Put the token in `wp-config.php`, an environment variable or `.env`, not in a public file.
- Escape dynamic text for Telegram's HTML mode.
- Use a short timeout and log errors without printing the token so orders are never disrupted.
- Send only the information that is needed, and protect public forms with a nonce and anti-spam.
- For high traffic, hand the sending off to a queue.

## پرسش‌های متداول

### Do I need a plugin or code to connect my website to Telegram?

Both work. If you only need a simple alert, a few lines of code in a small plugin are enough and add no dependencies. If you prefer not to write code, ready-made plugins exist, but before installing one make sure it stores the token safely and is kept up to date.

### Where should I put the Telegram bot token in WordPress?

In wp-config.php as a constant, or in an environment variable. The wp-config.php file is not served over the web and sits outside plugins and themes. Do not put the token in the options table of the database or in JavaScript files.

### Why are my messages not reaching Telegram?

Check that the token is correct, the bot is a member of the group or an admin of the channel, the chat ID is right, and the server can connect to api.telegram.org. Log errors in the server error log without printing the token.

### If Telegram is slow or down, will my customers' orders be affected?

They should not be. Use a short request timeout and only log the error instead of blocking order creation. For high traffic, it is better to send alerts from a background queue.
