Сценарий отправляет персонализированный маркетинговый шаблон WhatsApp подписанным контактам при начале промо-кампании. Сообщение включает имя клиента, рекламируемый продукт или категорию, детали предложения и дату окончания акции. Статическая кнопка URL открывает страницу с предложением.
Пример шаблона
Здравствуйте{{1}}! У нас есть специальное предложение на{{2}}: {{3}}. Акция действует до{{4}}. Нажмите кнопку ниже, чтобы посмотреть предложение и купить сейчас.
Просмотреть предложение
{{1}}
имя клиента
{{2}}
продвигаемый товар или категория
{{3}}
подробности рекламного предложения (размер скидки, условия)
{{4}}
предложение действительно до даты
“Просмотреть предложение”
кнопка — исправлено в шаблоне Meta
Когда использовать
Используйте этот сценарий, если у вас уже есть список для WhatsApp-маркетинга и вы хотите объявить скидку или специальное предложение для этой базы, а не для холодных контактов. Он подходит для сезонных распродаж в розничной торговле и электронной коммерции, продвижения обновлений SaaS для существующих подписчиков, а также для агентств, которые проводят промо-рассылки для брендов клиентов из сегментов CRM.
Связывайтесь с подписанными контактами вне 24-часового окна
Утверждённый шаблон MARKETING доставляет рекламное предложение в WhatsApp даже при отсутствии открытого разговора, поэтому кампания не зависит от недавнего входящего сообщения.
Предложения, где указаны имя клиента и условия сделки
Четыре переменные в теле содержат имя контакта, продвигаемый продукт или категорию, детали предложения и дату истечения срока, чтобы рассылка выглядела как целевая, а не общая.
Один тап на страницу продвижения
Кнопка со статическим URL, закреплённая в шаблоне Meta, открывает страницу с предложением, чтобы контакт мог воспользоваться скидкой, не ожидая в окне ответа.
Меньше ручной сборки кампаний
CRM или система автоматизации маркетинга предоставляет сегменты и поля персонализации, а шаблон отправляется по этому триггеру — менеджеру не нужно заново составлять список или перепечатывать условия предложения для каждого контакта.
Отслеживание доставки кампании
Результаты доставки записываются для отслеживания эффективности кампании, чтобы маркетологи знали, сколько подписавшихся контактов получили предложение перед измерением конверсий в других местах.
Как это работает
Триггер
Маркетинг или CRM выбирает сегмент, давший согласие, для рекламной кампании.
event · triggered
Захватить событие
Система определяет номера телефонов и поля персонализации для каждого контакта.
phone: "+…"
Собрать и отправить
Персонализированный рекламный шаблон состоит из четырёх переменных в теле и статической кнопки URL.
POST/sendTemplate
Доставлено
Каждый контакт, давший согласие, получает сообщение с маркетинговым предложением в WhatsApp.
delivered
Статус отслежен
Результаты доставки фиксируются для отслеживания эффективности кампаний и последующих действий.
#!/usr/bin/env bash
set -euo pipefail
# === Configuration (replace "___" placeholders) ===
API_BASE_URL="https://api.1msg.io" # production 1MSG API base URL
CHANNEL_ID="___" # channel ID from 1MSG dashboard
API_TOKEN="___" # channel JWT token (Bearer)
TEMPLATE_NAME="___" # approved template name
TEMPLATE_NAMESPACE="___" # template namespace (required — send fails without it)
TEMPLATE_LANGUAGE="___" # template language code, e.g. "en"
# === Test data ===
TEST_PHONE="___" # client phone in international format
TEST_CUSTOMERNAME="___" # {{1}} customer name
TEST_PRODUCTORSERVICENAME="___" # {{2}} product or service name
TEST_DETAILS="___" # {{3}} change details
TEST_DATE="___" # {{4}} date or time
PHONE_NORM="$(printf '%s' "$TEST_PHONE" | tr -cd '0-9')"
for pair in "CHANNEL_ID=$CHANNEL_ID" "API_TOKEN=$API_TOKEN" \
"TEMPLATE_NAME=$TEMPLATE_NAME" "TEMPLATE_NAMESPACE=$TEMPLATE_NAMESPACE" \
"TEMPLATE_LANGUAGE=$TEMPLATE_LANGUAGE" "TEST_PHONE=$TEST_PHONE" \
"TEST_CUSTOMERNAME=$TEST_CUSTOMERNAME" \
"TEST_PRODUCTORSERVICENAME=$TEST_PRODUCTORSERVICENAME" \
"TEST_DETAILS=$TEST_DETAILS" \
"TEST_DATE=$TEST_DATE"; do
val="${pair#*=}"
if [ -z "$val" ] || [ "$val" = "___" ]; then
echo "Missing configuration value: ${pair%%=*}" >&2
exit 1
fi
done
if [ -z "$PHONE_NORM" ]; then
echo "Error: phone number has no digits after normalization" >&2
exit 1
fi
URL="${API_BASE_URL%/}/${CHANNEL_ID}/sendTemplate"
# params carries body ONLY. Button text is fixed in the Meta template — no button param.
# {{1}} customer name → ${TEST_CUSTOMERNAME}
# {{2}} product or service name → ${TEST_PRODUCTORSERVICENAME}
# {{3}} change details → ${TEST_DETAILS}
# {{4}} date or time → ${TEST_DATE}
read -r -d '' PAYLOAD <<JSON || true
{
"phone": "${PHONE_NORM}",
"template": "${TEMPLATE_NAME}",
"namespace": "${TEMPLATE_NAMESPACE}",
"language": { "policy": "deterministic", "code": "${TEMPLATE_LANGUAGE}" },
"params": [
{
"type": "body",
"parameters": [
{ "type": "text", "text": "${TEST_CUSTOMERNAME}" },
{ "type": "text", "text": "${TEST_PRODUCTORSERVICENAME}" },
{ "type": "text", "text": "${TEST_DETAILS}" },
{ "type": "text", "text": "${TEST_DATE}" }
]
}
]
}
JSON
RESPONSE="$(curl -s -w '\n%{http_code}' -X POST "$URL" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${API_TOKEN}" \
-d "$PAYLOAD")"
HTTP_CODE="$(printf '%s' "$RESPONSE" | tail -n1)"
BODY="$(printf '%s' "$RESPONSE" | sed '$d')"
case "$BODY" in
*'"sent":true'*) ok=1 ;;
*) ok=0 ;;
esac
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ] && [ "$ok" -eq 1 ]; then
echo "Message sent to client."
echo "API response: $BODY"
else
echo "Send failed. HTTP status: $HTTP_CODE" >&2
echo "$BODY" >&2
exit 1
fi
Статус ответа и доставки
HTTP 2xx и JSON "sent": true обозначают, что 1MSG приняла сообщение для отправки — это не значит, что оно уже доставлено на телефон клиента. Сохранитеid поле (выглядит как wamid.…), чтобы сопоставить обратные вызовы доставки.
Принято для отправки — ещё не доставлено на телефон клиента
id
Сохраните это; обратные вызовы доставки и hookInfo привязаны к этому
Доставка поступает позже в виде отдельного обратного вызова. Зарегистрируйте POST …/webhookвебхук, и 1MSG POSTs статус обновления на ваш HTTPS-эндпоинт в hooks[]основной полезной нагрузке
200 OKВебхук статуса доставки — payload, который вы получаете
sent, delivered, read — или статус сбоя, если применимо
id
Связывает callback с id, возвращённым вызовом send
timestamp
Unix-время в виде строки
Если вы предпочитаете не получать обратные вызовы, вместо этого используйте опрос. GET {base}/{channel}/hookInfo?messageId=<id>На практике доставка часто завершается за считанные секунды — но контракт API этого не гарантирует, так что никогда не блокируйте поток, ожидая её.
Типичные ошибки
Статус
Ответ
Причина
200
Message was not sent: template is not defined
namespace, template or language missing from the request body.
200
template name (…) does not exist in <language>
The template is approved in a different language than the one requested.
200
Message was not sent: provide chatId, phone, bsuid, or username
No recipient the channel could resolve.
403
access denied
The token is wrong, or belongs to a different channel than the URL.
429
too many requests. please try later
The channel is over its send rate.
ЧАСТО ЗАДАВАЕМЫЕ ВОПРОСЫ
Да, для холодных сообщений в WhatsApp нужен одобренный Meta шаблон.