1msg official logo

WhatsApp Business API para nutrición de decisión de compra

Este escenario envía a un cliente potencial una plantilla de WhatsApp personalizada mientras aún decide.

Descripción del caso de uso

Este escenario envía a un cliente potencial una plantilla de WhatsApp personalizada mientras aún decide. El mensaje incluye su nombre, el producto o servicio en consideración y una pista útil de siguiente paso. Dos botones quick-reply permiten hacer una pregunta o señalar que están listos para comprar; los toques llegan vía webhook para enrutar a ventas o seguimiento automatizado.

Ejemplo de plantilla

Hola {{1}}! Estamos aquí para ayudarte a decidir sobre {{2}}. {{3}} — toca un botón abajo si tienes preguntas o estás listo para avanzar.

[Hacer una pregunta]

Variables y propósito

  • {{1}} — nombre del cliente o prospecto
  • {{2}} — nombre del producto o servicio en consideración
  • {{3}} — pista útil de siguiente paso o touchpoint de nutrición (p. ej. guía comparativa, FAQ, oferta de agendar llamada)

Ejemplo completado

Hola Ana! Estamos aquí para ayudarte a decidir sobre Suscripción Plan Premium. Nuestro equipo preparó una guía comparativa y puede responder preguntas de precios — toca un botón abajo si tienes preguntas o estás listo para avanzar.

[Hacer una pregunta]

Cuándo usarlo

  • b2b y servicios
  • e-commerce y saas
  • agencias y equipos pequeños

Valor para el negocio

  • detect a nurture touchpoint trigger for a prospect still in the decision stage
  • resolve customer phone, product or service context, and the next-step hint
  • send a personalised nurture template with two quick-reply engagement buttons
  • receive button taps via webhook and route to sales or automated follow-up
  • log delivery and engagement for CRM pipeline until buy or no-buy decision

Flujo de trabajo

  1. CRM o el pipeline de ventas detecta que corresponde un touchpoint de nutrición para un prospecto aún en etapa de decisión.
  2. Se toman del CRM o registro del pipeline el teléfono del cliente, contexto de producto o servicio y la pista de siguiente paso.
  3. Se envía una plantilla personalizada con tres variables en el cuerpo y dos botones quick-reply para engagement.
  4. El prospecto toca «Hacer una pregunta» o «Listo para comprar» — el evento llega vía webhook y el seguimiento se enruta en consecuencia.
  5. La entrega y el engagement se registran en CRM hasta que el prospecto compra, declina o sale del track de nutrición.
  6. El progreso de entrega se reporta de forma asíncrona — típicamente sent, luego delivered (o failed/undelivered).
  7. Tu sistema recibe el estado vía webhook (hooks[]) o consulta GET …/hookInfo?messageId=<id> y maneja fallos si es necesario.

Implementación técnica

Requisitos previos

  • Plantilla de WhatsApp aprobada con tres variables en el cuerpo y dos botones quick-reply («Hacer una pregunta», «Listo para comprar»).
  • Cuenta 1MSG con acceso a la API de envío de plantillas y webhook configurado para mensajes entrantes.
  • Integración con CRM o pipeline de ventas para programar touchpoints y registrar engagement hasta una decisión.
  • El handleIncomingMessage generado compara texto entrante con etiquetas de botones de plantilla — punto de partida; reemplázalo con tu router de producción.

Ejemplos de código

Node.js

#!/usr/bin/env node

// === Configuration (replace "___" placeholders) ===

const API_BASE_URL = "https://api.1msg.io"; // production 1MSG API base URL
const CHANNEL_ID = "___";                   // channel ID from 1MSG dashboard
const API_TOKEN = "___";                    // channel JWT token (Bearer)

const TEMPLATE_NAME = "___";                // approved template name
const TEMPLATE_NAMESPACE = "___";           // template namespace (422 without it)
const TEMPLATE_LANGUAGE = "___";            // template language code, e.g. "en"



// === Test data ===
const TEST_PHONE = "___";            // client phone in international format
const TEST_CUSTOMERNAME = "___";    // {{1}} customer name
const TEST_PRODUCTORSERVICENAME = "___";    // {{2}} product or service name
const TEST_NEXTSTEP = "___";    // {{3}} next step

function normalizePhone(phone) {
  return String(phone).replace(/\D/g, "");
}

function assertConfigured(values) {
  for (const [key, value] of Object.entries(values)) {
    if (value === "___" || value === "" || value === undefined || value === null) {
      throw new Error(`Missing configuration value: ${key}`);
    }
  }
}

