WhatsApp Business API для персональных предложений
Сценарий отправляет персонализированный шаблон маркетинга в WhatsApp, когда CRM делит базу на сегменты аудитории и назначает условия предложений для каждого.
Сценарий отправляет персонализированный WhatsApp маркетинговый шаблон, когда CRM разделяет согласившуюся базу на сегменты аудитории и назначает каждому индивидуальные условия предложения. Сообщение включает имя клиента, контекст сегмента, который объясняет, почему предложение подходит именно им, и детали предложения, специфичные для сегмента. Статическая кнопка URL открывает страницу персонализированного предложения.
Шаблон примера
Здравствуйте {{1}}! В качестве участника {{2}} мы подготовили специальное предложение для вас: {{3}}. Нажмите кнопку ниже, чтобы просмотреть ваше персональное предложение и воспользоваться им.
Просмотрите моё предложение.
{{1}}
имя клиента
{{2}}
контекст сегмента (уровень VIP, регион, уровень плана или метка группы RFM)
{{3}}
детали предложения для определённого сегмента (условия скидки, бонуса или привилегии)
“Просмотрите моё предложение.”
кнопка — зафиксирована в шаблоне Meta
Когда это использовать
Используйте этот сценарий, когда вы запускаете одну маркетинговую кампанию, но необходимо предложить разные условия для каждого сегмента аудитории — VIP уровень, регион, тарифный план подписки или группу RFM — и каждый контакт должен видеть условия, соответствующие его сегменту, а не одно общее сообщение. Это подходит для уровней лояльности в розничной торговле, предложений по обновлению на уровне тарифного плана в SaaS и агентств, отправляющих сегментированные предложения для брендов клиентов из разделов CRM.
Один шаблон, множество сегментных предложений
Три переменные тела содержат имя контакта, метку контекста сегмента и условия индивидуального предложения, поэтому CRM может сопоставлять разные значения для каждого сегмента, используя один утвержденный маркетинговый шаблон.
Предложения, которые выглядят так, будто созданы для получателя
Переменная контекста сегмента называет уровень или группу, к которой принадлежит контакт, поэтому сообщение объясняет, почему условия подходят именно им.
Достигайте согласованных сегментов вне 24-часового окна.
Одобренный МАРКЕТИНГОВЫЙ шаблон предлагает сегментированные предложения через WhatsApp даже тогда, когда разговор не открыт, поэтому кампания не зависит от недавнего входящего сообщения.
Меньше ручного разделения списков и перепечатывания
CRM определяет сегменты и предоставляет поля персонализации при экспорте, а шаблон отправляется по триггеру сегмента — никаких повторных сборок списков или ручного ввода условий предложений для каждого уровня.
Отслеживание доставки по сегментам
Результаты доставок регистрируются по сегментам для отслеживания эффективности кампании, поэтому маркетинг может сравнивать охват и вовлеченность между VIP, региональными и уровнями планов.
рабочий процесс
Сигнал
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_PRODUCTCONTEXT="___" # {{2}} product context
TEST_DETAILS="___" # {{3}} change details
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_PRODUCTCONTEXT=$TEST_PRODUCTCONTEXT" \
"TEST_DETAILS=$TEST_DETAILS"; 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 context → ${TEST_PRODUCTCONTEXT}
# {{3}} change details → ${TEST_DETAILS}
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_PRODUCTCONTEXT}" },
{ "type": "text", "text": "${TEST_DETAILS}" }
]
}
]
}
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 связаны с этим.
Доставка осуществляется позже, в виде отдельного обратного вызова. Зарегистрируйте webhook (POST …/webhook), и 1MSG отправляет обновления статуса на ваш HTTPS-эндпоинт в поле hooks[].
200 ХорошоСтатус доставки webhook — данные, которые вы получаете.
отправлено, доставлено, прочитано — или статус ошибки, если применимо
id
Сопоставляет обратный вызов с 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 шаблона.