async function sendTemplateMessage({ phone, customerName, productOrServiceName, nextStep }) {
  assertConfigured({
    CHANNEL_ID,
    API_TOKEN,
    TEMPLATE_NAME,
    TEMPLATE_NAMESPACE,
    TEMPLATE_LANGUAGE,
    phone,
    customerName,
    productOrServiceName,
    nextStep,
  });

  const url = `${API_BASE_URL}/${CHANNEL_ID}/sendTemplate`;

  // params carries body and button blocks (dynamic buttons).
  const requestBody = {
    phone: normalizePhone(phone),
    template: TEMPLATE_NAME,
    namespace: TEMPLATE_NAMESPACE,
    language: {
      policy: "deterministic",
      code: TEMPLATE_LANGUAGE,
    },
    params: [
      {
        type: "body",
        parameters: [
          { type: "text", text: String(customerName) }, // {{1}} customer name
          { type: "text", text: String(productOrServiceName) }, // {{2}} product or service name
          { type: "text", text: String(nextStep) }, // {{3}} next step
        ],
      },
    ],
  };

  const res = await fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${API_TOKEN}`,
    },
    body: JSON.stringify(requestBody),
  });

  const raw = await res.text();
  let data;
  try {
    data = JSON.parse(raw);
  } catch {
    data = null;
  }

  if (!res.ok || !data || data.sent !== true) {
    console.error("Send failed. API response:");
    console.error(raw);
    process.exit(1);
  }

  console.log("Message sent to client.");
  console.log("API response:", raw);
  return data;
}

function handleIncomingMessage(message) {
  const text = (message && (message.text || message.body || "")).trim();
  // Meta quick_reply label (from template.txt) → route key (code_contract.ref) "ask_question"
  if (text === "Ask a question") {
    console.log("Reply received: ask_question");
    return { status: "ask_question" };
  }
  // Meta quick_reply label (from template.txt) → route key (code_contract.ref) "ready_to_buy"
  if (text === "Ready to buy") {
    console.log("Reply received: ready_to_buy");
    return { status: "ready_to_buy" };
  }
  console.log("Free-text reply — handle separately.");
  return { status: "other" };
}

if (require.main === module) {
  sendTemplateMessage({
    phone: TEST_PHONE,
    customerName: TEST_CUSTOMERNAME,
    productOrServiceName: TEST_PRODUCTORSERVICENAME,
    nextStep: TEST_NEXTSTEP,
  }).catch((err) => {
    console.error("Execution failed:", err.message);
    process.exit(1);
  });
}

module.exports = { sendTemplateMessage, handleIncomingMessage };

Respuesta inmediata de la API (síncrona)

  • HTTP 2xx y JSON "sent": true significan que 1MSG aceptó el mensaje para envío — no que ya llegó al teléfono del cliente.
  • Guarda el campo `id` de la respuesta (valor tipo wamid.…). Úsalo para correlacionar callbacks de entrega o polling.
  • La respuesta también puede incluir message y description — solo informativos.

Estado de entrega (asíncrono)

  • Registra un webhook (POST …/webhook) para que 1MSG envíe actualizaciones de entrega a tu endpoint HTTPS en un payload `hooks[]` separado (sent, delivered, read, o failed/undelivered cuando aplique).
  • Opcionalmente consulta: GET {base}/{channel}/hookInfo?messageId=<id de sendTemplate>.
  • En la práctica, la entrega suele completarse en pocos segundos — pero eso no está garantizado por el contrato de la API.

Errores frecuentes

  • Número de teléfono inválido o no normalizado
  • Nombre de plantilla / namespace no aprobado o ausente
  • Sin opt-in del cliente para mensajes comerciales de WhatsApp
  • Cantidad de variables de plantilla incorrecta (422 de la API)
  • Fallo de entrega — revisa el webhook de estado y la política de reintentos

Preguntas frecuentes

  • ¿Necesito una plantilla aprobada? Sí — los mensajes cold-start de WhatsApp requieren una plantilla aprobada por Meta.
  • ¿Puedo personalizar el texto? Las variables del cuerpo son dinámicas; el texto fijo y las etiquetas de botones se definen en la plantilla de Meta.
  • ¿Cómo verifico la entrega? sent: true solo confirma aceptación. Rastrea la entrega vía webhook hooks[] o GET …/hookInfo?messageId=<id>.
  • ¿Qué pasa si no se entrega? Registra el hook failed/undelivered, verifica opt-in y estado de la plantilla, luego reintenta o usa otro canal.
  • ¿Puedo conectarlo a mi CRM o backend? Sí — dispara la llamada a la API desde el webhook de tu plataforma o manejador de eventos.

CTA

¿Listo para usar nutrición de decisión de compra? Conecta tu canal 1MSG y ejecuta los ejemplos de código de arriba.

Recursos relacionados

Build WhatsApp automation in minutes

Use 1MSG to automate this workflow and try it with our free demo.

Try the demo →